summaryrefslogtreecommitdiffstats
path: root/doc/api-and-naming.md
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:03:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:03:19 +0000
commit6c09f2a45c5541e9c207d14fc7aa21a4a0066bde (patch)
tree0221189d367bf661f6f9493c4f17a03f0dd4b7d2 /doc/api-and-naming.md
parentReleasing progress-linux version 1:2.11-8~progress7.99u1. (diff)
downloadbash-completion-6c09f2a45c5541e9c207d14fc7aa21a4a0066bde.tar.xz
bash-completion-6c09f2a45c5541e9c207d14fc7aa21a4a0066bde.zip
Merging upstream version 1:2.12.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'doc/api-and-naming.md')
-rw-r--r--doc/api-and-naming.md232
1 files changed, 232 insertions, 0 deletions
diff --git a/doc/api-and-naming.md b/doc/api-and-naming.md
new file mode 100644
index 0000000..59b2c36
--- /dev/null
+++ b/doc/api-and-naming.md
@@ -0,0 +1,232 @@
+# API and naming
+
+## General API conventions
+
+Most of the functions in bash-completion generate completions and directly
+inject them to the `COMPREPLY` array variable, as required for completions to
+work.
+
+Most other functions make use of "output" variables, i.e. assign values to
+them. The name of an output variable should be basically in lowercase.
+Consult the commentary before each function in the source to find out the
+specific names. `local`izing output variables before invoking a function that
+populates them is the caller's responsibility. Note that if calling multiple
+functions that assign output to the same variable during one completion
+function run, each result should be copied to another variable between the
+calls to avoid it possibly being overwritten and lost on the next call. Also,
+the variables should also be ensured to be clear before each call that
+references the value, variable name, or their existence, typically by `unset
+-v`ing them when multiple such calls are used, to avoid them interfering with
+each other.
+
+The most common output variable is named `REPLY`. The use of the uppercase is
+unconventional, but this choice of the name is intended to be consistent with
+the value substitutions `${| func; }`, which is originally supported by mksh
+and will be supported by Bash >= 5.3. The value substitutions are replaced by
+the contents of the output variable `REPLY` set by `func`. Although we cannot
+currently assume Bash 5.3 in the codebase, but we can switch to the value
+substitutions at the point Bash <= 5.2 disappear from the market.
+
+Everything in fallback completion files (ones starting with an underscore)
+is considered private and is to be named accordingly. Fallback files are not
+intended to be explicitly used with `_comp_xfunc`, and completion files having
+precedence over them may have a different API.
+
+## Availability
+
+All public API functions and variables are marked with a `@since VERSION`
+comment, where `VERSION` is the bash-completion version the thing was
+introduced in.
+
+Similarly, deprecated functions and variables are either marked with a
+`@deprecated VERSION ...` comment, or deprecated using the
+`_comp_deprecate_func VERSION OLD_NAME NEW_NAME` function.
+`VERSION` in both cases is the bash-completion version the thing was
+deprecated in.
+
+## Naming
+
+Due to its nature, bash-completion adds a number of functions and variables in
+the shell's environment.
+
+| | `bash_completion` | `completions/*` |
+|:------------------------------------|:--------------------|:--------------------------------------------------------------------------------------|
+| public configuration variables | `BASH_COMPLETION_*` | `BASH_COMPLETION_CMD_${Command^^}_${Config^^}` |
+| private non-local variables | `_comp__*` | `_comp_cmd_${Command}__${Data}` |
+| private non-local mutable variables | `_comp__*_mut_*` | `_comp_cmd_${Command}__mut_${Data}` |
+| exporter function local variables | `_*` (not `_comp*`) | `_*` (not `_comp*`) |
+| public/exported functions | `_comp_*` | `_comp_xfunc_${Command}_${Utility}` (functions for use with `_comp_xfunc`) |
+| - completers (for `complete -F`) | `_comp_complete_*` | `_comp_cmd_${Command}` |
+| - generators | `_comp_compgen_*` | `_comp_xfunc_${Command}_compgen_${Name}` (generators for use with `_comp_compgen -x`) |
+| private/internal functions | `_comp__*` | `_comp_cmd_${Command}__${Utility}` (utility functions) |
+| - generators | | `_comp_cmd_${Command}__compgen_${Name}` (generators for use with `_comp_compgen -i`) |
+
+`${Command}` refers to a command name (with characters not allowed in POSIX
+function or variable names replaced by an underscore), `${Config}` the name of
+a configurable thing, `^^` means uppercase, `${Data}` is an identifier for the
+data contained in the variable, and `${Utility}` describes the typical usage of
+the function.
+
+Variables and functions affecting multiple completions are usually defined
+in the main `bash_completion` file and do not require any additional files to
+be sourced. Variables and functions in command specific completion files in
+`completions/*` follow a slightly different naming scheme; they include
+`cmd` in their name as well as the name of the command.
+
+Public configuration variables are shell ones that affect the runtime behavior
+of various completions. As a rule of thumb, we lean towards not providing
+customizability but rather strive to provide great completion behavior out of
+the box. But there are some, see [configuration](configuration.md).
+
+Variables and functions whose name contains a double underscore (`__`) anywhere
+in their name are private implementation details, not part of the stable API,
+and not intended to be used outside of their defining context. Internally, the
+double underscores serve as privacy scope delimiters; there can be more than one
+pair of them in a name, and functions and variables are intended to reference
+and call other functions and variables within that scope, one level deep,
+sharing a common prefix. For example, a function named `_comp_foo` is "allowed"
+to access `_comp_foo__*` where `*` does not contain any double underscores,
+i.e. it should not access `_comp_foo__something__*` despite the common prefix.
+
+Private non-local variables are considered readonly by default. When a
+completion function needs to change variables for e.g. caching purposes, the
+variables should contain the infix `*_mut_*` anywhere in their names. This is
+needed to tell the test framework to allow these variables changing.
+Nevertheless, the completion results should be consistent among different calls
+and unaffected by the state of the cache variables when it is called.
+
+Internal local variables of functions that "export" their results using a
+variable name that is passed in start with an underscore and do not start with
+`_comp`. The variable names that are passed in for this purpose must not start
+with an underscore.
+
+Functions with names prefixed with `_comp_xfunc_` are intended to be used
+through the `_comp_xfunc` function from files other than the one they are
+defined in. From the same file they can be used directly using their complete
+name.
+
+Function names start with an underscore in order to avoid them being
+included in completions of command names. (Except naturally when a command
+starting with an underscore is being completed.) The underscore prefix does
+not have anything to do with whether the thing is considered public or
+private in the API, nor anything else really.
+
+The `BASH_COMPLETION_` prefix provides a namespace and makes it clear what
+these variables relate to. The `_comp` in other names serves a similar purpose,
+but because these are used a lot in the code (unlike the public configuration
+variables), using something shorter is beneficial. We hope and believe this is
+distinctive and clash free enough.
+
+It is known that a lot of functions and variables in the tree do not follow
+these naming rules yet. Things introduced after version 2.11 should, and we are
+evaluating our options for handling older ones.
+
+## Exported functions (xfunc)
+
+Exported functions (xfunc) are the functions defined in completion files for
+specific commands but exposed to other completion files. The xfuncs have the
+name `_comp_xfunc_CMD_NAME` where `CMD` is the name of the associated command,
+and `NAME` is the name of the utility. The other functions defined in specific
+completion files are considered private and should not be called outside the
+file.
+
+The xfuncs can be called by `_comp_xfunc CMD NAME ARGS` from external files.
+The xfuncs are supposed to be directly called as `_comp_xfunc_CMD_NAME ARGS`
+from the same file where they are defined, or if they wrap a `_comp_cmd_NAME__*`
+function, that one should be called directly instead.
+
+Note: The name `xfunc` was initially the name of a utility function, `_xfunc`,
+to call "eXternal FUNCtions" that are defined in other completion files. The
+concept is later extended to also mean "eXported".
+
+## Generator functions
+
+The generator functions, which have names of the form `_comp_compgen_NAME`, are
+used to generate completion candidates. A generator function is supposed to be
+called by `_comp_compgen [OPTS] NAME ARGS` where `OPTS = -aRl|-v var|-c cur|-C
+dir|-F sep` are the options to modify the behavior (see the code comment of
+`_comp_compgen` for details). When there are no `opts`, the generator function
+is supposed to be directly called as `_comp_compgen_NAME ARGS`. The result is
+stored in the target variable (which is `COMPREPLY` by default but can be
+specified by `-v var` in `OPTS`).
+
+### Implementing a generator function
+
+To implement a generator function, one should generate completion candidates by
+calling `_comp_compgen` or other generators.
+
+To avoid conflicts with the options specified to `_comp_compgen`, one should
+not directly modify or reference the target variable. When post-filtering is
+needed, store them in a local array, filter them, and finally append them by
+`_comp_compgen -- -W '"${_arr[@]}"'`. To split the output of commands and
+append the results to the target variable, use `_comp_compgen_split -- "$(cmd
+...)"` instead of using `_comp_split COMPREPLY "$(cmd ...)"`.
+
+A generator function should replace the existing content of the variable by
+default. When the appending behavior is favored, the caller should specify it
+through `_comp_compgen -a NAME`. The generator function do not need to process
+it because internal `_comp_compgen` calls automatically reflects the option
+`-a` specified to the outer calls of `_comp_compgen`.
+
+The exit status is implementation-defined.
+
+- The `_comp_compgen -- COMPGEN_ARGS` returns whether there is at least one
+ completion. This is useful when one wants to reuse the array content with
+ `"${tmp[@]}"` avoiding `nounset` error.
+- Some use other rules for the exit status. E.g., `help` and `usage` return
+ whether there were options *before* filtering by cur. This is used for
+ `_comp_compgen_help || _comp_compgen_usage`.
+
+Whether to clear the target variable on runtime error (when `-a` is not
+specified in `OPTS`) is implementation-defined. On the other hand, the
+generator function should not leave any side effects in the target variable on
+usage error. Note that the target variable might be cleared by the internal
+calls of `_comp_compgen`. To explicitly clear the target variable,
+`_comp_compgen_set` can be called without arguments.
+
+Exported generators are defined with the names `_comp_xfunc_CMD_compgen_NAME`
+and called by `_comp_compgen [opts] -x CMD NAME args`. Internal generators are
+defined with the names `_comp_cmd_CMD__compgen_NAME` and called by
+`_comp_compgen [opts] -i CMD NAME args`.
+
+#### Local variables of generator and `_comp_compgen -U var`
+
+A generator should basically define local variables with the names starting
+with `_`. However, a generator sometimes needs to use local variable names
+that do not start with `_`. When the child generator call with a variable name
+(such as `local var; _comp_compgen -v var`) is used within the generator, the
+local variable can unexpectedly mask a local variable of the upper call.
+
+For example, the following call fails to obtain the result of generator
+`mygen1` because the array `arr` is masked by the same name of a local variable
+in `_comp_compgen_mygen1`.
+
+```bash
+# generator with a problem
+_comp_compgen_mygen1()
+{
+ local -a arr=(1 2 3)
+ _comp_compgen -av arr -- -W '4 5 6'
+ _comp_compgen_set "${arr[@]/#p}"
+}
+
+_comp_compgen -v arr mygen1 # fails to get the result in array `arr`
+```
+
+To avoid this, a generator that defines a local variable with its name not
+starting with `_` can use the option `-U var` to unlocalize the variable on
+assigning the final result.
+
+```bash
+# properly designed generator
+_comp_compgen_mygen1()
+{
+ local -a arr=(1 2 3)
+ _comp_compgen -av arr -- -W '4 5 6'
+ _comp_compgen -U arr set "${arr[@]/#p}"
+}
+```
+
+To avoid unexpected unlocalization of previous-scope variables, a generator
+should specify `-U var` to a child generator (that attempts to store results to
+the current target variable) at most once.