-- | This module handles intrepreting players' commands. module Commands where {- import Text.ParserCombinators.Parsec import Data.List import Utils import Multi import Data.Maybe import Language.Nomic.Expression -- | All commands issuable. data Command = ListGame -- | Name | NewGame | JoinGame | LeaveGame | SubscribeGame | UnsubscribeGame | ShowSubscription | ShowSubGame | SubmitRule | SubmitRuleI | Constitution | ShowAllRules | ListPlayers | ShowPendingActions | ShowMyPendingActions | ShowCompletedActions | DoMyActions | DoAction | Amend | Help | QuitNomic deriving (Eq, Show) -- | Command's Strings commands = [--("newPlayer", NewPlayer, ": Internal command."), ("listGame", ListGame, ": list the active games"), -- ("name", Name, " : change own name"), ("newGame", NewGame, " : start a new game"), ("joinGame", JoinGame, " : play in a game (you must be subscribed)"), ("leaveGame", LeaveGame, " : stop playing in a game (you remain subscribed)"), ("subscribeGame", SubscribeGame, " : subscribe to an existing game"), ("unsubscribeGame", UnsubscribeGame," : unsubscribe to an existing game"), ("showSubscribtion", ShowSubscription, " : show the subscribtions in the current game"), ("showSubGame", ShowSubGame, " : show the subscribtions to that game"), ("submitRule", SubmitRule, " : submit a rule. your code must be in \"\""), ("iSubmitRule", SubmitRuleI, " submit a rule in interactive mode"), ("showConstitution", Constitution, ": show the constitution (must be in a game)"), ("showAllRules ", ShowAllRules, ": show every rules: Active (the current Constitution), Pending (currently proposed rules), Rejected (Proposed and rejected rules) and Suppressed (Once Active but suppressed rules)"), ("listPlayers", ListPlayers, ": show the list of the players"), ("amendConstitution", Amend, ": amend the constitution with the currently proposed rules"), ("showPendingActions", ShowPendingActions, ": show all actions that has to be completed by players"), --TODO: verify "by players" ("showMyPendingActions", ShowMyPendingActions, ": show all actions that has to be completed by you"), ("iDoActions", DoMyActions, ": realize now all your actions, in interactive mode"), ("doAction", DoAction, " : give the result of your action nĀ°num (the number is given by showmypendingactions)."), ("showCompletedActions", ShowCompletedActions, ": show all already completed actions"), ("help", Help, ": show an help message"), ("quit", QuitNomic, ": quit Nomic")] -- | parseLine analysis the line and return a command with optionnal arguments parseLine :: String -> Either ParseError (String, [String]) parseLine = parse line "parse error" -- | line is the parsec parser to analyse a command with optionnal arguments line :: Parser (String, [String]) line = do skipMany space command <- simpleArg skipMany space args <- (quotedArg <|> simpleArg) `sepBy` spaces skipMany space --TODO: trailing spaces return (command, args) -- | a simple argument's parser. simpleArg :: Parser String simpleArg = many1 $ noneOf " \n" -- | a rule parser. quotedArg :: Parser String quotedArg = between (char '"') (char '"') $ many $ noneOf ('"' : ['\NUL'..'\US']) -- | runLine takes a String a executes the represented command, if any. runLine :: String -> PlayerNumber -> Comm () runLine s pn = do let pl = parseLine s case pl of Left _ -> putCom "Command analysis error" Right (comm, args) -> runCommand comm args pn putCom "\n" -- | runCommand takes a String representing a command, optionnal arguments and runs it. runCommand :: String -> [String] -> PlayerNumber -> Comm () runCommand comm args pn = do let comm' = toLowerS comm let commands' = map (\(a,b,_) -> (toLowerS a, b)) commands --lookup the commands... case lookup comm' commands' of Just c -> runCommand' c args pn Nothing -> do --if not found, try abbreviations let mycomms = filter (\(sc, _) -> comm' `isPrefixOf` sc) commands' case mycomms of [] -> putCom "No command matchs your input" (_ , c):[] -> runCommand' c args pn _ -> putCom $ "Several commands match your input:\n\r" ++ concatMap (\(cs, _) -> cs ++ "\n\r") mycomms -- | commandMulti takes a command and optionnal arguments and runs it. runCommand' :: Command -> [String] -> PlayerNumber -> Comm () runCommand' ListGame _ = listGame --runCommand' Name (a:[]) = newName a runCommand' NewGame (g:[]) = newGame g runCommand' JoinGame (g:[]) = joinGame g runCommand' LeaveGame _ = leaveGame runCommand' SubscribeGame (g:[]) = subscribeGame g runCommand' UnsubscribeGame (g:[]) = unsubscribeGame g runCommand' ShowSubscription _ = showSubscribtion runCommand' ShowSubGame (g:[]) = showSubGame g runCommand' SubmitRule (name:text:rule:[]) = submitRule name text rule runCommand' SubmitRuleI _ = myCatch submitRuleI runCommand' Constitution _ = showConstitution runCommand' ShowAllRules _ = showAllRules runCommand' ListPlayers _ = listPlayers runCommand' Amend _ = amendConstitution runCommand' ShowPendingActions _ = showPendingActions runCommand' ShowMyPendingActions _ = showMyPendingActions runCommand' DoMyActions _ = doActionsI runCommand' DoAction (num:result:[]) = doAction num result runCommand' ShowCompletedActions _ = showCompletedActions runCommand' QuitNomic _ = quit runCommand' Help _ = const help runCommand' c _ = const $ putCom $ "the number of arguments doesn't match. \nUsage: \n" ++ getCommandUsage c getCommandUsage :: Command -> String getCommandUsage c = fromMaybe (error "getCommandUsage: Usage not found") $ lookup c $ map (\(a,b,c) -> (b,a++c)) commands -- | issue an help message help :: Comm () help = putCom $ "Nomic commands:\n" ++ concatMap (\(c, _, h) -> c ++"\t" ++ h ++ "\n\r") (tail commands) -}