### Example Usage and Output Source: https://github.com/pcapriotti/optparse-applicative/wiki/Version-Options These examples show the command-line help output and the expected output when the `--version` flag is used. ```bash > main --help Usage: main COMMAND Available options: -h,--help Show this help text --version Show version > main --version 0.1.0.0 ``` -------------------------------- ### Main Execution with Parser Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Example of how to execute a parser and use the parsed arguments in a main function. It shows how to combine the parser with helper functions for generating help text and running the parser. ```haskell main :: IO () main = greet =<< execParser opts where opts = info (sample <**> helper) ( 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 () ``` -------------------------------- ### Example of Option Completion Source: https://github.com/pcapriotti/optparse-applicative/wiki/Bash-Completion When typing an option's name, bash completion can suggest the full option. This example shows completing `--output` for a program named `foo`. ```bash $ foo --ou ``` -------------------------------- ### Add Version Option using infoOption and Cabal Source: https://github.com/pcapriotti/optparse-applicative/wiki/Version-Options This example demonstrates adding a version option using `infoOption`, which is a composition over `abortOption`. It retrieves the version from the `Paths_` module generated by Cabal and displays it using `showVersion`. ```haskell import Data.Version (showVersion) import Paths_your_package_name (version) versioner :: Parser (a -> a) versioner = infoOption (showVersion version) (long "version" <> help "Show version" <> hidden) opts :: Parser Command opts = info (base <**> helper <**> versioner) idm ``` -------------------------------- ### Full Backup Application Parser with Completion Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt A complete example of a parser for backup options, demonstrating the integration of directory completion, static list completion, and dynamic completer for scripts, along with standard help. ```haskell import Options.Applicative data BackupOpts = BackupOpts { backupTarget :: FilePath , backupFormat :: String , backupHook :: FilePath } deriving Show backupParser :: Parser BackupOpts backupParser = BackupOpts <$> strOption ( long "target" <> metavar "DIR" <> help "Directory to back up" <> action "directory" ) -- tab-complete directories <*> strOption ( long "format" <> metavar "FMT" <> value "tar.gz" <> help "Archive format" <> completeWith ["tar.gz", "zip", "tar.bz2", "tar.xz"] ) -- static list <*> strOption ( long "pre-hook" <> metavar "SCRIPT" <> value "" <> help "Pre-backup hook script" <> action "file" -- tab-complete any file <> completer dynamicCompleter ) -- also suggest known scripts -- Custom completer fetches suggestions at runtime: dynamicCompleter :: Completer dynamicCompleter = mkCompleter $ \prefix -> do -- In practice, query a database or scan a directory: let knownScripts = ["pre-backup.sh", "notify.sh", "check-space.sh"] return $ filter (prefix `isPrefixOf`) knownScripts where isPrefixOf p s = take (length p) s == p main :: IO () main = do opts <- execParser (info (backupParser <**> helper) (progDesc "Backup a directory")) print opts -- Install shell completion (bash): -- source <(./backup --bash-completion-script $(which backup)) -- Install for zsh: -- source <(./backup --zsh-completion-script $(which backup)) ``` -------------------------------- ### Customizing Help Screen with showHelpOnEmpty Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Demonstrates customizing the help screen behavior by enabling `showHelpOnEmpty` preference. This ensures the help text is displayed when a command is incomplete at the start of parsing. ```haskell myParser :: Parser () myParser = ... main :: IO () main = customExecParser p opts where opts = info (myParser <**> helper) idm p = prefs showHelpOnEmpty ``` -------------------------------- ### Execute IO Actions from Subcommands Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Defines subcommands that execute IO actions. The `start` command takes a string argument, while `stop` performs a simple IO action. The main function joins the result of the parser with `execParser`. ```haskell start :: String -> IO () stop :: IO () opts :: Parser (IO ()) opts = hsubparser ( command "start" (info (start <$> argument str idm) idm) <> command "stop" (info (pure stop) idm) ) main :: IO () main = join $ execParser (info opts idm) ``` -------------------------------- ### Sample Parser Definition Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Example of defining a Sample data type and a corresponding Parser using an applicative style. This demonstrates how to combine basic parsers for strings, booleans (switches), and integers with default values. ```haskell 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" ) ``` -------------------------------- ### Enable Option Disambiguation with customExecParser Source: https://github.com/pcapriotti/optparse-applicative/wiki/Disambiguation This example demonstrates how to enable automatic option prefix disambiguation. It defines two switches, `--filename` and `--filler`, and uses `customExecParser` with `prefs disambiguate` to allow unambiguous prefixes like `--file` to be recognized. ```haskell 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 = prefs disambiguate ``` -------------------------------- ### Enabling Option Disambiguation Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Configures `optparse-applicative` to automatically disambiguate prefixes of long options. This example enables disambiguation using the `disambiguate` `PrefsMod`. ```haskell 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 = prefs disambiguate ``` -------------------------------- ### Define a string option with strOption Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Use the `strOption` builder to create a regular option that accepts a string argument. This example defines an option with long and short names, a metadata variable, a default value, and a help message. ```haskell strOption ( long "output" <> short 'o' <> metavar "FILE" <> value "out.txt" <> help "Write output to FILE" ) ``` -------------------------------- ### Command Modifier Example Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Illustrates the type signature for the `command` modifier, which is used specifically with command builders. Modifiers can be combined using `mappend` or `(<>)`. ```haskell command :: String -> ParserInfo a -> Mod CommandFields a ``` -------------------------------- ### Implement Richer Version Banner with infoOption Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Utilize `infoOption` to create a custom `--version` flag that displays a more detailed banner including build information and license. This provides a richer user experience for version inquiries. ```haskell versionOpt :: Parser (a -> a) versionOpt = infoOption banner ( long "version" <> short 'V' <> help "Show version" <> hidden ) where banner = unlines ["myapp 2.1.0", "Compiled with GHC 9.6", "License: BSD-3"] ``` -------------------------------- ### Run Parser from Main with execParser Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `execParser` for the primary entry point in `main`. It reads arguments, handles help, and manages errors. ```haskell import Options.Applicative data Opts = Opts { file :: FilePath, count :: Int } deriving Show optsParser :: Parser Opts optsParser = Opts <$> strArgument (metavar "FILE" <> help "Input file") <*> option auto (long "count" <> short 'n' <> value 1 <> showDefault <> metavar "N" <> help "Repeat count") main :: IO () main = do opts <- execParser pinfo putStrLn $ "Processing " ++ file opts ++ " x" ++ show (count opts) where pinfo = info (optsParser <**> helper) ( fullDesc <> progDesc "Process FILE N times" <> header "processor - demo of execParser" ) -- $ ./processor input.txt --count 3 -- Processing input.txt x3 -- -- $ ./processor -- Missing: FILE -- Usage: processor FILE [-n|--count N] -- $ ./processor --help -- processor - demo of execParser -- Usage: processor FILE [-n|--count N] -- Process FILE N times -- Available options: -- FILE Input file -- -n,--count N Repeat count (default: 1) -- -h,--help Show this help text ``` -------------------------------- ### Define Subcommands with Descriptions Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Sets up a command-line interface with subcommands like 'add' and 'commit'. Each command can have its own description and options. ```haskell hsubparser ( command "add" (info addCommand ( progDesc "Add a file to the repository" )) <> command "commit" (info commitCommand ( progDesc "Record changes to the repository" )) ) ``` -------------------------------- ### Run Parser with Custom Preferences using customExecParser Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Employ `customExecParser` with `prefs` to customize help display, disambiguation, column width, and subparser behavior. ```haskell import Options.Applicative data Opts = Opts { filename :: String, verbose :: Bool } deriving Show optsParser :: Parser Opts optsParser = Opts <$> strOption (long "filename" <> metavar "FILE" <> help "Input filename") <*> switch (long "verbose" <> short 'v' <> help "Verbose output") main :: IO () main = do opts <- customExecParser myPrefs pinfo print opts where pinfo = info (optsParser <**> helper) (progDesc "Demo with custom prefs") myPrefs = prefs $ mconcat [ showHelpOnEmpty -- show help when no args given , showHelpOnError -- show full help on any parse error , disambiguate -- allow unambiguous prefix matching of long options , columns 100 -- wrap help text at 100 columns , helpLongEquals -- render "--opt=VALUE" instead of "--opt VALUE" ] -- $ ./app -- (displays full help because showHelpOnEmpty) -- -- $ ./app --file data.txt (unambiguous prefix of --filename, disambiguate enabled) -- Opts {filename = "data.txt", verbose = False} ``` -------------------------------- ### Define Version Command with optparse-applicative Source: https://github.com/pcapriotti/optparse-applicative/wiki/Version-Options This snippet shows how to define a `Version` command as an alternative case in your ADT. It uses `option` to create a parser that returns `Version` when the `--version` flag is encountered. ```haskell data Command = Base Some Things | Version base :: Parser Command version :: Parser (Command -> Command) version = option id (const Version) (long "version" <> help "Display version" <> hidden) opts :: ParserInfo Command opts = info (base <**> helper <**> version) mempty ``` -------------------------------- ### Add Shell Completion for Directories with action "directory" Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Enable tab-completion for directory paths using `action "directory"` on a `strOption`. This provides a convenient way for users to select directories. ```haskell <*> strOption ( long "target" <> metavar "DIR" <> help "Directory to back up" <> action "directory" ) -- tab-complete directories ``` -------------------------------- ### strOption — Build a string option Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Creates a regular option that accepts a string argument. It supports both long (--name) and short (-n) flags, an optional default value, and a metavariable for help text. ```APIDOC ## strOption — Build a string option ### Description Creates a regular option that takes a string argument. Accepts long (`--name`) and short (`-n`) flags, an optional default value, and a metavariable displayed in help text. ### Method Not applicable (Haskell function) ### Endpoint Not applicable (Haskell function) ### Parameters This function is used as a combinator within a Haskell parser. The parameters are configured via modifier functions like `long`, `short`, `metavar`, `value`, `showDefault`, and `help`. ### Request Example ```haskell import Options.Applicative data Config = Config { output :: String, input :: String } deriving Show configParser :: Parser Config configParser = Config <$> strOption ( long "output" <> short 'o' <> metavar "FILE" <> value "out.txt" <> showDefault <> help "Write output to FILE" ) <*> strOption ( long "input" <> short 'i' <> metavar "FILE" <> help "Read input from FILE" ) main :: IO () main = do cfg <- execParser (info (configParser <**> helper) (progDesc "Process a file")) print cfg ``` ### Response #### Success Response The parsed configuration object of type `Config`. #### Response Example ``` Config {output = "out.txt", input = "data.csv"} ``` ``` -------------------------------- ### Enable Argument Completion with action Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Use `action` to specify a completion 'action' that dynamically determines a list of possible completions for an argument. Common actions include 'file' and 'directory'. ```haskell action :: Completing (a -> IO [String]) -> Option a action = ... -- Example usage: -- option "--dir" (action directory) Nothing ``` -------------------------------- ### Build subcommand parsers Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `subparser` or `hsubparser` to create parsers that dispatch based on command names. `hsubparser` automatically includes help for subcommands. ```haskell import Options.Applicative import Data.List (intercalate) data Command = Hello [String] | Goodbye | Count Int FilePath deriving Show helloParser :: Parser Command helloParser = Hello <$> many (argument str (metavar "TARGET...")) countParser :: Parser Command countParser = Count <$> option auto (long "lines" <> short 'n' <> metavar "N" <> value 10 <> showDefault <> help "Number of lines") <*> strArgument (metavar "FILE" <> help "File to count") commandParser :: Parser Command commandParser = hsubparser ( command "hello" (info helloParser (progDesc "Print a greeting")) <> command "goodbye" (info (pure Goodbye) (progDesc "Say goodbye")) <> command "count" (info countParser (progDesc "Count lines in a file")) ) main :: IO () main = do cmd <- execParser (info (commandParser <**> helper) (progDesc "A multi-command demo" <> header "demo - optparse example")) case cmd of Hello ts -> putStrLn $ "Hello, " ++ intercalate ", " ts ++ "!" Goodbye -> putStrLn "Goodbye." Count n f -> putStrLn $ "Counting " ++ show n ++ " lines from " ++ f ``` -------------------------------- ### Add Static List Shell Completion with completeWith Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Provide shell completion with a predefined list of options using `completeWith`. This is useful for options with a fixed set of valid values, such as archive formats. ```haskell <*> strOption ( long "format" <> metavar "FMT" <> value "tar.gz" <> help "Archive format" <> completeWith ["tar.gz", "zip", "tar.bz2", "tar.xz"] ) -- static list ``` -------------------------------- ### Build a string option with strOption Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `strOption` to create an option that accepts a string argument. It supports long and short flags, default values, and custom metavariables for help text. Ensure `Options.Applicative` is imported. ```haskell import Options.Applicative data Config = Config { output :: String, input :: String } deriving Show configParser :: Parser Config configParser = Config <$> strOption ( long "output" <> short 'o' <> metavar "FILE" <> value "out.txt" <> showDefault <> help "Write output to FILE" ) <*> strOption ( long "input" <> short 'i' <> metavar "FILE" <> help "Read input from FILE" ) main :: IO () main = do cfg <- execParser (info (configParser <**> helper) (progDesc "Process a file")) print cfg ``` -------------------------------- ### Define ParserInfo with info function Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Use the `info` function to wrap a parser into a `ParserInfo` structure. This structure holds metadata for top-level parsers, such as help screen descriptions. The `helper` parser adds a dummy --help option. ```haskell opts :: ParserInfo Sample opts = info (sample <**> helper) ( fullDesc <> progDesc "Print a greeting for TARGET" <> header "hello - a test for optparse-applicative" ) ``` -------------------------------- ### Execute Parser with execParser Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md The `execParser` function is the simplest way to run a `ParserInfo`. It handles command-line argument retrieval, error display, help screens, and appropriate exit codes. ```haskell main :: IO () main = do options <- execParser opts ... ``` -------------------------------- ### Generate Bash Completion Script Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Generate a bash completion script by running the program with `--bash-completion-script`. This script, when sourced, enables bash completion for the program. ```bash source <(foo --bash-completion-script `which foo`) ``` -------------------------------- ### Generate Bash Completion Script Source: https://github.com/pcapriotti/optparse-applicative/wiki/Bash-Completion Source this command into your bash session to enable completion for your program. Replace `foo` with your program's name. ```bash $ source <(foo --bash-completion-script `which foo`) ``` -------------------------------- ### Define command aliases with commandWithAliases Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `commandWithAliases` to associate multiple names with a single command. All aliases are displayed together in the help text. ```haskell import Options.Applicative import Data.List.NonEmpty (NonEmpty((:|))) data Cmd = Install | Remove | Update deriving Show pkgParser :: Parser Cmd pkgParser = subparser ( commandWithAliases ("install" :| ["add", "i"]) (info (pure Install) (progDesc "Install a package")) <> commandWithAliases ("remove" :| ["rm", "uninstall"]) (info (pure Remove) (progDesc "Remove a package")) <> command "update" (info (pure Update) (progDesc "Update all packages")) ) main :: IO () main = execParser (info (pkgParser <**> helper) (progDesc "Package manager")) >>= print ``` -------------------------------- ### Define Options with Applicative Do Notation Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Utilize ApplicativeDo extension for a do-notation style parser definition when `Parser` is not a `Monad`. Requires GHC recent versions. RecordWildCards can simplify the specification. ```haskell {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ApplicativeDo #-} data Options = Options { optArgs :: [String] , optVerbose :: Bool } opts :: Parser Options opts = do optVerbose <- switch (short 'v') optArgs <- many (argument str idm) pure Options {..} ``` -------------------------------- ### Add Standard Help Flag with helper Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Integrate the standard `-h/--help` option into your parser using `helper`. This option is typically hidden from the main usage line but provides detailed help when invoked. ```haskell import Options.Applicative data Opts = Opts { quiet :: Bool } deriving Show optsParser :: Parser Opts optsParser = Opts <$> switch (long "quiet" <> short 'q' <> help "Suppress output") -- Standard --help / -h (hidden from usage line): main1 :: IO () main1 = execParser (info (optsParser <**> helper) (progDesc "Standard help")) >>= print ``` -------------------------------- ### Group options under a heading with parserOptionGroup Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Employ `parserOptionGroup` to organize a sub-parser's options under a specific heading in the help output. This improves the readability of complex argument structures. ```haskell import Options.Applicative data NetOpts = NetOpts { host :: String , netPort :: Int } deriving Show data TLSOpts = TLSOpts { cert :: FilePath , key :: FilePath } deriving Show data ServerCfg = ServerCfg { serverNet :: NetOpts , serverTLS :: TLSOpts , debug :: Bool } deriving Show netParser :: Parser NetOpts netParser = NetOpts <$> strOption (long "host" <> metavar "HOST" <> value "localhost" <> showDefault <> help "Server hostname") <*> option auto (long "port" <> short 'p' <> metavar "PORT" <> value 443 <> showDefault <> help "Server port") tlsParser :: Parser TLSOpts tlsParser = TLSOpts <$> strOption (long "cert" <> metavar "FILE" <> help "TLS certificate file") <*> strOption (long "key" <> metavar "FILE" <> help "TLS private key file") serverParser :: Parser ServerCfg serverParser = ServerCfg <$> parserOptionGroup "Network options:" netParser <*> parserOptionGroup "TLS options:" tlsParser <*> switch (long "debug" <> help "Enable debug mode") main :: IO () main = execParser (info (serverParser <**> helper) (progDesc "Start server")) >>= print ``` -------------------------------- ### Add Simple Version Flag with simpleVersioner Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `simpleVersioner` to add a hidden `--version` flag that prints a specified version string and exits. This is the simplest approach for versioning. ```haskell import Options.Applicative import Data.Version (showVersion) -- Using simpleVersioner (simplest approach): data Opts = Opts { input :: FilePath } deriving Show optsParser :: Parser Opts optsParser = Opts <$> strArgument (metavar "FILE" <> help "Input file") main :: IO () main = do opts <- execParser pinfo putStrLn $ "Processing: " ++ input opts where pinfo = info (optsParser <**> helper <**> simpleVersioner "2.1.0") (progDesc "Process a file" <> header "myapp v2.1.0") -- $ ./myapp --version -- 2.1.0 ``` -------------------------------- ### Add Dynamic Shell Completion with completer Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Implement dynamic shell completion by providing a custom `Completer` function using `completer`. This allows suggestions to be generated at runtime based on dynamic conditions, such as available scripts. ```haskell dynamicCompleter :: Completer dynamicCompleter = mkCompleter $ \prefix -> do -- In practice, query a database or scan a directory: let knownScripts = ["pre-backup.sh", "notify.sh", "check-space.sh"] return $ filter (prefix `isPrefixOf`) knownScripts where isPrefixOf p s = take (length p) s == p -- ... in backupParser ... <*> strOption ( long "pre-hook" <> metavar "SCRIPT" <> value "" <> help "Pre-backup hook script" <> action "file" -- tab-complete any file <> completer dynamicCompleter ) -- also suggest known scripts ``` -------------------------------- ### Run Parser in Pure Code with execParserPure Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Utilize `execParserPure` to parse a list of strings without IO, returning a `ParserResult` for manual inspection. ```haskell import Options.Applicative data Opts = Opts { name :: String, count :: Int } deriving Show optsParser :: Parser Opts optsParser = Opts <$> strOption (long "name" <> metavar "NAME" <> help "Your name") <*> option auto (long "count" <> value 1 <> showDefault <> metavar "N" <> help "Count") pinfo :: ParserInfo Opts pinfo = info (optsParser <**> helper) (progDesc "Pure parsing demo") -- Run in pure code (useful for testing): parseArgs :: [String] -> Either String Opts parseArgs args = case execParserPure defaultPrefs pinfo args of Success opts -> Right opts Failure err -> Left . fst $ renderFailure err "" CompletionInvoked _ -> Left "completion" main :: IO () main = do print $ parseArgs ["--name", "Alice", "--count", "3"] -- Right (Opts {name = "Alice", count = 3}) print $ parseArgs ["--name", "Bob"] -- Right (Opts {name = "Bob", count = 1}) print $ parseArgs [] -- Left "Missing: --name NAME\n\nUsage: ..." print $ parseArgs ["--bad-flag"] -- Left "Invalid option `--bad-flag'" ``` -------------------------------- ### Group Options with parserOptionGroup Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Use `parserOptionGroup` to group related options under a common heading in the help message. Options within groups are displayed after main and other options. ```haskell Args <*> parseMain <*> parserOptionGroup "Group A" parseA <*> parserOptionGroup "Group B" parseB <*> parseOther ``` -------------------------------- ### Correct and Incorrect Parser Composition Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Demonstrates the correct way to combine parsers for sum types using the Alternative instance, contrasting it with an incorrect approach that leads to parse failures. Ensure that `ReadM` operations are combined before being passed to the `argument` parser. ```haskell import Options.Applicative data S3orFile = S3 BucketKey | File FilePath s3Read, fileRead :: ReadM S3orFile s3Read = S3 <$> ... fileRead = File <$> ... correct :: Parser S3orFile correct = argument (s3Read <|> fileRead) idm incorrect :: Parser S3orFile incorrect = argument s3Read idm <|> argument fileRead idm ``` -------------------------------- ### Build flags with custom active/default values Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `flag` for flags with a default value and `flag'` for flags that must be present. Ensure necessary imports are included. ```haskell import Options.Applicative data Verbosity = Quiet | Normal | Verbose deriving (Show, Eq) data Format = JSON | CSV | Plain deriving Show data ExportOpts = ExportOpts { verbosity :: Verbosity , format :: Format } deriving Show exportParser :: Parser ExportOpts exportParser = ExportOpts <$> flag Normal Verbose ( long "verbose" <> short 'v' <> help "Produce verbose output" ) <*> ( flag' JSON (long "json" <> help "Output JSON") <|> flag' CSV (long "csv" <> help "Output CSV") <|> pure Plain ) main :: IO () main = do opts <- execParser (info (exportParser <**> helper) (progDesc "Export data")) print opts ``` -------------------------------- ### Define Argument Interspersing Policies Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Demonstrates how to define parsers and use `noIntersperse` and `forwardOptions` policies. Use `noIntersperse` when positional arguments should terminate option processing. Use `forwardOptions` when wrapping other CLI tools and unrecognised options should be passed through. ```haskell import Options.Applicative -- noIntersperse: once a positional is seen, all remaining args are positional data WrapOpts = WrapOpts { wrapVerbose :: Bool, wrapArgs :: [String] } deriving Show wrapParser :: Parser WrapOpts wrapParser = WrapOpts <$> switch (long "verbose" <> short 'v' <> help "Verbose mode") <*> many (strArgument (metavar "ARGS...")) -- Options after the first positional arg are treated as more positionals: noInterleaveOpts :: IO WrapOpts noInterleaveOpts = execParser $ info (wrapParser <**> helper) noIntersperse -- forwardOptions: unrecognised options are passed through as positionals -- (useful when wrapping another CLI tool) forwardOpts :: IO WrapOpts forwardOpts = execParser $ info (wrapParser <**> helper) forwardOptions main :: IO () main = do -- With noIntersperse: ./wrap -v cmd --sub-flag => args = ["cmd", "--sub-flag"] opts <- noInterleaveOpts print opts -- $ ./wrap -v git commit --amend -- WrapOpts {wrapVerbose = True, wrapArgs = ["git","commit","--amend"]} ``` -------------------------------- ### Custom option readers with eitherReader and maybeReader Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Create custom parsers for options using `eitherReader` and `maybeReader`. `eitherReader` allows for explicit `Left` or `Right` results, while `maybeReader` handles `Maybe` results, providing flexible input validation and conversion. ```haskell import Options.Applicative import Data.List (isPrefixOf) import Text.Read (readMaybe) data IpAddr = IpAddr Int Int Int Int deriving Show data SizeUnit = Bytes Int | Kilobytes Int | Megabytes Int deriving Show ipReader :: ReadM IpAddr ipReader = eitherReader $ \s -> case break (== '.') s of _ -> case mapM readMaybe (wordsWhen (== '.') s) of Just [a, b, c, d] -> Right (IpAddr a b c d) _ -> Left $ "Invalid IP address: " ++ s where wordsWhen p str = case dropWhile p str of "" -> [] s' -> w : wordsWhen p s'' where (w, s'') = break p s' sizeReader :: ReadM SizeUnit sizeReader = maybeReader $ \s | "mb" `isSuffixOf` s = Megabytes <$> readMaybe (dropLast 2 s) | "kb" `isSuffixOf` s = Kilobytes <$> readMaybe (dropLast 2 s) | otherwise = Bytes <$> readMaybe s where isSuffixOf suffix str = suffix `isPrefixOf` reverse (take (length suffix) (reverse str)) dropLast n xs = take (length xs - n) xs data NetCfg = NetCfg { bindAddr :: IpAddr, maxSize :: SizeUnit } deriving Show netCfgParser :: Parser NetCfg netCfgParser = NetCfg <$> option ipReader ( long "bind" <> metavar "IP" <> help "IP address to bind" ) <*> option sizeReader ( long "max-body" <> metavar "SIZE" <> value (Kilobytes 64) <> help "Maximum body size (e.g. 128kb, 2mb)" ) main :: IO () main = execParser (info (netCfgParser <**> helper) idm) >>= print ``` -------------------------------- ### Combine Parsers with Arrow Syntax Source: https://github.com/pcapriotti/optparse-applicative/wiki/Arrows Use `runA` and `asA` to define parsers using Arrow syntax. This is useful for complex data structures or when the order of parsing differs from the order of fields. ```haskell data Options = Options { optArgs :: [String] , optVerbose :: Bool } opts :: Parser Options opts = runA $ proc () -> do verbosity <- asA (option (short 'v' <> value 0)) -< () let verbose = verbosity > 0 args <- asA (many (argument str idm)) -< () returnA -< Options args verbose ``` -------------------------------- ### Separate commands into named groups Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `commandGroup` to organize subcommands under distinct headings in the help screen. `hidden` can be used to hide commands from the default help. ```haskell import Options.Applicative data Cmd = CmdBuild | CmdTest | CmdDeploy | CmdRollback deriving Show cmdParser :: Parser Cmd cmdParser = hsubparser ( command "build" (info (pure CmdBuild) (progDesc "Build the project")) <> command "test" (info (pure CmdTest) (progDesc "Run tests")) ) <|> hsubparser ( command "deploy" (info (pure CmdDeploy) (progDesc "Deploy to production")) <> command "rollback" (info (pure CmdRollback) (progDesc "Rollback deployment")) <> commandGroup "Deployment commands:" <> hidden ) main :: IO () main = execParser (info (cmdParser <**> helper) idm) >>= print ``` -------------------------------- ### option — Build a typed option with a reader Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Constructs a regular option where the argument is parsed using a `ReadM` reader. It supports automatic parsing for any type with a `Read` instance using `auto`, or custom readers can be provided. ```APIDOC ## option — Build a typed option with a reader ### Description Creates a regular option whose argument is parsed by a `ReadM` reader. Use `auto` for any `Read` instance, or supply a custom reader. ### Method Not applicable (Haskell function) ### Endpoint Not applicable (Haskell function) ### Parameters This function is used as a combinator within a Haskell parser. The parameters are configured via modifier functions like `long`, `short`, `metavar`, `value`, `showDefault`, and `help`. The `auto` function is commonly used to specify the reader. ### Request Example ```haskell import Options.Applicative data LogLevel = Debug | Info | Warn | Error deriving (Show, Read) data AppOpts = AppOpts { port :: Int, logLevel :: LogLevel, timeout :: Double } deriving Show optsParser :: Parser AppOpts optsParser = AppOpts <$> option auto ( long "port" <> short 'p' <> metavar "PORT" <> value 8080 <> showDefault <> help "Port to listen on" ) <*> option auto ( long "log-level" <> metavar "LEVEL" <> value Info <> showDefaultWith show <> help "Logging level (Debug|Info|Warn|Error)" ) <*> option auto ( long "timeout" <> metavar "SECONDS" <> value 30.0 <> showDefault <> help "Request timeout in seconds" ) main :: IO () main = do opts <- execParser (info (optsParser <**> helper) (header "myapp - a network service")) print opts ``` ### Response #### Success Response The parsed application options object of type `AppOpts`. #### Response Example ``` AppOpts {port = 9090, logLevel = Debug, timeout = 30.0} ``` ``` -------------------------------- ### Define Parsers for Alternative Inputs Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Model programs that accept input from different sources (e.g., file or stdin) using sum types. Define separate parsers for each input type and combine them using the `Alternative` operator `(<|>)`. ```haskell data Input = FileInput FilePath | StdInput 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" ) input :: Parser Input input = fileInput <|> stdInput ``` -------------------------------- ### Build a typed option with option and auto Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `option auto` to create an option whose argument is parsed using the `Read` typeclass. This is suitable for options with predefined enumerated types or other types that implement `Read`. Ensure `Options.Applicative` is imported. ```haskell import Options.Applicative data LogLevel = Debug | Info | Warn | Error deriving (Show, Read) data AppOpts = AppOpts { port :: Int, logLevel :: LogLevel, timeout :: Double } deriving Show optsParser :: Parser AppOpts optsParser = AppOpts <$> option auto ( long "port" <> short 'p' <> metavar "PORT" <> value 8080 <> showDefault <> help "Port to listen on" ) <*> option auto ( long "log-level" <> metavar "LEVEL" <> value Info <> showDefaultWith show <> help "Logging level (Debug|Info|Warn|Error)" ) <*> option auto ( long "timeout" <> metavar "SECONDS" <> value 30.0 <> showDefault <> help "Request timeout in seconds" ) main :: IO () main = do opts <- execParser (info (optsParser <**> helper) (header "myapp - a network service")) print opts ``` -------------------------------- ### Define an integer option with option auto Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Use the `option` builder with the `auto` reader to create a regular option that parses an integer argument. The `auto` reader requires a `Read` instance for the return type. Type annotations may be needed if inference is ambiguous. ```haskell lineCount :: Parser Int lineCount = option auto ( long "lines" <> short 'n' <> metavar "K" <> help "Output the last K lines" ) ``` -------------------------------- ### Alternative Composition for Mutually Exclusive Options Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `(<|>)` from `Control.Applicative.Alternative` to define mutually exclusive options or optional parsers. This allows for flexible input and output handling. ```haskell import Options.Applicative import Control.Applicative ((<|>)) data Input = FileInput FilePath | UrlInput String | StdInput deriving Show data Output = FileOutput FilePath | StdOutput deriving Show inputParser :: Parser Input inputParser = (FileInput <$> strOption (long "file" <> short 'f' <> metavar "FILE" <> help "Read from file")) <|> (UrlInput <$> strOption (long "url" <> short 'u' <> metavar "URL" <> help "Fetch from URL")) <|> flag' StdInput (long "stdin" <> help "Read from stdin") outputParser :: Parser Output outputParser = (FileOutput <$> strOption (long "output" <> short 'o' <> metavar "FILE" <> help "Write to file")) <|> pure StdOutput data PipeOpts = PipeOpts { pipeInput :: Input, pipeOutput :: Output } deriving Show pipeParser :: Parser PipeOpts pipeParser = PipeOpts <$> inputParser <*> outputParser main :: IO () main = execParser (info (pipeParser <**> helper) (progDesc "Data pipeline")) >>= print -- $ ./pipe --file data.json --output result.json -- PipeOpts {pipeInput = FileInput "data.json", pipeOutput = FileOutput "result.json"} -- $ ./pipe --stdin -- PipeOpts {pipeInput = StdInput, pipeOutput = StdOutput} -- optional :: Alternative f => f a -> f (Maybe a) optionalOutput :: Parser (Maybe FilePath) optionalOutput = optional $ strOption (long "output" <> metavar "DIR") ``` -------------------------------- ### Customize Help Flag with helperWith Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `helperWith` to customize the help option's behavior, such as making it visible in the usage line or changing its name and help text. This allows for more tailored user interaction. ```haskell myHelpMod = mconcat [ long "help" , short 'h' , help "Display this help message" -- omitting `hidden` makes it appear in the brief usage line ] -- Customised help option (visible in usage, different name): main2 :: IO () main2 = do opts <- execParser pinfo print opts where pinfo = info (optsParser <**> helperWith myHelpMod) (progDesc "Custom help option") ``` -------------------------------- ### ApplicativeDo Style Parser with do-notation Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Leverage GHC's `ApplicativeDo` extension to write parsers using do-notation for improved readability. This works because `Parser` is an `Applicative` functor. ```haskell {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE RecordWildCards #-} import Options.Applicative data Config = Config { cfgHost :: String , cfgPort :: Int , cfgVerbose :: Bool , cfgWorkers :: Int } deriving Show configParser :: Parser Config configParser = do cfgHost <- strOption ( long "host" <> metavar "HOST" <> value "localhost" <> showDefault <> help "Server host" ) cfgPort <- option auto ( long "port" <> short 'p' <> metavar "PORT" <> value 8080 <> showDefault <> help "Server port" ) cfgVerbose <- switch ( long "verbose" <> short 'v' <> help "Verbose logging" ) cfgWorkers <- option auto ( long "workers" <> metavar "N" <> value 4 <> showDefault <> help "Worker thread count" ) pure Config {..} main :: IO () main = do cfg <- execParser (info (configParser <**> helper) ( progDesc "Start the server" <> header "server - applicative-do example" )) putStrLn $ "Starting on " ++ cfgHost cfg ++ ":" ++ show (cfgPort cfg) print cfg -- $ ./server --port 9000 -v --workers 8 -- Starting on localhost:9000 -- Config {cfgHost = "localhost", cfgPort = 9000, cfgVerbose = True, cfgWorkers = 8} ``` -------------------------------- ### Combine Parsers using Applicative Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Combine multiple parsers into a single parser that returns a structured data type. This uses the Applicative interface (`<$>`, `<*>`) to combine results, allowing options to appear in any order on the command line. ```haskell data Options = Options { optTarget :: String , optQuiet :: Bool } opts :: Parser Options opts = Options <$> target <*> quiet ``` -------------------------------- ### Build a boolean flag with switch Source: https://context7.com/pcapriotti/optparse-applicative/llms.txt Use `switch` to create a boolean flag that is `True` if present and `False` otherwise. This is useful for enabling or disabling features. Ensure `Options.Applicative` is imported. ```haskell import Options.Applicative data ToolOpts = ToolOpts { verbose :: Bool, dryRun :: Bool, recursive :: Bool } deriving Show toolParser :: Parser ToolOpts toolParser = ToolOpts <$> switch ( long "verbose" <> short 'v' <> help "Enable verbose output" ) <*> switch ( long "dry-run" <> short 'n' <> help "Simulate without executing" ) <*> switch ( long "recursive" <> short 'r' <> help "Recurse into subdirectories" ) main :: IO () main = do opts <- execParser (info (toolParser <**> helper) (progDesc "File processing tool")) print opts ``` -------------------------------- ### Nested Option Groups Source: https://github.com/pcapriotti/optparse-applicative/blob/master/README.md Nested option groups are supported and will be indented in the help output. This allows for hierarchical organization of options. ```haskell parserOptionGroup "Group Outer" (parserOptionGroup "Group Inner" parseA) ```