Safe Haskell | None |
---|---|
Language | Haskell2010 |
Provides Commands for REPLs. Commands take care of input and parameter-handling, and allow parameters to be supplied in the same line as the command's name (e.g. ":cmd param1 param2" on stdin). Provided parameters can be parsed and checked (say, against databases) before they are passed to the actual command function. They are relatively large units of abstraction, but they allow the easy creation of relatively sophisticated command loops, and have the advantage that one doesn't need to fiddle around with input handling in the middle of the actual command code.
- data Command m a = Command {
- commandName :: Text
- commandTest :: Text -> Bool
- commandDesc :: Text
- numParameters :: Maybe Int
- runCommand :: Text -> m a
- commandInfo :: MonadIO m => Command m a -> m ()
- runOnce :: MonadIO m => Text -> Command m a -> m (Maybe a)
- commandDispatch :: (MonadIO m, MonadCatch m, Functor m) => Text -> [Command m z] -> m z
- summarizeCommands :: MonadIO m => [Command m2 z] -> m ()
- readArgs :: Text -> Either Text [Text]
- quoteArg :: Text -> Text
- makeCommand :: (MonadIO m, MonadCatch m, Functor m) => Text -> (Text -> Bool) -> Text -> (Text -> m a) -> Command m a
- makeCommand1 :: (MonadIO m, MonadCatch m, Functor m, Read a) => Text -> (Text -> Bool) -> Text -> Asker m a -> (Text -> a -> m z) -> Command m z
- makeCommand2 :: (MonadIO m, MonadCatch m, Functor m, Read a, Read b) => Text -> (Text -> Bool) -> Text -> Asker m a -> Asker m b -> (Text -> a -> b -> m z) -> Command m z
- makeCommand3 :: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c) => Text -> (Text -> Bool) -> Text -> Asker m a -> Asker m b -> Asker m c -> (Text -> a -> b -> c -> m z) -> Command m z
- makeCommand4 :: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d) => Text -> (Text -> Bool) -> Text -> Asker m a -> Asker m b -> Asker m c -> Asker m d -> (Text -> a -> b -> c -> d -> m z) -> Command m z
- makeCommand5 :: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d, Read e) => Text -> (Text -> Bool) -> Text -> Asker m a -> Asker m b -> Asker m c -> Asker m d -> Asker m e -> (Text -> a -> b -> c -> d -> e -> m z) -> Command m z
- makeCommand6 :: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d, Read e, Read f) => Text -> (Text -> Bool) -> Text -> Asker m a -> Asker m b -> Asker m c -> Asker m d -> Asker m e -> Asker m f -> (Text -> a -> b -> c -> d -> e -> f -> m z) -> Command m z
- makeCommandN :: (MonadIO m, MonadCatch m, Functor m, Read a) => Text -> (Text -> Bool) -> Text -> [Asker m a] -> [Asker m a] -> (Text -> [a] -> m z) -> Command m z
Command dispatch
Using the Command
class is not necessary, but it makes dealing with
user input considerably easier. When a command is run with a line of
input, it automatically segments it by whitespace, tries to interpret
each part as one of its arguments and passes them to the actual command
function. If any arguments haven't been supplies, it asks for them on
stdin. If too many arguments have been supplied, or if any argument'
parsing returns an error, the command is aborted.
Example:
cd = makeCommand1 ...
>>>
:cd ../
Directory changed!>>>
:cd
Enter new directory:>>>
../
Directory changed!
A REPL command, possibly with parameters.
Command | |
|
commandInfo :: MonadIO m => Command m a -> m () Source
Prints information (the command name, description and, if given, the number of parameters) about a command to the console.
runOnce :: MonadIO m => Text -> Command m a -> m (Maybe a) Source
Takes a line of text and a command.
If the text matches the given command's commandTest
,
the command is run with it. If not, Nothing
is returned.
:: (MonadIO m, MonadCatch m, Functor m) | |
=> Text | The user's input. |
-> [Command m z] | The command library. |
-> m z |
Takes an input and tries to run it against a list of commands,
trying the out in sequence. The first command whose commandTest
returns True is executed. If none of the commands match,
NothingFoundFailure
is thrown.
summarizeCommands :: MonadIO m => [Command m2 z] -> m () Source
Prints out a list of command names, with their descriptions.
readArgs :: Text -> Either Text [Text] Source
Splits and trims the input of a command. Any non-whitespace sequence of characters is interpreted as one argument, unless double quotes (") are used, in which case they demarcate an argument. Each argument is parsed as a haskell string literal (quote-less arguments have quotes inserted around them). If the number of quotes in the input is not even, the operating will fail.
Arguments are parsed using parsec's stringLiteral
(haskell-style),
meaning that escape sequences and unicode characters are handled automatically.
quoteArg :: Text -> Text Source
Surrounds an argument in quote marks, if necessary.
This is useful when arguments were extracted via readArgs
, which deletes
quote marks. Quotes are placed around the input iff it doesn't begin with
a quote mark (").
readArgs
and quoteArg
are inverse up to suitable isomorphism, i.e.
if 'readArgs orig = (Right res)', then it holds that
readArgs orig = readArgs $ intercalate " " $ map quoteArg res
Making commands.
:: (MonadIO m, MonadCatch m, Functor m) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description. |
-> (Text -> m a) | The actual command. |
-> Command m a |
Creates a command without parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> (Text -> a -> m z) | |
-> Command m z |
Creates a command with one parameter.
:: (MonadIO m, MonadCatch m, Functor m, Read a, Read b) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> Asker m b |
|
-> (Text -> a -> b -> m z) | |
-> Command m z |
Creates a command with two parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> Asker m b |
|
-> Asker m c |
|
-> (Text -> a -> b -> c -> m z) | |
-> Command m z |
Creates a command with three parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> Asker m b |
|
-> Asker m c |
|
-> Asker m d |
|
-> (Text -> a -> b -> c -> d -> m z) | |
-> Command m z |
Creates a command with four parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d, Read e) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> Asker m b |
|
-> Asker m c |
|
-> Asker m d |
|
-> Asker m e |
|
-> (Text -> a -> b -> c -> d -> e -> m z) | |
-> Command m z |
Creates a command with five parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a, Read b, Read c, Read d, Read e, Read f) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> Asker m a |
|
-> Asker m b |
|
-> Asker m c |
|
-> Asker m d |
|
-> Asker m e |
|
-> Asker m f |
|
-> (Text -> a -> b -> c -> d -> e -> f -> m z) | |
-> Command m z |
Creates a command with four parameters.
:: (MonadIO m, MonadCatch m, Functor m, Read a) | |
=> Text | Command name. |
-> (Text -> Bool) | Command test. |
-> Text | Command description |
-> [Asker m a] |
|
-> [Asker m a] |
|
-> (Text -> [a] -> m z) | |
-> Command m z |
Creates a command with a list of parameters.
The first list necc
of Asker
s indicates the necessary parameters;
the user must at least provide this many. The second list opt
contains
Asker
s for additional, optional parameters, and may be infinite.
If the number of passed parameters exceeds
length necc + length opt
, or if any Asker
fails,
the command returns an AskFailure
.