读取monad库的命令行参数

时间:2013-06-30 22:20:23

标签: haskell command-line-arguments

我正在寻找一个使用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之类的软件包之后,我还没有发现任何接近此的内容。但在深入实施之前,我想确保我没有错过任何东西。那么是否有一个利用类似方法解决问题的库?

2 个答案:

答案 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