mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-03 09:35:00 -05:00
**What type of PR is this?**
Feature
**What does this PR do? Why is it needed?**
Introduces a `completion` subcommand to `beacon-chain` and `validator`
that outputs shell completion scripts. Supports Bash, Zsh, and Fish
shells.
```bash
# Load completions in current session
source <(beacon-chain completion bash)
# Persist for future sessions
beacon-chain completion zsh > "${fpath[1]}/_beacon-chain"
validator completion fish > ~/.config/fish/completions/validator.fish
```
Once loaded, users can press TAB to complete subcommands, nested
commands, and flags. Flag completion supports prefix matching (e.g.,
typing `--exec<TAB>` suggests `--execution-endpoint`,
`--execution-headers`).
**Which issues(s) does this PR fix?**
Fixes #16244
**Other notes for review**
The implementation adds three files to the existing `cmd` package:
- `completion.go` - Defines `CompletionCommand()` returning a
`*cli.Command` with `bash`, `zsh`, `fish` subcommands
- `completion_scripts.go` - Contains the shell script templates
- `completion_test.go` - Unit tests for command structure and script
content
Changes to `beacon-chain` and `validator`:
- Import `cmd.CompletionCommand("binary-name")` in the Commands slice
- Set `EnableBashCompletion: true` on the cli.App to activate
urfave/cli's `--generate-bash-completion` hidden flag
The shell scripts call the binary with `--generate-bash-completion`
appended to get context-aware suggestions. This means completions
automatically reflect the current binary's flags and commands.
**Acknowledgements**
- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).
Signed-off-by: Willian Paixao <willian@ufpa.br>
100 lines
2.9 KiB
Go
100 lines
2.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// bashCompletionScript returns the bash completion script for the given binary.
|
|
func bashCompletionScript(binaryName string) string {
|
|
// Convert hyphens to underscores for bash function names
|
|
funcName := strings.ReplaceAll(binaryName, "-", "_")
|
|
return fmt.Sprintf(`#!/bin/bash
|
|
|
|
_%[1]s_completions() {
|
|
local cur prev words cword opts
|
|
COMPREPLY=()
|
|
|
|
# Use bash-completion if available, otherwise set variables directly
|
|
if declare -F _init_completion >/dev/null 2>&1; then
|
|
_init_completion -n "=:" || return
|
|
else
|
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
words=("${COMP_WORDS[@]}")
|
|
cword=$COMP_CWORD
|
|
fi
|
|
|
|
# Build command array for completion - flag must be at the END
|
|
local -a requestComp
|
|
if [[ "$cur" == "-"* ]]; then
|
|
requestComp=("${COMP_WORDS[@]:0:COMP_CWORD}" "$cur" --generate-bash-completion)
|
|
else
|
|
requestComp=("${COMP_WORDS[@]:0:COMP_CWORD}" --generate-bash-completion)
|
|
fi
|
|
|
|
opts=$("${requestComp[@]}" 2>/dev/null)
|
|
COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
|
|
return 0
|
|
}
|
|
|
|
complete -o bashdefault -o default -o nospace -F _%[1]s_completions %[2]s
|
|
`, funcName, binaryName)
|
|
}
|
|
|
|
// zshCompletionScript returns the zsh completion script for the given binary.
|
|
func zshCompletionScript(binaryName string) string {
|
|
// Convert hyphens to underscores for zsh function names
|
|
funcName := strings.ReplaceAll(binaryName, "-", "_")
|
|
return fmt.Sprintf(`#compdef %[2]s
|
|
|
|
_%[1]s() {
|
|
local curcontext="$curcontext" ret=1
|
|
local -a completions
|
|
|
|
# Build command array with --generate-bash-completion at the END
|
|
local -a requestComp
|
|
if [[ "${words[CURRENT]}" == -* ]]; then
|
|
requestComp=(${words[1,CURRENT]} --generate-bash-completion)
|
|
else
|
|
requestComp=(${words[1,CURRENT-1]} --generate-bash-completion)
|
|
fi
|
|
|
|
completions=($("${requestComp[@]}" 2>/dev/null))
|
|
|
|
if [[ ${#completions[@]} -gt 0 ]]; then
|
|
_describe -t commands '%[2]s' completions && ret=0
|
|
fi
|
|
|
|
# Fallback to file completion
|
|
_files && ret=0
|
|
|
|
return ret
|
|
}
|
|
|
|
compdef _%[1]s %[2]s
|
|
`, funcName, binaryName)
|
|
}
|
|
|
|
// fishCompletionScript returns the fish completion script for the given binary.
|
|
func fishCompletionScript(binaryName string) string {
|
|
// Convert hyphens to underscores for fish function names
|
|
funcName := strings.ReplaceAll(binaryName, "-", "_")
|
|
return fmt.Sprintf(`# Fish completion for %[2]s
|
|
|
|
function __fish_%[1]s_complete
|
|
set -l args (commandline -opc)
|
|
set -l cur (commandline -ct)
|
|
|
|
# Build command with --generate-bash-completion at the END
|
|
if string match -q -- '-*' "$cur"
|
|
%[2]s $args $cur --generate-bash-completion 2>/dev/null
|
|
else
|
|
%[2]s $args --generate-bash-completion 2>/dev/null
|
|
end
|
|
end
|
|
|
|
complete -c %[2]s -f -a "(__fish_%[1]s_complete)"
|
|
`, funcName, binaryName)
|
|
}
|