2022-03-12 00:18:41 +08:00
fish_opt - create an option specification for the argparse command
==================================================================
2018-12-16 17:39:33 -08:00
2018-12-17 17:58:24 -08:00
Synopsis
--------
docs synopsis: add HTML highlighing and automate manpage markup
Recent synopsis changes move from literal code blocks to
[RST line blocks]. This does not translate well to HTML: it's not
rendered in monospace, so aligment is lost. Additionally, we don't
get syntax highlighting in HTML, which adds differences to our code
samples which are highlighted.
We hard-wrap synopsis lines (like code blocks). To align continuation
lines in manpages we need [backslashes in weird places]. Combined with
the **, *, and `` markup, it's a bit hard to get the alignment right.
Fix these by moving synopsis sources back to code blocks and compute
HTML syntax highlighting and manpage markup with a custom Sphinx
extension.
The new Pygments lexer can tokenize a synopsis and assign the various
highlighting roles, which closely matches fish's syntax highlighing:
- command/keyword (dark blue)
- parameter (light blue)
- operator like and/or/not/&&/|| (cyan)
- grammar metacharacter (black)
For manpage output, we don't project the fish syntax highlighting
but follow the markup convention in GNU's man(1):
bold text type exactly as shown.
italic text replace with appropriate argument.
To make it easy to separate these two automatically, formalize that
(italic) placeholders must be uppercase; while all lowercase text is
interpreted literally (so rendered bold).
This makes manpages more consistent, see string-join(1) and and(1).
Implementation notes:
Since we want manpage formatting but Sphinx's Pygments highlighing
plugin does not support manpage output, add our custom "synopsis"
directive. This directive parses differently when manpage output is
specified. This means that the HTML and manpage build processes must
not share a cache, because the parsed doctrees are cached. Work around
this by using separate cache locations for build targets "sphinx-docs"
(which creates HTML) and "sphinx-manpages". A better solution would
be to only override Sphinx's ManualPageBuilder but that would take a
bit more code (ideally we could override ManualPageWriter but Sphinx
4.3.2 doesn't really support that).
---
Alternative solution: stick with line blocks but use roles like
:command: or :option: (or custom ones). While this would make it
possible to produce HTML that is consistent with code blocks (by adding
a bit of CSS), the source would look uglier and is harder to maintain.
(Let's say we want to add custom formatting to the [|] metacharacters
in HTML. This is much easier with the proposed patch.)
---
[RST line blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#line-blocks
[backslashes in weird places]: https://github.com/fish-shell/fish-shell/pull/8626#discussion_r782837750
2022-01-09 15:09:46 +01:00
.. synopsis ::
2025-08-03 10:07:08 +10:00
fish_opt [-s ALPHANUM] [-l LONG-NAME] [-ormd] [--long-only] [-v COMMAND OPTIONS ... ]
2022-03-12 00:18:41 +08:00
fish_opt --help
2018-12-16 13:08:41 -08:00
2018-12-18 18:44:30 -08:00
Description
2019-01-02 20:10:47 -08:00
-----------
2018-12-16 13:08:41 -08:00
2022-09-23 19:57:49 +02:00
This command provides a way to produce option specifications suitable for use with the :doc: `argparse <argparse>` command. You can, of course, write the option specifications by hand without using this command. But you might prefer to use this for the clarity it provides.
2018-12-16 13:08:41 -08:00
2018-12-19 12:02:45 -08:00
The following `` argparse `` options are available:
2018-12-16 13:08:41 -08:00
2025-08-18 08:14:54 +10:00
**-s** or **--short** *ALPHANUM*
2025-08-03 10:07:08 +10:00
Takes a single letter or number that is used as the short flag in the option being defined. Either this option or the **--long** option must be provided.
2018-12-16 13:08:41 -08:00
2025-08-18 08:14:54 +10:00
**-l** or **--long** *LONG-NAME*
2025-08-03 10:07:08 +10:00
Takes a string that is used as the long flag in the option being defined. This option is optional and has no default. If no long flag is defined then only the short flag will be allowed when parsing arguments using the option specification.
2018-12-16 13:08:41 -08:00
2022-03-11 23:56:20 +08:00
**--long-only**
2025-08-03 10:07:08 +10:00
Deprecated. The option being defined will only allow the long flag name to be used, even if the short flag is defined (i.e., **--short** is specified).
2018-12-16 13:08:41 -08:00
2022-03-11 23:56:20 +08:00
**-o** or **--optional-val**
2023-11-18 17:51:52 +01:00
The option being defined can take a value, but it is optional rather than required. If the option is seen more than once when parsing arguments, only the last value seen is saved. This means the resulting flag variable created by `` argparse `` will zero elements if no value was given with the option else it will have exactly one element.
2018-12-16 13:08:41 -08:00
2022-03-11 23:56:20 +08:00
**-r** or **--required-val**
The option being defined requires a value. If the option is seen more than once when parsing arguments, only the last value seen is saved. This means the resulting flag variable created by `` argparse `` will have exactly one element.
2018-12-16 13:08:41 -08:00
Added argparse support for arguments with multiple optional values.
This commit fixes #8432 by adding put =* in an option spec to indicate that the
option takes an optional value, where subsequent uses of the option accumulate
the value (so the parsing behaviour is like =?, but the _flag_ variables are
appended to like =+). If the option didn't have a value, it appends an empty
string. As an example,. long=* -- --long=1 --long will execute
set -l _flag_long 1 '' (i.e. count $_flag_long is 2), whereas with =? instead,
you'd get set -l _flag_long (i.e. count $_flag_long is 0).
As a use case, I'm aware of git clone which has a
--recurse-submodules=[<pathspec>]: if you use it without a value, it operates on
all submodules, with a value, it operates on the given submodule.
The fish_opt function will generate an =* option spec when given both the
--optional-val and --multiple-vals options (previously, doing so was an error).
fish_opt now also accepts -m as an abbreviation for --multiple-vals, to go with
the pre-existing -o and -r abbreviations for --optional-val and --required-val.
2025-08-19 13:25:26 +10:00
**-m** or **--multiple-vals**
The value of each instance of the option is accumulated. If **--optional-val** is provided, the value is optional, and an empty string is stored if no value is provided. Otherwise, the **--requiured-val** option is implied and each instance of the option requires a value. This means the resulting flag variable created by `` argparse `` will have one element for each instance of this option in the arguments, even for instances that did not provide a value.
2018-12-16 13:08:41 -08:00
Added way to tell argparse to delete an option from $argv_opts.
The intention is that if you want to parse some of your options verbatim to
another command, but you want to modfy other options (e.g. change their value,
convert them to other options, or delete them entirely), you mark the options
you want to modify with an &, and argparse will not add them to argv_opts. You
can then call the other command with argv_opts together with any new/modified
options, ensuring that the other command doesn't set the pre-modified options.
As with other known options, & options will be removed from $argv, and have
their $_flag_ variables set.
The `&` goes at the end of the option spec, or if the option spec contains a
validation script, immediately before the `!`. There is also now a -d/--delete
flag to fish_opt that will generate such an option spec.
See the changes in doc_src/cmds/argparse.rst for more details and an example use
case.
2025-08-03 10:07:08 +10:00
**-d** or **--delete**
The option and any values will be deleted from the `` $argv_opts `` variables set by `` argparse ``
(as with other options, it will also be deleted from `` $argv `` ).
2025-08-03 10:07:08 +10:00
**-v** or **--validate** *COMMAND* *OPTION...*
This option must be the last one, and requires one of `` -o `` , `` -r `` , or `` -m `` . All the remaining arguments are interpreted a fish script to run to validate the value of the argument, see `` argparse `` documentation for more details. Note that the interpretation of *COMMAND* *OPTION...* is similar to `` eval `` , so you may need to quote or escape special characters *twice* if you want them to be interpreted literally when the validate script is run.
2022-03-11 23:56:20 +08:00
**-h** or **--help**
Displays help about using this command.
2018-12-16 13:08:41 -08:00
2018-12-18 18:44:30 -08:00
Examples
2019-01-02 20:10:47 -08:00
--------
2018-12-16 13:08:41 -08:00
2022-03-12 00:18:41 +08:00
Define a single option specification for the boolean help flag:
2018-12-16 13:08:41 -08:00
2018-12-18 19:14:04 -08:00
::
set -l options (fish_opt -s h -l help)
argparse $options -- $argv
2018-12-16 13:08:41 -08:00
Same as above but with a second flag that requires a value:
2018-12-18 19:14:04 -08:00
::
set -l options (fish_opt -s h -l help)
2025-08-03 10:07:08 +10:00
set options $options (fish_opt -s m -l max -r)
2018-12-18 19:14:04 -08:00
argparse $options -- $argv
2025-08-03 10:07:08 +10:00
Same as above but the value of the second flag cannot be the empty string:
::
set -l options (fish_opt -s h -l help)
2025-12-04 01:13:17 -08:00
set options $options (fish_opt -s m -l max -rv test \$_flag_value != "''")
2025-08-03 10:07:08 +10:00
argparse $options -- $argv
2018-12-16 13:08:41 -08:00
2025-08-03 10:07:08 +10:00
Same as above but with a third flag that can be given multiple times saving the value of each instance seen and only a long flag name (`` --token `` ) is defined:
2018-12-16 13:08:41 -08:00
2018-12-18 19:14:04 -08:00
::
set -l options (fish_opt --short=h --long=help)
2025-12-04 01:13:17 -08:00
set options $options (fish_opt --short=m --long=max --required-val --validate test \$_flag_value != "''")
2025-08-03 10:07:08 +10:00
set options $options (fish_opt --long=token --multiple-vals)
2018-12-18 19:14:04 -08:00
argparse $options -- $argv