owned this note
owned this note
Published
Linked with GitHub
# Clap Completion Requirements
## bash
Bash's expectations
Inputs for `-F` and `-C`:
- COMP_LINE: The current command line. This variable is available only in shell functions and external commands invoked by the programmable completion facilities
- COMP_POINT: The index of the current cursor position relative to the beginning of the current command. If the current cursor position is at the end of the current command, the value of this variable is equal to ${#COMP_LINE}. This variable is available only in shell functions and external commands invoked by the programmable completion facilities
- COMP_KEY: The key (or final key of a key sequence) used to invoke the current completion function.
- COMP_TYPE: Set to an integer value corresponding to the type of completion attempted that caused a completion function to be called: TAB, for normal completion, ‘?’, for listing completions after successive tabs, ‘!’, for listing alternatives on partial word completion, ‘@’, to list completions if the word is not unmodified, or ‘%’, for menu completion. This variable is available only in shell functions and external commands invoked by the programmable completion facilities
- 1: name of the command whose arguments are being completed
- 2: word being completed
- 3: word preceding the word being completed on the current command line
Inputs for `-F`:
- COMP_WORDS, COMP_CWORD when used with `-F`
Output for `-C`:
- print a list of completions, one per line, to the standard output. Backslash may be used to escape a newline, if necessary.
Output for `-F`:
- It must put the possible completions in the COMPREPLY array variable, one per array element.
See
- https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html#Programmable-Completion
- https://www.gnu.org/software/bash/manual/html_node/A-Programmable-Completion-Example.html#A-Programmable-Completion-Example
- https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins
- https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html
### clap_complete
```bash=
_clap_complete_NAME() {
local IFS=$'\013'
local SUPPRESS_SPACE=0
if compopt +o nospace 2> /dev/null; then
SUPPRESS_SPACE=1
fi
if [[ ${SUPPRESS_SPACE} == 1 ]]; then
SPACE_ARG="--no-space"
else
SPACE_ARG="--space"
fi
COMPREPLY=( $("COMPLETER" complete --index ${COMP_CWORD} --type ${COMP_TYPE} ${SPACE_ARG} --ifs="$IFS" -- "${COMP_WORDS[@]}") )
if [[ $? != 0 ]]; then
unset COMPREPLY
elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
compopt -o nospace
fi
}
complete OPTIONS -F _clap_complete_NAME EXECUTABLES
```
- Command line (COMP_WORDS) is passed after `--`
- We complete the argument at argument index specified via `--index COMP_CWORD`
- We could get the char (or byte?) index to complete at but that gets more complicated to parse
- `SUPPRESS_SPACE` / `--[no-]space` isn't something I fully understand how we should be handling at the moment
- `--type COMP_TYPE` isn't something I fully understand how we should be handling at the moment
## fish
### registration
Fish shell only suports dynamic arguments not flags (https://github.com/fish-shell/fish-shell/issues/7943), therefore all flag specific logic needs to be implemented manually.
This snippet expects the completion logic implemented in https://github.com/clap-rs/clap/pull/4177.
```fish
complete -x -c {name} -a "{name} complete --previous=(commandline --current-process --tokenize --cut-at-cursor) --current (commandline --current-token)"
```
### requirements of returned completions
- Only return short flags, when the current token starts with `-`
- When returning short flags provide completions with an additional joined flag:
* Given the short flags a, b, c
* When the current token is -b provide the completions -ba and -bc
* Display the help of the added flag i.e. a or c
- Only return long flags when the current token starts with `--`
* Return help/about tab seperated from the completion item
### Prior Art
argcomplete emulates bash's interface in fish by
```
set -x COMP_LINE (commandline -p)
set -x COMP_POINT (string length (commandline -cp))
set -x COMP_TYPE
```
and then just registers that function
https://github.com/kislyuk/argcomplete/blob/develop/argcomplete/shell_integration.py#L60
[cobra](https://github.com/spf13/cobra): TBD
[bpaf](https://github.com/pacak/bpaf): TBD
- https://github.com/pacak/bpaf/blob/master/src/complete_run.rs
- https://github.com/pacak/bpaf/blob/master/src/complete_gen.rs
# Proposed shared interface
This interface would allow the dynamic bash completions to be the same as it is currently, and support almost the full fish feature
## Necessary flags
- `separator` character used to seperate returned completions e.g. `\n` for fish and `\013` for bash. (Maybe make newline the default)
- `current` the word the curser is on when triggering completions, leave empty when cursor not on word e.g. `COMP_WORDS[COMP_CWORD]` for bash and `commandline --current-token`
- `preceding` all tokens making up the command preceding the token containing the cursor e.g. `COMP_WORDS[@]::COMP_CWORD` for bash and `commandline --current-process --tokenize --cut-at-cursor` for fish
- `help-seperator` seperater to put between completion item and help/about text `\t` for fish (Optional if not set no help will be returned)
- `short-flag-joining` support joining multiple short flags via completions i.e. will return -ra as a completion if the current token is -r
### starts with dash condition for flags
#### decision in clap
- `flags-require-dash` only return short flags when current token starts with `-` and long flags if current token starts with `--`
#### decision in shell
- `show-short` e.g. for fish `commandline --current-token | string match -- "--*"`
- `show-long` e.g. for fish `commandline --current-token | string match -r -- "^-[^-]"`
### Shell native like path completions
#### Emulate in clap
Probably not a great idea as e.g. fish does quite a lot here:
- expand globs: `*/ba` would complete to `*/bash.rs` and `*/banana.rs` (given the paths `a/bash.rs` and `b/bash.rs`)
- complete substrings (not only prefixes) `rc/he/ba` would complete to `src/shell/bash.rs`.
#### pass path completions in
Prefered, but requires us to allow `*` in the paths returned from fish
- `paths` optional, completes current token as path if not present we do our own basic path completions e.g. for fish `complete -C "__fish_complete_path "(commandline --current-token)` (ideally this would be `__fish_complete_path (commandline --current-token)` but that is currently not supported fully: [fish-shell/fish-shell#9285](https://github.com/fish-shell/fish-shell/issues/9285))
- `paths-allow-fish-globs` allows `*` and `?` in paths used for completions (only has impact when `paths` is provided), only necessary to implement filtering could be skipped at first.
#### have a complete files/dirs query flag
Not ideal as it removes us from the ability to filter the results
- `should-complete-path` exits with 0 when the next argument should be a path
## Potential flags
These are the flags the current bash implementation taking, but don't have any implementation yet. I'd skip them for now.
* `comp-type`
* `space`