This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
484
unikernel/duniverse/cmdliner/doc/cli.mld
Normal file
484
unikernel/duniverse/cmdliner/doc/cli.mld
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
{0:cmdline Command line interface}
|
||||
|
||||
This manual describes how your tool ends up interacting
|
||||
with shells when you use Cmdliner.
|
||||
|
||||
{1:invocation Tool invocation}
|
||||
|
||||
For tools evaluating a command without subcommands the most general
|
||||
form of invocation is:
|
||||
|
||||
{v
|
||||
tool [OPTION]… [ARG]…
|
||||
v}
|
||||
|
||||
The tool automatically reponds to the [--help] option by printing
|
||||
{{!help}the help}. If a version string is provided in the
|
||||
{{!Cmdliner.Cmd.val-info}command information}, it also automatically
|
||||
responds to the [--version] option by printing this string on standard
|
||||
output.
|
||||
|
||||
Command line arguments are either {{!optargs}{e optional}} or
|
||||
{{!posargs}{e positional}}. Both can be freely interleaved but since
|
||||
[Cmdliner] accepts many optional forms this may result in
|
||||
ambiguities. The special {{!posargs} token [--]} can be used to
|
||||
resolve them: anything that follows it is treated as a positional
|
||||
argument.
|
||||
|
||||
Tools evaluating commands with subcommands have this form of invocation
|
||||
|
||||
{v
|
||||
tool [COMMAND]… [OPTION]… [ARG]…
|
||||
v}
|
||||
|
||||
Commands automatically respond to the [--help] option by printing
|
||||
{{!help}their help}. The sequence of [COMMAND] strings must be the first
|
||||
strings following the tool name – as soon as an optional argument is
|
||||
seen the search for a subcommand stops.
|
||||
|
||||
{1:args Arguments}
|
||||
|
||||
{2:optargs Optional arguments}
|
||||
|
||||
An optional argument is specified on the command line by a {e name}
|
||||
possibly followed by a {e value}.
|
||||
|
||||
The name of an option can be short or long.
|
||||
|
||||
{ul
|
||||
{- A {e short} name is a dash followed by a single alphanumeric
|
||||
character: [-h], [-q], [-I].}
|
||||
{- A {e long} name is two dashes followed by alphanumeric
|
||||
characters and dashes: [--help], [--silent], [--ignore-case].}}
|
||||
|
||||
More than one name may refer to the same optional argument. For
|
||||
example in a given program the names [-q], [--quiet] and [--silent]
|
||||
may all stand for the same boolean argument indicating the program to
|
||||
be quiet.
|
||||
|
||||
The value of an option can be specified in three different ways.
|
||||
|
||||
{ul
|
||||
{- As the next token on the command line: [-o a.out], [--output a.out].}
|
||||
{- Glued to a short name: [-oa.out].}
|
||||
{- Glued to a long name after an equal character: [--output=a.out].}}
|
||||
|
||||
Glued forms are especially useful if the value itself starts with a
|
||||
dash as is the case for negative numbers, [--min=-10].
|
||||
|
||||
An optional argument without a value is either a {e flag} (see
|
||||
{!Cmdliner.Arg.flag}, {!Cmdliner.Arg.vflag}) or an optional argument with
|
||||
an optional value (see the [~vopt] argument of {!Cmdliner.Arg.opt}).
|
||||
|
||||
Short flags can be grouped together to share a single dash and the
|
||||
group can end with a short option. For example assuming [-v] and
|
||||
[-x] are flags and [-f] is a short option:
|
||||
|
||||
{ul
|
||||
{- [-vx] will be parsed as [-v -x].}
|
||||
{- [-vxfopt] will be parsed as [-v -x -fopt].}
|
||||
{- [-vxf opt] will be parsed as [-v -x -fopt].}
|
||||
{- [-fvx] will be parsed as [-f=vx].}}
|
||||
|
||||
{2:posargs Positional arguments}
|
||||
|
||||
Positional arguments are tokens on the command line that are not
|
||||
option names and are not the value of an optional argument. They are
|
||||
numbered from left to right starting with zero.
|
||||
|
||||
Since positional arguments may be mistaken as the optional value of an
|
||||
optional argument or they may need to look like option names, anything
|
||||
that follows the special token ["--"] on the command line is
|
||||
considered to be a positional argument:
|
||||
|
||||
{v
|
||||
tool --option -- but --now we -are --all positional --argu=ments
|
||||
v}
|
||||
|
||||
{2:constraints Constraints on option names}
|
||||
|
||||
Using the cmdliner library puts the following constraints on your
|
||||
command line interface:
|
||||
|
||||
{ul
|
||||
{- The option names [--cmdliner] and [--__complete] are reserved by the
|
||||
library.}
|
||||
{- The option name [--help], (and [--version] if you specify a version
|
||||
string) is reserved by the library. Using it as a term or option
|
||||
name may result in undefined behaviour.}
|
||||
{- Defining the same option or command name via two different
|
||||
arguments or terms is illegal and raises [Invalid_argument].}}
|
||||
|
||||
{1:envlookup Environment variables}
|
||||
|
||||
Non-required command line arguments can be backed up by an environment
|
||||
variable. If the argument is absent from the command line and
|
||||
the environment variable is defined, its value is parsed using the
|
||||
argument converter and defines the value of the argument.
|
||||
|
||||
For {!Cmdliner.Arg.flag} and {!Cmdliner.Arg.flag_all} that do not have an
|
||||
argument converter a boolean is parsed from the lowercased variable value
|
||||
as follows:
|
||||
|
||||
{ul
|
||||
{- [""], ["false"], ["no"], ["n"] or ["0"] is [false].}
|
||||
{- ["true"], ["yes"], ["y"] or ["1"] is [true].}
|
||||
{- Any other string is an error.}}
|
||||
|
||||
Note that environment variables are not supported for
|
||||
{!Cmdliner.Arg.vflag} and {!Cmdliner.Arg.vflag_all}.
|
||||
|
||||
{1:help Help and man pages}
|
||||
|
||||
Help and man pages are are generated when you call your tool or a subcommand
|
||||
with [--help]. By default, if the [TERM] environment variable
|
||||
is not [dumb] or unset, the tool tries to {{!paging}page} the manual
|
||||
so that you can directly search it. Otherwise it outputs the manual
|
||||
as plain text.
|
||||
|
||||
Alternative help formats can be specified with the optional argument
|
||||
of [--help], see your own [tool --help] for more information.
|
||||
|
||||
{@sh[
|
||||
tool --help
|
||||
tool cmd --help
|
||||
tool --help=groff > tool.1
|
||||
]}
|
||||
|
||||
{2:paging Paging}
|
||||
|
||||
The pager is selected by looking up, in order:
|
||||
|
||||
{ol
|
||||
{- The [MANPAGER] variable.}
|
||||
{- The [PAGER] variable.}
|
||||
{- The tool [less].}
|
||||
{- The tool [more].}}
|
||||
|
||||
Regardless of the pager, it is invoked with [LESS=FRX] set in the
|
||||
environment unless, the [LESS] environment variable is set in your
|
||||
environment.
|
||||
|
||||
{2:install_tool_manpages Install}
|
||||
|
||||
The manpages of a tool and its subcommands can be installed to a root
|
||||
[man] directory [$MANDIR] by invoking:
|
||||
|
||||
{@shell[
|
||||
cmdliner install tool-manpages thetool $MANDIR
|
||||
]}
|
||||
|
||||
This looks up [thetool] in the [PATH]. Use an explicit file path like
|
||||
[./thetool] to directly specify an executable.
|
||||
|
||||
If you are also {{!install_tool_completion}installing completions}
|
||||
rather use the [install tool-support] command, see this
|
||||
{{!page-cookbook.tip_tool_support}cookbook tip} which also has
|
||||
instructions on how to install if you are using [opam].
|
||||
|
||||
{1:cli_completion Command line completion}
|
||||
|
||||
Cmdliner programs automatically get support for shell command line
|
||||
completion.
|
||||
|
||||
The completion process happens via a {{!completion_protocol}protocol}
|
||||
which is interpreted by generic shell completion scripts that are
|
||||
installed by the library. For now the [zsh] and [bash] shells are
|
||||
supported.
|
||||
|
||||
Tool developers can easily {{!install_tool_completion}install}
|
||||
completion definitions that invoke these completion scripts. Tool
|
||||
end-users need to {{!user_configuration}make sure} these definitions are
|
||||
looked up by their shell.
|
||||
|
||||
{2:user_configuration End-user configuration}
|
||||
|
||||
If you are the user of a cmdliner based tool, the following
|
||||
shell-dependent steps need to be performed in order to benefit from
|
||||
command line completion.
|
||||
|
||||
{3:user_zsh For [zsh]}
|
||||
|
||||
The [FPATH] environment variable must be setup to include the
|
||||
directory where the generic cmdliner completion function is
|
||||
{{!install_completion} installed} {b before} properly initializing the
|
||||
completion system.
|
||||
|
||||
For example, {{:https://github.com/ocaml/opam/issues/6427}for now}, if
|
||||
you are using [opam]. You should add something like this to your
|
||||
[.zshrc]:
|
||||
|
||||
{@sh[
|
||||
FPATH="$(opam var share)/zsh/site-functions:${FPATH}"
|
||||
autoload -Uz compinit
|
||||
compinit -u
|
||||
]}
|
||||
|
||||
Also make sure this {b happens before} [opam]'s [zsh] init script
|
||||
inclusion, see {{:https://github.com/ocaml/opam/issues/6428}this
|
||||
issue}. Note that these instruction do not react dynamically
|
||||
to [opam] switches changes so you may see odd completion behaviours
|
||||
when you do so, see this {{:https://github.com/ocaml/opam/issues/6427}this
|
||||
opam issue}.
|
||||
|
||||
After this, to test everything is right, check that the [_cmdliner_generic]
|
||||
function can be looked by invoking it (this will result in an error).
|
||||
|
||||
{@sh[
|
||||
> autoload _cmdliner_generic
|
||||
> _cmdliner_generic
|
||||
_cmdliner_generic:1: words: assignment to invalid subscript range
|
||||
]}
|
||||
|
||||
If the function cannnot be found make sure the [cmdliner] library is
|
||||
installed, that the generic scripts were
|
||||
{{!install_generic_completion}installed} and that the
|
||||
[_cmdliner_generic] file can be found in one of the directories
|
||||
mentioned in the [FPATH] variable.
|
||||
|
||||
With this setup, if you are using a cmdliner based tool named
|
||||
[thetool] that did not {{!install_tool_completion}install} a completion
|
||||
definition. You can always do it yourself by invoking:
|
||||
|
||||
{@sh[
|
||||
autoload _cmdliner_generic
|
||||
compdef _cmdliner_generic thetool
|
||||
]}
|
||||
|
||||
{3:user_bash For [bash]}
|
||||
|
||||
These instructions assume that you have
|
||||
{{:https://repology.org/project/bash-completion/versions}[bash-completion]}
|
||||
installed and setup in some way in your [.bashrc].
|
||||
|
||||
The [XDG_DATA_DIRS] environment variable must be setup to include the
|
||||
[share] directory where the generic cmdliner completion function is
|
||||
{{!install_completion}installed}.
|
||||
|
||||
For example, {{:https://github.com/ocaml/opam/issues/6427}for now}, if
|
||||
you are using [opam]. You should add something like this to your
|
||||
[.bashrc]:
|
||||
{@sh[
|
||||
XDG_DATA_DIRS="$(opam var share):${XDG_DATA_DIRS}"
|
||||
]}
|
||||
|
||||
Note that these instruction do not react dynamically to [opam]
|
||||
switches changes so you may see odd completion behaviours when you do
|
||||
so, see this {{:https://github.com/ocaml/opam/issues/6427}this opam
|
||||
issue}.
|
||||
|
||||
After this, to test everything is right, check that the [_cmdliner_generic]
|
||||
function can be looked up:
|
||||
|
||||
{@sh[
|
||||
> _completion_loader _cmdliner_generic
|
||||
> declare -F _cmdliner_generic &>/dev/null && echo "Found" || echo "Not found"
|
||||
Found!
|
||||
]}
|
||||
|
||||
If the function cannot be found make sure the [cmdliner] library is
|
||||
installed, that the generic scripts were
|
||||
{{!install_generic_completion}installed} and that the
|
||||
[_cmdliner_generic] file can be looked up by [_completion_loader].
|
||||
|
||||
With this setup, if you are using a cmdliner based tool named
|
||||
[thetool] that did not {{!install_tool_completion}install} a completion
|
||||
definition. You can always do it yourself by invoking:
|
||||
|
||||
{@sh[
|
||||
_completion_loader _cmdliner_generic
|
||||
complete -F _cmdliner_generic thetool
|
||||
]}
|
||||
|
||||
{b Note.} {{:https://github.com/scop/bash-completion/commit/9efc596735c4509001178f0cf28e02f66d1f7703}It seems} [_completion_loader] was deprecated in
|
||||
bash-completion [2.12] in favour of [_comp_load] but many distributions
|
||||
are on [< 2.12] and in [2.12] [_completion_loader] simply calls
|
||||
[_comp_load].
|
||||
|
||||
{2:install_completion Install}
|
||||
|
||||
Completion scripts need to be installed in subdirectories of a
|
||||
{{:https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s11.html}[share]}
|
||||
directory which we denote by the [$SHAREDIR] variable below. In a
|
||||
package installation script this variable is typically defined by:
|
||||
|
||||
{@sh[
|
||||
SHAREDIR="$DESTDIR/$PREFIX/share"
|
||||
]}
|
||||
|
||||
The final destination directory in [share] depends on the shell:
|
||||
|
||||
{ul
|
||||
{- For [zsh] it is [$SHAREDIR/zsh/site-functions]}
|
||||
{- For [bash] it is [$SHAREDIR/bash-completion/completions]}}
|
||||
|
||||
If that is unsatisfying you can output the completion scripts directly
|
||||
where you want with the [cmdliner generic-completion] and
|
||||
[cmdliner tool-completion] commands.
|
||||
|
||||
{3:install_generic_completion Generic completion scripts}
|
||||
|
||||
The generic completion scripts must be installed by the
|
||||
[cmdliner] library. They should not be part of your tool install. If
|
||||
they are not installed you can inspect and install them with the
|
||||
following invocations, invoke with [--help] for more information.
|
||||
|
||||
{@sh[
|
||||
cmdliner generic-completion zsh # Output generic zsh script on stdout
|
||||
cmdliner install generic-completion $SHAREDIR # All shells
|
||||
cmdliner install generic-completion --shell zsh $SHAREDIR # Only zsh
|
||||
]}
|
||||
|
||||
Directories are created as needed. Use option [--dry-run] to see which
|
||||
paths would be written by an [install] invocation.
|
||||
|
||||
{3:install_tool_completion Tool completion scripts}
|
||||
|
||||
If your tool named [thetool] uses Cmdliner you should install completion
|
||||
definitions for them. They rely on the {{!install_generic_completion}generic
|
||||
scripts} to be installed. These tool specific scripts can be inspected
|
||||
and installed via these invocations:
|
||||
|
||||
{@sh[
|
||||
cmdliner tool-completion zsh thetool # Output tool zsh script on stdout.
|
||||
cmdliner install tool-completion thetool $SHAREDIR # All shells
|
||||
cmdliner install tool-completion --shell zsh thetool $SHAREDIR # Only zsh
|
||||
]}
|
||||
|
||||
Directories are created as needed. Use option [--dry-run] to see which
|
||||
paths would be written by an [install] invocation.
|
||||
|
||||
If you are also {{!install_tool_manpages}installing manpages} rather
|
||||
use the [install tool-support] command, see this
|
||||
{{!page-cookbook.tip_tool_support}cookbook tip} which also has
|
||||
instructions on how to install if you are using [opam].
|
||||
|
||||
{2:completion_protocol Completion protocol}
|
||||
|
||||
There is no standard that allows tools and shells to interact to
|
||||
perform shell command line completion. Completion is supposed to
|
||||
happen through idiosyncratic, ad-hoc, obscure and brain damaging
|
||||
shell-specific completion scripts.
|
||||
|
||||
To alleviate this, Cmdliner defines one generic script per shell and
|
||||
interacts with it using the protocol described below. The protocol can
|
||||
be used to implement generic completion scripts for other shells. The
|
||||
protocol is versioned but can change even between minor versions of
|
||||
Cmdliner. Generic scripts for popular shells can be inspected via
|
||||
the [cmdliner generic-completion] command.
|
||||
|
||||
The protocol betwen the shell completion {e script} and a
|
||||
cmdliner based {e tool} is as follows:
|
||||
|
||||
{ol
|
||||
{- When completion is requested the script invokes the tool with a
|
||||
modified command line:
|
||||
{ul
|
||||
{- The first argument to the tool ([Sys.argv.(1)]) must be the
|
||||
option [--__complete].}
|
||||
{- The (possibly empty) argument [ARG] on which the completion is
|
||||
requested must be replaced by {e exactly} [--__complete=ARG]. Note
|
||||
that this can happen after the [--] token, this is the reason
|
||||
why we have an explicit [--__complete] argument in [Sys.argv.(1)]:
|
||||
it indicates the command line parser must operate in a special mode.}}}
|
||||
{- The tool responds by writing on standard output a list of
|
||||
completion directives which match the [completions] rule of the grammar
|
||||
given below.}
|
||||
{- The script interprets the completion directives according
|
||||
to the given semantics below so that the shell can display the
|
||||
completions. The script is free to ignore directives
|
||||
or data that it is unable to present.}}
|
||||
|
||||
The following ABNF grammar is described using the notations of
|
||||
{{:https://www.rfc-editor.org/rfc/rfc5234}RFC 5234} and
|
||||
{{:https://www.rfc-editor.org/rfc/rfc7405}RFC 7405}. A few constraints
|
||||
are not expressed by the grammar:
|
||||
|
||||
{ul
|
||||
{- Except in the [completion] rule, the byte stream may contain ANSI escape
|
||||
sequences introduced by the byte [0x1B].}
|
||||
{- After stripping the ANSI escape sequences, the resulting byte stream must
|
||||
be valid UTF-8 text.}}
|
||||
|
||||
{@abnf[
|
||||
completions = version nl directives
|
||||
version = "1"
|
||||
directives = *(directive nl)
|
||||
directive = message / group / %s"files" / %s"dirs" / %"restart"
|
||||
message = %s"message" nl text nl %s"message-end"
|
||||
group = %s"group" nl group_name nl *item
|
||||
group_name = *pchar
|
||||
item = %s"item" nl completion nl item_doc nl %s"item-end"
|
||||
completion = *pchar
|
||||
item_doc = text
|
||||
text = *(pchar / nl)
|
||||
nl = %0A
|
||||
pchar = %20-%7E / %8A-%FF
|
||||
]}
|
||||
|
||||
The semantics of directives is as follows:
|
||||
|
||||
{ul
|
||||
{- A [message] directive defines a message to be reported to the user.
|
||||
It is multi-line ANSI styled text which cannot have a line that is
|
||||
exactly made of the text [message-end] as it is used to signal the
|
||||
end of the message. Messages should be reported in the order they
|
||||
are received.}
|
||||
{- A [group] directive defines an informational [group_name] followed
|
||||
by a possibly empty list of completion items that are part of the
|
||||
group. An item provides a [completion] value, this is a string that
|
||||
defines what the requested [ARG] value can be replaced with. It is
|
||||
followed by an [item_doc], multi-line ANSI styled text which cannot
|
||||
have a line that is exactly made of the text [item-end] as it is
|
||||
used to signal the end of the item.}
|
||||
{- A [file] directive indicates that the script should add existing
|
||||
files staring with [ARG] to completion values.}
|
||||
{- A [dir] directive indicates that the script should add existing
|
||||
directories starting with [ARG] to completion values.}
|
||||
{- A [restart] directive indicates that the script should restart
|
||||
shell completion as if the command line was starting after the leftmost
|
||||
[--] disambiguation token. The directive never gets emited if
|
||||
there is no [--] on the command line.}}
|
||||
|
||||
You can easily inspect the completions of any cmdliner based tool by
|
||||
invoking it like the protocol suggests. For example for the [cmdliner]
|
||||
tool itself:
|
||||
|
||||
{@shell[
|
||||
cmdliner --__complete --__complete=
|
||||
]}
|
||||
|
||||
{1:error_message_styling Error message ANSI styling}
|
||||
|
||||
Since Cmdliner 2.0 error messages printed on [stderr] use styled text
|
||||
with ANSI escapes unless one of the following conditions is met:
|
||||
|
||||
{ul
|
||||
{- The [NO_COLOR] environment variable is set and different
|
||||
from the empty string. Yes, even if you have [NO_COLOR=false], that's
|
||||
what the particularly dumb {:https://no-color.org} standard says.}
|
||||
{- The [TERM] environment variable is [dumb].}
|
||||
{- The [TERM] environment variable is unset and {!Sys.backend_type} is
|
||||
not [Other "js_of_ocaml"]. Yes, browser consoles support
|
||||
ANSI escapes. Yes, you can run Cmdliner in your browser.}}
|
||||
|
||||
{1:legacy_prefix_specification Legacy prefix specification}
|
||||
|
||||
Before Cmdliner 2.0, command names, long option names and
|
||||
{!Cmdliner.Arg.enum} values could be specified by a prefix as long as
|
||||
the prefix was not ambiguous.
|
||||
|
||||
This turned out to be a mistake. It makes the user experience of the
|
||||
tool unstable as it evolves: former user established shortcuts or
|
||||
invocations in scripts may be broken by new command, option and
|
||||
enumerant additions.
|
||||
|
||||
Therefore this behaviour was unconditionally removed in Cmdliner
|
||||
2.0. If you happen to have scripts that rely on it, you can invoke
|
||||
them with [CMDLINER_LEGACY_PREFIXES=true] set in the environment to
|
||||
recover the old behaviour. {b However the scripts should be fixed: this
|
||||
escape hatch will be removed in the future.}
|
||||
|
||||
The [CMDLINER_LEGACY_PREFIX=true] escape hatch should not be used for
|
||||
interactive tool interaction. In particular the behaviour of Cmdliner
|
||||
completion support under this setting is undefined.
|
||||
Loading…
Add table
Add a link
Reference in a new issue