我使用Options.Applicative
来处理Haskell命令行,我的选项记录类型如下:
data Options = Options { xml :: String
,eut :: String
} deriving (Show)
options :: Parser Options
options = Options
<$> strOption ( short 'x'
<> long "xml"
<> metavar "XMLFILE"
<> value []
<> help "GCCXML file for parsing" )
<*> strOption ( short 'e'
<> long "eut"
<> metavar "PATH_2_EUT"
<> value []
<> help "EUT Json filepath for parsing" )
然后在我的 haskell 主代码中,我有:
main :: IO ()
main = do
options <- execParser parseOpts
case options of
Options {xml = [], eut = []} -> putStrLn "use -h to print usage info"
-- xml option
Options {xml = _, eut = []} -> parseXML $ xml options
-- eut option
Options {xml = [], eut = _} -> genMeta $ eut options
-- no matching
_ -> putStrLn "use -h to print usage info"
where
parseOpts = info (helper <*> options)
( fullDesc
<> progDesc "Given GCCXML file, generate EUT json and test meta files"
<> header "map2meta - Generate test meta files" )
我的目的是为"-x"
或"-e"
进行处理。我通过使用模式Options {xml = _, eut = []}
来匹配命令行有"-x"
但没有"-e"
的情况来实现这一点,而Options {xml = [], eut = _ }
匹配命令行有"-e"
但没有"-x"
的情况。但是,当我在没有任何选项的情况下运行该程序时,它似乎Options {xml = _ , eut = [] }
匹配。所以我添加了Options {xml = [], eut = []}
来拦截这个案子。我认为占位符"_"实际上可以用来匹配"[]",尽管我希望它只匹配"某物"而不是空字符串。因此,我的第一个问题是如何创建一个模式来匹配非空字符串?
我的第二个问题是如何添加代码以打印出使用信息?现在,它仅在我使用"-h"
时打印它。我想在命令行中没有提供选项时打印它。
由于String
只是[Char]
的类型同义词,你可以在非空字符串上与模式_:_
匹配,即一个非空列表,有一个 head 元素_
(无论什么)和一个尾列表_
(不管什么)。
因此,您可能有三种情况:
-
Options {xml = _:_, eut = []}
:xml
已设置,eut
未设置 -
Options {xml = [], eut = _:_}
:eut
已设置,xml
未设置 -
_
:其余的(要么都不设置,要么两者都设置)
或者,您可以使用多路if
:
Options{..} <- execParser ...
if | not (null xml) && null eot -> ...
| not (null eot) && null xml -> ...
| otherwise -> error ...