如何简化以下命令行选项解析代码?

时间:2013-04-21 18:28:09

标签: parsing haskell command-line-arguments

我正在为家庭作业经理做个人用途,用Haskell开发它。作为一个开头,我首先使用以下代码来解析命令行参数,这些代码随后可以通过添加到dispatch来轻松扩展。这些函数本身就是用于测试目的的假人。但是,我觉得这个代码可以变得更简单,更安全,但我看不清楚如何。代码是这样的:

module Main where

import System.Environment

main = getArgs >>= parse

parse :: [String] -> IO ()
parse [] = usage
parse (file:mode:[]) = if mode == "list"
                       then list file
                       else case lookup mode dispatch of
                         Just _ -> putStrLn "That mode requires arguments" >> usage
                         Nothing -> putStrLn "Please supply a valid mode" >> usage
parse (file:mode:args) = case lookup mode dispatch of
  Nothing -> do case lookup file dispatch of
                  Just _ -> putStrLn "Please supply a data file"
                  Nothing -> putStrLn "Please supply a valid mode"
                usage
  Just fun -> fun file args
parse (file:[]) = case lookup file dispatch of
  Just _ -> putStrLn "Please supply a datafile" >> usage
  Nothing -> list file

usage :: IO ()
usage = mapM_ putStrLn helptext

helptext :: [String]
helptext = ["Homework manager by Marcus Medom Ryding <mrok4a@gmail.com>"
           ,"Copyright 2013, licensed under BSD3"
           ,"Usage: homework filepath [mode] [arguments]"]

dispatch :: [(String, String -> [String] -> IO ())]
dispatch  = [("new",new)]

new :: String -> [String] -> IO ()
new file args = putStrLn ("NEW: " ++ file) >> mapM_ putStrLn args

list :: String -> IO ()
list file = putStrLn ("LIST: " ++ file)

2 个答案:

答案 0 :(得分:4)

您应该使用库,而不是手动解析命令行。看看cmdargs

它允许您以声明方式定义命令行选项:

{-# LANGUAGE DeriveDataTypeable #-}

import System.Console.CmdArgs

data MyProg = New {comment :: String}
             | Delete {howMany :: Int}
               deriving (Show, Data, Typeable)

new = New {comment = "this is a parameter with a default value"}
delete = Delete {howMany = 10}

main = print =<< cmdArgs (modes [new, delete])

这就是:

% ./prog new -c "hello world"
New {comment = "hello world"}
% ./prog delete              
Delete {howMany = 10}

您也可以免费获得帮助:

% ./prog --help      
The myprog program

myprog [COMMAND] ... [OPTIONS]

Common flags:
  -? --help          Display help message
  -V --version       Print version information

myprog new [OPTIONS]

  -c --comment=ITEM

myprog delete [OPTIONS]

  -h --howmany=INT

作者还有一个nice tutorial。您需要执行与“多种模式”部分类似的操作。

答案 1 :(得分:1)

除上述答案外,仅根据您的代码:

module Main where

import System.Environment

main∷ IO ()
main = getArgs »= parse2

parse2 ∷ [String] → IO ()
parse2 [] = usage
parse2 (file:mode:[])
    | mode ≡ "list" = list file
    | mode ≠ "list" =
    case lookup mode dispatch of
        Just _ → putStrLn "That mode requires arguments" » usage
        Nothing → putStrLn "Please supply a valid mode" » usage
parse2 (file:mode:args) =
    case lookup mode dispatch of
        Nothing → err (lookup file dispatch) » usage
        Just fun → fun file args
        where err (Just _) = putStrLn "Please supply a data file"
              err Nothing = putStrLn "Please supply a valid mode"
parse2 (file:[]) =
    case lookup file dispatch of
        Just _ → putStrLn "Please supply a datafile" » usage
        Nothing → list file

usage ∷ IO ()
usage = mapM_ putStrLn helptext

helptext ∷ [String]
helptext = ["Homework manager by Marcus Medom Ryding <mrok4a@gmail.com>"
           ,"Copyright 2013, licensed under BSD3"
           ,"Usage: homework filepath [mode] [arguments]"]

dispatch ∷ [(String, String → [String] → IO ())]
dispatch  = [("new",new)]

new ∷ String → [String] → IO ()
new file args = putStrLn ("NEW: " ⧺ file) » mapM_ putStrLn args

list ∷ String → IO ()
list file = putStrLn ("LIST: " ⧺ file)
相关问题