{-#LANGUAGE RecordWildCards#-}
{-#LANGUAGE ScopedTypeVariables#-}

------------------------------------------------------------------------------
-- |
-- Module: Xmobar.Plugins.Monitors.Parsers
-- Copyright: (c) 2018, 2020 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
-- Stability: unstable
-- Portability: portable
-- Created: Sun Dec 02, 2018 04:49
--
--
-- Parsing template strings
--
------------------------------------------------------------------------------


module Xmobar.Plugins.Monitors.Common.Parsers ( runP
                                              , skipRestOfLine
                                              , getNumbers
                                              , getNumbersAsString
                                              , getAllBut
                                              , getAfterString
                                              , skipTillString
                                              , parseTemplate
                                              , parseTemplate'
                                              , parseOptsWith
                                              , templateParser
                                              , runExportParser
                                              , runTemplateParser
                                              , pureParseTemplate
                                              ) where

import Xmobar.Plugins.Monitors.Common.Types

import qualified Data.Map as Map
import System.Console.GetOpt (ArgOrder(Permute), OptDescr, getOpt)
import Text.ParserCombinators.Parsec

runTemplateParser :: MonitorConfig -> IO [(String, String, String)]
runTemplateParser :: MonitorConfig -> IO [(String, String, String)]
runTemplateParser MonitorConfig{Bool
Int
String
[String]
Maybe String
pMaxTotalWidthEllipsis :: MonitorConfig -> String
pMaxTotalWidth :: MonitorConfig -> Int
pNaString :: MonitorConfig -> String
pUseSuffix :: MonitorConfig -> Bool
pBarWidth :: MonitorConfig -> Int
pBarFore :: MonitorConfig -> String
pBarBack :: MonitorConfig -> String
pPadRight :: MonitorConfig -> Bool
pPadChars :: MonitorConfig -> String
pMaxWidthEllipsis :: MonitorConfig -> String
pMaxWidth :: MonitorConfig -> Int
pMinWidth :: MonitorConfig -> Int
pDecDigits :: MonitorConfig -> Int
pPpad :: MonitorConfig -> Int
pExport :: MonitorConfig -> [String]
pTemplate :: MonitorConfig -> String
pHighColor :: MonitorConfig -> Maybe String
pHigh :: MonitorConfig -> Int
pLowColor :: MonitorConfig -> Maybe String
pLow :: MonitorConfig -> Int
pNormalColor :: MonitorConfig -> Maybe String
pMaxTotalWidthEllipsis :: String
pMaxTotalWidth :: Int
pNaString :: String
pUseSuffix :: Bool
pBarWidth :: Int
pBarFore :: String
pBarBack :: String
pPadRight :: Bool
pPadChars :: String
pMaxWidthEllipsis :: String
pMaxWidth :: Int
pMinWidth :: Int
pDecDigits :: Int
pPpad :: Int
pExport :: [String]
pTemplate :: String
pHighColor :: Maybe String
pHigh :: Int
pLowColor :: Maybe String
pLow :: Int
pNormalColor :: Maybe String
..} = forall a. Parser [a] -> String -> IO [a]
runP Parser [(String, String, String)]
templateParser String
pTemplate

runExportParser :: [String] -> IO [(String, [(String, String,String)])]
runExportParser :: [String] -> IO [(String, [(String, String, String)])]
runExportParser [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure []
runExportParser (String
x:[String]
xs) = do
  [(String, String, String)]
s <- forall a. Parser [a] -> String -> IO [a]
runP Parser [(String, String, String)]
templateParser String
x
  [(String, [(String, String, String)])]
rest <- [String] -> IO [(String, [(String, String, String)])]
runExportParser [String]
xs
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ (String
x,[(String, String, String)]
s)forall a. a -> [a] -> [a]
:[(String, [(String, String, String)])]
rest

pureParseTemplate :: MonitorConfig -> TemplateInput -> IO String
pureParseTemplate :: MonitorConfig -> TemplateInput -> IO String
pureParseTemplate MonitorConfig{Bool
Int
String
[String]
Maybe String
pMaxTotalWidthEllipsis :: String
pMaxTotalWidth :: Int
pNaString :: String
pUseSuffix :: Bool
pBarWidth :: Int
pBarFore :: String
pBarBack :: String
pPadRight :: Bool
pPadChars :: String
pMaxWidthEllipsis :: String
pMaxWidth :: Int
pMinWidth :: Int
pDecDigits :: Int
pPpad :: Int
pExport :: [String]
pTemplate :: String
pHighColor :: Maybe String
pHigh :: Int
pLowColor :: Maybe String
pLow :: Int
pNormalColor :: Maybe String
pMaxTotalWidthEllipsis :: MonitorConfig -> String
pMaxTotalWidth :: MonitorConfig -> Int
pNaString :: MonitorConfig -> String
pUseSuffix :: MonitorConfig -> Bool
pBarWidth :: MonitorConfig -> Int
pBarFore :: MonitorConfig -> String
pBarBack :: MonitorConfig -> String
pPadRight :: MonitorConfig -> Bool
pPadChars :: MonitorConfig -> String
pMaxWidthEllipsis :: MonitorConfig -> String
pMaxWidth :: MonitorConfig -> Int
pMinWidth :: MonitorConfig -> Int
pDecDigits :: MonitorConfig -> Int
pPpad :: MonitorConfig -> Int
pExport :: MonitorConfig -> [String]
pTemplate :: MonitorConfig -> String
pHighColor :: MonitorConfig -> Maybe String
pHigh :: MonitorConfig -> Int
pLowColor :: MonitorConfig -> Maybe String
pLow :: MonitorConfig -> Int
pNormalColor :: MonitorConfig -> Maybe String
..} TemplateInput{[String]
[(String, [(String, String, String)])]
[(String, String, String)]
temAllTemplate :: TemplateInput -> [(String, [(String, String, String)])]
temInputTemplate :: TemplateInput -> [(String, String, String)]
temMonitorValues :: TemplateInput -> [String]
temAllTemplate :: [(String, [(String, String, String)])]
temInputTemplate :: [(String, String, String)]
temMonitorValues :: [String]
..} =
    do let m :: Map String ([(String, String, String)], String)
m = let [([(String, String, String)], String)]
expSnds :: [([(String, String, String)], String)]  = forall a b. [a] -> [b] -> [(a, b)]
zip (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [(String, [(String, String, String)])]
temAllTemplate) [String]
temMonitorValues
               in forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(String, [(String, String, String)])]
temAllTemplate) [([(String, String, String)], String)]
expSnds
       String
s <- Map String ([(String, String, String)], String)
-> [(String, String, String)] -> IO String
minCombine Map String ([(String, String, String)], String)
m [(String, String, String)]
temInputTemplate
       let (Int
n, String
s') = if Int
pMaxTotalWidth forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s forall a. Ord a => a -> a -> Bool
> Int
pMaxTotalWidth
                     then Int -> String -> String -> (Int, String)
trimTo (Int
pMaxTotalWidth forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> Int
length String
pMaxTotalWidthEllipsis) String
"" String
s
                     else (Int
1, String
s)
       forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if Int
n forall a. Ord a => a -> a -> Bool
> Int
0 then String
s' else String
s' forall a. [a] -> [a] -> [a]
++ String
pMaxTotalWidthEllipsis

minCombine :: Map.Map String ([(String, String, String)], String) -> [(String, String, String)] -> IO String
minCombine :: Map String ([(String, String, String)], String)
-> [(String, String, String)] -> IO String
minCombine Map String ([(String, String, String)], String)
_ [] = forall (m :: * -> *) a. Monad m => a -> m a
return []
minCombine Map String ([(String, String, String)], String)
m ((String
s,String
ts,String
ss):[(String, String, String)]
xs) =
    do String
next <- Map String ([(String, String, String)], String)
-> [(String, String, String)] -> IO String
minCombine Map String ([(String, String, String)], String)
m [(String, String, String)]
xs
       String
str <- case forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
ts Map String ([(String, String, String)], String)
m of
         Maybe ([(String, String, String)], String)
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"<" forall a. [a] -> [a] -> [a]
++ String
ts forall a. [a] -> [a] -> [a]
++ String
">"
         Just ([(String, String, String)]
s',String
r) -> let f :: String -> String
f String
"" = String
r; f String
n = String
n; in String -> String
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map String ([(String, String, String)], String)
-> [(String, String, String)] -> IO String
minCombine Map String ([(String, String, String)], String)
m [(String, String, String)]
s'
       forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
str forall a. [a] -> [a] -> [a]
++ String
ss forall a. [a] -> [a] -> [a]
++ String
next

runP :: Parser [a] -> String -> IO [a]
runP :: forall a. Parser [a] -> String -> IO [a]
runP Parser [a]
p String
i =
    case forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
parse Parser [a]
p String
"" String
i of
      Left ParseError
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return []
      Right [a]
x  -> forall (m :: * -> *) a. Monad m => a -> m a
return [a]
x

getAllBut :: String -> Parser String
getAllBut :: String -> Parser String
getAllBut String
s =
    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 (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
s) (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head String
s)

getNumbers :: Parser Float
getNumbers :: Parser Float
getNumbers = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
skipMany forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
n -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Read a => String -> a
read String
n

getNumbersAsString :: Parser String
getNumbersAsString :: Parser String
getNumbersAsString = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
skipMany forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
space forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
n -> forall (m :: * -> *) a. Monad m => a -> m a
return String
n

skipRestOfLine :: Parser Char
skipRestOfLine :: ParsecT String () Identity Char
skipRestOfLine =
    do forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"\n\r"
       forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline

getAfterString :: String -> Parser String
getAfterString :: String -> Parser String
getAfterString String
s =
    do { forall tok st a. GenParser tok st a -> GenParser tok st a
try forall a b. (a -> b) -> a -> b
$ 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 ParsecT String () Identity Char
skipRestOfLine forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
s
       ; 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 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
newline
       } forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall (m :: * -> *) a. Monad m => a -> m a
return String
""

skipTillString :: String -> Parser String
skipTillString :: String -> Parser String
skipTillString String
s =
    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 ParsecT String () Identity Char
skipRestOfLine forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
s

-- | Parses the output template string
templateStringParser :: Parser (String,String,String)
templateStringParser :: Parser (String, String, String)
templateStringParser =
    do { String
s <- Parser String
nonPlaceHolder
       ; String
com <- Parser String
templateCommandParser
       ; String
ss <- Parser String
nonPlaceHolder
       ; forall (m :: * -> *) a. Monad m => a -> m a
return (String
s, String
com, String
ss)
       }
    where
      nonPlaceHolder :: Parser String
nonPlaceHolder = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many forall a b. (a -> b) -> a -> b
$
                       forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"<") forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser String
colorSpec forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser String
iconSpec

-- | Recognizes color specification and returns it unchanged
colorSpec :: Parser String
colorSpec :: Parser String
colorSpec = forall tok st a. GenParser tok st a -> GenParser tok st a
try (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"</fc>") forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall tok st a. GenParser tok st a -> GenParser tok st a
try (
            do forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<fc="
               String
s <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
many1 (forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
',' forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'#')
               forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>'
               forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"<fc=" forall a. [a] -> [a] -> [a]
++ String
s forall a. [a] -> [a] -> [a]
++ String
">")

-- | Recognizes icon specification and returns it unchanged
iconSpec :: Parser String
iconSpec :: Parser String
iconSpec = forall tok st a. GenParser tok st a -> GenParser tok st a
try (do forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"<icon="
                   String
i <- 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 (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
">") (forall tok st a. GenParser tok st a -> GenParser tok st a
try (forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"/>"))
                   forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"<icon=" forall a. [a] -> [a] -> [a]
++ String
i forall a. [a] -> [a] -> [a]
++ String
"/>")

-- | Parses the command part of the template string
templateCommandParser :: Parser String
templateCommandParser :: Parser String
templateCommandParser =
    do { forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'<'
       ; String
com <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many forall a b. (a -> b) -> a -> b
$ forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
">"
       ; forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>'
       ; forall (m :: * -> *) a. Monad m => a -> m a
return String
com
       }

-- | Combines the template parsers
templateParser :: Parser [(String,String,String)]
templateParser :: Parser [(String, String, String)]
templateParser = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many Parser (String, String, String)
templateStringParser --"%")

trimTo :: Int -> String -> String -> (Int, String)
trimTo :: Int -> String -> String -> (Int, String)
trimTo Int
n String
p String
"" = (Int
n, String
p)
trimTo Int
n String
p (Char
'<':String
cs) = Int -> String -> String -> (Int, String)
trimTo Int
n String
p' String
s
  where p' :: String
p' = String
p forall a. [a] -> [a] -> [a]
++ String
"<" forall a. [a] -> [a] -> [a]
++ forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
/= Char
'>') String
cs forall a. [a] -> [a] -> [a]
++ String
">"
        s :: String
s = forall a. Int -> [a] -> [a]
drop Int
1 (forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
/= Char
'>') String
cs)
trimTo Int
0 String
p String
s = Int -> String -> String -> (Int, String)
trimTo Int
0 String
p (forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
/= Char
'<') String
s)
trimTo Int
n String
p String
s = let p' :: String
p' = forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
/= Char
'<') String
s
                   s' :: String
s' = forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
/= Char
'<') String
s
               in
                 if forall (t :: * -> *) a. Foldable t => t a -> Int
length String
p' forall a. Ord a => a -> a -> Bool
<= Int
n
                 then Int -> String -> String -> (Int, String)
trimTo (Int
n forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> Int
length String
p') (String
p forall a. [a] -> [a] -> [a]
++ String
p') String
s'
                 else Int -> String -> String -> (Int, String)
trimTo Int
0 (String
p forall a. [a] -> [a] -> [a]
++ forall a. Int -> [a] -> [a]
take Int
n String
p') String
s'

-- | Takes a list of strings that represent the values of the exported
-- keys. The strings are joined with the exported keys to form a map
-- to be combined with 'combine' to the parsed template. Returns the
-- final output of the monitor, trimmed to MaxTotalWidth if that
-- configuration value is positive.
parseTemplate :: [String] -> Monitor String
parseTemplate :: [String] -> Monitor String
parseTemplate [String]
l =
    do String
t <- forall a. Selector a -> Monitor a
getConfigValue MConfig -> IORef String
template
       [String]
e <- forall a. Selector a -> Monitor a
getConfigValue MConfig -> IORef [String]
export
       Int
w <- forall a. Selector a -> Monitor a
getConfigValue MConfig -> IORef Int
maxTotalWidth
       String
ell <- forall a. Selector a -> Monitor a
getConfigValue MConfig -> IORef String
maxTotalWidthEllipsis
       let m :: Map String String
m = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. [a] -> [b] -> [(a, b)]
zip [String]
e forall a b. (a -> b) -> a -> b
$ [String]
l
       String
s <- String -> Map String String -> Monitor String
parseTemplate' String
t Map String String
m
       let (Int
n, String
s') = if Int
w forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s forall a. Ord a => a -> a -> Bool
> Int
w
                     then Int -> String -> String -> (Int, String)
trimTo (Int
w forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ell) String
"" String
s
                     else (Int
1, String
s)
       forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if Int
n forall a. Ord a => a -> a -> Bool
> Int
0 then String
s' else String
s' forall a. [a] -> [a] -> [a]
++ String
ell

-- | Parses the template given to it with a map of export values and combines
-- them
parseTemplate' :: String -> Map.Map String String -> Monitor String
parseTemplate' :: String -> Map String String -> Monitor String
parseTemplate' String
t Map String String
m =
    do [(String, String, String)]
s <- forall a. IO a -> Monitor a
io forall a b. (a -> b) -> a -> b
$ forall a. Parser [a] -> String -> IO [a]
runP Parser [(String, String, String)]
templateParser String
t
       Map String String -> [(String, String, String)] -> Monitor String
combine Map String String
m [(String, String, String)]
s

-- | Given a finite "Map" and a parsed template t produces the
-- | resulting output string as the output of the monitor.
combine :: Map.Map String String -> [(String, String, String)] -> Monitor String
combine :: Map String String -> [(String, String, String)] -> Monitor String
combine Map String String
_ [] = forall (m :: * -> *) a. Monad m => a -> m a
return []
combine Map String String
m ((String
s,String
ts,String
ss):[(String, String, String)]
xs) =
    do String
next <- Map String String -> [(String, String, String)] -> Monitor String
combine Map String String
m [(String, String, String)]
xs
       String
str <- case forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
ts Map String String
m of
         Maybe String
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
"<" forall a. [a] -> [a] -> [a]
++ String
ts forall a. [a] -> [a] -> [a]
++ String
">"
         Just  String
r -> let f :: String -> String
f String
"" = String
r; f String
n = String
n; in String -> String
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Map String String -> Monitor String
parseTemplate' String
r Map String String
m
       forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String
s forall a. [a] -> [a] -> [a]
++ String
str forall a. [a] -> [a] -> [a]
++ String
ss forall a. [a] -> [a] -> [a]
++ String
next

-- | Try to parse arguments from the config file and apply them to Options.
parseOptsWith
    :: [OptDescr (opts -> opts)]  -- ^ Options that are specifiable
    -> opts                       -- ^ Default options to use as a fallback
    -> [String]                   -- ^ Actual arguments given
    -> IO opts
parseOptsWith :: forall opts.
[OptDescr (opts -> opts)] -> opts -> [String] -> IO opts
parseOptsWith [OptDescr (opts -> opts)]
options opts
defaultOpts [String]
argv =
    case forall a.
ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
getOpt forall a. ArgOrder a
Permute [OptDescr (opts -> opts)]
options [String]
argv of
        ([opts -> opts]
o, [String]
_, []  ) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall a. a -> a
id opts
defaultOpts [opts -> opts]
o
        ([opts -> opts]
_, [String]
_, [String]
errs) -> forall a. IOError -> IO a
ioError forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IOError
userError forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
errs