module CmdLineParser where data Cmd cmd = Null cmd | Args String ([String] -> cmd) fileArgs = Args "<files>" fileArg f = fileArgs (mapM_ f) kwOption kw cmd = case cmd of Null f -> addKwArg id (null2args f) Args args f -> addKwArg (++' ':args) f where addKwArg rest f = Args (rest ("["++kw++"]")) f' where f' (a:as) | a==kw = f as True f' as = f as False null2args f [] o = f o null2args f _ o = fail "superflous arguments" doCmd (cmds,default_cmd) prg args = case args of [] -> default_cmd cmd:args -> case lookup cmd cmds of Nothing -> fail $ "Unknown command: "++cmd Just (cmd,_) -> case (cmd,args) of (Null cmd,[]) -> cmd (Args _ cmd,_ ) -> cmd args _ -> fail "Malformed command" usage prg cmds = unlines $ ["Usage: "++prg++ " <command>", " where <command> is one of:"]++ map ((" "++).cmdusage) cmds where cmdusage (name,(cmd,res)) = case cmd of Null _ -> unwords [name,"--",res] Args args _ -> unwords [name,args,"--",res]