module System.Console.ArgParser.SubParser (
mkSubParser
, mkSubParserWithName
) where
import qualified Data.List as L
import qualified Data.Map as M
import Data.Maybe
import System.Console.ArgParser.BaseType
import System.Console.ArgParser.Parser
import System.Console.ArgParser.Run
import System.Environment
mkSubParser :: [(Arg, CmdLnInterface a)] -> IO (CmdLnInterface a)
mkSubParser parsers = do
name <- getProgName
return $ mkSubParserWithName name parsers
mkSubParserWithName :: String -> [(Arg, CmdLnInterface a)] -> CmdLnInterface a
mkSubParserWithName name parsers = CmdLnInterface
parser cmdSpecialFlags name Nothing Nothing Nothing
where
parser = liftParam EmptyParam
cmdSpecialFlags = command:defaultSpecialFlags
command = mkSpecialFlag name parsers
mkSpecialFlag :: String -> [(Arg, CmdLnInterface a)] -> SpecialFlag a
mkSpecialFlag topname subapps = (parser, action) where
parser = liftParam $ CommandParam cmdMap id
action _ (posargs, flagargs) =
case listToMaybe posargs >>= flip M.lookup cmdMap of
Nothing -> error "impossible"
Just subapp -> parseNiceArgs
(drop 1 posargs, flagargs)
(subapp `setAppName` (topname ++ " " ++ getAppName subapp))
cmdMap = M.fromList subapps
data EmptyParam a = EmptyParam
instance ParamSpec EmptyParam where
getParser _ = Parser $ \args -> (Left "command not found", args)
getParamDescr _ = []
data CommandParam appT resT = CommandParam
(M.Map String (CmdLnInterface appT))
(Bool -> resT)
instance ParamSpec (CommandParam resT) where
getParser (CommandParam cmdMap convert) = Parser cmdParser where
cmdParser (pos, flags) = case pos of
[] -> (Left "No command provided", (pos, flags))
arg:_ -> (Right $ convert isMatch, ([], M.empty)) where
isMatch = arg `M.member` cmdMap
getParamDescr (CommandParam cmdMap _) = summary:commands where
cmds = M.elems cmdMap
names = map getAppName cmds
descrs = map (fromMaybe "" . getAppDescr) cmds
summaryUsage = const $ "{" ++ L.intercalate "," names ++ "}"
summary = ParamDescr
summaryUsage "commands arguments" summaryUsage "" ""
singleCmdDescr name descr = ParamDescr
(const "") "commands arguments" (const name) descr ""
commands = zipWith singleCmdDescr names descrs