module Application.CLI
(
defaultMain
, CLI(..)
, OptHelp(..)
, Help(..)
, printHelp
, CLIContext
, getHeader
, initialize
, initializeWithDefault
, with
, Options
, withStr
, withOptionalStr
, withParameterStr
, withOptionalParameterStr
, withFlag
) where
import Application.CLI.Class
import Application.CLI.Types
import Data.List
import System.Environment
import System.Exit
data Usage = Usage
instance CLI Usage where
name _ = ""
desc _ = ""
options _ = []
action _ ctx opts = do
progName <- getProgName
usage (printUsage " " progName ctx) opts
usage :: String
-> [String]
-> IO ()
usage list msgs = do
mapM_ (\str -> putStrLn str) msgs
putStrLn list
exitFailure
data Help = Help
instance CLI Help where
name _ = "help"
desc _ = "show help message"
options _ = [ OptHelp [] (Just "command") "print the help message for a specific command"
]
action _ ctx =
withOptionalStr $ \mcommand _ -> do
case mcommand of
Nothing -> printStdHelp
Just c -> printCmdHelp c
where
printCmdHelp :: String -> IO ()
printCmdHelp cmd = do
case lookupCommand cmd ctx of
Nothing -> error $ "command '" ++ cmd ++ "' does not exist"
Just c -> putStrLn $ printCommandHelp " " c
printStdHelp :: IO ()
printStdHelp = do
progName <- getProgName
putStrLn $ progName ++ ": " ++ getHeader ctx
putStrLn $ printHelp " " progName ctx
with :: CLI cli
=> cli
-> CLIContext
-> CLIContext
with c l = insertCommand (cliToCommand c) l
initializeWithDefault :: CLI cliDefault
=> cliDefault
-> String
-> CLIContext
initializeWithDefault defaultCli description =
insertDefault (cliToCommand defaultCli) cmdMap
where
cmdMap = initialize description
initialize :: String
-> CLIContext
initialize description =
createContext (cliToCommand Usage) description
withStr :: String
-> (String -> Options -> IO a)
-> Options
-> IO a
withStr what _ [] = error $ "expecting <" ++ what ++ ">"
withStr _ f (x:xs) = f x xs
withOptionalStr :: (Maybe String -> Options -> IO a)
-> Options
-> IO a
withOptionalStr f [] = f Nothing []
withOptionalStr f (x:xs) = f (Just x) xs
withParameterStr :: [String]
-> (String -> Options -> IO a)
-> Options
-> IO a
withParameterStr flags f l =
case break (flip elem flags) l of
(_ , []) -> error $ "expecting parameter " ++ intercalate ", " flags ++ " <value>"
(_ , _:[]) -> error $ "parameter " ++ intercalate ", " flags ++ " is expection an argument"
(xs1, _:p:xs2) -> f p (xs1 ++ xs2)
withOptionalParameterStr :: [String]
-> (Maybe String -> Options -> IO a)
-> Options
-> IO a
withOptionalParameterStr flags f l =
case break (flip elem flags) l of
(xs1, []) -> f Nothing xs1
(_ , _:[]) -> error $ "parameter " ++ intercalate ", " flags ++ " is expecting an argument"
(xs1, _:p:xs2) -> f (Just p) (xs1 ++ xs2)
withFlag :: [String]
-> (Bool -> Options -> IO a)
-> Options
-> IO a
withFlag flags f l =
case break (flip elem flags) l of
(xs1, []) -> f False xs1
(xs1, _:xs2) -> f True (xs1 ++ xs2)
defaultMain :: CLIContext
-> IO ()
defaultMain cmdMap = do
args <- getArgs
case args of
[] -> tryDefault
(x:xs) -> tryCommand x xs
where
raiseHelper :: String
-> IO ()
raiseHelper what =
cmdAction (getHelper cmdMap) cmdMap [what]
tryDefault :: IO ()
tryDefault = do
progName <- getProgName
case getDefault cmdMap of
Nothing -> raiseHelper $ progName ++ " does not provide default command"
Just cmd -> cmdAction cmd cmdMap []
tryCommand :: String
-> [String]
-> IO ()
tryCommand cmdstr opts =
case lookupCommand cmdstr cmdMap of
Nothing -> raiseHelper $ cmdstr ++ ": command does not exist"
Just cmd -> cmdAction cmd cmdMap opts