Safe Haskell | None |
---|---|
Language | Haskell2010 |
Building-blocks of a CmdParser.
The simplest sensible CmdParser is just
addCmdImpl $ putStrLn "hello, world!"
(assuming out is IO ()).
The empty CmdParser is also valid:
return ()
But not very interesting - you won't get an out
value from this (e.g. an
IO-action to execute) when this matches (on the empty input).
do addCmd "sub" $ do addCmdImpl $ putStrLn "sub successful"
Here, note that there is no implementation at the top-level. This means that on the empty input the resulting CommandDesc has no out-value, but on "sub" it has. Executed as a program, the user would be shown the usage on empty input, and the putStrLn would happen on "sub".
More than one subcommand? easy:
do addCmd "foo" $ do {..} addCmd "bar" $ do {..}
Basic flag usage:
do shouldVerbose <- addSimpleBoolFlag "v" ["verbose"] mzero addCmdImpl $ if shouldVerbose then putStrLn "Hello, World!!!!!" else putStrLn "hi."
Basic param usage:
addCmd "echo" $ do addCmdHelpStr "print its parameter to output" str <- addRestOfInputStringParam "STRING" (paramHelpStr "the string to print") addCmdImpl $ putStrLn str addCmd "echoInt" $ do i <- addReadParam "INT" mempty addCmdImpl $ print (i::Int) -- need to disambiguate via typesig.
There are some other flag/param methods in the respective modules.
Also note the example at reorderStart
.
- addCmd :: Applicative f => String -> CmdParser f out () -> CmdParser f out ()
- addCmdHidden :: Applicative f => String -> CmdParser f out () -> CmdParser f out ()
- addNullCmd :: Applicative f => CmdParser f out () -> CmdParser f out ()
- addCmdImpl :: out -> CmdParser f out ()
- addCmdSynopsis :: String -> CmdParser f out ()
- addCmdHelp :: Doc -> CmdParser f out ()
- addCmdHelpStr :: String -> CmdParser f out ()
- reorderStart :: CmdParser f out ()
- reorderStop :: CmdParser f out ()
- withReorder :: CmdParser f out a -> CmdParser f out a
- peekCmdDesc :: CmdParser f out (CommandDesc ())
- peekInput :: CmdParser f out String
- module UI.Butcher.Monadic.Flag
- module UI.Butcher.Monadic.Param
- addCmdPart :: (Applicative f, Typeable p) => PartDesc -> (String -> Maybe (p, String)) -> CmdParser f out p
- addCmdPartMany :: (Applicative f, Typeable p) => ManyUpperBound -> PartDesc -> (String -> Maybe (p, String)) -> CmdParser f out [p]
- addCmdPartInp :: (Applicative f, Typeable p) => PartDesc -> (Input -> Maybe (p, Input)) -> CmdParser f out p
- addCmdPartManyInp :: (Applicative f, Typeable p) => ManyUpperBound -> PartDesc -> (Input -> Maybe (p, Input)) -> CmdParser f out [p]
- addAlternatives :: Typeable p => [(String, String -> Bool, CmdParser f out p)] -> CmdParser f out p
- data ManyUpperBound
- varPartDesc :: String -> PartDesc
Documentation
:: Applicative f | |
=> String | command name |
-> CmdParser f out () | subcommand |
-> CmdParser f out () |
Add a new child command in the current context.
:: Applicative f | |
=> String | command name |
-> CmdParser f out () | subcommand |
-> CmdParser f out () |
Add a new child command in the current context, but make it hidden. It
will not appear in docs/help generated by e.g. the functions in the
Pretty
module.
This feature is not well tested yet.
addNullCmd :: Applicative f => CmdParser f out () -> CmdParser f out () Source #
Add a new nameless child command in the current context. Nameless means that this command matches the empty input, i.e. will always apply. This feature is experimental and CommandDesc pretty-printing might not correctly in presense of nullCmds.
addCmdImpl :: out -> CmdParser f out () Source #
Add an implementation to the current command.
addCmdSynopsis :: String -> CmdParser f out () Source #
Add a synopsis to the command currently in scope; at top level this will be the implicit top-level command.
Adding a second synopsis will overwrite a previous synopsis;
checkCmdParser
will check that you don't (accidentally) do this however.
addCmdHelp :: Doc -> CmdParser f out () Source #
Add a help document to the command currently in scope; at top level this will be the implicit top-level command.
Adding a second document will overwrite a previous document;
checkCmdParser
will check that you don't (accidentally) do this however.
addCmdHelpStr :: String -> CmdParser f out () Source #
Like addCmdHelp
. PP.text
reorderStart :: CmdParser f out () Source #
Best explained via example:
do reorderStart bright <- addSimpleBoolFlag "" ["bright"] mempty yellow <- addSimpleBoolFlag "" ["yellow"] mempty reorderStop ..
will accept any inputs "" "--bright" "--yellow" "--bright --yellow" "--yellow --bright".
This works for any flags/params, but bear in mind that the results might be unexpected because params may match on any input.
Note that start/stop must occur in pairs, and it will be a runtime error
if you mess this up. Use checkCmdParser
if you want to check all parts
of your CmdParser
without providing inputs that provide 100% coverage.
reorderStop :: CmdParser f out () Source #
See reorderStart
withReorder :: CmdParser f out a -> CmdParser f out a Source #
Safe wrapper around 'reorderStart'/'reorderStop' for cases where reducing to a single binding is possible/preferable.
peekCmdDesc :: CmdParser f out (CommandDesc ()) Source #
Semi-hacky way of accessing the output CommandDesc from inside of a
CmdParser
. This is not implemented via knot-tying, i.e. the CommandDesc
you get is _not_ equivalent to the CommandDesc returned by runCmdParser
.
Also see runCmdParserWithHelpDesc
which does knot-tying.
For best results, use this "below"
any addCmd
invocations in the current context, e.g. directly before
the addCmdImpl
invocation.
peekInput :: CmdParser f out String Source #
Semi-hacky way of accessing the current input that is not yet processed.
This must not be used to do any parsing. The purpose of this function is
to provide a String to be used for output to the user, as feedback about
what command was executed. For example we may think of an interactive
program reacting to commandline input such as
"run --delay 60 fire-rockets" which shows a 60 second delay on the
"fire-rockets" command. The latter string could have been obtained
via peekInput
after having parsed "run --delay 60" already.
Building CmdParsers - myprog -v --input PATH
module UI.Butcher.Monadic.Flag
Building CmdParsers - myprog SOME_INT
module UI.Butcher.Monadic.Param
Low-level part functions
addCmdPart :: (Applicative f, Typeable p) => PartDesc -> (String -> Maybe (p, String)) -> CmdParser f out p Source #
Add part that is expected to occur exactly once in the input. May succeed on empty input (e.g. by having a default).
addCmdPartMany :: (Applicative f, Typeable p) => ManyUpperBound -> PartDesc -> (String -> Maybe (p, String)) -> CmdParser f out [p] Source #
Add part that is not required to occur, and can occur as often as
indicated by ManyUpperBound
. Must not succeed on empty input.
addCmdPartInp :: (Applicative f, Typeable p) => PartDesc -> (Input -> Maybe (p, Input)) -> CmdParser f out p Source #
Add part that is expected to occur exactly once in the input. May succeed on empty input (e.g. by having a default).
Only difference to addCmdPart
is that it accepts Input
, i.e. can
behave differently for String
and [String]
input.
addCmdPartManyInp :: (Applicative f, Typeable p) => ManyUpperBound -> PartDesc -> (Input -> Maybe (p, Input)) -> CmdParser f out [p] Source #
Add part that is not required to occur, and can occur as often as
indicated by ManyUpperBound
. Must not succeed on empty input.
Only difference to addCmdPart
is that it accepts Input
, i.e. can
behave differently for String
and [String]
input.
addAlternatives :: Typeable p => [(String, String -> Bool, CmdParser f out p)] -> CmdParser f out p Source #
Add a list of sub-parsers one of which will be selected and used based on the provided predicate function. The input elements consist of: a) a name used for the command description of the output, b) a predicate function; the first True predicate determines which element to apply c) a CmdParser.
data ManyUpperBound Source #
Specifies whether we accept 0-1 or 0-n for CmdParserPart
s.
varPartDesc :: String -> PartDesc Source #
Create a simple PartDesc from a string.