module System.Console.MultiArg.Combinator (
option,
optionMaybe,
notFollowedBy,
shortNoArg,
shortOptionalArg,
shortOneArg,
shortTwoArg,
shortVariableArg,
nonGNUexactLongOpt,
matchApproxLongOpt,
matchNonGNUApproxLongOpt,
longNoArg,
longOptionalArg,
longOneArg,
longTwoArg,
longVariableArg,
mixedNoArg,
mixedOptionalArg,
mixedOneArg,
mixedTwoArg,
mixedVariableArg,
matchApproxWord ) where
import Data.Text ( Text, isPrefixOf )
import Data.Set ( Set )
import qualified Data.Set as Set
import Control.Monad ( liftM )
import System.Console.MultiArg.Prim
( ParserT, throw, try, approxLongOpt,
nextArg, pendingShortOptArg, nonOptionPosArg,
pendingShortOpt, nonPendingShortOpt,
exactLongOpt, nextArg, (<?>))
import System.Console.MultiArg.Option
( LongOpt, ShortOpt )
import qualified System.Console.MultiArg.Error as E
import System.Console.MultiArg.Error
( Error, parseErr )
import Control.Applicative ((<|>), many)
import Control.Monad ( void )
import Data.Monoid ( mconcat )
option :: (Error e, Monad m) =>
a
-> ParserT s e m a
-> ParserT s e m a
option x p = p <|> return x
optionMaybe :: (Error e, Monad m)
=> ParserT s e m a
-> ParserT s e m (Maybe a)
optionMaybe p = option Nothing (liftM Just p)
notFollowedBy :: (Error e, Monad m)
=> ParserT s e m a
-> ParserT s e m ()
notFollowedBy p =
void $ ((try p >> throw (E.parseErr E.ExpNotFollowedBy E.SawFollowedBy))
<|> return ())
nonGNUexactLongOpt :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m LongOpt
nonGNUexactLongOpt l = try $ do
(lo, maybeArg) <- exactLongOpt l
case maybeArg of
Nothing -> return lo
(Just t) ->
throw (parseErr (E.ExpNonGNUExactLong l)
(E.SawGNULongOptArg t))
matchApproxLongOpt :: (Error e, Monad m)
=> LongOpt
-> Set LongOpt
-> ParserT s e m (Text, LongOpt, Maybe Text)
matchApproxLongOpt l s = try $ do
a@(t, lo, _) <- approxLongOpt s
if lo == l
then return a
else throw (parseErr (E.ExpMatchingApproxLong l s)
(E.SawNotMatchingApproxLong t lo))
matchNonGNUApproxLongOpt :: (Error e, Monad m)
=> LongOpt
-> Set LongOpt
-> ParserT s e m (Text, LongOpt)
matchNonGNUApproxLongOpt l s = try $ do
(t, lo, arg) <- matchApproxLongOpt l s
let err b = throw (parseErr (E.ExpNonGNUMatchingApproxLong l s)
(E.SawMatchingApproxLongWithArg b))
maybe (return (t, lo)) err arg
matchApproxWord :: (Error e, Monad m)
=> Set Text
-> ParserT s e m (Text, Text)
matchApproxWord s = try $ do
a <- nextArg
let p t = a `isPrefixOf` t
matches = Set.filter p s
err saw = throw (parseErr (E.ExpApproxWord s) saw)
case Set.toList matches of
[] -> err (E.SawNoMatches a)
(x:[]) -> return (a, x)
_ -> err (E.SawMultipleApproxMatches matches a)
shortNoArg :: (Error e, Monad m)
=> ShortOpt
-> ParserT s e m ShortOpt
shortNoArg s = pendingShortOpt s <|> nonPendingShortOpt s
shortOptionalArg :: (Error e, Monad m)
=> ShortOpt
-> ParserT s e m (ShortOpt, Maybe Text)
shortOptionalArg s = do
so <- shortNoArg s
a <- optionMaybe (pendingShortOptArg <|> nonOptionPosArg)
return (so, a)
shortOneArg :: (Error e, Monad m) =>
ShortOpt
-> ParserT s e m (ShortOpt, Text)
shortOneArg s = do
so <- shortNoArg s
a <- pendingShortOptArg <|> nextArg
return (so, a)
shortTwoArg :: (Error e, Monad m)
=> ShortOpt
-> ParserT s e m (ShortOpt, Text, Text)
shortTwoArg s = do
(so, a1) <- shortOneArg s
a2 <- nextArg
return (so, a1, a2)
shortVariableArg :: (Error e, Monad m)
=> ShortOpt
-> ParserT s e m (ShortOpt, [Text])
shortVariableArg s = do
so <- shortNoArg s
firstArg <- optionMaybe pendingShortOptArg
rest <- many nonOptionPosArg
let result = maybe rest ( : rest ) firstArg
return (so, result)
longNoArg :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m LongOpt
longNoArg = nonGNUexactLongOpt
longOptionalArg :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m (LongOpt, Maybe Text)
longOptionalArg = exactLongOpt
longOneArg :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m (LongOpt, Text)
longOneArg l = do
(lo, mt) <- longOptionalArg l
case mt of
(Just t) -> return (lo, t)
Nothing -> do
a <- nextArg <?> E.parseErr E.ExpLongOptArg E.SawNoArgsLeft
return (l, a)
longTwoArg :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m (LongOpt, Text, Text)
longTwoArg l = do
(lo, mt) <- longOptionalArg l
case mt of
(Just t) -> do
a2 <- nextArg
return (lo, t, a2)
Nothing -> do
a1 <- nextArg
a2 <- nextArg
return (lo, a1, a2)
longVariableArg :: (Error e, Monad m)
=> LongOpt
-> ParserT s e m (LongOpt, [Text])
longVariableArg l = do
(lo, mt) <- longOptionalArg l
rest <- many nonOptionPosArg
return (lo, maybe rest (:rest) mt)
mixedNoArg :: (Error e, Monad m)
=> LongOpt
-> [LongOpt]
-> [ShortOpt]
-> ParserT s e m (Either ShortOpt LongOpt)
mixedNoArg l ls ss = mconcat ([f] ++ longs ++ shorts) where
toLong lo = do
r <- longNoArg lo
return $ Right r
toShort so = do
s <- shortNoArg so
return $ Left s
f = toLong l
longs = map toLong ls
shorts = map toShort ss
mixedOptionalArg ::
(Error e, Monad m)
=> LongOpt
-> [LongOpt]
-> [ShortOpt]
-> ParserT s e m ((Either ShortOpt LongOpt), Maybe Text)
mixedOptionalArg l ls ss = mconcat ([f] ++ longs ++ shorts) where
toLong lo = do
(o, a) <- longOptionalArg lo
return $ (Right o, a)
toShort so = do
(o, a) <- shortOptionalArg so
return $ (Left o, a)
f = toLong l
longs = map toLong ls
shorts = map toShort ss
mixedOneArg ::
(Error e, Monad m)
=> LongOpt
-> [LongOpt]
-> [ShortOpt]
-> ParserT s e m ((Either ShortOpt LongOpt), Text)
mixedOneArg l ls ss = mconcat ([f] ++ longs ++ shorts) where
toLong lo = do
(o, a) <- longOneArg lo
return (Right o, a)
toShort lo = do
(o, a) <- shortOneArg lo
return (Left o, a)
f = toLong l
longs = map toLong ls
shorts = map toShort ss
mixedTwoArg ::
(Error e, Monad m)
=> LongOpt
-> [LongOpt]
-> [ShortOpt]
-> ParserT s e m ((Either ShortOpt LongOpt), Text, Text)
mixedTwoArg l ls ss = mconcat ([f] ++ longs ++ shorts) where
toLong lo = do
(o, a1, a2) <- longTwoArg lo
return (Right o, a1, a2)
toShort lo = do
(o, a1, a2) <- shortTwoArg lo
return (Left o, a1, a2)
f = toLong l
longs = map toLong ls
shorts = map toShort ss
mixedVariableArg ::
(Error e, Monad m)
=> LongOpt
-> [LongOpt]
-> [ShortOpt]
-> ParserT s e m ((Either ShortOpt LongOpt), [Text])
mixedVariableArg l ls ss = mconcat ([f] ++ longs ++ shorts) where
toLong lo = do
(o, a) <- longVariableArg lo
return (Right o, a)
toShort lo = do
(o, a) <- shortVariableArg lo
return (Left o, a)
f = toLong l
longs = map toLong ls
shorts = map toShort ss