butcher-1.3.2.3: Chops a command or program invocation into digestable pieces.

Safe HaskellNone
LanguageHaskell2010

UI.Butcher.Monadic.Command

Contents

Description

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.

Synopsis

Documentation

addCmd Source #

Arguments

:: Applicative f 
=> String

command name

-> CmdParser f out ()

subcommand

-> CmdParser f out () 

Add a new child command in the current context.

addCmdHidden Source #

Arguments

:: 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.

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

Building CmdParsers - myprog SOME_INT

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 CmdParserParts.

varPartDesc :: String -> PartDesc Source #

Create a simple PartDesc from a string.