Install shell completion as an optional command

This commit is contained in:
2026-11-03 03:50:12 +00:00
parent 0bed76a6f7
commit fc2f6d5346
9 changed files with 219 additions and 3 deletions

View File

@@ -1,6 +1,53 @@
package commandkit
import commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
import (
"fmt"
"io"
"strings"
"unicode"
internalcobra "gitea.maximumdirect.net/eric/CommandKit/internal/cobra"
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
)
// Completion declares opt-in shell script generation for the executable
// basename used to invoke the application. Install it at the application root.
// Generated shell identifiers support letters, digits, underscores, dots,
// hyphens, and colons; a leading hyphen is not supported.
func Completion(executable string) Command {
children := make([]Command, 0, 3)
for _, shell := range []string{"bash", "zsh", "fish"} {
shell := shell
children = append(children, NewCommand(CommandSpec[struct{}]{
Name: shell, Summary: "Generate " + shell + " completion script.",
Run: func(invocation Invocation, _ struct{}) Outcome {
_ = invocation.Reporter().RenderOutput(func(writer io.Writer) error {
return internalcobra.CompletionScript(writer, executable, shell)
})
return Success()
},
}))
}
command := RootGroup("completion", "Generate shell completion scripts.", children...)
command.record.completion = true
if !validCompletionExecutable(executable) {
return WithError(command, fmt.Errorf("unsupported completion executable basename %q", executable))
}
return command
}
// Cobra emits the basename into shell identifiers and unquoted command words.
func validCompletionExecutable(name string) bool {
if name == "" || name == "." || name == ".." || strings.HasPrefix(name, "-") {
return false
}
for _, ch := range name {
if !(unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' || ch == '-' || ch == ':' || ch == '.') {
return false
}
}
return true
}
// CompletionChoice is a literal suggested value and its optional description.
type CompletionChoice struct {