pcapriotti / optparse-applicative Goto Github PK
View Code? Open in Web Editor NEWApplicative option parser
License: BSD 3-Clause "New" or "Revised" License
Applicative option parser
License: BSD 3-Clause "New" or "Revised" License
I'm writing a program that takes multiple arguments and performs an operation on each. Unfortunately, the arguments
parser succeeds even when I supply no arguments, even though it doesn't make sense for my application.
Is there a way to force arguments
to parse at least one argument?
Henning Thielemann observes that the README doesn't make it clear that the Arrow
interface is completely optional, and it's actually possible to write any sort of parser using just the Applicative
(and Alternative
) instance.
Hi, is there any chance that the requirement on process == 1.1.*
can be relaxed? This restrictions means that optparse-applicative can effectively not be used with GHC 7.0.4, because process 1.0.1.5 is a base library of that compiler. This means that no other program that depends on optparse-applicative can be copmiled with GHC 7.0.4 either.
In version 0.6 in order argument parsing was introduced and my code stopped working and I do not know if it is fixable now. There are 2 main problems:
INPUT
and has got flag -v
and we want the user to be able to use it before OR after the INPUT, how can we do it now?many1 p = (:) <$> p <*> many p
and use it like:[...]
<$> many1 ( argument str ( metavar "INPUTS" ))
<*> switch ( long "version" <> short 'V' )
[...]
Than the option --version
is unreachable - even if we provide the input parameter, parser does not parse --version
after it (probably waiting for next inputs args)
optparse-applicative-0.5.2.1
:
% ./program --my-option=asdf
program: Cannot parse value
optparse-applicative-0.6.0
:
% ./program --my-option=asdf
Usage: program [--my-option ARG]
Something eats the error message.
I have a subcommand parser that looks like
data CLICommands = Featurize FeatureConfig
| TrainModel TrainingConfig
-- | EvaluatePredictions PredictionConfig
data FeatureConfig = FeatureConfig {yesEventsName :: Maybe String
,noEventsName :: Maybe String
,yesWeightFt :: Double
,noWeightFt :: Double
,featureMapFileName :: Maybe String
,bitWidth :: Int }
featureParser = Featurize<$> (FeatureConfig <$>
(optional . strOption) (long "yesEvents" <> metavar "FILE"
<> help "input json array of positive events") <*>
(optional . strOption) (long "noEvents" <> metavar "FILE"
<> help "input json array of positive events") <*>
option (long "yesWeight" <> value 1.0 <> metavar "positiveFloat"
<> help "training weight for yes examples. Defaults to 1.0" ) <*>
option (long "noWeight" <> value 1.0 <> metavar "positiveFloat"
<> help "training weight for no examples. Defaults to 1.0" ) <*>
(optional . strOption) (long "featureMap" <> metavar "FILE"
<> help "map between features and hashes, needed to interpret models directly") <*>
option (long "hashWidth" <> value 18 <> metavar "Int" <> help "how many bits of feature hash to keep") )
data TrainingConfig = TrainingConfig {humanModelVW :: String
,featureHashFile :: String
,vwExtraOptions :: [String]
}
trainingParser = TrainModel<$> (TrainingConfig <$>
(strOption) (long "readable_model" <> metavar "FILE" <>
help "save a human readable vowpal model file") <*>
strOption (long "featureHashFile" <> metavar "FILE"
<> help "mapping from hashe numbers to feature names") <*>
arguments Just (metavar "options" <> help "options to pass to VW" ) )
betterCLI :: Parser CLICommands
betterCLI = subparser $ (command "featurize" (info featureParser (progDesc "Generate vowpal feature training file")) )
<> (command "train" (info trainingParser (progDesc "Train vowpal model and export ")))
when i call the app with help flags, it behaves correctly on "featurize" subcommand, but not on "train"
carter raven-ad-code/vw-setup ‹master*› » ./dist/build/pw/pw featurize --help 1 ↵
Usage: pw featurize [--yesEvents FILE] [--noEvents FILE] [--yesWeight positiveFloat] [--noWeight positiveFloat] [--featureMap FILE] [--hashWidth Int]
Generate vowpal feature training file
Available options:
--yesEvents FILE input json array of positive events
--noEvents FILE input json array of positive events
--yesWeight positiveFloat training weight for yes examples. Defaults to 1.0
--noWeight positiveFloat training weight for no examples. Defaults to 1.0
--featureMap FILE map between features and hashes, needed to interpret models directly
--hashWidth Int how many bits of feature hash to keep
carter raven-ad-code/vw-setup ‹master*› » ./dist/build/pw/pw train --help 1 ↵
Invalid option `--help'
Usage: pw train --readable_model FILE --featureHashFile FILE [options]
If an option has a default value, provide some way to have it shown in help pages. This can be undesirably noisy, so should probably be optional.
Related to snoyberg/stackage#2.
When I try to build the test suites from Hackage, I get:
tests/Tests.hs:7:18:
Could not find module `Examples.Alternatives'
Use -v to see a list of the files searched for.
It seems like the Github version of this library is already past version 0.4, so I wasn't sure how to send a pull request most effectively. Would it be possible to release a new version in the 0.4 series that adds the missing test files?
Thank you
Currently an invalid or missing argument will cause the library to simply display the usage message. It would be nice if we could tell the user specifically what he did wrong as well.
I don't need this critically, but thought I'd suggest it anyway. The "obvious" way to do it seems to me to be having messages be algebraic types, probably one user-provided and one library-provided. Something like how errors are handled in reform.
Previous versions of this package used to compile fine with older versions of GHC, but the recent update broke those builds: http://hydra.cryp.to/eval/2655.
Was that intentional?
value
and option
have type ... -> Mod f a
. Since they are polymorphic in f
you can apply these to switch
and some strange behaviour results:
% cat test.hs && ghc test.hs
import Options.Applicative
import Data.Monoid (mempty)
main :: IO ()
main = execParser (info a_switch mempty) >>= main'
main' :: Bool -> IO ()
main' a = putStrLn $ "a was set to " ++ show a
a_switch :: Parser Bool
a_switch = switch (short 'a'
<> metavar "NOSUCHARGUMENT"
<> value True)
[1 of 1] Compiling Main ( test.hs, test.o )
Linking test ...
% ./test -a an_argument
Usage: test [-a NOSUCHARGUMENT]
% ./test -a
a was set to True
% ./test
a was set to True
Supplying a metavar
to switch leads to misleading "Usage" output and allowing a default value
renders it useless. It would be better if a way were found to make it impossible to specify these on switch
.
I don't know how easy it'd be to implement this, but it'd be nice to be able to something like this:
data Opts = Opts
{ inputDb :: String
, optKeywords :: Maybe String -- Maybe here means this is optional
}
Then the parser:
options :: Parser Opts
options = Opts
<$> strOption (long "input-db"
& metavar "FILE"
& help "Input database file")
<*> strOption (long "keywords"
& help "Comma-delimited list of bug keywords")
If the type of the strOption being used is a Maybe, then it'd automatically mean that particular option is optional. Right now I think the only way to specify optional arguments is to provide them a default value with "value". It'd be much nicer to use Maybe directly.
Any chance something like this could work? Or would it be possible to add something like "strMaybeOption" that would mean optional arguments and would return Maybe String values..?
I'm sorry if this is a FAQ, I didn't see a link to a mailing list on the github page, so I filed a feature req instead. Feel free to close if there's a trivial way to do this already. If there is, perhaps it'd make sense to have that in the usage examples - I think this is a fairly common use-case.
I'd like the ability to have option parsing stop on the first non-flag argument encountered, to prevent having to always use "--" for a command that is a runner for other programs with their own arguments.
(like python's optparse, when `disable_interspersed_args() is called):
http://docs.python.org/library/optparse.html#optparse.OptionParser.disable_interspersed_args
I had a go at adding a strict
version of arguments and arguments1, but had trouble with the tests and wasn't sure how to best integrate it. Here's what I came up with which only supports non-interspersed mode, if that's useful:
arguments_ allow_empty p m = set_default <$> fromM args1
where
Mod f (DefaultProp def sdef) g = m
show_def = sdef <*> def
props = mkProps mempty g
props' = (mkProps mempty g) { propShowDefault = show_def }
args1 | allow_empty = args
| otherwise = do
mx <- oneM arg_or_ddash
case mx of
Nothing -> someM arg
Just x -> (x:) <$> manyM arg
args = do
mx <- oneM $ optional arg_or_ddash
case mx of
Nothing -> return []
Just Nothing -> manyM arg
Just (Just x) -> (x:) <$> manyM arg
arg_or_ddash = (ddash *> pure Nothing) <|> (p <$> nonOpt)
set_default [] = fromMaybe [] def
set_default xs = xs
arg = liftOpt (Option (ArgReader (CReader compl p)) props)
ddash :: Parser ()
ddash = argument' (guard . (== "--")) internal
nonOpt = argument' nonOpt' internal
nonOpt' ('-':_) = Nothing
nonOpt' a = Just a
ArgumentFields compl = f (ArgumentFields mempty)
caveat: this could be wrong, I don't fully understand the code yet ;). Seems to work in the cases I threw at it though.
It could be a better idea to have this flag be over the whole of argument parsing, rather than built into the arguments
parser. But I'm not even sure if that's possible with the current structure of parsers.
Can optparse-applicative parse CPP-style options, like
-DFOO
? Note that there's no space betwee -D
and the parameter, and the list of possible parameter values is not known in advance.
This code now produces a type error with the 0.2 release:
parseServe = Serve
<$> arguments (`lookup` services)
( metavar "dict|irc|state|web..."
. value [minBound..]
)
src/Kibr/CLI.hs:149:19:
Couldn't match expected type `Service' with actual type `[t0]'
In the first argument of `value', namely `[minBound .. ]'
In the second argument of `(.)', namely `value [minBound .. ]'
In the second argument of `arguments', namely
`(metavar "dict|irc|state|web..." . value [minBound .. ])'
Currently I'm mostly copy-pasting examples from README and adjusting them to my needs.
But I would like to understand what exactly I'm writing.
A lot of functions, for instance, return the Mod
type. But neither its meaning nor meaning of the type arguments are documented. I would find it very useful to have some semantic model for Mod.
With a program like this:
import Options.Applicative
parser = arguments Just idm
main = execParser (info parser fullDesc) >> return ()
I run it like this:
$ cat /usr/share/dict/words | xargs -d'\n' optparse --
optparse: out of memory (requested 1048576 bytes)
If I change the program to simply,
main = getArgs >>= print
It runs just fine.
I get the "Available commands" list with descriptions, but there's no prog cmd --help
listing flags for the specific command. If the command fails, I get the normal help page for the whole program, and if I try to add helper
to a command I get --help
for commands but that too only shows the normal help page.
So far all my subparsers only take positional arguments, don't know if that matters.
It would be very nice to be able to add a --help
option to all subcommands. This --help
option would print the usage information for that subcommand.
This kind of an issue of style, but I think it would be less confusing if you changed the documentation to use (<>)
instead of (&)
. That's one less combinator to learn, and it also makes it more obvious to users that options are monoids, so that they know they can use other monoid combinators like mconcat
to collect options.
You don't really need to remove the (&)
combinator if you are worried about backwards compatibility, although my understanding is that the libraries mailing list has been discussing appropriating (&)
for postfix function application.
I have this code:
arguments service (metavar "SERVICE" . value [minBound..])
The help for this renders as such:
Usage: kibr serve [SERVICE]
This format suggests that SERVICE is a scalar, optional positional argument. However, the conventional format for repeated arguments, looking at existing programs, seems to be for example:
ls [OPTION]... [FILE]...
Not sure if I have a bad version of something, but I get:
$ cabal install optparse-applicative
Resolving dependencies...
Downloading optparse-applicative-0.4.1...
Configuring optparse-applicative-0.4.1...
Preprocessing library optparse-applicative-0.4.1...
Preprocessing test suites for optparse-applicative-0.4.1...
Building optparse-applicative-0.4.1...
[ 1 of 11] Compiling Options.Applicative.Utils ( Options/Applicative/Utils.hs, dist/build/Options/Applicative/Utils.o )
[ 2 of 11] Compiling Options.Applicative.Types ( Options/Applicative/Types.hs, dist/build/Options/Applicative/Types.o )
[ 3 of 11] Compiling Options.Applicative.Internal ( Options/Applicative/Internal.hs, dist/build/Options/Applicative/Internal.o )
Options/Applicative/Internal.hs:54:10:
Illegal instance declaration for `MonadP P'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `MonadP P'
Options/Applicative/Internal.hs:105:10:
Illegal instance declaration for `MonadP Completion'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `MonadP Completion'
cabal: Error: some packages failed to install:
optparse-applicative-0.4.1 failed during the building phase. The exception
was:
ExitFailure 1
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.0.4
$ cabal --version
cabal-install version 0.10.2
using version 1.10.2.0 of the Cabal library
Unfortunately I'm largely at the mercy of fedora 17 packaging for these versions, as I'm not too comfortable building either ghc or cabal from source (unless there's an easier way).
I want to complete XML files. You can do this with bash completions via -A file -G '*.xml'
.
I get the arguments in reverse order from what I type at the command-line.
Test suite cannot be run from a pristine tarball.
When I enter a wrong argument the example program responds with the general usage pattern:
$ example --hello
Usage: args --hello TARGET [--quiet]
An error message like "missing parameter for option 'hello'" would be more helpful.
Or "option X required", "unknown option", "option parameter must be integer" etc.
import Options.Applicative
import Control.Applicative
data Program = Program { progOption :: String
, progCommand :: Command
}
deriving (Show)
data Command = Command { commandOption :: String }
deriving (Show)
commandOpts :: Parser Command
commandOpts = Command <$> strOption ( long "command-option" )
options :: Parser Program
options = pure Program
<*> strOption ( long "program-option" )
<*> subparser ( command "command" ( info commandOpts idm ) )
main :: IO ()
main = execParser (info options idm) >>= print
Example of the order-specific behaviour:
$ runghc Test.hs command --program-option=foo --command-option=bar
Usage: Test.hs command --command-option ARG
$ runghc Test.hs command --command-option=bar --program-option=foo
Program {progOption = "foo", progCommand = Command {commandOption = "bar"}}
I would expect both of these to work, given that there's no ambiguity in the option names.
Hi!
Would it be possible to add support for multiple usage of the same flag?
I would love to allow users to use arguments like this myprog --dump ast --dump va --dump test
and I would like to get array of String's as a result.
And here is what I was trying (what was natural to me, because I have some Parsec background) and it hanged optparse when printing help:
[...] many (strOption (long "dump" <> value "" <> metavar "DUMP")) [...]
Thank you.
For parsing simple arguments, I often define functions of type parseFoo :: String -> Either String a
, which are used in multiple places, and then I want to use them with reader
.
Could we have a convenience function like this?
eitherReader str2either = reader (either (Left . ErrorMsg) Right . str2either)
This would not be necessary if the fail
instance of Either String
was not an exception, but it is and fail
isn't a realy thing in Monad
either (no pun intended).
Thanks :)
Currently, if an option
parser fails on some argument it will report only Cannot parse value
and a user will be confused about what exactly went wrong. Consider this situation:
$ ./mbus-server --port dsf --key dsf
mbus-server: Cannot parse value
In this case you should figure out on your own whether you mistyped port
or it was key
. I believe some context information would help, e. g. an option/argument on which parser failed and a relevant piece of input.
It seems like the options parser cannot handle '-' characters in strOption argument values. E.g.,
options :: Parser Opts
options = Opts
<$> strOption (long "bindings"
& metavar "LIBRARY"
& help "Which sqlite library to benchmark (direct-sqlite or sqlite-simple)")
main :: IO ()
main =
options <- execParser $ info (helper <*> options)
(fullDesc
& progDesc "Generate test database")
if I run this program with
$ ./cabal-dev/bin/bench --bindings=sqlite-simple
Error: unrecognized option `--bindings=sqlite-simple'
But if I don't use a dash:
$ ./cabal-dev/bin/bench --bindings=sqlite_simple
it works.
This is with optparse-applicative 0.4.2
With 0.5, I had to
import Options.Applicative.Builder.Internal (ArgumentFields, Mod,
OptionFields)
because I have things like
valueAll :: (Bounded a, Enum a) => Mod f [a]
valueAll = Opt.value [minBound..]
Previously these types were exported from Options.Applicative
, which I think is useful because it allows you to write type signatures for reusable pieces of code.
Hi! I havent found a way to print to user the output of myprog --help when no options are provided and such solution is very important to me.
I do not know if it is implemented, but I did not managed to do it.
Is it possible at the moment or would it be possible in the future?
Thank you.
So now that I managed to implement --version
properly, the usage looks like this:
Usage: kibr (--version | [--language TAG] [--output MODE] COMMAND)
I'm impressed that it figured this out, but I actually don't want it in this case, so I add hidden
to the version parser. Now the usage looks like this:
Usage: kibr ([--language TAG] [--output MODE] COMMAND)
Problem is the parenthesis that got added with the version parser remain. That is, before adding the version flag the usage looked like this:
Usage: kibr [--language TAG] [--output MODE] COMMAND
You said it was planned, so why not have an issue filed for it? ☺
The cmdargs
package supports Bash and ZSH completions and seems to do so by providing different "formats" to render help pages in: System.Console.CmdArgs.Explicit / Displaying help
dag reports:
Also to bike shed, the extra empty lines around the list of commands make the help page rather ugly, and inconsistent with most other programs. ☺
Given the following program :
data Configuration = Configuration
{ configDropCount :: Int
, configOutputFilename :: String
, configInputFilename :: String
}
configParser :: Parser Configuration
configParser = Configuration
<$> option (long "dropcount" & short 'd' & metavar "COUNT" & help "Drop count frequency")
<*> strOption (long "outputfilename" & short 'o' & metavar "OUTFILENAME" & help "output ts filename")
<*> argument str ( metavar "FILE")
runner :: Configuration -> IO ()
runner = return ()
main :: IO ()
main = execParser opts >>= runner
where opts = info (helper <*> configParser)
( fullDesc
& progDesc "Corrupt a ts file"
& header "TSBreaker")
Trying to execute it under windows with runhaskell give the following error :
C:\...>runhaskell.exe .\tsbreaker.exe -d=500 -o=pouet jdajdoa
tsbreaker.exe:1:3: lexical error (UTF-8 decoding error)
But it works if compiled with ghc
I think that there should be possibility to disable backtracking on commands (or even make it the default).
What I mean is, if a program can be run with a subcommand or without one, supplying the subcommand should commit to that choice. Currently, if the subcommand parser fails, control is passed to the non-subcommand parser.
(If this description is not very clear, I can write a small example.)
in 0.5.2.1 i could have a ["string with spaces", "another one"] default for an arguments str. now in 0.7.0.2 that doesn't compile, i have to have ""string with spaces", "another one"", but that hangs (on one computer, another OOM's) when i execParser it!
also, it wasn't clear from the docs that i can't use auto for [String] arguments, took me a while to figure out i had to use str...
If "arguments" isn't the last argument in the applicative declaration it swallows all options (including --hyphenated
ones etc). I'm not sure whether this is a bug or a limitation of applicative?
I suppose a work around if you don't want to reorder your data structure is to use some helper function instead of applying your data constructor directly. But if this isn't about a limitation of applicative it would be nice to need no such workarounds! :)
data FluxCapacitor = ...
parseFluxCapacitor :: String -> Maybe FluxCapacitor
option
( long "flux-capacitor"
<> reader parseFluxCapacitor )
reader
now takes something that returns an Either
.
In most option parsers, if I have the long option --trace-level
, I should be able to type just --trace
provided it's unambiguous.
I feel like we had a ticket for this already but can't find it ...
$ kibr import
Usage: kibr import [--trace-level 0..4] FILE
Import words from an XML export
Available options:
-h,--help Show this help text
--trace-level 0..4 Set the tracing level for the XML parser
$ kibr import --help
fatal error: file read error: "file not found" when accessing "/home/dag/Haskell/kibr/--help"
Importing...
Finished importing 0 words.
$ ghc-pkg field kibr depends | grep optparse
optparse-applicative-0.4.2-4eac8083032f7394d98da97b11b17bb7
parseOptions :: Config -> Parser Options
parseOptions config = Options
<$> [...]
<*> Opt.subparser
( mkcmd "import" parseImport "Import words from an XML export"
<> [...]
)
where
mkcmd name parser desc = Opt.command name $ Opt.info (Opt.helper <*> parser) $ Opt.progDesc desc
parseImport :: Parser Command
parseImport = Import
<$> Opt.option
( Opt.long "trace-level"
<> Opt.metavar "0..4"
<> Opt.value 0
<> Opt.help "Set the tracing level for the XML parser"
)
<*> Opt.argument Opt.str (Opt.metavar "FILE" <> Opt.action "file")
The bash completions break too, duno if it's a separate bug? Here I'm hitting tab after --tr
:
$ kibr import --trbash: line 0: compgen: --: invalid option
compgen: usage: compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
ace-level ^C
Possibly related to #10.
The CmdTheLine
package supports formatting the help page in many ways: normal plain text, pager, man page, groff markup. I tried this package and really liked the man-page-like help page, but ended up with optparse-applicative in the end because I found CmdTheLine awkward in other areas (specifically the subcommands handling). Also it uses some weird custom string interpolation for writing these help pages.
Would be nice if optparse-applicative could do this as well, but using something like ansi-wl-pprint
for the "markup" instead.
I'm also thinking that when possible it could find out the width of the terminal window and wrap lines nicely to that margin. This is easy with ansi-wl-pprint
. For example I have this in my program, and it's longer than a normal terminal width of 80 columns:
--output MODE Control how output is printed (tty|colored|plain|quiet)
Using smart wrapping this could render as something like, pretending we have a really narrow terminal window:
--output MODE Control how output is
printed (tty|colored|plain|quiet)
Also if a line in the column where the flags are listed is longer than that column, the description could be pushed down to a new line instead of indented further, like,
-h,--help Show this help text
--trace-level SOME_INSANELY_LONG_METAVAR
Set the tracing level for the XML parser
I suspect (but baseless-assertion.jpg) that this sort of thing is also easy with ansi-wl-pprint
.
It would also remove the need for the Options.Applicative.Utils
module.
% gen-iface --help
Usage: gen-iface ([--version] | [--numeric-version] | [--hspkg-version] | [--supported-extensions] | [COMMAND] | [-i PATH] [--build-dir PATH] [-X extension] ([-D sym[=var]] | [-I PATH]) ([--global] | [--user] | [--package-db PATH]) [--package-id ARG] [MODULE])
Available options:
-h,--help Show this help text
Available commands:
pkg
The long line is not very aesthetic. It would be great if it was wrapped nicely.
I have a lot of code like this:
data Service = DICT | IRC | State | Web deriving (Eq, Bounded, Enum)
parseServe :: Parser Command
parseServe = Serve
<$> arguments (`lookup` services)
( metavar "dict|irc|state|web..."
. value [minBound..]
)
where
services = [("dict",DICT), ("irc",IRC), ("state",State), ("web",Web)]
This could probably be automated more. If there is a fixed set of valid values, the "reader" could be automatic, and the valid values could be displayed in the help output.
Possibly the valid set of values could even be generated for algebraic types with instances of Bounded, Enum, Show
. My services
definition could be generated by mapping toLower . show
over [minBound..]
.
I should add that I have this pattern not just for "arguments" but also for options. In that case my default tends to be simply the minBound
rather than [minBound..]
.
data OutputMode = TTY | Colored | Plain | Quiet
parseOptions = Options
<$> nullOption
( reader (`lookup` outputModes)
. long "output"
. metavar "MODE"
. value TTY
. help "Control how output is printed (tty|colored|plain|quiet)"
)
where
outputModes = [("tty",TTY), ("colored",Colored), ("plain",Plain), ("quiet",Quiet)]
Since one might not want a default value these two could be provided as Mod
ifiers:
parseOptions = Options <$> enumOption (long "output" . metavar "MODE" . valueFirst)
parseServe = Serve <$> enumArguments (valueAll)
So the problem is if I parse it together with the rest of my options it will fail (and print the help page) because other required options (specifically commands) are missing, but if I parse it separately and try to use Alternative it will always print the version because builders like switch
always succeed.
Perhaps a utility similar to helper
could be added specifically for dealing with versions, but in the more general case I think i need something that would let me write something like,
options :: Parser (Maybe Options)
options = Nothing <$ alternative (long "version") <|> Just . Options <$> ...
Or maybe something like (but this is less general)
options = maybeSwitch (long "version") $ Options <$> ...
Or am I missing something and there's already a straight-forward way to deal with this?
I was using Optparse successfully, but upgraded and the following code no longer works:
import Options.Applicative
data Params = Params
{ pMHoliday :: Maybe String -- Just date of holiday or Nothing
, pUpdateFile :: String -- file with raw trade data for a day
} deriving Show
getParams :: Parser Params
getParams = Params
<$> option
( long "holiday"
& value Nothing
& reader (Just . str)
& metavar "HOLIDAY-DATE"
& help "Create holiday records for HOLIDAY-DATE using close from UPDATE-FILE"
)
<*> argument str
( metavar "UPDATE-FILE"
& help "The XCHG_YYYYMMDD.txt file for the update"
)
main = execParser opts >>= print
where opts = info (helper <*> getParams)
( fullDesc
& progDesc "Perform daily update to the stock DB from UPDATE-FILE."
)
The part that fails is trying to input a value for the optional "--holiday". It seems to regard this as invalid and just outputs the help text.
BTW, it took me a while to figure out how to get an option with a maybe value in the previous version. Maybe a new option type would make this simpler, since i think it would be a common need.
Right now we are able to create hidden options (not displayed in the help), but as far as I know we cannot create hidden commands - would it be possible to add such feature please?
thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.