-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Command line option parsing library with a twice applicative interface -- -- Provides tools to create command line parsers. The library has a -- simple interface to create atomic parsers and combine them into more -- complex structures. The interface has a low-level feel but still lets -- you solve common use-cases with minimal work. -- -- Has support for: -- --
-- p <|> orElse x ---- -- will run the parser p, and if p consumes any token -- (normal or EOF), then p will finish the parse. If p -- doesn't consume any tokens at all and never finishes then the -- alternative parser will produce the value x upon receiving -- EOF. -- -- Note that orElse has the same type as pure: a -> -- p a. They produce the same parse result. However, unlike -- orElse pure finishes the parse immediately, without -- waiting for EOF. This makes pure unsuitable as a fallback -- alternative most of the time. orElse :: SelectiveParser p => a -> p a -- | Convenience wrapper around many. Will start with a given value -- of type a, and then will parse zero or more "updates" of type -- a -> a. Updates will be applied to the original value -- left-to-right until EOF is reached, at which point the final updated -- value will be produced. applyMany :: SelectiveParser p => a -> p (a -> a) -> p a -- | Convenience wrapper around some. Like applyMany but will -- insist on parsing at least one update of type a -> a. If -- no update items are parsed from the input then applySome will -- refuse to consume EOF. applySome :: SelectiveParser p => a -> p (a -> a) -> p a -- | Like <#> but ignores the value produced by the right hand -- side parser. (<#) :: SelectiveParser p => p a -> p b -> p a infixl 4 <# -- | Like <#> but ignores the value produced by the left hand -- side parser. (#>) :: SelectiveParser p => p a -> p b -> p b infixl 4 #> -- | Like <#> but with the types of the arguments swappped. -- Note that a <##> f is not the same as f -- <#> a. In both <#> and -- <##> the left hand side parser looks at each input token -- before the right hand side parser. (<##>) :: SelectiveParser p => p a -> p (a -> b) -> p b infixl 4 <##> -- | Like <-#> but ignores the value produced by the right -- hand side parser. (<-#) :: SelectiveParser p => p a -> p b -> p a infixl 4 <-# -- | Like <-#> but ignores the value produced by the left hand -- side parser. (-#>) :: SelectiveParser p => p a -> p b -> p b infixl 4 -#> -- | Like <-#> but with the types of the arguments swappped. -- Note that a <-##> f is not the same as f -- <#-> a. In both cases the parser a will be -- gracefully terminated once f consumes an input. However, in -- a <-##> f it is a that gets the first -- look at each input token, whereas in f <#-> a it -- is f. (<-##>) :: SelectiveParser p => p a -> p (a -> b) -> p b infixl 4 <-##> -- | Like <#-> but ignores the value produced by the right -- hand side parser. (<#-) :: SelectiveParser p => p a -> p b -> p a infixl 4 <#- -- | Like <#-> but ignores the value produced by the left hand -- side parser. (#->) :: SelectiveParser p => p a -> p b -> p b infixl 4 #-> -- | Like <#-> but with the types of the arguments swappped. -- Note that a <##-> f is not the same as f -- <-#> a. In both cases the parser f will be -- gracefully terminated once a consumes an input. However, in -- a <##-> f it is a that gets the first -- look at each input token, whereas in f <-#> a it -- is f. (<##->) :: SelectiveParser p => p a -> p (a -> b) -> p b infixl 4 <##-> -- | A functor with failure. Instances are expected to satisfy the laws: -- -- Coordinated with fmap: -- --
-- fmapOrFail (Right . f) = fmap f ---- -- Composition: -- --
-- fmapOrFail f . fmapOrFail g = fmapOrFail (g >=> f) ---- -- Additionally, if f is a MonadFail, it is expected that -- failure is the same as the monadic fail: -- --
-- fmapOrFail Left (return err) = fail err --class Functor f => FunctorFail f -- | Like fmap but with a possibility for failure. This applies a -- function of type (a -> Either String b) to a -- value of type f a. If the function returns a Left, -- this represents failure, with the String being a message -- describing the nature of the failure. In this case the resulting value -- of type f b should encapsulate this failure. -- -- In command line parsing this is used by functions like -- paramRead to produce an unrecoverable failure when a parameter -- cannot be parsed e.g. as an integer. fmapOrFail :: FunctorFail f => (a -> Either String b) -> f a -> f b -- | Like liftM but with a possibility for failure. Suitable as a -- drop-in implementation of fmapOrFail for monads. fmapOrFailM :: MonadFail f => (a -> Either String b) -> f a -> f b -- | Operator form of fmapOrFail. Provided for convenience. (<$?>) :: FunctorFail f => (a -> Either String b) -> f a -> f b infixl 4 <$?> -- | A version <$?> with the arguments flipped. Provided for -- convenience. (<&?>) :: FunctorFail f => f a -> (a -> Either String b) -> f b infixl 1 <&?> -- | An Applicative that is also a FunctorFail. Instances are -- expected to satisfy the law: -- --
-- failA err = fmapOrFail Left (pure err) ---- -- This is also the default implementation of failA. class (Applicative f, FunctorFail f) => ApplicativeFail f -- | Unconditional failure. failA :: ApplicativeFail f => String -> f a -- | This module defines IOOps, which is a way to abstract away IO -- operations required for Options.OptStream. module Options.OptStream.IOOps -- | IOOps is a typeclass that describes parts of IO used by -- Options.OptStream. It is meant to be represented by IO -- in production and a mock implementation in tests. class Monad m => IOOps m getArgs :: IOOps m => m [String] getProgName :: IOOps m => m String putStrLn :: IOOps m => String -> m () die :: IOOps m => String -> m a exitSuccess :: IOOps m => m a instance Options.OptStream.IOOps.IOOps GHC.Types.IO -- | This module contains lower-level functions for working with -- Help objects. You may need to import this if you work with -- Help objects directly, as opposed to relying on them being -- handled automatically by Parser. module Options.OptStream.Help -- | Represents help information that could be printed when the user passes -- --help on the command line. -- -- A Help object contains three parts, each of which could be -- empty: a header, an options table, and a footer. Help objects -- can be composed together using <>. That will separately -- concatenate headers, option tables, and footers. data Help -- | Formats the Help object. -- --
-- h :: Help -- h = makeHeader "Usage: program [options] ARG" -- <> makeFreeArgHelp "ARG" "Positional argument." -- <> makeFlagHelp ["-f", "--foo"] "A flag." -- <> makeParamHelp ["-p", "--param"] "VAL" "A parameter." -- <> makeFooter "Example: program --foo bar" ---- --
-- >>> putStrLn $ formatHelp h -- Usage: program [options] ARG -- -- ARG Positional argument. -- -f, --foo A flag. -- -p, --param=VAL A parameter. -- -- Example: program --foo bar --formatHelp :: Help -> String -- | Makes a Help object that contains one paragraph in the header. makeHeader :: String -> Help -- | Makes a Help object that contains one paragraph in the footer. makeFooter :: String -> Help -- | Makes a Help object that contains one row in the options table. -- This function is suitable to add Help to a flag, i.e. an option -- that doesn't take any additional arguments. -- -- You may pass any number of option forms. However, only the first one -- of each kind (short and long) will be used. -- --
-- >>> formatHelp $ makeFlagHelp ["-f", "--foo"] "Description." -- " -f, --foo Description." --makeFlagHelp :: [OptionForm] -> String -> Help -- | Makes a Help object that contains one row in the options table. -- This function is suitable to add Help to a parameter, i.e. an -- option that takes one additional argument. -- -- You may pass any number of option forms. However, only the first one -- of each kind (short and long) will be used. -- --
-- >>> formatHelp $ makeParamHelp ["-i", "--input"] "FILE" "Input file." -- " -i, --input=FILE Input file." --makeParamHelp :: [OptionForm] -> String -> String -> Help -- | Makes a Help object that contains one row in the options table. -- This function is suitable to add Help to a multi-parameter, -- i.e. an option that takes an arbitrary number of additional arguments. -- -- In practice this behaves almost the same as makeParamHelp, -- except it advertises a slightly different syntax for passing -- additional arguments: as proper additional arguments, without -- '='. -- -- You may pass any number of option forms. However, only the first one -- of each kind (short and long) will be used. -- --
-- >>> formatHelp $ makeMultiParamHelp ["-n", "--full-name"] "FIRST LAST" "First and last name." -- " -n, --full-name FIRST LAST First and last name." --makeMultiParamHelp :: [OptionForm] -> String -> String -> Help -- | Makes a Help object that contains one row in the options table. -- This function is suitable to add Help to a free argument. -- --
-- >>> formatHelp $ makeFreeArgHelp "FILE" "Input file." -- " FILE Input file." --makeFreeArgHelp :: String -> String -> Help -- | Clears the header of a Help object. Doesn't affect the options -- table and the footer. clearHelpHeader :: Help -> Help -- | Clears the footer of a Help object. Doesn't affect the header -- and the options table. clearHelpFooter :: Help -> Help -- | Clears the options table of a Help object. Doesn't affect the -- header and the footer. clearHelpTable :: Help -> Help -- | Sorts the options table so that: -- --
-- >>> isLegalOptionForm "-f" -- True -- -- >>> isLegalOptionForm "--foo" -- True -- -- >>> isLegalOptionForm "bar" -- False -- -- >>> isLegalOptionForm "" -- False -- -- >>> isLegalOptionForm "-" -- False -- -- >>> isLegalOptionForm "--" -- False -- -- >>> isLegalOptionForm "---" -- True --isLegalOptionForm :: OptionForm -> Bool -- | See flag'. flag' :: [OptionForm] -> RawParser () -- | See flagSep'. flagSep' :: [OptionForm] -> RawParser () -- | See param'. param' :: [OptionForm] -> String -> RawParser String -- | See paramRead'. paramRead' :: Read a => [OptionForm] -> String -> RawParser a -- | See paramChar'. paramChar' :: [OptionForm] -> String -> RawParser Char -- | See freeArg'. freeArg' :: String -> RawParser String -- | See freeArgRead'. freeArgRead' :: Read a => String -> RawParser a -- | See freeArgChar'. freeArgChar' :: String -> RawParser Char -- | See anyArg'. anyArg' :: String -> RawParser String -- | See anyArgRead'. anyArgRead' :: Read a => String -> RawParser a -- | See anyArgChar'. anyArgChar' :: String -> RawParser Char -- | See multiParam'. multiParam' :: [OptionForm] -> RawFollower a -> RawParser a -- | A RawFollower consumes zero or more strings from a stream and -- then produces a result of type a. This is the type that -- Follower uses internally. The differences between -- RawFollower and Follower are: -- --
-- module Main where
--
-- import Control.Applicative
-- import Data.Functor
-- import Options.OptStream
--
-- data Options = Options
-- { strParam :: String
-- , intParam :: Int
-- , boolFlag :: Bool
-- , positional :: String
-- }
-- deriving Show
--
-- optionsP :: Parser Options
-- optionsP = Options
-- <$> (param ["-s", "--string"] "STR" "String parameter." <|> orElse "")
-- <#> (paramRead ["-i", "--int"] "INT" "Integer parameter." <|> orElse 0)
-- <#> (flag ["-b", "--bool"] "Boolean flag." $> True <|> orElse False)
-- <#> (freeArg "ARG" "Positional argument.")
--
-- main = do
-- opts <- parseArgsWithHelp
-- $ header "Usage: demo [options] ARG"
-- $ footer "Example: demo -b --int=42 foo"
-- $ optionsP
--
-- print opts
--
--
-- Note that in the code above:
--
--
-- >>> ./demo -s foo -i 42 -b bar
-- Options {strParam = "foo", intParam = 42, boolFlag = True, positional = "bar"}
--
--
--
-- >>> ./demo foo
-- Options {strParam = "", intParam = 0, boolFlag = False, positional = "foo"}
--
--
-- -- >>> ./demo --help -- Usage: demo [options] ARG -- -- -s, --string=STR String parameter. -- -i, --int=INT Integer parameter. -- -b, --bool Boolean flag. -- ARG Positional argument. -- --help Show this help message and exit. -- -- Example: demo -b --int=42 foo --module Options.OptStream -- | A Parser processes (part of) a stream of command line arguments -- and produces an output value of type a. It also contains -- information necessary to generate help. -- -- The general steps for working with parsers are: -- --
-- >>> runParser (param' ["--foo"] "FOO") ["--foo=bar"] -- Right "bar" ---- --
-- >>> runParser (param' ["--foo"] "FOO") [] -- Left (MissingArg CtxEnd ["--foo"]) --runParser :: Parser a -> [String] -> Either ParserError a -- | runParserIO is like runParser, except that it terminates -- the program with die in case of failure. In case of success it -- returns a pure IO value. -- -- This is convenient for testing parsers in a REPL: -- --
-- >>> runParserIO (param' ["--foo"] "FOO") ["--foo=bar"] -- "bar" ---- --
-- >>> runParserIO (param' ["--foo"] "FOO") [] -- <interactive>: missing command line argument: --foo --runParserIO :: IOOps m => Parser a -> [String] -> m a -- | parseArgs is like runParserIO, except that it gets the -- arguments from the environment. You can think of it as a more -- structured replacement for getArgs. -- --
-- main :: IO () -- main = do -- (src, dst) <- parseArgs $ (,) -- <$> param' ["-i", "--input"] "FILE" -- <#> param' ["-o", "--output"] "FILE" -- -- contents <- readFile src -- writeFile dst contents --parseArgs :: IOOps m => Parser a -> m a -- | parseArgsWithHelp is like parseArgs, but it also adds a -- --help option to the parser. If the user passes -- --help, parseArgsWithHelp will print the help and exit -- the program. If there is a parse error, it will print an error message -- suggesting to use --help. -- --
-- main :: IO () -- main = do -- (src, dst) <- parseArgsWithHelp -- $ header "Usage: copy [options]" -- $ footer "Example: copy -i input.txt -o output.txt" -- $ (,) -- <$> param ["-i", "--input"] "FILE" "Input file." -- <#> param ["-o", "--output"] "FILE" "Output file." -- -- contents <- readFile src -- writeFile dst contents ---- --
-- >>> ./copy --help -- Usage: copy [options] -- -- -i, --input=FILE Input file. -- -o, --output=FILE Output file. -- --help Show this help message and exit. -- -- Example: copy -i input.txt -o output.txt --parseArgsWithHelp :: IOOps m => Parser a -> m a -- | High-level option parsers all accept a list of option forms. An -- option form is simply a String. -- -- There are two kinds of legal option forms: short forms, e.g. -- "-f", and long forms, e.g. "--foo". Any -- function that accepts an OptionForm will fail with an -- error if the option form is illegal. See -- isLegalOptionForm. type OptionForm = String -- | Checks whether the given string is a legal option form. A legal short -- form is -C, where C is any character other than -- -. A legal long form is --STR, where STR is -- any non-empty string. -- -- This function is here just in case. Normally the programmer will -- provide option forms as string literals, so they will probably be -- legal. -- --
-- >>> isLegalOptionForm "-f" -- True -- -- >>> isLegalOptionForm "--foo" -- True -- -- >>> isLegalOptionForm "bar" -- False -- -- >>> isLegalOptionForm "" -- False -- -- >>> isLegalOptionForm "-" -- False -- -- >>> isLegalOptionForm "--" -- False -- -- >>> isLegalOptionForm "---" -- True --isLegalOptionForm :: OptionForm -> Bool -- | A flag is a simple option with no arguments. It is simply there -- or not there. For example, sort from GNU coreutils has a flag -- -r, --reverse to sort in reverse order. -- -- The first argument to flag is for all the forms of the flag, -- both short and long. You can pass as many forms as you like. They will -- all match, but only the first one of each kind (short and long), if -- any, will appear in the generated help. -- -- An empty list or a list containing illegal forms will result in an -- error (see OptionForm). -- -- Since a flag doesn't carry any information except for its own -- presence, the returned value is Parser (). If you want -- to turn it into a Bool that is False by default and -- turns to True when the flag is present, you can do that using -- the $> <|> orElse idiom: -- --
-- >>> let f = flag ["-v", "--verbose"] "Verbose output." $> True <|> orElse False -- -- >>> runParserIO f [] -- False -- -- >>> runParserIO f ["-v"] -- True ---- -- Short forms of flags can be bundled together, e.g. -ab will -- work the same as -a -b. If you don't want bundling, use -- flagSep instead. -- --
-- >>> let foo = flag ["-f"] "Foo" $> "foo" <|> orElse "no foo" -- -- >>> let bar = flag ["-b"] "Bar" $> "bar" <|> orElse "no bar" -- -- >>> let foobar = (,) <$> foo <#> bar ---- --
-- >>> runParserIO foobar ["-f"]
-- ("foo", "no bar")
--
--
--
-- >>> runParserIO foobar ["-b"]
-- ("no foo", "bar")
--
--
--
-- >>> runParserIO foobar ["-f", "-b"]
-- ("foo", "bar")
--
--
--
-- >>> runParserIO foobar ["-fb"]
-- ("foo", "bar")
--
--
--
-- >>> runParserIO foobar ["-bf"]
-- ("foo", "bar")
--
flag :: [OptionForm] -> String -> Parser ()
-- | Like flag but doesn't generate any help.
flag' :: [OptionForm] -> Parser ()
-- | Like flag but doesn't support bundling. A flagSep will
-- only work separately, it will not bundle with other flags, even if
-- they are defined with flag.
--
-- -- >>> let foo = flag ["-f"] "Foo" $> "foo" <|> orElse "no foo" -- -- >>> let bar = flagSep ["-b"] "Bar" $> "bar" <|> orElse "no bar" -- -- >>> let foobar = (,) <$> foo <#> bar ---- --
-- >>> runParserIO foobar ["-f", "-b"]
-- ("foo", "bar")
--
--
-- -- >>> runParserIO foobar ["-fb"] -- <interactive>: unexpected character 'b' in command line argument "-fb" --flagSep :: [OptionForm] -> String -> Parser () -- | Like flagSep but doesn't generate any help. flagSep' :: [OptionForm] -> Parser () -- | A parameter is an option that has one string argument, e.g. -- --input=FILENAME or -i FILENAME. -- -- The first argument to param should list all the forms of the -- parameter, both short and long. For every short form -f the -- parser will accept: -- --
-- >>> let p = param ["-i", "--input"] "FILENAME" "Input filename." -- -- >>> runParserIO p ["-i", "foo.txt"] -- "foo.txt" ---- --
-- >>> runParserIO p ["--input=bar.txt"] -- "bar.txt" ---- --
-- >>> runParserIO p ["--input="] -- "" ---- --
-- >>> runParserIO p ["--input"] -- <interactive>: missing command line argument after "--input": FILENAME ---- --
-- >>> runParserIO p [] -- <interactive>: missing command line argument: --input | -i ---- --
-- >>> let p = param ["-n"] "NAME" "Your name. Default: James Bond." <|> orElse "James Bond" -- -- >>> runParserIO p ["-n", "Sherlock Holmes"] -- "Sherlock Holmes" ---- --
-- >>> runParserIO p [] -- "James Bond" --param :: [OptionForm] -> String -> String -> Parser String -- | Like param but doesn't generate help. param' :: [OptionForm] -> String -> Parser String -- | Like param but parses the parameter value down to a type -- Read a => a. Can be used e.g. for Int and -- Float params. -- --
-- >>> let p = paramRead ["-n", "--number"] "INT" "An integer parameter." :: Parser Int -- -- >>> runParserIO p ["--number=42"] -- 42 ---- --
-- >>> runParserIO p ["--number=fourty_two"] -- <interactive>: command line error at "--number=fourty_two": Prelude.read: no parse --paramRead :: Read a => [OptionForm] -> String -> String -> Parser a -- | Like paramRead but doesn't generate help. paramRead' :: Read a => [OptionForm] -> String -> Parser a -- | Like param but parses the parameter value down to a -- Char. Fails if the value is anything else than one character -- long. -- --
-- >>> let p = paramChar ["-s"] "CHAR" "Separator character." -- -- >>> runParserIO p ["-s|"] -- '|' ---- --
-- >>> runParserIO p ["-s\n"] -- '\n' ---- --
-- >>> runParserIO p ["-sabc"] -- <interactive>: command line error at "-sabc": expected one character, got 3 --paramChar :: [OptionForm] -> String -> String -> Parser Char -- | Like paramChar but doesn't generate help. paramChar' :: [OptionForm] -> String -> Parser Char -- | Matches any free argument, i.e. any argument that doesn't start -- with -. Returns this argument verbatim as a string. -- -- If you want to match any argument, including those starting with -- -, use anyArg. -- -- Like all the other atomic parsers in this module, freeArg is -- mandatory. It can be made optional with <|> -- orElse. -- --
-- >>> let p = freeArg "FILENAME" "Input file." -- -- >>> runParserIO p ["input.txt"] -- "input.txt" ---- --
-- >>> runParserIO p [""] -- "" ---- --
-- >>> runParserIO p ["--foo"] -- <interactive>: unexpected command line argument "--foo" ---- --
-- >>> runParserIO p [] -- <interactive>: missing command line argument: FILENAME ---- --
-- >>> let p = freeArg "FILENAME" "Output file. Default: a.out." <|> orElse "a.out" -- -- >>> runParserIO p ["./binary"] -- "./binary" ---- --
-- >>> runParserIO p [] -- "a.out" --freeArg :: String -> String -> Parser String -- | Like freeArg but doesn't generate help. freeArg' :: String -> Parser String -- | Like freeArg but parses the argument down to a Read -- a => a. Can be used to parse e.g. integers and floating point -- values. -- --
-- >>> let p = freeArgRead "NUM" "A floating point argument." :: Parser Float -- -- >>> runParserIO p ["2.718"] -- 2.718 ---- --
-- >>> runParserIO p ["foo"] -- <interactive>: command line error at "foo": Prelude.read: no parse --freeArgRead :: Read a => String -> String -> Parser a -- | Like freeArgRead but doesn't generate help. freeArgRead' :: Read a => String -> Parser a -- | Like freeArg but parses the argument down to a Char. -- Note that a free argument cannot begin with -, so the parser -- will never return '-'. -- --
-- >>> let p = freeArgChar "C" "Any character except \'-\'." -- -- >>> runParserIO p ["x"] -- 'x' ---- --
-- >>> runParserIO p ["-"] -- <interactive>: unexpected command line argument "-" ---- --
-- >>> runParserIO p [""] -- <interactive>: command line error at "": expected one character, got zero --freeArgChar :: String -> String -> Parser Char -- | Like freeArgChar but doesn't generate help. freeArgChar' :: String -> Parser Char -- | Consumes and returns any command line argument. Unlike -- freeArg this parser will also consume arguments starting with -- -, so the following holds: -- --
-- runParser (many (anyArg _ _)) xs == Right xs ---- -- In most cases you should prefer freeArg. However, anyArg -- can be useful in certain situations, for example if you want to -- collect all arguments after -- (see beforeDashes). anyArg :: String -> String -> Parser String -- | Like anyArg but doesn't generate help. anyArg' :: String -> Parser String -- | Consumes any command line argument and parses it down to a -- value of a given type a that is an instance of Read. -- Unlike freeArgRead this parser will also consume arguments -- starting with -. -- --
-- >>> let p = anyArgRead "NUM" "An integer." :: Parser Int -- -- >>> runParserIO p ["-10"] -- -10 ---- -- In most cases you should prefer freeArgRead. The function -- anyArgRead is provided for completeness. anyArgRead :: Read a => String -> String -> Parser a -- | Like anyArgRead but doesn't generate help. anyArgRead' :: Read a => String -> Parser a -- | Consumes any command line argument and parses it down to a -- character. Produces a failure if the argument is anything other than -- one character long. Unlike freeArgChar this will also consume -- arguments starting with -. -- -- In most cases you should prefer freeArgChar. The function -- anyArgChar is provided for completeness. -- --
-- >>> let p = anyArgChar "CHAR" "A character." -- -- >>> runParserIO p ["a"] -- 'a' ---- --
-- >>> runParserIO p ["-"] -- '-' ---- --
-- >>> runParserIO p ["abc"] -- <interactive>: command line error at "abc": expected one character, got 3 ---- --
-- >>> runParserIO p ["--"] -- <interactive>: command line error at "--": expected one character, got 2 --anyArgChar :: String -> String -> Parser Char -- | Like anyArgChar but doesn't generate help. anyArgChar' :: String -> Parser Char -- | A multi-parameter is an option that takes an arbitrary number -- of arguments, e.g. --person NAME AGE. multiParam lets -- you parse such options by providing the option form (in this case -- --person), and a special Follower object that reads -- zero or more arguments that follow (in this case NAME and -- AGE) using next. -- --
-- data Person = Person
-- { name :: String
-- , age :: Int
-- }
-- deriving Show
--
-- personP :: Parser Person
-- personP = multiParam
-- ["-p", "--person"]
-- (Person <$> next "NAME" <*> nextRead "AGE")
-- "A person's name and age."
--
--
--
-- >>> runParserIO personP ["--person", "John", "20"]
-- Person {name = "John", age = 20}
--
--
-- -- >>> runParserIO personP ["--person"] -- <interactive>: missing command line argument after "--person": NAME ---- --
-- >>> runParserIO personP ["--person", "John"] -- <interactive>: missing command line argument after "--person" "John": AGE --multiParam :: [OptionForm] -> Follower a -> String -> Parser a -- | Like multiParam but doesn't generate help. multiParam' :: [OptionForm] -> Follower a -> Parser a -- | A Follower consumes a (prefix of a) stream of command line -- arguments and produces a value of type a. Unlike a -- Parser, a Follower cannot decide to skip an argument -- based on its value. Once the Follower has read an argument, the -- argument is consumed, and the Follower can decide to either -- stop and produce a result (an a), or to read another -- argument. -- -- You work with followers in the following way: -- --
-- >>> let p = multiParam ["-n"] (nextRead "NUM" :: Follower Int) "An integer." -- -- >>> runParserIO p ["-n", "42"] -- 42 ---- --
-- >>> runParserIO p ["-n", "42.0"] -- <interactive>: command line error at "42.0": Prelude.read: no parse --nextRead :: Read a => String -> Follower a -- | Like next but parses the argument down to a Char. Fails -- if the argument has length other than 1. -- --
-- >>> let p = multiParam ["--pair"] ((,) <$> nextChar "CHAR" <*> nextChar "CHAR") "Two characters."
--
-- >>> runParserIO p ["--pair", "a", "b"]
-- ('a','b')
--
--
-- -- >>> runParserIO p ["--pair", "ab"] -- <interactive>: command line error at "ab": expected one character, got 2 --nextChar :: String -> Follower Char -- | Returns the metavariable corresponding to the next argument that the -- Follower wants to consume. Nothing if the follower -- doesn't want any more input. The following identities hold: -- --
-- nextMetavar (next x) = Just x -- nextMetavar (pure a) = Nothing --nextMetavar :: Follower a -> Maybe String -- | Adds a --help flag to an existing parser. If the user passes -- --help, and the existing parser doesn't consume it, the -- returned wrapper parser will return a Left containing a -- Help object that can be formatted and shown to the user. -- --
-- >>> let p = withHelp $ param ["--foo"] "FOO" "Some parameter." -- -- >>> runParserIO p ["--foo=bar"] -- Right "bar" ---- --
-- >>> runParserIO p ["--help"] -- Left (Help ...) ---- --
-- >>> Left help <- runParserIO p ["--help"] -- -- >>> putStrLn $ formatHelp help -- --foo=FOO Some parameter. -- --help Show this help message and exit. --withHelp :: Parser a -> Parser (Either Help a) -- | Like withHelp but doesn't generate help about the -- --help flag itself. You can use this to replace the built-in -- "Show this help message and exit" with your own. -- --
-- >>> let p = param ["--foo"] "FOO" "Some parameter." -- -- >>> let p' = withHelp' . flagHelp ["--help"] "Foo bar baz." $ p ---- --
-- >>> Left help <- runParserIO p' ["--help"] -- -- >>> putStrLn $ formatHelp help -- --foo=FOO Some parameter. -- --help Foo bar baz. --withHelp' :: Parser a -> Parser (Either Help a) -- | Like withHelp but empties the help of the resulting -- Parser. Shorthand for: -- --
-- withSubHelp = clearHelp . withHelp ---- -- This can be useful if you want to generate help for subcommands and -- don't want subcommand options to show up in the main help. -- --
-- import Control.Applicative hiding (optional) -- import Options.OptStream -- -- data Command -- = Send String String -- -- ^ Send email to given recipient with given content. -- | Fetch (Maybe Int) -- -- ^ Fetch emails, with optional count limit. -- deriving Show -- -- commandP :: Parser (Either Help Command) -- commandP = join <$> ( withHelp -- $ header "Usage: email (send | fetch) [options]" -- -- $ match "send" *> ( withSubHelp -- $ header "Usage: email send --to=EMAIL BODY" -- $ footer "Example: email send --to=foo@bar.com \'Hello, world!\'" -- $ Send -- <$> param ["--to"] "EMAIL" "Recipient." -- <#> freeArg "BODY" "Email body." -- ) -- -- <|> match "fetch" *> ( withSubHelp -- $ header "Usage: email fetch [--limit=N]" -- $ footer "Example: email fetch --limit=10" -- $ Fetch -- <$> optional (paramRead ["--limit"] "N" "Limit email count.") -- ) -- ) ---- --
-- >>> runParserIO commandP ["send", "--to=foo@bar.com", "Hello, world!"] -- Right (Send "foo@bar.com" "Hello, world!") ---- --
-- >>> runParserIO commandP ["fetch", "--limit=42"] -- Right (Fetch (Just 42)) ---- --
-- >>> Left help <- runParserIO commandP ["--help"] -- -- >>> putStrLn . formatHelp $ help -- Usage: email (send | fetch) [options] -- -- --help Show this help message and exit. ---- --
-- >>> Left help <- runParserIO commandP ["send", "--help"] -- -- >>> putStrLn . formatHelp $ help -- Usage: email send --to=EMAIL BODY -- -- --to=EMAIL Recipient. -- BODY Email body. -- --help Show this help message and exit. -- -- Example: email send --to=foo@bar.com 'Hello, world!' ---- --
-- >>> Left help <- runParserIO commandP ["fetch", "--help"] -- -- >>> putStrLn . formatHelp $ help -- Usage: email fetch [--limit=N] -- -- --limit=N Limit email count. -- --help Show this help message and exit. -- -- Example: email fetch --limit=10 --withSubHelp :: Parser a -> Parser (Either Help a) -- | Like withSubHelp but doesn't generate help about the -- --help flag itself. withSubHelp' :: Parser a -> Parser (Either Help a) -- | Adds a --version flag to an existing parser. If -- --version is on the command line, and is not consumed by the -- existing parser, the returned wrapper parser will consume the flag and -- return a Left with the given version information. -- --
-- >>> let p = withVersion "Baz v0.1" $ param ["--foo"] "FOO" "Some parameter." -- -- >>> runParserIO p ["--foo=bar"] -- Right "bar" ---- --
-- >>> runParserIO p ["--version"] -- Left "Baz v0.1" --withVersion :: String -> Parser a -> Parser (Either String a) -- | Like withVersion but doesn't generate help about the -- --version flag. withVersion' :: String -> Parser a -> Parser (Either String a) -- | Makes an existing Parser stop at --. If there is a -- -- on the command line and the existing parser doesn't -- consume it, the wrapper parser will consume the -- and stop. -- -- You can use this to treat options like --foo as positional -- arguments. Just wrap all your option parsers in one single -- beforeDashes and parse the rest with e.g. anyArg. -- --
-- -- echo.hs -- -- import Control.Applicative hiding (many) -- import Options.OptStream -- ... -- -- transformP :: Parser (Char -> Char) -- transformP -- = flag' ["-u", "--uppercase"] $> toUpper -- <|> flag' ["-l", "--lowercase"] $> toLower -- <|> orElse id -- -- main :: IO () -- main = do -- (transform, args) <- parseArgs $ (,) -- <$> beforeDashes transformP -- <#> many (anyArg' "WORD") -- -- putStrLn . map transform . concat . intersperse " " $ args ---- -- This echo tool will copy all of its arguments verbatim to -- stdout, with two exceptions: the first occurrence of flags -- -u, -uppercase, -l, and -lowercase -- will make it convert the output to uppercase/lowercase. -- -- If you want to echo "--uppercase" verbatim, you can use -- -- for that. Note that in this example we use -- <#> to combine the beforeDashes wrapper with -- many arbitrary arguments, which makes it possible to pass -- arbitrary arguments on both sides of --. Whatever arguments -- are skipped by beforeDashes transformP will be consumed by -- many (anyArg' "WORD"). -- --
-- >>> ./echo Hello, world! -- Hello, world! ---- --
-- >>> ./echo --uppercase Hello, world! -- HELLO, WORLD! ---- --
-- >>> ./echo -- --uppercase Hello, world! -- --uppercase Hello, world! ---- --
-- >>> ./echo foo -- bar -- foo bar ---- --
-- >>> ./echo foo -- bar -- baz -- foo bar -- baz ---- --
-- >>> ./echo --fake-option -- -- --fake-option ---- --
-- >>> ./echo -- --fake-option -- --fake-option ---- --
-- -- dashes.hs
--
-- import Control.Applicative hiding (many)
-- import Options.OptStream
-- ...
--
-- -- Options that can show up to the left of '--'.
-- data Options = Options
-- { bool :: Bool
-- , int :: Int
-- , freeArgs :: [String]
-- }
--
-- optionsP :: Parser Options
-- optionsP = Options
-- <$> (flag ["-b", "--bool"] "Boolean flag." $> True <|> orElse False)
-- <#> (paramRead ["-i", "--int"] "INT" "Integer parameter." <|> orElse 0)
-- <#> many (freeArg "LEFT" "Free arguments to the left of --.")
--
-- run :: Options -> [String] -> IO ()
-- run opts args = do
-- putStrLn $ "bool : " ++ show (bool opts)
-- putStrLn $ "int : " ++ show (int opts)
-- putStrLn $ "left of -- : " ++ show (freeArgs opts)
-- putStrLn $ "right of --: " ++ show args
--
-- main = join . parseArgsWithHelp
-- $ header "Usage: dashes [options] LEFT... [-- RIGHT...]"
-- $ sortTable
-- $ run
-- <$> beforeDashes optionsP
-- <*> many (anyArg "RIGHT" "Arguments to the right of --.")
--
--
-- -- >>> ./dashes foo -b bar -i 42 baz -- qux -- bool : True -- int : 42 -- left of -- : ["foo","bar","baz"] -- right of --: ["qux"] ---- --
-- >>> ./dashes -- foo -b bar -i 42 baz qux -- bool : False -- int : 0 -- left of -- : [] -- right of --: ["foo","-b","bar","-i","42","baz","qux"] ---- -- Note that we used the standard applicative <*> to combine -- beforeDashes with many. This way many only starts -- getting input when beforeDashes is done, i.e. after -- --. The command line is cleanly separated into two parts. To -- the left of -- we have freeArg that will consume -- free arguments, but will not accept arguments that start with -- -. To the right of -- we have anyArg that -- will accept anything. -- --
-- >>> ./dashes --fake-option -- dashes: unexpected command line argument "--fake-option" -- Try "dashes --help" for more information. ---- --
-- >>> ./dashes -- --fake-option -- bool : False -- int : 0 -- left of -- : [] -- right of --: ["--fake-option"] ---- --
-- >>> ./dashes --help -- Usage: dashes [options] LEFT... [-- RIGHT...] -- -- LEFT Free arguments to the left of --. -- RIGHT Arguments to the right of --. -- -b, --bool Boolean flag. -- -i, --int=INT Integer parameter. -- --help Show this help message and exit. ---- --
-- >>> ./dashes -- --help -- bool : False -- int : 0 -- left of -- : [] -- right of --: ["--help"] --beforeDashes :: Parser a -> Parser a -- | Adds help to an IO-style Parser. It theere is --help -- on the command line and the existing Parser doesn't consume it, -- then the created wrapper will return an IO action that prints -- the help and exits the program. Otherwise the existing parser will -- produce an IO action to run the program as usual. -- -- If you are using parseArgsWithHelp, that will already take care -- of all the above. However, sometimes you may still want to use -- withHelpIO or withSubHelpIO to deal with subcommands, or -- in other special cases. withHelpIO :: IOOps m => Parser (m a) -> Parser (m a) -- | Like withHelpIO but doesn't generate help about the added -- --help flag itself. You can use this e.g. if you don't like -- the standard "Show this help message and exit" text. -- --
-- hello :: String -> IO () -- hello name = putStrLn $ "Hello, " ++ name ++ "!" -- -- main :: IO () -- main = join . parseArgs -- $ withHelpIO' -- $ flagHelp ["--help"] "Print this special help message!" -- $ header "Usage: hello [NAME]" -- $ hello <$> (freeArg' "NAME" <|> orElse "James Bond") ---- --
-- >>> ./hello -- Hello, James Bond! ---- --
-- >>> ./hello --help -- Usage: hello [NAME] -- -- --help Print this special help message! --withHelpIO' :: IOOps m => Parser (m a) -> Parser (m a) -- | Like withHelpIO but empties the help of the returned wrapper -- Parser. Equivalent to -- --
-- clearHelp . withHelpIO ---- -- This can be useful if you want to generate help for subcommands and -- don't want subcommand options to show up in the main help. -- --
-- import Control.Applicative hiding (optional) -- import Options.OptStream -- -- send :: String -> String -> IO () -- send src dst = putStrLn $ "Would send " ++ show dst ++ " to " ++ src ++ "." -- -- fetch :: Maybe Int -> IO () -- fetch Nothing = putStrLn $ "Would fetch all emails." -- fetch (Just n) = putStrLn $ "Would fetch at most " ++ show n ++ " emails." -- -- main :: IO () -- main = join . parseArgsWithHelp -- $ header "Usage: email (send | fetch) [options]" -- -- $ match "send" *> ( withSubHelpIO -- $ header "Usage: email send --to=EMAIL BODY" -- $ footer "Example: email send --to=foo@bar.com \'Hello, world!\'" -- $ send -- <$> param ["--to"] "EMAIL" "Recipient." -- <#> freeArg "BODY" "Email body." -- ) -- -- <|> match "fetch" *> ( withSubHelpIO -- $ header "Usage: email fetch [--limit=N]" -- $ footer "Example: email fetch --limit=10" -- $ fetch -- <$> optional (paramRead ["--limit"] "N" "Limit email count.") -- ) ---- --
-- >>> ./email send --to=foo@bar.com 'Hello, world!' -- Would send "Hello, world!" to foo@bar.com. ---- --
-- >>> ./email fetch -- Would fetch all emails. ---- --
-- >>> ./email --help -- Usage: email (send | fetch) [options] -- -- --help Show this help message and exit. ---- --
-- >>> ./email send --help -- Usage: email send --to=EMAIL BODY -- -- --to=EMAIL Recipient. -- BODY Email body. -- --help Show this help message and exit. -- -- Example: email send --to=foo@bar.com 'Hello, world!' ---- --
-- >>> ./email fetch --help -- Usage: email fetch [--limit=N] -- -- --limit=N Limit email count. -- --help Show this help message and exit. -- -- Example: email fetch --limit=10 --withSubHelpIO :: IOOps m => Parser (m a) -> Parser (m a) -- | Like withSubHelpIO but doesn't generate help about the added -- --help flag itself. Equivalent to: -- --
-- clearHelp . withHelpIO' --withSubHelpIO' :: IOOps m => Parser (m a) -> Parser (m a) -- | Adds a --version flag to an existing IO-style Parser. -- If the user passes --version on the command line and the -- existing parser doesn't consume this flag, the wrapper will consume it -- and return an IO action that prints version information and -- exits. Otherwise the wrapper will let the existing parser finish the -- parse normally. -- --
-- hello :: String -> IO () -- hello name = putStrLn $ "Hello, " ++ name ++ "!" -- -- main :: IO () -- main = join . parseArgsWithHelp -- $ withVersionIO "Hello, version 1.0" -- $ header "Usage: hello [NAME]" -- $ footer "Example: hello \'Sherlock Holmes\'" -- $ hello -- <$> (freeArg "NAME" "Your name (optional)." <|> orElse "James Bond") ---- --
-- >>> ./hello -- Hello, James Bond! ---- --
-- >>> ./hello --version -- Hello, version 1.0 ---- --
-- >>> ./hello --help -- Usage: hello [NAME] -- -- NAME Your name (optional). -- --version Show version information and exit. -- --help Show this help message and exit. -- -- Example: hello 'Sherlock Holmes' --withVersionIO :: IOOps m => String -> Parser (m a) -> Parser (m a) -- | Like withVersionIO but doesn't generate help about the -- --version flag. withVersionIO' :: IOOps m => String -> Parser (m a) -> Parser (m a) -- | The most general atomic parser. All the other atomic parsers in this -- library are built on top of block (and sometimes short). -- -- block accepts a function that, given a command line argument, -- decides what to do with it. If the function returns Nothing, -- the parser will skip the argument. If this happens, the parser -- remains in its original state, as if the argument was never seen. The -- argument can then be consumed by another Parser running in -- parallel with this one (via e.g. <#> or -- <|>). -- -- Alternatively, the function can return a Just value with a -- Follower. In this case the Parser is considered to have -- consumed the argument. After that the Follower seizes -- control and has the option to consume more arguments immediately after -- the current one. Finally, when the Follower releases the stream -- and produces a value of type a, that value becomes the result -- of the parser. block :: String -> (String -> Maybe (Follower a)) -> Parser a -- | General atomic parser for short flags with bundling. -- -- short accepts a function that, given a Char representing -- a short flag, decides what to do with it. The options are: skip -- the flag (by returning Nothing), or consume the flag and -- return a value of type a (by returning Just -- a). -- --
-- letter :: Parser Char -- letter = short "LETTER" $ \c -> guard (isLetter c) $> c -- -- digit :: Parser Char -- digit = short "DIGIT" $ \c -> guard (isDigit c) $> c ---- --
-- >>> let p = (,) <$> many letter <#> many digit
--
-- >>> runParserIO p ["-a", "-1", "-b2c3"]
-- ("abc","123")
--
short :: String -> (Char -> Maybe a) -> Parser a
-- | Consumes and returns the exact given string. Skips any other argument.
match :: String -> Parser String
-- | Consumes a block of command line arguments starting with the exact
-- given string. Once the string is consumed, the rest of the block is
-- consumed by the given Follower.
matchAndFollow :: String -> Follower a -> Parser a
-- | Consumes and returns the exact given short flag, skips everything
-- else.
--
-- This Parser supports bundling. If you don't want it, use
-- match.
--
-- -- >>> runParserIO (many $ matchShort 'x') ["-x"] -- "x" ---- --
-- >>> runParserIO (many $ matchShort 'x') ["-x", "-x"] -- "xx" ---- --
-- >>> runParserIO (many $ matchShort 'x') ["-xx"] -- "xx" --matchShort :: Char -> Parser Char -- | Suppresses "missing argument" suggestions from the Parser. This -- is used in the implementation of withHelp and -- withVersion, so that --help and --version, -- which are always valid arguments, don't show up in error messages. -- -- Note that quiet only works until the parser consumes some -- input. Once the parser has consumed an argument, it is in a new state -- and no longer quiet. -- --
-- >>> let p = flag' ["-a"] <|> quiet (flag' ["-b"]) <|> flag' ["-c"] -- -- >>> runParserIO p [] -- <interactive>: missing command line argument: -a | -c --quiet :: Parser a -> Parser a -- | Helper: run a Parser with an option to "eject". -- -- Parser a runs normally, but parser b gets to look at -- every argument that parser a has skipped (even after parser -- a has finished). If EOF is reached and parser b -- never consumes anything, then a's result is returned normally -- as a Right value. However, if parser b consumes an -- argument, parser a is killed ("ejected" from), all its state -- discarded. Parser b then runs until the end and its result is -- returned in a Left value. Any arguments left unread after -- b has finished are also discarded. -- -- This is used in the implementation of withHelp and -- withVersion. You can use it to make similar-behaving flags. eject :: Parser a -> Parser b -> Parser (Either b a) -- | Convenience helper. Adds a paragraph to the help header. The paragraph -- is added to the beginning of the existing header, if any. header :: String -> Parser a -> Parser a -- | Convenience helper. Adds a paragraph to the help footer. The paragraph -- is added to the beginning of the existing footer, if any. footer :: String -> Parser a -> Parser a -- | Convenience helper. Adds a row to the help table describing one flag -- in the same way as flag does. The row is added to the beginning -- of the existing table, if any. -- -- You may pass any number of flag forms (except zero). However, only the -- first form of each kind (short and long) will appear in the help -- table. flagHelp :: [OptionForm] -> String -> Parser a -> Parser a -- | Convenience helper. Adds a row to the help table describing one -- parameter in the same way as param does. The row is added to -- the beginning of the existing table, if any. -- -- You may pass any number of parameter forms (except zero). However, -- only the first form of each kind (short and long) will appear in the -- help table. paramHelp :: [OptionForm] -> String -> String -> Parser a -> Parser a -- | Convenience helper. Adds a row to the help table describing one free -- argument in the same way as freeArg does. The row is added to -- the beginning of the existing table, if any. freeArgHelp :: String -> String -> Parser a -> Parser a -- | Convenience helper. Adds a row to the help table describing one -- multi-parameter in the same way as multiParam does. The row is -- added to the beginning of the existing table, if any. -- -- You may pass any number of parameter forms (except zero). However, -- only the first form of each kind (short and long) will appear in the -- help table. multiParamHelp :: [OptionForm] -> String -> String -> Parser a -> Parser a -- | Empties the Help stored in a given Parser. Shorthand -- for: -- --
-- clearHelp = setHelp mempty --clearHelp :: Parser a -> Parser a -- | Empties the header portion of the Help object stored in a given -- Parser. clearHeader :: Parser a -> Parser a -- | Empties the footer portion of the Help object stored in a given -- Parser. clearFooter :: Parser a -> Parser a -- | Empties the options table in the Help object stored in a given -- Parser. clearTable :: Parser a -> Parser a -- | Sorts the options table in the Help object stored in a given -- Parser. The table is sorted so that free arguments go first and -- options follow after them. sortTable :: Parser a -> Parser a -- | Retrieves the Help object stored in a given Parser. getHelp :: Parser a -> Help -- | Replaces the Help object stored in a Parser with another -- one. setHelp :: Help -> Parser a -> Parser a -- | Modifies the Help object stored in a Parser using a -- given function. modifyHelp :: (Help -> Help) -> Parser a -> Parser a -- | Retrieves the help string stored in a Follower. This string is -- used in the help generated by multiParam. getFollowerHelp :: Follower a -> String -- | Changes the help string stored in a Follower. setFollowerHelp :: String -> Follower a -> Follower a -- | Modifies the help string stored in a Follower using a given -- function. modifyFollowerHelp :: (String -> String) -> Follower a -> Follower a -- | Retrieves the actual RawParser object backing the given -- Parser. toRaw :: Parser a -> RawParser a -- | Converts a RawParser into a Parser. The Parser -- has the exact same parsing behavior as the RawParser, and an -- empty Help attached to it. You can attach your own Help -- to the Parser using setHelp or a number of other helper -- functions, e.g. header and footer. fromRaw :: RawParser a -> Parser a -- | Retrieves the actual RawFollower object backing the given -- Follower. toRawFollower :: Follower a -> RawFollower a -- | Converts a RawFollower into a Follower. The -- Follower will have exactly the same behavior as the -- RawFollower, and it will get a default help string (either -- "" or "..." depending on whether the follower wants -- any input). You can replace the default help string with your own -- using setFollowerHelp. fromRawFollower :: RawFollower a -> Follower a -- | An error returned by runParser. There are three kinds of -- errors: -- --