From 7488196f36824184e2e9088ed9984a189a87cffa Mon Sep 17 00:00:00 2001 From: defanor Date: Sun, 5 Nov 2017 07:28:36 +0300 Subject: Use Parsec for command parsing --- Pancake/Command.hs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Pancake/Command.hs (limited to 'Pancake/Command.hs') diff --git a/Pancake/Command.hs b/Pancake/Command.hs new file mode 100644 index 0000000..46a3e66 --- /dev/null +++ b/Pancake/Command.hs @@ -0,0 +1,86 @@ +{- | +Module : Pancake.Command +Maintainer : defanor +Stability : unstable +Portability : portable + +User command parsing. +-} + +module Pancake.Command ( Command(..) + , parseCommand + ) where + +import Network.URI +import Text.Parsec +import Text.Parsec.String +import qualified Data.Map as M + +import Pancake.Configuration + + +-- | Interactive user command. +data Command = Quit + | Follow Int + | More + | GoTo URI + | Reload + | Back + | Forward + | Help + | Show Int + | ShowCurrent + | Shortcut String String + | ReloadConfig + deriving (Show, Eq) + +-- | Parses a user command. +parseCommand :: Config -> String -> Command +parseCommand c = either (const Help) id . parse (command c) "user input" + +-- | Basic (constant) command parser. +basicCommand :: Parser Command +basicCommand = choice . map (\(s, c) -> try (string s <* eof) *> pure c) $ + [ ("q", Quit) + , ("b", Back) + , ("f", Forward) + , ("r", Reload) + , ("re", ReloadConfig) + , ("h", Help) + , ("?", ShowCurrent) + , ("", More)] + +-- | 'Follow' command parser. +followRef :: Parser Command +followRef = Follow . read <$> many1 digit <* eof + +-- | 'Show' command parser. +showRef :: Parser Command +showRef = char '?' *> (Show . read <$> many1 digit) <* eof + +-- | 'GoTo' command parser. +goTo :: Parser Command +goTo = do + s <- manyTill anyChar eof + maybe (fail "Failed to parse URI") (pure . GoTo) $ parseURIReference s + +-- | 'Shortcut' command parser. +shortcut :: M.Map String String -> Parser Command +shortcut m = do + s <- choice $ map (try . string) $ M.keys m + _ <- space + case M.lookup s m of + Nothing -> fail $ "No such shortcut: " ++ s + Just u -> do + q <- manyTill anyChar eof + pure $ Shortcut u q + +-- | Command parser. +command :: Config -> Parser Command +command c = + choice (map try + [ basicCommand "basic command" + , followRef "follow ref" + , showRef "show ref" + , goTo "go to" + , shortcut (shortcuts c) "shortcut"]) -- cgit v1.2.3