| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
System.Console.Repline
Description
Repline exposes an additional monad transformer on top of Haskeline called HaskelineT. It simplifies several
aspects of composing Haskeline with State and Exception monads in modern versions of mtl.
type Repl a = HaskelineT IO a
The evaluator evalRepl evaluates a HaskelineT monad transformer by constructing a shell with several
custom functions and evaluating it inside of IO:
- Commands: Handled on ordinary input.
- Completions: Handled when tab key is pressed.
- Options: Handled when a command prefixed by a prefix character is entered.
- Command prefix character: Optional command prefix ( passing Nothing ignores the Options argument ).
- Multi-line command: Optional command name that switches to a multi-line input. (Press Ctrl-D to exit and commit the multi-line input). Passing Nothing disables multi-line input support.
- Banner: Text Displayed at initialisation. It takes an argument so it can take into account if the current line is part of a multi-line input.
- Initialiser: Run at initialisation.
- Finaliser: Run on Ctrl-D, it can be used to output a custom exit message or to choose whether to exit or not depending on the application state
A simple evaluation function might simply echo the output back to the screen.
-- Evaluation : handle each line user inputs cmd :: String -> Repl () cmd input = liftIO $ print input
Several tab completion options are available, the most common is the WordCompleter which completes on single
words separated by spaces from a list of matches. The internal logic can be whatever is required and can also
access a StateT instance to query application state.
-- Tab Completion: return a completion for partial words entered completer :: Monad m => WordCompleter m completer n = do let names = ["kirk", "spock", "mccoy"] return $ filter (isPrefixOf n) names
Input which is prefixed by a colon (commands like ":type" and ":help") queries an association list of
functions which map to custom logic. The function takes a space-separated list of augments in it's first
argument. If the entire line is desired then the unwords function can be used to concatenate.
-- Commands help :: [String] -> Repl () help args = liftIO $ print $ "Help: " ++ show args say :: String -> Repl () say arg = do _ <- liftIO $ callCommand $ "cowsay" ++ " " ++ arg return ()
(You may need the following import in pull callCommand into scope)
import System.Process (callCommand)
Now we need only map these functions to their commands.
options :: Options (HaskelineT IO)
options = [
("help", help . words) -- :help
, ("say", say) -- :say
]The initialiser function is simply an IO action that is called at the start of the shell.
ini :: Repl () ini = liftIO $ putStrLn "Welcome!"
The finaliser function is an IO action that is called at the end of the shell.
final :: Repl ExitDecision final = do liftIO $ putStrLn "Goodbye!" return Exit
Putting it all together we have a little shell.
main :: IO () main = evalRepl (const . pure $ ">>> ") cmd options (Just ':') (Just "paste") (Word completer) ini final
Synopsis
- data HaskelineT (m :: Type -> Type) a
- runHaskelineT :: (MonadMask m, MonadIO m) => Settings m -> HaskelineT m a -> m a
- class MonadCatch m => MonadHaskeline (m :: Type -> Type)
- evalRepl :: (MonadMask m, MonadIO m) => (MultiLine -> HaskelineT m String) -> Command (HaskelineT m) -> Options (HaskelineT m) -> Maybe Char -> Maybe String -> CompleterStyle m -> HaskelineT m a -> HaskelineT m ExitDecision -> m ()
- data ReplOpts (m :: Type -> Type) = ReplOpts {
- banner :: MultiLine -> HaskelineT m String
- command :: Command (HaskelineT m)
- options :: Options (HaskelineT m)
- prefix :: Maybe Char
- multilineCommand :: Maybe String
- tabComplete :: CompleterStyle m
- initialiser :: HaskelineT m ()
- finaliser :: HaskelineT m ExitDecision
- evalReplOpts :: (MonadMask m, MonadIO m) => ReplOpts m -> m ()
- type Cmd (m :: Type -> Type) = String -> m ()
- type Options (m :: Type -> Type) = [(String, Cmd m)]
- type WordCompleter (m :: Type -> Type) = String -> m [String]
- type LineCompleter (m :: Type -> Type) = String -> String -> m [Completion]
- data CompleterStyle (m :: Type -> Type)
- = Word (WordCompleter m)
- | Word0 (WordCompleter m)
- | Cursor (LineCompleter m)
- | File
- | Prefix (CompletionFunc m) [(String, CompletionFunc m)]
- | Combine (CompleterStyle m) (CompleterStyle m)
- | Custom (CompletionFunc m)
- type Command (m :: Type -> Type) = String -> m ()
- data ExitDecision
- data MultiLine
- type CompletionFunc (m :: Type -> Type) = (String, String) -> m (String, [Completion])
- fallbackCompletion :: Monad m => CompletionFunc m -> CompletionFunc m -> CompletionFunc m
- wordCompleter :: Monad m => WordCompleter m -> CompletionFunc m
- listCompleter :: Monad m => [String] -> CompletionFunc m
- fileCompleter :: MonadIO m => CompletionFunc m
- listWordCompleter :: Monad m => [String] -> WordCompleter m
- runMatcher :: Monad m => [(String, CompletionFunc m)] -> CompletionFunc m -> CompletionFunc m
- trimComplete :: String -> Completion -> Completion
- abort :: forall (m :: Type -> Type) a. MonadThrow m => HaskelineT m a
- tryAction :: forall (m :: Type -> Type) a. (MonadMask m, MonadIO m) => HaskelineT m a -> HaskelineT m a
- dontCrash :: (MonadIO m, MonadCatch m) => m () -> m ()
Repline Monad
data HaskelineT (m :: Type -> Type) a #
Monad transformer for readline input
Instances
runHaskelineT :: (MonadMask m, MonadIO m) => Settings m -> HaskelineT m a -> m a #
Run HaskelineT monad
class MonadCatch m => MonadHaskeline (m :: Type -> Type) #
Minimal complete definition
getInputLine, getInputChar, outputStr, outputStrLn
Instances
| (MonadMask m, MonadIO m) => MonadHaskeline (InputT m) # | |
Defined in System.Console.Repline | |
| (MonadMask m, MonadIO m) => MonadHaskeline (HaskelineT m) # | |
Defined in System.Console.Repline Methods getInputLine :: String -> HaskelineT m (Maybe String) getInputChar :: String -> HaskelineT m (Maybe Char) outputStr :: String -> HaskelineT m () outputStrLn :: String -> HaskelineT m () | |
| MonadHaskeline m => MonadHaskeline (StateT s m) # | |
Defined in System.Console.Repline | |
Toplevel
Arguments
| :: (MonadMask m, MonadIO m) | |
| => (MultiLine -> HaskelineT m String) | Banner |
| -> Command (HaskelineT m) | Command function |
| -> Options (HaskelineT m) | Options list and commands |
| -> Maybe Char | Optional command prefix ( passing Nothing ignores the Options argument ) |
| -> Maybe String | Optional multi-line command ( passing Nothing disables multi-line support ) |
| -> CompleterStyle m | Tab completion function |
| -> HaskelineT m a | Initialiser |
| -> HaskelineT m ExitDecision | Finaliser ( runs on Ctrl-D ) |
| -> m () |
Evaluate the REPL logic into a MonadCatch context.
data ReplOpts (m :: Type -> Type) #
REPL Options datatype
Constructors
| ReplOpts | |
Fields
| |
evalReplOpts :: (MonadMask m, MonadIO m) => ReplOpts m -> m () #
Evaluate the REPL logic into a MonadCatch context from the ReplOpts configuration.
Repline Types
type Cmd (m :: Type -> Type) = String -> m () #
Command function synonym
The argument corresponds to the arguments of the command, it may contain spaces or newlines (when input is multi-line).
For example, with prefix and command :"command" the argument String for:
:command some arguments
is "some arguments"
type LineCompleter (m :: Type -> Type) = String -> String -> m [Completion] #
Line completer
data CompleterStyle (m :: Type -> Type) #
Tab completer types
Constructors
| Word (WordCompleter m) | Completion function takes single word. |
| Word0 (WordCompleter m) | Completion function takes single word ( no space ). |
| Cursor (LineCompleter m) | Completion function takes tuple of full line. |
| File | Completion function completes files in CWD. |
| Prefix (CompletionFunc m) [(String, CompletionFunc m)] | Conditional tab completion based on prefix. |
| Combine (CompleterStyle m) (CompleterStyle m) | Combine two completions |
| Custom (CompletionFunc m) | Custom completion |
data ExitDecision #
Decide whether to exit the REPL or not
Context for the current line if it is part of a multi-line input or not
Constructors
| MultiLine | |
| SingleLine |
Instances
Completers
type CompletionFunc (m :: Type -> Type) = (String, String) -> m (String, [Completion]) #
fallbackCompletion :: Monad m => CompletionFunc m -> CompletionFunc m -> CompletionFunc m #
If the first completer produces no suggestions, fallback to the second completer's output.
wordCompleter :: Monad m => WordCompleter m -> CompletionFunc m #
Word completer function
listCompleter :: Monad m => [String] -> CompletionFunc m #
List completer function
fileCompleter :: MonadIO m => CompletionFunc m #
File completer function
listWordCompleter :: Monad m => [String] -> WordCompleter m #
List word completer
runMatcher :: Monad m => [(String, CompletionFunc m)] -> CompletionFunc m -> CompletionFunc m #
Return a completion function a line fragment
trimComplete :: String -> Completion -> Completion #
Trim completion
Utilities
abort :: forall (m :: Type -> Type) a. MonadThrow m => HaskelineT m a #
Abort the current REPL loop, and continue.
tryAction :: forall (m :: Type -> Type) a. (MonadMask m, MonadIO m) => HaskelineT m a -> HaskelineT m a #
Wrap a HasklineT action so that if an interrupt is thrown the shell continues as normal.
dontCrash :: (MonadIO m, MonadCatch m) => m () -> m () #
Catch all toplevel failures.