Shellac-0.9.5.1: src/System/Console/Shell/ShellMonad.hs
{-
-
- Copyright 2005-2007, Robert Dockins.
-
-}
-- | This module implements a monad for use in shell commands and in
-- evaluation functions. It is a state moand layered over @IO@.
-- @liftIO@ may be used to execute arbitrary I\/O actions. However,
-- the @shellPut@* commands are the preferred way to output text.
module System.Console.Shell.ShellMonad (
-- * The Shell monad
Sh
, runSh
-- * Output functions
, shellPut
, shellPutStr, shellPutStrLn
, shellPutInfo, shellPutInfoLn
, shellPutErr, shellPutErrLn
-- * Shell state accessors
, getShellSt, putShellSt
, modifyShellSt
-- * Special actions
, shellSpecial
-- * Extracting and using the shell context
, ShellContext
, extractContext, runWithContext, updateCommandResult
) where
import Control.Monad.Reader
import Control.Monad.State
import System.Console.Shell.Backend
import System.Console.Shell.Types
-- | Execute a shell action
runSh :: st -> OutputCommand -> Sh st () -> IO (CommandResult st)
runSh st info = (flip runReaderT) info . (flip execStateT) (st,Nothing) . unSh
-- | Output a tagged string to the console
shellPut :: BackendOutput -> Sh st ()
shellPut out = Sh (lift ask >>= \f -> liftIO (f out))
-- | Prints a regular output string
shellPutStr :: String -> Sh st ()
shellPutStr = shellPut . RegularOutput
-- | Prints an informational output string
shellPutInfo :: String -> Sh st ()
shellPutInfo = shellPut . InfoOutput
-- | Prints an error output string
shellPutErr :: String -> Sh st ()
shellPutErr = shellPut . ErrorOutput
-- | Prints regular output with a line terminator
shellPutStrLn :: String -> Sh st ()
shellPutStrLn = shellPutStr . (++"\n")
-- | Prints an informational output string with a line terminator
shellPutInfoLn :: String -> Sh st ()
shellPutInfoLn = shellPutInfo . (++"\n")
-- | Prints and error output string with a line terminator
shellPutErrLn :: String -> Sh st ()
shellPutErrLn = shellPutErr . (++"\n")
-- | Get the current shell state
getShellSt :: Sh st st
getShellSt = Sh (get >>= return . fst)
-- | Set the shell state
putShellSt :: st -> Sh st ()
putShellSt st = Sh (get >>= \ (_,spec) -> put (st,spec))
-- | Apply the given funtion to the shell state
modifyShellSt :: (st -> st) -> Sh st ()
modifyShellSt f = getShellSt >>= putShellSt . f
-- | Schedule a shell \"special\" action. Only the last call to
-- this function will affect the shell's behavior! It modifies
-- a bit of state that is overwritten on each call.
shellSpecial :: ShellSpecial st -> Sh st ()
shellSpecial spec = Sh (get >>= \ (st,_) -> put (st,Just spec))
instance MonadState st (Sh st) where
get = getShellSt
put = putShellSt
-- | The total context held by the shell, with @'CommandResult' st@
-- being mutable and 'OutputCommand' immutable
type ShellContext st = (CommandResult st, OutputCommand)
-- | Extract the current shell context for future use, see 'runWithContext'
extractContext :: Sh st (ShellContext st)
extractContext = (Sh . StateT) $ \s -> do
imC <- ask
return ((s, imC), s)
-- | Run a shell with the supplied context, useful if you need to
-- invoke a shell within a new IO context, for example when using
-- 'System.Timeout.timeout'
runWithContext :: ShellContext st -> Sh st a -> IO (a, CommandResult st)
runWithContext (mC, imC) = (flip runReaderT) imC . (flip runStateT) mC . unSh
-- | Update the mutable context of this shell
updateCommandResult :: CommandResult st -> Sh st ()
updateCommandResult s = (Sh . StateT) $ \_ -> return (() , s)