我正在寻找一个使用monad来抽象的命令行参数解析和帮助生成的文章库。我有以下相当明显的使用模式:
main = do
portOrSocket <- Args.run $ do
mbSocket <- Args.read $ Args.Arg "s" "socket" "Description"
mbPort <- Args.read $ Args.Arg "p" "port" "Description"
case mbSocket of
Just socket -> return $ Right socket
Nothing -> case mbPort of
Just port -> return $ Left port
Nothing -> return $ Left defaultPort
...
上面的代码包含处理解析,验证和使用生成所需的所有信息,IMO很容易理解。不幸的是,在通过hackage查看并查看cmdargs,cmdlib,parseargs,ReadArgs之类的软件包之后,我还没有发现任何接近此的内容。但在深入实施之前,我想确保我没有错过任何东西。那么是否有一个利用类似方法解决问题的库?
答案 0 :(得分:8)
您可以使用optparse-applicative
。最常见的使用模式看起来像这样(我只是从我使用的小工具中复制粘贴):
options :: Parser (String, String)
options = (,)
<$> (strOption $ mconcat [
short 'n',
long "node",
metavar "NODE",
value "127.0.0.1",
showDefaultWith id,
completer (bashCompleter "hostname"),
help "AMQP node to connect to" ] )
<*> (strOption $ mconcat [
short 'q',
long "queue",
metavar "QUEUE",
value "1.0.0",
showDefaultWith id,
help "Queue to initialize" ] )
main = do
(hostName, queue) <-
execParser $ info (helper <*> options) $ mconcat [
fullDesc,
header "The Suns setup utility",
progDesc "Sets up an AMQP node",
footer "Report bugs to Gabriel439@gmail.com" ]
...
当我使用-h
运行已编译的程序时,我得到:
$ suns-admin -h
The Suns setup utility
Usage: suns-admin [-n|--node NODE] [-q|--queue QUEUE]
Sets up an AMQP node
Available options:
-h,--help Show this help text
-n,--node NODE AMQP node to connect to (default: 127.0.0.1)
-q,--queue QUEUE Queue to initialize (default: 1.0.0)
Report bugs to Gabriel439@gmail.com
这可以让你了解一些可以使用的漂亮选项以及程序生成的优秀输出。
答案 1 :(得分:2)
如果有人有兴趣使用optparse-applicative
来解决问题中提出的问题,那么我就是这样做的:
import Options.Applicative
getOptions :: Int -> IO (Either Int String)
getOptions defaultPort =
execParser $
info (helper <*> parser defaultPort) $
fullDesc <>
progDesc "Run a content-db server on a socket or a port" <>
header "Run a content-db server"
parser :: Int -> Parser (Either Int String)
parser defaultPort =
portOrSocket <$>
(optional . strOption)
( short 's' <>
long "socket" <>
help "Socket" )
<*>
option
( short 'p' <>
long "port" <>
help "Port" <>
value defaultPort )
where
portOrSocket (Just socket) _ = Right socket
portOrSocket _ port = Left port
main = do
getOptions 43400 >>= \o -> case o of
Left port -> print port
Right socket -> print socket