{-# LANGUAGE RecordWildCards, FlexibleContexts #-} module Main where import Control.Monad.IO.Class (liftIO) import Control.Monad.State.Strict (StateT, evalStateT, gets, modify) import Data.Default (def) import System.Console.StructuredCLI import Text.Read (readMaybe) data AppState = AppState { bars :: Int, bazs :: Int } type StateM = StateT AppState IO root :: CommandsT StateM () root = do basic foo basic :: CommandsT StateM () basic = do command "top" "return to the top of the tree" top command "exit" "go back one level up" exit foo :: CommandsT StateM () foo = command "foo" "pity the foo" (return NewLevel) >+ do basic bar baz bar :: CommandsT StateM () bar = param "bar" "" parseBars setBars >+ do basic frob where setBars int = do bars <- gets bars modify $ \s -> s { bars = bars + int } return NewLevel baz :: CommandsT StateM () baz = command' "baz" "do the baz thing" checkBazs $ do n <- modify incBaz >> gets bazs liftIO . putStrLn $ "You have bazzed " ++ show n ++ " times" return NoAction where incBaz s@AppState{..} = s { bazs = bazs + 1 } checkBazs = do bazCount <- gets bazs return $ bazCount < 3 -- after 3 bazs, disable baz command frob :: CommandsT StateM () frob = command "frob" "frob this level" $ do n <- gets bars liftIO . putStrLn $ "frobbing " ++ show n ++ " bars" return NoAction parseBars :: Validator StateM Int parseBars = return . readMaybe main :: IO () main = do let state0 = AppState 0 0 evalStateT run state0 where run = do result <- runCLI "some CLI" settings root either (error.show) return result settings = def { getBanner = "Some CLI Application\nTab completion is your friend!", getHistory = Just ".someCLI.history" }