在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):pcapriotti/optparse-applicative开源软件地址(OpenSource Url):https://github.com/pcapriotti/optparse-applicative开源编程语言(OpenSource Language):Haskell 100.0%开源软件介绍(OpenSource Introduction):optparse-applicativeoptparse-applicative is a haskell library for parsing options on the command line, and providing a powerful applicative interface for composing them. optparse-applicative takes care of reading and validating the arguments passed to the command line, handling and reporting errors, generating a usage line, a comprehensive help screen, and enabling context-sensitive bash, zsh, and fish completions. Table of Contents
IntroductionThe core type in optparse-applicative is a data Parser a
instance Functor Parser
instance Applicative Parser
instance Alternative Parser A value of type If you are familiar with parser combinator libraries like parsec, attoparsec, or the json parser aeson you will feel right at home with optparse-applicative. If not, don't worry! All you really need to learn are a few basic
parsers, and how to compose them as instances of Quick StartHere's a simple example of a parser. import Options.Applicative
data Sample = Sample
{ hello :: String
, quiet :: Bool
, enthusiasm :: Int }
sample :: Parser Sample
sample = Sample
<$> strOption
( long "hello"
<> metavar "TARGET"
<> help "Target for the greeting" )
<*> switch
( long "quiet"
<> short 'q'
<> help "Whether to be quiet" )
<*> option auto
( long "enthusiasm"
<> help "How enthusiastically to greet"
<> showDefault
<> value 1
<> metavar "INT" ) The parser is built using an applicative style starting from a
set of basic combinators. In this example, hello is defined as an
option with a The parser can be used like this: main :: IO ()
main = greet =<< execParser opts
where
opts = info (sample <**> helper)
( fullDesc
<> progDesc "Print a greeting for TARGET"
<> header "hello - a test for optparse-applicative" )
greet :: Sample -> IO ()
greet (Sample h False n) = putStrLn $ "Hello, " ++ h ++ replicate n '!'
greet _ = return () The The
Running the program with the
BasicsParsersoptparse-applicative provides a number of primitive parsers, corresponding to different posix style options, through its Builder interface. These are detailed in their own section below, for now, here's a look at a few more examples to get a feel for how parsers can be defined. Here is a parser for a mandatory option with an argument: target :: Parser String
target = strOption
( long "hello"
<> metavar "TARGET"
<> help "Target for the greeting" ) One can see that we are defining an option parser for a
on the command line. The metavariable and the help text will appear in the generated help text, but don't otherwise affect the behaviour of the parser. The attributes passed to the option are called modifiers, and are
composed using the semigroup operation Options with an argument such as quiet :: Parser Bool
quiet = switch ( long "quiet" <> short 'q' <> help "Whether to be quiet" ) Here we used a Flags, unlike regular options, have no arguments. They simply return
a predetermined value. For the simple switch above, this is There are other kinds of basic parsers, and several ways to configure them. These are covered in the Builders section. ApplicativeNow we may combine the data Options = Options
{ optTarget :: String
, optQuiet :: Bool } and now it's just a matter of using opts :: Parser Options
opts = Options <$> target <*> quiet No matter which parsers appear first in the sequence, options will still be parsed in whatever order they appear in the command line. A parser with such a property is sometimes called a permutation parser. In our example, a command line like:
will give the same result as
It is this property which leads us to an Applicative interface instead of a Monadic one, as all options must be considered in parallel, and can not depend on the output of other options. Note, however, that the order of sequencing is still somewhat significant, in that it affects the generated help text. Customisation can be achieved easily through a lambda abstraction, with Arrow notation, or by taking advantage of GHC 8's ApplicativeDo extension. AlternativeIt is also common to find programs that can be configured in different ways through the command line. A typical example is a program that can be given a text file as input, or alternatively read it directly from the standard input. We can model this easily and effectively in Haskell using sum types: data Input
= FileInput FilePath
| StdInput
run :: Input -> IO ()
run = ... We can now define two basic parsers for the components of the sum type: fileInput :: Parser Input
fileInput = FileInput <$> strOption
( long "file"
<> short 'f'
<> metavar "FILENAME"
<> help "Input file" )
stdInput :: Parser Input
stdInput = flag' StdInput
( long "stdin"
<> help "Read from stdin" ) As the input :: Parser Input
input = fileInput <|> stdInput Now
will be rejected. Having Running parsersBefore we can run a The function opts :: ParserInfo Sample
opts = info (sample <**> helper)
( fullDesc
<> progDesc "Print a greeting for TARGET"
<> header "hello - a test for optparse-applicative" ) The main :: IO ()
main = do
options <- execParser opts
... The There are other ways to run a BuildersBuilders allow you to define parsers using a convenient combinator-based
syntax. We have already seen examples of builders in action, like
Builders always take a modifier argument, which is essentially a composition of functions acting on the option, setting values for properties or adding features. Builders work by building the option from scratch, and eventually
lifting it to a single-option parser, ready to be combined with
other parsers using normal See the haddock documentation for There are four different kinds of options in Regular optionsA regular option is an option which takes a single argument, parses it, and returns a value. A regular option can have a default value, which is used as the result if the option is not found in the command line. An option without a default value is considered mandatory, and produces an error when not found. Regular options can have long names, or short (one-character) names, which determine when the option matches and how the argument is extracted. An option with a long name (say "output") is specified on the command line as
or
while a short name option (say "o") can be specified with
or
Options can have more than one name, usually one long and one short, although you are free to create options with an arbitrary combination of long and short names. Regular options returning strings are the most common, and they can
be created using the strOption
( long "output"
<> short 'o'
<> metavar "FILE"
<> value "out.txt"
<> help "Write output to FILE" ) creates a regular option with a string argument (which can be
referred to as A regular lineCount :: Parser Int
lineCount = option auto
( long "lines"
<> short 'n'
<> metavar "K"
<> help "Output the last K lines" ) specifies a regular option with an Further information on readers is available below. FlagsA flag is just like a regular option, but it doesn't take any arguments, it is either present in the command line or not. A flag has a default value and an active value. If the flag is found on the command line, the active value is returned, otherwise the default value is used. For example: data Verbosity = Normal | Verbose
flag Normal Verbose
( long "verbose"
<> short 'v'
<> help "Enable verbose mode" ) is a flag parser returning a Simple boolean flags can be specified using the switch
( long "keep-tmp-files"
<> help "Retain all intermediate temporary files" ) There is also a Another interesting use for the length <$> many (flag' () (short 'v')) Flags can be used together after a single hyphen, so ArgumentsAn argument parser specifies a positional command line argument. The argument str (metavar "FILE") creates an argument accepting any string. To accept an arbitrary
number of arguments, combine the some (argument str (metavar "FILES...")) Note that arguments starting with However, parsers always accept a special argument: Arguments use the same readers as regular options. CommandsA command can be used to specify a sub-parser to be used when a certain string is encountered in the command line. Commands are useful to implement command line programs with multiple
functions, each with its own set of options, and possibly some
global options that apply to all of them. Typical examples are
version control systems like Note that all the parsers appearing in a command need to have the same type. For this reason, it is often best to use a sum type which has the same structure as the command itself. For example, for the parser above, you would define a type like: data Options = Options
{ optCommand :: Command
, ... }
data Command
= Add AddOptions
| Commit CommitOptions
... A command can then be created using the subparser
( command "add" (info addCommand ( progDesc "Add a file to the repository" ))
<> command "commit" (info commitCommand ( progDesc "Record changes to the repository" ))
) Each command takes a full Alternatively, you can directly return an start :: String -> IO ()
stop :: IO ()
opts :: Parser (IO ())
opts = subparser
( command "start" (info (start <$> argument str idm) idm)
<> command "stop" (info (pure stop) idm) )
main :: IO ()
main = join $ execParser (info opts idm) ModifiersModifiers are instances of the For example, command :: String -> ParserInfo a -> Mod CommandFields a can only be used with commands, as the Many modifiers are polymorphic in this type argument, which means that they can be used with any builder. Custom parsing and error handlingParser runnersParsers are run with the execParser :: ParserInfo a -> IO a
customExecParser :: ParserPrefs -> ParserInfo a -> IO a
execParserPure :: ParserPrefs -> ParserInfo a -> [String] -> ParserResult a When using the handleParseResult :: ParserResult a -> IO a
overFailure :: (ParserHelp -> ParserHelp) -> ParserResult a -> ParserResult a can be used to correctly set exit codes and display the help message; and modify the help message in the event of a failure (adding additional information for example). Option readersOptions and Arguments require a way to interpret the string passed
on the command line to the type desired. The We provide the data FluxCapacitor = ...
parseFluxCapacitor :: ReadM FluxCapacitor
parseFluxCapacitor = eitherReader $ \s -> ...
option parseFluxCapacitor ( long "flux-capacitor" ) One can also use One nice property of import qualified Data.Attoparsec.Text as A
attoReadM :: A.Parser a -> ReadM a
attoReadM p = eitherReader (A.parseOnly p . T.pack) Preferences
To use these modifications, provide them to the DisambiguationIt is possible to configure optparse-applicative to perform automatic
disambiguation of prefixes of long options. For example, given a
program
fails, whereas typing
succeeds, and correctly identifies Option disambiguation is off by default. To enable it, use the
Here is a minimal example: import Options.Applicative
sample :: Parser ()
sample = () <$
switch (long "filename") <*
switch (long "filler")
main :: IO ()
main = customExecParser p opts
where
opts = info (helper <*> sample) idm
p = |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论