{-# LANGUAGE FlexibleContexts #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Xmobar.Parsers
-- Copyright   :  (c) Andrea Rossato
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Jose A. Ortega Ruiz <jao@gnu.org>
-- Stability   :  unstable
-- Portability :  unportable
--
-- Parsing for template substrings
--
-----------------------------------------------------------------------------

module Xmobar.X11.Parsers (parseString, Box(..), BoxBorder(..), BoxOffset(..),
  BoxMargins(..), TextRenderInfo(..), Widget(..)) where

import Xmobar.Config.Types
import Xmobar.X11.Actions

import Control.Monad (guard, mzero)
import Data.Maybe (fromMaybe)
import Data.Int (Int32)
import Text.ParserCombinators.Parsec
import Text.Read (readMaybe)
import Graphics.X11.Types (Button)
import Foreign.C.Types (CInt)

data Widget = Icon String | Text String

data BoxOffset = BoxOffset Align Int32 deriving BoxOffset -> BoxOffset -> Bool
(BoxOffset -> BoxOffset -> Bool)
-> (BoxOffset -> BoxOffset -> Bool) -> Eq BoxOffset
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BoxOffset -> BoxOffset -> Bool
$c/= :: BoxOffset -> BoxOffset -> Bool
== :: BoxOffset -> BoxOffset -> Bool
$c== :: BoxOffset -> BoxOffset -> Bool
Eq 
-- margins: Top, Right, Bottom, Left
data BoxMargins = BoxMargins Int32 Int32 Int32 Int32 deriving BoxMargins -> BoxMargins -> Bool
(BoxMargins -> BoxMargins -> Bool)
-> (BoxMargins -> BoxMargins -> Bool) -> Eq BoxMargins
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BoxMargins -> BoxMargins -> Bool
$c/= :: BoxMargins -> BoxMargins -> Bool
== :: BoxMargins -> BoxMargins -> Bool
$c== :: BoxMargins -> BoxMargins -> Bool
Eq
data BoxBorder = BBTop
               | BBBottom
               | BBVBoth
               | BBLeft
               | BBRight
               | BBHBoth
               | BBFull
                 deriving ( ReadPrec [BoxBorder]
ReadPrec BoxBorder
Int -> ReadS BoxBorder
ReadS [BoxBorder]
(Int -> ReadS BoxBorder)
-> ReadS [BoxBorder]
-> ReadPrec BoxBorder
-> ReadPrec [BoxBorder]
-> Read BoxBorder
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BoxBorder]
$creadListPrec :: ReadPrec [BoxBorder]
readPrec :: ReadPrec BoxBorder
$creadPrec :: ReadPrec BoxBorder
readList :: ReadS [BoxBorder]
$creadList :: ReadS [BoxBorder]
readsPrec :: Int -> ReadS BoxBorder
$creadsPrec :: Int -> ReadS BoxBorder
Read, BoxBorder -> BoxBorder -> Bool
(BoxBorder -> BoxBorder -> Bool)
-> (BoxBorder -> BoxBorder -> Bool) -> Eq BoxBorder
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BoxBorder -> BoxBorder -> Bool
$c/= :: BoxBorder -> BoxBorder -> Bool
== :: BoxBorder -> BoxBorder -> Bool
$c== :: BoxBorder -> BoxBorder -> Bool
Eq )
data Box = Box BoxBorder BoxOffset CInt String BoxMargins deriving Box -> Box -> Bool
(Box -> Box -> Bool) -> (Box -> Box -> Bool) -> Eq Box
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Box -> Box -> Bool
$c/= :: Box -> Box -> Bool
== :: Box -> Box -> Bool
$c== :: Box -> Box -> Bool
Eq
data TextRenderInfo =
    TextRenderInfo { TextRenderInfo -> String
tColorsString   :: String
                   , TextRenderInfo -> Int32
tBgTopOffset    :: Int32
                   , TextRenderInfo -> Int32
tBgBottomOffset :: Int32
                   , TextRenderInfo -> [Box]
tBoxes          :: [Box]
                   }
type FontIndex   = Int

-- | Runs the string parser
parseString :: Config -> String
               -> IO [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
parseString :: Config
-> String -> IO [(Widget, TextRenderInfo, Int, Maybe [Action])]
parseString Config
c String
s =
    case Parsec String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> String
-> String
-> Either
     ParseError [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
stringParser TextRenderInfo
ci Int
0 Maybe [Action]
forall a. Maybe a
Nothing) String
"" String
s of
      Left  ParseError
_ -> [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> IO [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String -> Widget
Text (String -> Widget) -> String -> Widget
forall a b. (a -> b) -> a -> b
$ String
"Could not parse string: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s
                          , TextRenderInfo
ci
                          , Int
0
                          , Maybe [Action]
forall a. Maybe a
Nothing)]
      Right [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
x -> [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> IO [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
x)
    where ci :: TextRenderInfo
ci = String -> Int32 -> Int32 -> [Box] -> TextRenderInfo
TextRenderInfo (Config -> String
fgColor Config
c) Int32
0 Int32
0 []

allParsers :: TextRenderInfo
           -> FontIndex
           -> Maybe [Action]
           -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
allParsers :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers TextRenderInfo
c Int
f Maybe [Action]
a =  TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
textParser TextRenderInfo
c Int
f Maybe [Action]
a
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall tok st a. GenParser tok st a -> GenParser tok st a
try (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
iconParser TextRenderInfo
c Int
f Maybe [Action]
a)
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall tok st a. GenParser tok st a -> GenParser tok st a
try (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
rawParser TextRenderInfo
c Int
f Maybe [Action]
a)
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall tok st a. GenParser tok st a -> GenParser tok st a
try (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
actionParser TextRenderInfo
c Int
f Maybe [Action]
a)
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall tok st a. GenParser tok st a -> GenParser tok st a
try (TextRenderInfo
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
fontParser TextRenderInfo
c Maybe [Action]
a)
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall tok st a. GenParser tok st a -> GenParser tok st a
try (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
boxParser TextRenderInfo
c Int
f Maybe [Action]
a)
                Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
colorParser TextRenderInfo
c Int
f Maybe [Action]
a

-- | Gets the string and combines the needed parsers
stringParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
                -> Parser [[(Widget, TextRenderInfo, FontIndex, Maybe [Action])]]
stringParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
stringParser TextRenderInfo
c Int
f Maybe [Action]
a = Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> ParsecT String () Identity ()
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers TextRenderInfo
c Int
f Maybe [Action]
a) ParsecT String () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof

-- | Parses a maximal string without markup.
textParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
              -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
textParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
textParser TextRenderInfo
c Int
f Maybe [Action]
a = do String
s <- ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (ParsecT String () Identity Char
 -> ParsecT String () Identity String)
-> ParsecT String () Identity Char
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$
                            String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"<" ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                              ParsecT String () Identity Char -> ParsecT String () Identity Char
forall tok st a. GenParser tok st a -> GenParser tok st a
try (ParsecT String () Identity Char
-> ParsecT String () Identity String
-> ParsecT String () Identity Char
forall a b. Parser a -> Parser b -> Parser a
notFollowedBy' (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'<')
                                    (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"fc=")  ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"box")  ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"fn=")  ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"action=") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/action>") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"icon=") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"raw=") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/fn>") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/box>") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
                                     String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/fc>"))
                      [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String -> Widget
Text String
s, TextRenderInfo
c, Int
f, Maybe [Action]
a)]

-- | Parse a "raw" tag, which we use to prevent other tags from creeping in.
-- The format here is net-string-esque: a literal "<raw=" followed by a
-- string of digits (base 10) denoting the length of the raw string,
-- a literal ":" as digit-string-terminator, the raw string itself, and
-- then a literal "/>".
rawParser :: TextRenderInfo
          -> FontIndex
          -> Maybe [Action]
          -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
rawParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
rawParser TextRenderInfo
c Int
f Maybe [Action]
a = do
  String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<raw="
  String
lenstr <- ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit
  Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
':'
  case ReadS Integer
forall a. Read a => ReadS a
reads String
lenstr of
    [(Integer
len,[])] -> do
      Bool -> ParsecT String () Identity ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard ((Integer
len :: Integer) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int))
      String
s <- Int
-> ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
Int -> ParsecT s u m a -> ParsecT s u m [a]
count (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
len) ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
      String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/>"
      [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String -> Widget
Text String
s, TextRenderInfo
c, Int
f, Maybe [Action]
a)]
    [(Integer, String)]
_ -> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. MonadPlus m => m a
mzero

-- | Wrapper for notFollowedBy that returns the result of the first parser.
--   Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy
--   accepts only parsers with return type Char.
notFollowedBy' :: Parser a -> Parser b -> Parser a
notFollowedBy' :: Parser a -> Parser b -> Parser a
notFollowedBy' Parser a
p Parser b
e = do a
x <- Parser a
p
                        ParsecT String () Identity Char -> ParsecT String () Identity ()
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> ParsecT s u m ()
notFollowedBy (ParsecT String () Identity Char -> ParsecT String () Identity ())
-> ParsecT String () Identity Char -> ParsecT String () Identity ()
forall a b. (a -> b) -> a -> b
$ ParsecT String () Identity Char -> ParsecT String () Identity Char
forall tok st a. GenParser tok st a -> GenParser tok st a
try (Parser b
e Parser b
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> ParsecT String () Identity Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
'*')
                        a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

iconParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
              -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
iconParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
iconParser TextRenderInfo
c Int
f Maybe [Action]
a = do
  String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<icon="
  String
i <- ParsecT String () Identity Char
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill (String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
">") (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/>"))
  [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String -> Widget
Icon String
i, TextRenderInfo
c, Int
f, Maybe [Action]
a)]

actionParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
                -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
actionParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
actionParser TextRenderInfo
c Int
f Maybe [Action]
act = do
  String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<action="
  String
command <- [ParsecT String () Identity String]
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice [ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'`') (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'`') (ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"`")),
                   ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
">")]
  String
buttons <- (Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>' ParsecT String () Identity Char
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT String () Identity String
forall (m :: * -> *) a. Monad m => a -> m a
return String
"1") ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space ParsecT String () Identity Char
-> ParsecT String () Identity () -> ParsecT String () Identity ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT String () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
spaces ParsecT String () Identity ()
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
    ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"button=") (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
">") (ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (String -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"12345")))
  let a :: Action
a = [Button] -> String -> Action
Spawn (String -> [Button]
toButtons String
buttons) String
command
      a' :: Maybe [Action]
a' = case Maybe [Action]
act of
        Maybe [Action]
Nothing -> [Action] -> Maybe [Action]
forall a. a -> Maybe a
Just [Action
a]
        Just [Action]
act' -> [Action] -> Maybe [Action]
forall a. a -> Maybe a
Just ([Action] -> Maybe [Action]) -> [Action] -> Maybe [Action]
forall a b. (a -> b) -> a -> b
$ Action
a Action -> [Action] -> [Action]
forall a. a -> [a] -> [a]
: [Action]
act'
  [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s <- Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> ParsecT String () Identity String
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers TextRenderInfo
c Int
f Maybe [Action]
a') (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (ParsecT String () Identity String
 -> ParsecT String () Identity String)
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"</action>")
  [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s)

toButtons :: String -> [Button]
toButtons :: String -> [Button]
toButtons = (Char -> Button) -> String -> [Button]
forall a b. (a -> b) -> [a] -> [b]
map (\Char
x -> String -> Button
forall a. Read a => String -> a
read [Char
x])

-- | Parsers a string wrapped in a color specification.
colorParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
               -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
colorParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
colorParser (TextRenderInfo String
_ Int32
_ Int32
_ [Box]
bs) Int
f Maybe [Action]
a = do
  String
c <- ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<fc=") (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
">") ParsecT String () Identity String
colors
  let colorParts :: (String, String)
colorParts = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
':') String
c
  let (String
ot,String
ob) = case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
',') (Int -> String -> String
forall a. Int -> [a] -> [a]
Prelude.drop Int
1 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (String, String) -> String
forall a b. (a, b) -> b
snd (String, String)
colorParts) of
             (String
top,Char
',':String
btm) -> (String
top, String
btm)
             (String
top,      String
_) -> (String
top, String
top)
  [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s <- Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> ParsecT String () Identity String
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill
       (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers (String -> Int32 -> Int32 -> [Box] -> TextRenderInfo
TextRenderInfo ((String, String) -> String
forall a b. (a, b) -> a
fst (String, String)
colorParts) (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe (-Int32
1) (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
ot) (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe (-Int32
1) (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
ob) [Box]
bs) Int
f Maybe [Action]
a)
       (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (ParsecT String () Identity String
 -> ParsecT String () Identity String)
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"</fc>")
  [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s)

-- | Parses a string wrapped in a box specification.
boxParser :: TextRenderInfo -> FontIndex -> Maybe [Action]
              -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
boxParser :: TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
boxParser (TextRenderInfo String
cs Int32
ot Int32
ob [Box]
bs) Int
f Maybe [Action]
a = do
  String
c <- ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<box") (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
">") (String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
option String
"" (ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'=' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
' ' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'#' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',')))
  let b :: Box
b = BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box BoxBorder
BBFull (Align -> Int32 -> BoxOffset
BoxOffset Align
C Int32
0) CInt
1 String
cs (Int32 -> Int32 -> Int32 -> Int32 -> BoxMargins
BoxMargins Int32
0 Int32
0 Int32
0 Int32
0)
  let g :: Box
g = Box -> [String] -> Box
boxReader Box
b (String -> [String]
words String
c)
  [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s <- Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> ParsecT String () Identity String
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill
       (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers (String -> Int32 -> Int32 -> [Box] -> TextRenderInfo
TextRenderInfo String
cs Int32
ot Int32
ob (Box
g Box -> [Box] -> [Box]
forall a. a -> [a] -> [a]
: [Box]
bs)) Int
f Maybe [Action]
a)
       (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (ParsecT String () Identity String
 -> ParsecT String () Identity String)
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"</box>")
  [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s)

boxReader :: Box -> [String] -> Box
boxReader :: Box -> [String] -> Box
boxReader Box
b [] = Box
b
boxReader Box
b (String
x:[String]
xs) = do
  let (String
param,String
val) = case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'=') String
x of
                 (String
p,Char
'=':String
v) -> (String
p, String
v)
                 (String
p,    String
_) -> (String
p, String
"")
  Box -> [String] -> Box
boxReader (Box -> String -> String -> Box
boxParamReader Box
b String
param String
val) [String]
xs
 
boxParamReader :: Box -> String -> String -> Box
boxParamReader :: Box -> String -> String -> Box
boxParamReader Box
b String
_ String
"" = Box
b
boxParamReader (Box BoxBorder
bb BoxOffset
off CInt
lw String
fc BoxMargins
mgs) String
"type" String
val = 
  BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box (BoxBorder -> Maybe BoxBorder -> BoxBorder
forall a. a -> Maybe a -> a
fromMaybe BoxBorder
bb (Maybe BoxBorder -> BoxBorder) -> Maybe BoxBorder -> BoxBorder
forall a b. (a -> b) -> a -> b
$ String -> Maybe BoxBorder
forall a. Read a => String -> Maybe a
readMaybe (String
"BB" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
val)) BoxOffset
off CInt
lw String
fc BoxMargins
mgs
boxParamReader (Box BoxBorder
bb (BoxOffset Align
alg Int32
off) CInt
lw String
fc BoxMargins
mgs) String
"offset" (Char
a:String
o) =
  BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box BoxBorder
bb (Align -> Int32 -> BoxOffset
BoxOffset (Align -> Maybe Align -> Align
forall a. a -> Maybe a -> a
fromMaybe Align
alg (Maybe Align -> Align) -> Maybe Align -> Align
forall a b. (a -> b) -> a -> b
$ String -> Maybe Align
forall a. Read a => String -> Maybe a
readMaybe [Char
a]) (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe Int32
off (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
o)) CInt
lw String
fc BoxMargins
mgs
boxParamReader (Box BoxBorder
bb BoxOffset
off CInt
lw String
fc BoxMargins
mgs) String
"width" String
val = 
  BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box BoxBorder
bb BoxOffset
off (CInt -> Maybe CInt -> CInt
forall a. a -> Maybe a -> a
fromMaybe CInt
lw (Maybe CInt -> CInt) -> Maybe CInt -> CInt
forall a b. (a -> b) -> a -> b
$ String -> Maybe CInt
forall a. Read a => String -> Maybe a
readMaybe String
val) String
fc BoxMargins
mgs
boxParamReader (Box BoxBorder
bb BoxOffset
off CInt
lw String
_ BoxMargins
mgs) String
"color" String
val = 
  BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box BoxBorder
bb BoxOffset
off CInt
lw String
val BoxMargins
mgs
boxParamReader (Box BoxBorder
bb BoxOffset
off CInt
lw String
fc mgs :: BoxMargins
mgs@(BoxMargins Int32
mt Int32
mr Int32
mb Int32
ml)) (Char
'm':String
pos) String
val = do
  let mgs' :: BoxMargins
mgs' = case String
pos of
         String
"t" -> Int32 -> Int32 -> Int32 -> Int32 -> BoxMargins
BoxMargins (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe Int32
mt (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
val) Int32
mr Int32
mb Int32
ml
         String
"r" -> Int32 -> Int32 -> Int32 -> Int32 -> BoxMargins
BoxMargins Int32
mt (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe Int32
mr (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
val) Int32
mb Int32
ml
         String
"b" -> Int32 -> Int32 -> Int32 -> Int32 -> BoxMargins
BoxMargins Int32
mt Int32
mr (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe Int32
mb (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
val) Int32
ml
         String
"l" -> Int32 -> Int32 -> Int32 -> Int32 -> BoxMargins
BoxMargins Int32
mt Int32
mr Int32
mb (Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe Int32
ml (Maybe Int32 -> Int32) -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int32
forall a. Read a => String -> Maybe a
readMaybe String
val)
         String
_ -> BoxMargins
mgs
  BoxBorder -> BoxOffset -> CInt -> String -> BoxMargins -> Box
Box BoxBorder
bb BoxOffset
off CInt
lw String
fc BoxMargins
mgs'
boxParamReader Box
b String
_ String
_ = Box
b

-- | Parsers a string wrapped in a font specification.
fontParser :: TextRenderInfo -> Maybe [Action]
              -> Parser [(Widget, TextRenderInfo, FontIndex, Maybe [Action])]
fontParser :: TextRenderInfo
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
fontParser TextRenderInfo
c Maybe [Action]
a = do
  String
f <- ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<fn=") (String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
">") ParsecT String () Identity String
colors
  [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s <- Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> ParsecT String () Identity String
-> Parsec
     String () [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
forall s (m :: * -> *) t u a end.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
manyTill (TextRenderInfo
-> Int
-> Maybe [Action]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
allParsers TextRenderInfo
c (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe String
f) Maybe [Action]
a) (ParsecT String () Identity String
-> ParsecT String () Identity String
forall tok st a. GenParser tok st a -> GenParser tok st a
try (ParsecT String () Identity String
 -> ParsecT String () Identity String)
-> ParsecT String () Identity String
-> ParsecT String () Identity String
forall a b. (a -> b) -> a -> b
$ String -> ParsecT String () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"</fn>")
  [(Widget, TextRenderInfo, Int, Maybe [Action])]
-> Parser [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(Widget, TextRenderInfo, Int, Maybe [Action])]]
-> [(Widget, TextRenderInfo, Int, Maybe [Action])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Widget, TextRenderInfo, Int, Maybe [Action])]]
s)

-- | Parses a color specification (hex or named)
colors :: Parser String
colors :: ParsecT String () Identity String
colors = ParsecT String () Identity Char
-> ParsecT String () Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (ParsecT String () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
':' ParsecT String () Identity Char
-> ParsecT String () Identity Char
-> ParsecT String () Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT String () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'#')