{"id":13532801,"url":"https://github.com/purescript-contrib/purescript-optparse","last_synced_at":"2026-03-09T17:15:49.305Z","repository":{"id":34302705,"uuid":"172104082","full_name":"purescript-contrib/purescript-optparse","owner":"purescript-contrib","description":" Applicative option parser","archived":false,"fork":false,"pushed_at":"2023-12-22T15:39:23.000Z","size":948,"stargazers_count":40,"open_issues_count":7,"forks_count":16,"subscribers_count":8,"default_branch":"main","last_synced_at":"2024-05-21T13:55:02.281Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purescript-contrib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-02-22T17:08:59.000Z","updated_at":"2024-01-23T15:54:20.000Z","dependencies_parsed_at":"2023-12-22T16:44:58.261Z","dependency_job_id":"ad2b2295-91fc-4497-9a45-2242cec2f7f4","html_url":"https://github.com/purescript-contrib/purescript-optparse","commit_stats":null,"previous_names":["purescript-contrib/purescript-optparse","f-o-a-m/purescript-optparse"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript-contrib%2Fpurescript-optparse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript-contrib%2Fpurescript-optparse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript-contrib%2Fpurescript-optparse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript-contrib%2Fpurescript-optparse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purescript-contrib","download_url":"https://codeload.github.com/purescript-contrib/purescript-optparse/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242635336,"owners_count":20161437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T07:01:13.840Z","updated_at":"2025-12-05T05:05:13.939Z","avatar_url":"https://github.com/purescript-contrib.png","language":"PureScript","funding_links":[],"categories":["[Purescript](https://www.purescript.org/)"],"sub_categories":["Useful awesome list for Go cli"],"readme":"# purescript-optparse\n\n[![Continuous Integration status][status-png]][status]\n\n\npurescript-optparse is a port of haskell lib [optparse-applicative] for parsing\noptions on the command line, providing a powerful applicative interface\nfor composing these options.\n\npurescript-optparse takes care of reading and validating the\narguments passed to the command line, handling and reporting errors,\ngenerating a usage line, a comprehensive help screen, and enabling\ncontext-sensitive bash, zsh, and fish completions.\n\n**Table of Contents**\n\n- [Introduction](#introduction)\n- [Quick Start](#quick-start)\n- [Basics](#basics)\n    - [Parsers](#parsers)\n    - [Applicative](#applicative)\n    - [Alternative](#alternative)\n    - [Running parsers](#running-parsers)\n- [Builders](#builders)\n    - [Regular options](#regular-options)\n    - [Flags](#flags)\n    - [Arguments](#arguments)\n    - [Commands](#commands)\n    - [Modifiers](#modifiers)\n    - [Common Builder Patterns](#common-builder-patterns)\n        - [A list of values with a default](#a-list-of-values-with-a-default)\n- [Custom parsing and error handling](#custom-parsing-and-error-handling)\n    - [Parser runners](#parser-runners)\n    - [Option readers](#option-readers)\n    - [Preferences](#preferences)\n    - [Disambiguation](#disambiguation)\n    - [Customising the help screen](#customising-the-help-screen)\n    - [Command Groups](#command-groups)\n- [Bash completion](#bash-zsh-and-fish-completions)\n    - [Actions and completers](#actions-and-completers)\n    - [Internals](#internals)\n- [Applicative Do](#applicative-do)\n- [FAQ](#faq)\n- [How it works](#how-it-works)\n\n## Introduction\n\nThe core type in purescript-optparse is a `Parser`\n\n```purs\ndata Parser a\n\ninstance Functor Parser\ninstance Applicative Parser\ninstance Alternative Parser\n```\n\nA value of type `Parser a` represents a specification for a set of\noptions, which will yield a value of type `a` when the command line\narguments are successfully parsed.\n\nIf you are familiar with parser combinator libraries like [parsec],\n[attoparsec], or the json parser [aeson] you will feel right at\nhome with purescript-optparse.\n\nIf not, don't worry! All you really need to learn are a few basic\nparsers, and how to compose them as instances of `Applicative` and\n`Alternative`.\n\n## Quick Start\n\nHere's a simple example of a parser.\n\n```purs\nimport Options.Applicative\nimport Data.Semigroup ((\u003c\u003e))\n\ndata Sample = Sample\n  { hello      :: String\n  , quiet      :: Boolean\n  , enthusiasm :: Int }\n\nsample :: Parser Sample\nsample = ado\n  hello \u003c- strOption $ fold\n    [ long \"hello\"\n    , metavar \"TARGET\"\n    , help \"Target for the greeting\"\n    ]\n\n  -- OR\n  -- hello \u003c- strOption\n  --         ( long \"hello\"\n  --        \u003c\u003e metavar \"TARGET\"\n  --        \u003c\u003e help \"Target for the greeting\" )\n\n  quiet \u003c- switch $ fold\n    [ long \"quiet\"\n    , short 'q'\n    , help \"Whether to be quiet\"\n    ]\n\n  enthusiasm \u003c- option int $ fold\n    [ long \"enthusiasm\"\n    , help \"How enthusiastically to greet\"\n    , showDefault\n    , value 1\n    , metavar \"INT\"\n    ]\n  \n  in Sample { hello, quiet, enthusiasm }\n```\n\nThe parser is built using an applicative style starting from a\nset of basic combinators (you can also check [Applicative Do](#applicative-do)\nsection for definition of `sample` using `ado`). In this example, hello is defined as an\noption with a `String` argument, while quiet is a boolean flag\n(called a switch) and enthusiasm gets parsed as an `Int` with help\nof the `int :: ReadM Int`.\n\n\nThe parser can be used like this:\n\n```purs\nmain :: Effect Unit\nmain = greet =\u003c\u003c execParser opts\n  where\n    opts = info (sample \u003c**\u003e helper)\n      ( fullDesc\n     \u003c\u003e progDesc \"Print a greeting for TARGET\"\n     \u003c\u003e header \"hello - a test for purescript-optparse\" )\n\ngreet :: Sample -\u003e Effect Unit\ngreet (Sample h false n) = putStrLn $ \"Hello, \" ++ h ++ replicate n '!'\ngreet _ = return unit\n```\n\nThe `greet` function is the entry point of the program, while `opts`\nis a complete description of the program, used when generating a\nhelp text. The `helper` combinator takes any parser, and adds a\n`help` option to it.\n\nThe `hello` option in this example is mandatory since it doesn't\nhave a default value, so running the program without any argument\nwill display an appropriate error message and a short option summary:\n\n    Missing: --hello TARGET\n\n    Usage: hello --hello TARGET [-q|--quiet] [--enthusiasm INT]\n      Print a greeting for TARGET\n\nRunning the program with the `--help` option will display the full help text\ncontaining a detailed list of options with descriptions\n\n```\n    hello - a test for purescript-optparse\n\n    Usage: hello --hello TARGET [-q|--quiet] [--enthusiasm INT]\n      Print a greeting for TARGET\n\n    Available options:\n      --hello TARGET           Target for the greeting\n      -q,--quiet               Whether to be quiet\n      --enthusiasm INT         How enthusiastically to greet (default: 1)\n      -h,--help                Show this help text\n```\n\n## Basics\n### Parsers\n\npurescript-optparse provides a number of primitive parsers,\ncorresponding to different posix style options, through its *Builder*\ninterface. These are detailed in their [own section](#builders)\nbelow, for now, here's a look at a few more examples to get a feel\nfor how parsers can be defined.\n\n\nHere is a parser for a mandatory option with an argument:\n\n```purs\ntarget :: Parser String\ntarget = strOption\n  (  long \"hello\"\n  \u003c\u003e metavar \"TARGET\"\n  \u003c\u003e help \"Target for the greeting\" )\n```\n\nOne can see that we are defining an option parser for a `String`\nargument, with *long* option name \"hello\", *metavariable* \"TARGET\",\nand the given help text. This means that the `target` parser defined\nabove will require an option like\n\n    --hello world\n\non the command line. The metavariable and the help text will appear\nin the generated help text, but don't otherwise affect the behaviour\nof the parser.\n\nThe attributes passed to the option are called *modifiers*, and are\ncomposed using the semigroup operation `(\u003c\u003e)`.\n\nOptions with an argument such as `target` are referred to as *regular\noptions*, and are very common.  Another type of option is a *flag*,\nthe simplest of which is a boolean *switch*, for example:\n\n```purs\nquiet :: Parser Boolean\nquiet = switch ( long \"quiet\" \u003c\u003e short 'q' \u003c\u003e help \"Whether to be quiet\" )\n```\n\nHere we used a `short` modifier to specify a one-letter name for\nthe option.  This means that this switch can be set either with\n`--quiet` or `-q`.\n\nFlags, unlike regular options, have no arguments. They simply return\na predetermined value. For the simple switch above, this is `true`\nif the user types the flag, and `false` otherwise.\n\nThere are other kinds of basic parsers, and several ways to configure\nthem.  These are covered in the [Builders](#builders) section.\n\n### Applicative\n\nNow we may combine the `target` and `quiet` into a single parser that\naccepts both options and returns a combined value. Given a type\n\n```purs\ndata Options = Options\n  { optTarget :: String\n  , optQuiet :: Boolean }\n```\n\nand now it's just a matter of using `Applicative`'s apply operator `(\u003c*\u003e)`\nto combine the two previously defined parsers\n\n```purs\nopts :: Parser Options\nopts = Options \u003c$\u003e target \u003c*\u003e quiet\n```\n\nNo matter which parsers appear first in the sequence, options will\nstill be parsed in whatever order they appear in the command line.\nA parser with such a property is sometimes called a *permutation\nparser*.\n\nIn our example, a command line like:\n\n    --target world -q\n\nwill give the same result as\n\n    -q --target world\n\nIt is this property which leads us to an Applicative interface\ninstead of a Monadic one, as all options must be considered in\nparallel, and can not depend on the output of other options.\n\nNote, however, that the order of sequencing is still somewhat\nsignificant, in that it affects the generated help text. Customisation\ncan be achieved easily by using [ApplicativeDo](#applicative-do).\n\n### Alternative\n\nIt is also common to find programs that can be configured in different\nways through the command line.  A typical example is a program that\ncan be given a text file as input, or alternatively read it directly\nfrom the standard input.\n\nWe can model this easily and effectively in Haskell using *sum types*:\n\n```purs\ndata Input\n  = FileInput FilePath\n  | StdInput\n\nrun :: Input -\u003e Effect Unit\nrun = ...\n```\n\nWe can now define two basic parsers for the components of the sum type:\n\n```purs\nfileInput :: Parser Input\nfileInput = FileInput \u003c$\u003e strOption\n  (  long \"file\"\n  \u003c\u003e short 'f'\n  \u003c\u003e metavar \"FILENAME\"\n  \u003c\u003e help \"Input file\" )\n\nstdInput :: Parser Input\nstdInput = flag' StdInput\n  (  long \"stdin\"\n  \u003c\u003e help \"Read from stdin\" )\n```\n\nAs the `Parser` type constructor is an instance of `Alternative`, we can\ncompose these parsers with a choice operator `(\u003c|\u003e)`\n\n```purs\ninput :: Parser Input\ninput = fileInput \u003c|\u003e stdInput\n```\n\nNow `--file \"foo.txt\"` will be parsed as `FileInput \"foo.txt\"`, `--stdin`\nwill be parsed as `StdInput`, but a command line containing both options,\nlike\n\n    --file \"foo.txt\" --stdin\n\nwill be rejected.\n\nHaving `Applicative` and `Alternative` instances, purescript-optparse\nparsers are also able to be composed with standard combinators. For\nexample: `optional :: Alternative f =\u003e f a -\u003e f (Maybe a)` will\nmean the user is not required to provide input for the affected\n`Parser`.\n\n### Running parsers\n\nBefore we can run a `Parser`, we need to wrap it into a `ParserInfo`\nstructure, that specifies a number of properties that only apply\nto top level parsers, such as a header describing what the program\ndoes, to be displayed in the help screen.\n\nThe function `info` will help with this step.  In the [Quick Start](#quick-start)\nwe saw\n\n```purs\nopts :: ParserInfo Sample\nopts = info (sample \u003c**\u003e helper)\n  ( fullDesc\n  \u003c\u003e progDesc \"Print a greeting for TARGET\"\n  \u003c\u003e header \"hello - a test for purescript-optparse\" )\n```\n\nThe `helper` parser that we added after `opts` just creates a dummy\n`--help` option that displays the help text. Besides that, we just\nset some of the fields of the `ParserInfo` structure with meaningful\nvalues. Now that we have a `ParserInfo`, we can finally run the\nparser. The simplest way to do so is to simply call the `execParser`\nfunction in your `main`:\n\n```purs\nmain :: Effect Unit\nmain = do\n  options \u003c- execParser opts\n  ...\n```\n\nThe `execParser` function takes care of everything, including getting\nthe arguments from the command line, displaying errors and help\nscreens to the user, and exiting with an appropriate exit code.\n\nThere are other ways to run a `ParserInfo`, in situations where you\nneed finer control over the behaviour of your parser, or if you\nwant to use it in pure code. They will be covered in [Custom parsing\nand error handling](#custom-parsing-and-error-handling).\n\n## Builders\n\nBuilders allow you to define parsers using a convenient combinator-based\nsyntax. We have already seen examples of builders in action, like\n`strOption` and `switch`, which we used to define the `opts` parser\nfor our \"hello\" example.\n\nBuilders always take a [modifier](#modifiers) argument, which is\nessentially a composition of functions acting on the option, setting\nvalues for properties or adding features.\n\nBuilders work by building the option from scratch, and eventually\nlifting it to a single-option parser, ready to be combined with\nother parsers using normal `Applicative` and `Alternative` combinators.\n\nThere are four different kinds of options in `purescript-optparse`:\nregular options, flags, arguments, and commands. In the following,\nwe will go over each one of these and describe the builders that\ncan be used to create them.\n\n### Regular options\n\nA *regular option* is an option which takes a single argument,\nparses it, and returns a value.\n\nA regular option can have a default value, which is used as the\nresult if the option is not found in the command line. An option\nwithout a default value is considered mandatory, and produces an\nerror when not found.\n\nRegular options can have *long* names, or *short* (one-character)\nnames, which determine when the option matches and how the argument\nis extracted.\n\nAn option with a long name (say \"output\") is specified on the command\nline as\n\n\n    --output filename.txt\n\nor\n\n    --output=filename.txt\n\nwhile a short name option (say \"o\") can be specified with\n\n    -o filename.txt\n\nor\n\n    -ofilename.txt\n\nOptions can have more than one name, usually one long and one short,\nalthough you are free to create options with an arbitrary combination\nof long and short names.\n\nRegular options returning strings are the most common, and they can\nbe created using the `strOption` builder. For example,\n\n```purs\nstrOption\n   ( long \"output\"\n  \u003c\u003e short 'o'\n  \u003c\u003e metavar \"FILE\"\n  \u003c\u003e value \"out.txt\"\n  \u003c\u003e help \"Write output to FILE\" )\n```\n\ncreates a regular option with a string argument (which can be\nreferred to as `FILE` in the help text and documentation), default\nvalue \"out.txt\", a long name \"output\" and a short name \"o\".\n\nA regular `option` can return an object of any type, and takes a\n*reader* parameter which specifies how the argument should be parsed.\nBuilt in readers are `str`, `int`, `number` and `boolean` for example:\n\n```purs\nlineCount :: Parser Int\nlineCount = option int\n            ( long \"lines\"\n           \u003c\u003e short 'n'\n           \u003c\u003e metavar \"K\"\n           \u003c\u003e help \"Output the last K lines\" )\n```\n\nFurther information on *readers* is available [below](#option-readers).\n\n### Flags\n\nA *flag* is just like a regular option, but it doesn't take any\narguments, it is either present in the command line or not.\n\nA flag has a default value and an *active value*. If the flag is\nfound on the command line, the active value is returned, otherwise\nthe default value is used. For example:\n\n```purs\ndata Verbosity = Normal | Verbose\n\nflag Normal Verbose\n  ( long \"verbose\"\n \u003c\u003e short 'v'\n \u003c\u003e help \"Enable verbose mode\" )\n```\n\nis a flag parser returning a `Verbosity` value.\n\nSimple boolean flags can be specified using the `switch` builder, like so:\n\n```purs\nswitch\n  ( long \"keep-tmp-files\"\n \u003c\u003e help \"Retain all intermediate temporary files\" )\n```\n\nThere is also a `flag'` builder, which has no default value. This\nwas demonstrated earlier for our `--stdin` flag example, and is\nusually used as one side of an alternative.\n\nAnother interesting use for the `flag'` builder is to count the\nnumber of instances on the command line, for example, verbosity\nsettings could be specified on a scale; the following parser will\ncount the number of instances of `-v` on the command line.\n\n```purs\nlength \u003c$\u003e many (flag' unit (short 'v'))\n```\n\nFlags can be used together after a single hyphen, so  `-vvv` and\n`-v -v -v` will both yield 3 for the above parser.\n\n### Arguments\n\nAn *argument* parser specifies a positional command line argument.\n\nThe `argument` builder takes a reader parameter, and creates a\nparser which will return the parsed value every time it is passed\na command line argument for which the reader succeeds. For example\n\n```purs\nargument str (metavar \"FILE\")\n```\n\ncreates an argument accepting any string. To accept an arbitrary\nnumber of arguments, combine the `argument` builder with either the\n`many` or `some` combinator:\n\n```purs\nsome (argument str (metavar \"FILES...\"))\n```\n\nNote that arguments starting with `-` are considered options by\ndefault, and will not be considered by an `argument` parser.\n\nHowever, parsers always accept a special argument: `--`. When a\n`--` is found on the command line, all the following words are\nconsidered by `argument` parsers, regardless of whether they start\nwith `-` or not.\n\nArguments use the same *readers* as regular options.\n\n### Commands\n\nA *command* can be used to specify a sub-parser to be used when a\ncertain string is encountered in the command line.\n\nCommands are useful to implement command line programs with multiple\nfunctions, each with its own set of options, and possibly some\nglobal options that apply to all of them. Typical examples are\nversion control systems like `git`, or build tools like `cabal`.\n\nA command can be created using the `subparser` builder (or `hsubparser`,\nwhich is identical but for an additional `--help` option on each\ncommand), and commands can be added with the `command` modifier.\nFor example\n\n```purs\nsubparser\n  ( command \"add\" (info addOptions ( progDesc \"Add a file to the repository\" ))\n \u003c\u003e command \"commit\" (info commitOptions ( progDesc \"Record changes to the repository\" ))\n  )\n```\n\nEach command takes a full `ParserInfo` structure, which will be\nused to extract a description for this command when generating a\nhelp text.\n\nNote that all the parsers appearing in a command need to have the\nsame type.  For this reason, it is often best to use a sum type\nwhich has the same structure as the command itself. For example,\nfor the parser above, you would define a type like:\n\n```purs\ndata Options = Options\n  { optCommand :: Command\n  , ... }\n\ndata Command\n  = Add AddOptions\n  | Commit CommitOptions\n  ...\n```\n\nAlternatively, you can directly return an `Effect` action from a parser,\nand execute it using `join` from `Control.Monad`.\n\n```purs\nstart :: String -\u003e Effect Unit\nstop :: Effect Unit\n\nopts :: Parser (Effect Unit)\nopts = subparser\n  ( command \"start\" (info (start \u003c$\u003e argument str idm) idm)\n \u003c\u003e command \"stop\"  (info (pure stop) idm) )\n\nmain :: Effect Unit\nmain = join $ execParser (info opts idm)\n```\n\n### Modifiers\n\n*Modifiers* are instances of the `Semigroup` and `Monoid` typeclasses,\nso they can be combined using the composition function `append`\n(or simply `(\u003c\u003e)`). Since different builders accept different sets\nof modifiers, modifiers have a type parameter that specifies which\nbuilders support it.\n\nFor example,\n\n```purs\ncommand :: forall a. String -\u003e ParserInfo a -\u003e Mod CommandFields a\n```\n\ncan only be used with [commands](#commands), as the `CommandFields`\ntype argument of `Mod` will prevent it from being passed to builders\nfor other types of options.\n\nMany modifiers are polymorphic in this type argument, which means\nthat they can be used with any builder.\n\n### Common Builder Patterns\n\n#### A list of values with a default\n\nWe'll show one wrong way to do it and then show 2 ways of implementing it.\n\nWrong way: using `some (strOption modifiers)`/`many (strOption modifiers)`.\nWe could use `some (strOption (long \"arg-name\" \u003c\u003e value \"default\"))`, which allows you to pass in values like this:\n`command --arg-name value1 --arg-name value2`\n\nHowever, combining `some`/`many` with a default `value` modifier guarantees that the parser will never terminate. Rather, it'll run forever and eventually your machine will run out of stack/memory and crash. Why? Because `some`/`many` work by parsing forever until they fail and then they return all the results they found. If the `value` modifier is added, then these parsers will never fail.\n\nRight way (but inconsistent): using `many (optionArgs) \u003c|\u003e pure (\"default\" : Nil)`\nThis will terminate, but it's implementation is not consistent with how we implement other options with a default value that appears in the help text.\n\nUsing a more verbose example:\n```purescript\nparseStringList :: Parser (List String)\nparseStringList =\n  let\n    defaultValue = \"default\" : Nil\n    listStrOption =\n      many (strOption ( long \"arg-name\"\n                      \u003c\u003e help (\"Option explanation, \\\n                               \\default: \" \u003c\u003e show defaultValue\n                              )\n                      )\n           )\n  in listStrOption \u003c|\u003e (pure defaultValue)\n```\n\nRight way (and consistent: use `eitherReader` to define our own `ReadM` that properly handles this:\n```purescript\nmultiString :: Pattern -\u003e ReadM (Array String)\nmultiString splitPattern = eitherReader \\s -\u003e\n  let strArray = filter (not \u003c\u003c\u003c String.null) $ split splitPattern s\n  in\n    if Array.null strArray\n      then Left \"got empty string as input\"\n      else Right strArray\n\ncommaSeparatedStringList :: Parser (Array String)\ncommaSeparatedStringList =\noption (multiString $ Pattern \",\")\n    ( long \"arg-name\"\n   \u003c\u003e metavar \"value1,value2,...,value3\"\n   \u003c\u003e help \"A comma-separated list of strings\"\n   \u003c\u003e value [ \"first\", \"second\", \"third\" ]\n   \u003c\u003e showDefaultWith (\\array -\u003e intercalate \",\" array)\n    )\n```\nUsing the above, we could then pass in our arguments like this:\n`command --arg-name first,second,third`\n\nMoreover, the help text would also display useful information here:\n```\n--arg-name value1,value2,...,value3\n      A comma-separated list of strings. (default: first,second,third)\n```\n\n## Custom parsing and error handling\n\n### Parser runners\nParsers are run with the `execParser` family of functions — from\neasiest to use to most flexible these are:\n\n```purs\nexecParser       :: forall a. ParserInfo a -\u003e Effect a\ncustomExecParser :: forall a. ParserPrefs -\u003e ParserInfo a -\u003e Effect a\nexecParserPure   :: forall a. ParserPrefs -\u003e ParserInfo a -\u003e Array String -\u003e ParserResult a\n```\n\nWhen using the `Effect` functions, retrieving command line arguments\nand handling exit codes and failure will be done automatically.\nWhen using `execParserPure`, the functions\n\n```purs\nhandleParseResult :: forall a. ParserResult a -\u003e Effect a\noverFailure :: forall a. (ParserHelp -\u003e ParserHelp) -\u003e ParserResult a -\u003e ParserResult a\n```\n\ncan be used to correctly set exit codes and display the help message;\nand modify the help message in the event of a failure (adding\nadditional information for example).\n\n### Option readers\n\nOptions and Arguments require a way to interpret the string passed\non the command line to the type desired. `str`, `int`, `number` and\n`boolean` are Built in *readers*, but one can also create a custom\nreader and use it to parse the option. A custom reader is a value in the\n`ReadM` monad.\n\nWe provide the `eitherReader :: forall a. (String -\u003e Either String a) -\u003e ReadM a`\nconvenience function to help create these values, where a `Left` will\nhold the error message for a parse failure.\n\n```purs\ndata FluxCapacitor = ...\n\nparseFluxCapacitor :: ReadM FluxCapacitor\nparseFluxCapacitor = eitherReader $ \\s -\u003e ...\n\noption parseFluxCapacitor ( long \"flux-capacitor\" )\n```\n\nOne can also use `ReadM` directly, using `readerAsk` to obtain the\ncommand line string, and `readerAbort` or `readerError` within the\n`ReadM` monad to exit with an error message.\n\n### Preferences\n`PrefsMod`s can be used to customise the look of the usage text and\ncontrol when it is displayed; turn off backtracking of subparsers;\nand turn on [disambiguation](#disambiguation).\n\nTo use these modifications, provide them to the `prefs` builder,\nand pass the resulting preferences to one of the parser runners\nthat take an `ParserPrefs` parameter, like `customExecParser`.\n\n\n### Disambiguation\n\nIt is possible to configure purescript-optparse to perform automatic\ndisambiguation of prefixes of long options. For example, given a\nprogram `foo` with options `--filename` and `--filler`, typing\n\n    $ foo --fil test.txt\n\nfails, whereas typing\n\n    $ foo --file test.txt\n\nsucceeds, and correctly identifies `\"file\"` as an unambiguous prefix\nof the `filename` option.\n\nOption disambiguation is *off* by default. To enable it, use the\n`disambiguate` `PrefsMod` modifier as described above.\n\nHere is a minimal example:\n\n```purs\nimport Options.Applicative\n\nsample :: Parser Unit\nsample = unit \u003c$\n  switch (long \"filename\") \u003c*\n  switch (long \"filler\")\n\nmain :: Effect Unit\nmain = customExecParser p opts\n  where\n    opts = info (helper \u003c*\u003e sample) idm\n    p = prefs disambiguate\n\n```\n\n### Customising the help screen\n\npurescript-optparse has a number of combinators to help customise\nthe usage text, and determine when it should be displayed.\n\nThe `progDesc`, `header`, and `footer` functions can be used to\nspecify a brief description or tagline for the program, and detailed\ninformation surrounding the generated option and command descriptions.\n\nInternally we actually use the port of [ansi-wl-pprint][ansi-wl-pprint]\nlibrary, and one can use the `headerDoc` combinator and friends if\nadditional customisation is required.\n\nTo display the usage text, the user may type `--help` if the `helper`\ncombinator has been applied to the `Parser`.\n\nAuthors can also use the preferences `showHelpOnError` or\n`showHelpOnEmpty` to show the help text on any parser failure or\nwhen a command is not complete and at the beginning of the parse\nof the main program or one of its subcommands respectively.\n\nEven if the help text is not shown for an error, a specific error\nmessage will be, indicating what's missing, or what was unable to\nbe parsed.\n\n```purs\nmyParser :: Parser Unit\nmyParser = ...\n\nmain :: Effect Unit\nmain = customExecParser p opts\n  where\n    opts = info (myParser \u003c**\u003e helper) idm\n    p = prefs showHelpOnEmpty\n```\n\n### Command groups\n\nOne experimental feature which may be useful for programs with many\nsubcommands is command group separation.\n\n```purs\ndata Sample\n  = Hello (Array String)\n  | Goodbye\n  deriving (Eq, Show)\n\nhello :: Parser Sample\nhello = Hello \u003c$\u003e many (argument str (metavar \"TARGET...\"))\n\nsample :: Parser Sample\nsample = subparser\n       ( command \"hello\" (info hello (progDesc \"Print greeting\"))\n      \u003c\u003e command \"goodbye\" (info (pure Goodbye) (progDesc \"Say goodbye\"))\n       )\n      \u003c|\u003e subparser\n       ( command \"bonjour\" (info hello (progDesc \"Print greeting\"))\n      \u003c\u003e command \"au-revoir\" (info (pure Goodbye) (progDesc \"Say goodbye\"))\n      \u003c\u003e commandGroup \"French commands:\"\n      \u003c\u003e hidden\n       )\n```\n\nThis will logically separate the usage text for the two subparsers\n(these would normally appear together if the `commandGroup` modifier\nwas not used). The `hidden` modifier suppresses the metavariable\nfor the second subparser being show in the brief usage line, which\nis desirable in some cases.\n\nIn this example we have essentially created synonyms for our parser,\nbut one could use this to separate common commands from rare ones,\nor safe from dangerous.\n\nThe usage text for the preceding example is:\n```\nUsage: commands COMMAND\n\nAvailable options:\n  -h,--help                Show this help text\n\nAvailable commands:\n  hello                    Print greeting\n  goodbye                  Say goodbye\n\nFrench commands:\n  bonjour                  Print greeting\n  au-revoir                Say goodbye\n```\n\n## Bash, Zsh, and Fish Completions\n\n`purescript-optparse` has built-in support for the completion of\ncommand line options and arguments in bash, zsh, and fish shells.\nAny parser, when run using the `execParser` family of functions,\nis automatically extended with a few (hidden) options for the\ncompletion system:\n\n - `--bash-completion-script`: this takes the full path of the program as\n   argument, and prints a bash script, which, when sourced into a bash session,\n   will install the necessary machinery to make bash completion work. For a\n   quick test, you can run something like (for a program called `foo` on the\n   `PATH`):\n\n   ```console\n   $ source \u003c(foo --bash-completion-script `which foo`)\n   ```\n\n   Normally, the output of `--bash-completion-script` should be shipped with\n   the program and copied to the appropriate directory (usually\n   `/etc/bash_completion.d/`) during installation;\n\n - `--zsh-completion-script`: which is analogous for zsh;\n\n - `--fish-completion-script`: which is analogous for fish shell;\n\n - `--bash-completion-index`, `--bash-completion-word`: internal options used\n   by the completion script to obtain a list of possible completions for a\n   given command line;\n\n - `--bash-completion-enriched`: a flag to tell the completion system to emit\n   descriptions along with possible completions. This is used to provide help\n   along with the completion for `zsh` and `fish`.\n\n### Actions and completers\n\nBy default, options and commands are always completed. So, for example, if the\nprogram `foo` has an option with a long name `output`, typing\n\n```console\n$ foo --ou\u003cTAB\u003e\n```\n\nwill complete `--output` automatically.\n\nArguments (either of regular options, or top-level) are not completed by\ndefault. To enable completion for arguments, use one of the following modifiers\non a regular option or argument:\n\n - `completeWith`: specifies a list of possible completions to choose from;\n - `action`: specifies a completion \"action\". An action dynamically determines\n   a list of possible completions. Common actions are \"file\" and \"directory\";\n   the full list of actions can be found in the [bash documentation];\n - `completer`: a completer is a function `String -\u003e Effect (Array String)`, returning\n   all possible completions for a given string. You can use this modifier to\n   specify a custom completion for an argument.\n\nCompletion modifiers can be used multiple times: the resulting completions will\ncall all of them and join the results.\n\n### Internals\n\nWhen running a parser with `execParser`, the parser is extended with\n`bashCompletionParser`, which defines the above options.\n\nWhen completion is triggered, the completion script calls the executable with\nthe special `--bash-completion-index` and `--bash-completion-word` options.\n\nThe original parser is therefore run in *completion mode*, i.e. `runParser` is\ncalled on a different monad, which keeps track of the current state of the\nparser, and exits when all arguments have been processed.\n\nThe completion monad returns, on failure, either the last state of the parser\n(if no option could be matched), or the completer associated to an option (if\nit failed while fetching the argument for that option).\n\nFrom that we generate a list of possible completions, and print them to\nstandard output. They are then read by the completion script and put into the\n`COMPREPLY` variable (or an appropriate alternative for the other shells).\n\n## Applicative do\n\nSome may find using purescript-optparse easier using `ado` notation. For example,\na parser specified in this `Sample` outlined in [Quick Start](#quick-start)\nwill look like this:\n\n```purs\nsample :: Parser Sample\nsample = ado\n  hello \u003c- strOption\n          ( long \"hello\"\n         \u003c\u003e metavar \"TARGET\"\n         \u003c\u003e help \"Target for the greeting\" )\n  quiet \u003c- switch\n          ( long \"quiet\"\n         \u003c\u003e short 'q'\n         \u003c\u003e help \"Whether to be quiet\" )\n  enthusiasm \u003c- option auto\n          ( long \"enthusiasm\"\n         \u003c\u003e help \"How enthusiastically to greet\"\n         \u003c\u003e showDefault\n         \u003c\u003e value 1\n         \u003c\u003e metavar \"INT\" )\n  in Sample { hello, quiet, enthusiasm }\n```\n\n## FAQ\n\n* Monadic parsing?\n\n  If a Monadic style were to be used, there would be no possible\n  way to traverse the parser and generate a usage string, or for\n  us to allow for options to be parsed in any order. Therefore it\n  is intentionally unsupported to write a `Parser` in this manner\n  with purescript-optparse, and the `Parser` type does not have\n  an instance for `Monad`.\n\n* Overlapping flags and options / options with optional arguments?\n\n  This is not supported as it can lead to an ambiguous parse.\n\n  For example, if we supported and had an optional value option\n  \"--foo\" and a flag \"--bar\", is \"--foo --bar\" the option with value\n  \"--bar\", or the default value with the flag switched on? What if\n  instead of a switch we had many positional string arguments, is\n  the first string the option's value or the first positional?\n\n  It is suggested to instead use the `Alternative` instance of\n  `Parser` and create a flag', an option, and a pure value for the\n  default (with different names for the flag and option).\n\n* Backtracking on `ReadM` errors?\n\n  Parser structures are predetermined at parse time. This means\n  that if a `ReadM` fails, the whole parse must also fail, we can't\n  consider any alternatives, as there can be no guarantee that the\n  remaining structure will fit.  One occasionally confusing side\n  effect of this is that two positional arguments for different\n  constructors of a sum type can't be composed at the parser level;\n  rather, this must be done at the `ReadM` level. For example:\n\n  ```purs\n  import Options.Applicative\n\n  data S3orFile = S3 BucketKey | File FilePath\n\n  s3Read, fileRead :: ReadM S3orFile\n  s3Read = S3 \u003c$\u003e ...\n  fileRead = File \u003c$\u003e ...\n\n  correct :: Parser S3orFile\n  correct = argument (s3Read \u003c|\u003e fileRead) idm\n\n  incorrect :: Parser S3orFile\n  incorrect = argument s3Read idm \u003c|\u003e argument fileRead idm\n  ```\n\n## How it works\nAn applicative `Parser` is essentially a heterogeneous list or tree\nof `Option`s, implemented with existential types.\n\nAll options are therefore known statically (i.e. before parsing,\nnot necessarily before runtime), and can, for example, be traversed\nto generate a help text. Indeed, when displaying the usage text for\na parser, we use an intermediate tree structure.\n\nWhen we examine the user's input, each argument is examined to\ndetermine if it's an option or flag, or a positional argument. The\nparse tree is then searched for a matching term, and if it finds\none, that leaf of the tree is replaced with the value itself. When\nall input has been processed, we see if we can generate the complete\nvalue, and if not issue an error.\n\nSee [this blog post][blog] for a more detailed explanation based on a\nsimplified implementation.\n\n [aeson]: http://hackage.haskell.org/package/aeson\n [attoparsec]: http://hackage.haskell.org/package/attoparsec\n [bash documentation]: http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html\n [blog]: http://paolocapriotti.com/blog/2012/04/27/applicative-option-parser/\n [parsec]: http://hackage.haskell.org/package/parsec\n [status]: http://travis-ci.org/f-o-a-m/purescript-optparse?branch=master\n [status-png]: https://api.travis-ci.org/f-o-a-m/purescript-optparse.svg?branch=master\n [ansi-wl-pprint]: http://hackage.haskell.org/package/ansi-wl-pprint\n [optparse-applicative]: https://github.com/pcapriotti/optparse-applicative\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurescript-contrib%2Fpurescript-optparse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurescript-contrib%2Fpurescript-optparse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurescript-contrib%2Fpurescript-optparse/lists"}