release notes: https://github.com/spf13/cobra/releases/tag/v1.7.0
Features
- Allow to preserve ordering of completions in bash, zsh, pwsh, & fish
- Add support for PowerShell 7.2+ in completions
- Allow sourcing zsh completion script
Bug fixes
- Don't remove flag values that match sub-command name
- Fix powershell completions not returning single word
- Remove masked template import variable name
- Correctly detect completions with dash in argument
Testing & CI/CD
- Deprecate Go 1.15 in CI
- Deprecate Go 1.16 in CI
- Add testing for Go 1.20 in CI
- Add tests to illustrate unknown flag bug
Maintenance
- Update main image to better handle dark backgrounds
- Fix stale.yaml mispellings
- Remove stale bot from GitHub actions
- Add makefile target for installing dependencies
- Add Sia to projects using Cobra
- Add Vitess and Arewefastyet to projects using cobra
- Fixup for Kubescape github org
- Fix route for GitHub workflows badge
- Fixup for GoDoc style documentation
- Various bash scripting improvements for completion
- Add Constellation to projects using Cobra
Documentation
- Add documentation about disabling completion descriptions
- Improve MarkFlagsMutuallyExclusive example in user guide
- Update shell_completions.md
- Update copywrite year
- Document suggested layout of subcommands
- Replace deprecated ExactValidArgs with MatchAll in doc
full diff: https://github.com/spf13/cobra/compare/v1.6.1...v1.7.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -79,7 +79,7 @@ require ( |
| 79 | 79 |
github.com/prometheus/client_golang v1.14.0 |
| 80 | 80 |
github.com/rootless-containers/rootlesskit v1.1.0 |
| 81 | 81 |
github.com/sirupsen/logrus v1.9.0 |
| 82 |
- github.com/spf13/cobra v1.6.1 |
|
| 82 |
+ github.com/spf13/cobra v1.7.0 |
|
| 83 | 83 |
github.com/spf13/pflag v1.0.5 |
| 84 | 84 |
github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa |
| 85 | 85 |
github.com/tonistiigi/go-archvariant v1.0.0 |
| ... | ... |
@@ -150,7 +150,7 @@ require ( |
| 150 | 150 |
github.com/hashicorp/go-sockaddr v1.0.2 // indirect |
| 151 | 151 |
github.com/hashicorp/golang-lru v0.5.4 // indirect |
| 152 | 152 |
github.com/in-toto/in-toto-golang v0.5.0 // indirect |
| 153 |
- github.com/inconshreveable/mousetrap v1.0.1 // indirect |
|
| 153 |
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect |
|
| 154 | 154 |
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect |
| 155 | 155 |
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect |
| 156 | 156 |
github.com/onsi/ginkgo/v2 v2.1.4 // indirect |
| ... | ... |
@@ -909,8 +909,8 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK |
| 909 | 909 |
github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY= |
| 910 | 910 |
github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1GdHMCq8+WPxw8/BE= |
| 911 | 911 |
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= |
| 912 |
-github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= |
|
| 913 |
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= |
|
| 912 |
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= |
|
| 913 |
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= |
|
| 914 | 914 |
github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= |
| 915 | 915 |
github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 h1:i2fYnDurfLlJH8AyyMOnkLHnHeP8Ff/DDpuZA/D3bPo= |
| 916 | 916 |
github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= |
| ... | ... |
@@ -1327,8 +1327,8 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 |
| 1327 | 1327 |
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= |
| 1328 | 1328 |
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= |
| 1329 | 1329 |
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= |
| 1330 |
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= |
|
| 1331 |
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= |
|
| 1330 |
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= |
|
| 1331 |
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= |
|
| 1332 | 1332 |
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= |
| 1333 | 1333 |
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= |
| 1334 | 1334 |
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= |
| ... | ... |
@@ -1,81 +1,32 @@ |
| 1 |
-// +build windows |
|
| 2 |
-// +build !go1.4 |
|
| 3 |
- |
|
| 4 | 1 |
package mousetrap |
| 5 | 2 |
|
| 6 | 3 |
import ( |
| 7 |
- "fmt" |
|
| 8 |
- "os" |
|
| 9 | 4 |
"syscall" |
| 10 | 5 |
"unsafe" |
| 11 | 6 |
) |
| 12 | 7 |
|
| 13 |
-const ( |
|
| 14 |
- // defined by the Win32 API |
|
| 15 |
- th32cs_snapprocess uintptr = 0x2 |
|
| 16 |
-) |
|
| 17 |
- |
|
| 18 |
-var ( |
|
| 19 |
- kernel = syscall.MustLoadDLL("kernel32.dll")
|
|
| 20 |
- CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
|
|
| 21 |
- Process32First = kernel.MustFindProc("Process32FirstW")
|
|
| 22 |
- Process32Next = kernel.MustFindProc("Process32NextW")
|
|
| 23 |
-) |
|
| 24 |
- |
|
| 25 |
-// ProcessEntry32 structure defined by the Win32 API |
|
| 26 |
-type processEntry32 struct {
|
|
| 27 |
- dwSize uint32 |
|
| 28 |
- cntUsage uint32 |
|
| 29 |
- th32ProcessID uint32 |
|
| 30 |
- th32DefaultHeapID int |
|
| 31 |
- th32ModuleID uint32 |
|
| 32 |
- cntThreads uint32 |
|
| 33 |
- th32ParentProcessID uint32 |
|
| 34 |
- pcPriClassBase int32 |
|
| 35 |
- dwFlags uint32 |
|
| 36 |
- szExeFile [syscall.MAX_PATH]uint16 |
|
| 37 |
-} |
|
| 38 |
- |
|
| 39 |
-func getProcessEntry(pid int) (pe *processEntry32, err error) {
|
|
| 40 |
- snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) |
|
| 41 |
- if snapshot == uintptr(syscall.InvalidHandle) {
|
|
| 42 |
- err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
|
|
| 43 |
- return |
|
| 8 |
+func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
|
|
| 9 |
+ snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) |
|
| 10 |
+ if err != nil {
|
|
| 11 |
+ return nil, err |
|
| 44 | 12 |
} |
| 45 |
- defer syscall.CloseHandle(syscall.Handle(snapshot)) |
|
| 46 |
- |
|
| 47 |
- var processEntry processEntry32 |
|
| 48 |
- processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) |
|
| 49 |
- ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) |
|
| 50 |
- if ok == 0 {
|
|
| 51 |
- err = fmt.Errorf("Process32First: %v", e1)
|
|
| 52 |
- return |
|
| 13 |
+ defer syscall.CloseHandle(snapshot) |
|
| 14 |
+ var procEntry syscall.ProcessEntry32 |
|
| 15 |
+ procEntry.Size = uint32(unsafe.Sizeof(procEntry)) |
|
| 16 |
+ if err = syscall.Process32First(snapshot, &procEntry); err != nil {
|
|
| 17 |
+ return nil, err |
|
| 53 | 18 |
} |
| 54 |
- |
|
| 55 | 19 |
for {
|
| 56 |
- if processEntry.th32ProcessID == uint32(pid) {
|
|
| 57 |
- pe = &processEntry |
|
| 58 |
- return |
|
| 20 |
+ if procEntry.ProcessID == uint32(pid) {
|
|
| 21 |
+ return &procEntry, nil |
|
| 59 | 22 |
} |
| 60 |
- |
|
| 61 |
- ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) |
|
| 62 |
- if ok == 0 {
|
|
| 63 |
- err = fmt.Errorf("Process32Next: %v", e1)
|
|
| 64 |
- return |
|
| 23 |
+ err = syscall.Process32Next(snapshot, &procEntry) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return nil, err |
|
| 65 | 26 |
} |
| 66 | 27 |
} |
| 67 | 28 |
} |
| 68 | 29 |
|
| 69 |
-func getppid() (pid int, err error) {
|
|
| 70 |
- pe, err := getProcessEntry(os.Getpid()) |
|
| 71 |
- if err != nil {
|
|
| 72 |
- return |
|
| 73 |
- } |
|
| 74 |
- |
|
| 75 |
- pid = int(pe.th32ParentProcessID) |
|
| 76 |
- return |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 | 30 |
// StartedByExplorer returns true if the program was invoked by the user double-clicking |
| 80 | 31 |
// on the executable from explorer.exe |
| 81 | 32 |
// |
| ... | ... |
@@ -83,16 +34,9 @@ func getppid() (pid int, err error) {
|
| 83 | 83 |
// It does not guarantee that the program was run from a terminal. It only can tell you |
| 84 | 84 |
// whether it was launched from explorer.exe |
| 85 | 85 |
func StartedByExplorer() bool {
|
| 86 |
- ppid, err := getppid() |
|
| 86 |
+ pe, err := getProcessEntry(syscall.Getppid()) |
|
| 87 | 87 |
if err != nil {
|
| 88 | 88 |
return false |
| 89 | 89 |
} |
| 90 |
- |
|
| 91 |
- pe, err := getProcessEntry(ppid) |
|
| 92 |
- if err != nil {
|
|
| 93 |
- return false |
|
| 94 |
- } |
|
| 95 |
- |
|
| 96 |
- name := syscall.UTF16ToString(pe.szExeFile[:]) |
|
| 97 |
- return name == "explorer.exe" |
|
| 90 |
+ return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) |
|
| 98 | 91 |
} |
| 99 | 92 |
deleted file mode 100644 |
| ... | ... |
@@ -1,46 +0,0 @@ |
| 1 |
-// +build windows |
|
| 2 |
-// +build go1.4 |
|
| 3 |
- |
|
| 4 |
-package mousetrap |
|
| 5 |
- |
|
| 6 |
-import ( |
|
| 7 |
- "os" |
|
| 8 |
- "syscall" |
|
| 9 |
- "unsafe" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
|
|
| 13 |
- snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) |
|
| 14 |
- if err != nil {
|
|
| 15 |
- return nil, err |
|
| 16 |
- } |
|
| 17 |
- defer syscall.CloseHandle(snapshot) |
|
| 18 |
- var procEntry syscall.ProcessEntry32 |
|
| 19 |
- procEntry.Size = uint32(unsafe.Sizeof(procEntry)) |
|
| 20 |
- if err = syscall.Process32First(snapshot, &procEntry); err != nil {
|
|
| 21 |
- return nil, err |
|
| 22 |
- } |
|
| 23 |
- for {
|
|
| 24 |
- if procEntry.ProcessID == uint32(pid) {
|
|
| 25 |
- return &procEntry, nil |
|
| 26 |
- } |
|
| 27 |
- err = syscall.Process32Next(snapshot, &procEntry) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- return nil, err |
|
| 30 |
- } |
|
| 31 |
- } |
|
| 32 |
-} |
|
| 33 |
- |
|
| 34 |
-// StartedByExplorer returns true if the program was invoked by the user double-clicking |
|
| 35 |
-// on the executable from explorer.exe |
|
| 36 |
-// |
|
| 37 |
-// It is conservative and returns false if any of the internal calls fail. |
|
| 38 |
-// It does not guarantee that the program was run from a terminal. It only can tell you |
|
| 39 |
-// whether it was launched from explorer.exe |
|
| 40 |
-func StartedByExplorer() bool {
|
|
| 41 |
- pe, err := getProcessEntry(os.Getppid()) |
|
| 42 |
- if err != nil {
|
|
| 43 |
- return false |
|
| 44 |
- } |
|
| 45 |
- return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) |
|
| 46 |
-} |
| ... | ... |
@@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint)) |
| 5 | 5 |
$(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh") |
| 6 | 6 |
endif |
| 7 | 7 |
|
| 8 |
-ifeq (, $(shell which richgo)) |
|
| 9 |
-$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest") |
|
| 10 |
-endif |
|
| 11 |
- |
|
| 12 | 8 |
.PHONY: fmt lint test install_deps clean |
| 13 | 9 |
|
| 14 | 10 |
default: all |
| ... | ... |
@@ -25,6 +21,10 @@ lint: |
| 25 | 25 |
|
| 26 | 26 |
test: install_deps |
| 27 | 27 |
$(info ******************** running tests ********************) |
| 28 |
+ go test -v ./... |
|
| 29 |
+ |
|
| 30 |
+richtest: install_deps |
|
| 31 |
+ $(info ******************** running tests with kyoh86/richgo ********************) |
|
| 28 | 32 |
richgo test -v ./... |
| 29 | 33 |
|
| 30 | 34 |
install_deps: |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
- |
|
| 1 |
+ |
|
| 2 | 2 |
|
| 3 | 3 |
Cobra is a library for creating powerful modern CLI applications. |
| 4 | 4 |
|
| ... | ... |
@@ -6,7 +6,7 @@ Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), |
| 6 | 6 |
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to |
| 7 | 7 |
name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra. |
| 8 | 8 |
|
| 9 |
-[](https://github.com/spf13/cobra/actions?query=workflow%3ATest) |
|
| 9 |
+[](https://github.com/spf13/cobra/actions?query=workflow%3ATest) |
|
| 10 | 10 |
[](https://pkg.go.dev/github.com/spf13/cobra) |
| 11 | 11 |
[](https://goreportcard.com/report/github.com/spf13/cobra) |
| 12 | 12 |
[](https://gophers.slack.com/archives/CD3LP1199) |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -21,7 +21,7 @@ import ( |
| 21 | 21 |
|
| 22 | 22 |
type PositionalArgs func(cmd *Command, args []string) error |
| 23 | 23 |
|
| 24 |
-// Legacy arg validation has the following behaviour: |
|
| 24 |
+// legacyArgs validation has the following behaviour: |
|
| 25 | 25 |
// - root commands with no subcommands can take arbitrary arguments |
| 26 | 26 |
// - root commands with subcommands will do subcommand validity checking |
| 27 | 27 |
// - subcommands will always accept arbitrary arguments |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -532,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
|
| 532 | 532 |
} |
| 533 | 533 |
} |
| 534 | 534 |
|
| 535 |
-// Setup annotations for go completions for registered flags |
|
| 535 |
+// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags |
|
| 536 | 536 |
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
| 537 | 537 |
flagCompletionMutex.RLock() |
| 538 | 538 |
defer flagCompletionMutex.RUnlock() |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -38,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
|
| 38 | 38 |
|
| 39 | 39 |
__%[1]s_debug() |
| 40 | 40 |
{
|
| 41 |
- if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
|
|
| 41 |
+ if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then
|
|
| 42 | 42 |
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
| 43 | 43 |
fi |
| 44 | 44 |
} |
| ... | ... |
@@ -65,7 +65,7 @@ __%[1]s_get_completion_results() {
|
| 65 | 65 |
lastChar=${lastParam:$((${#lastParam}-1)):1}
|
| 66 | 66 |
__%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"
|
| 67 | 67 |
|
| 68 |
- if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
|
|
| 68 |
+ if [[ -z ${cur} && ${lastChar} != = ]]; then
|
|
| 69 | 69 |
# If the last parameter is complete (there is a space following it) |
| 70 | 70 |
# We add an extra empty parameter so we can indicate this to the go method. |
| 71 | 71 |
__%[1]s_debug "Adding extra empty parameter" |
| ... | ... |
@@ -75,7 +75,7 @@ __%[1]s_get_completion_results() {
|
| 75 | 75 |
# When completing a flag with an = (e.g., %[1]s -n=<TAB>) |
| 76 | 76 |
# bash focuses on the part after the =, so we need to remove |
| 77 | 77 |
# the flag part from $cur |
| 78 |
- if [[ "${cur}" == -*=* ]]; then
|
|
| 78 |
+ if [[ ${cur} == -*=* ]]; then
|
|
| 79 | 79 |
cur="${cur#*=}"
|
| 80 | 80 |
fi |
| 81 | 81 |
|
| ... | ... |
@@ -87,7 +87,7 @@ __%[1]s_get_completion_results() {
|
| 87 | 87 |
directive=${out##*:}
|
| 88 | 88 |
# Remove the directive |
| 89 | 89 |
out=${out%%:*}
|
| 90 |
- if [ "${directive}" = "${out}" ]; then
|
|
| 90 |
+ if [[ ${directive} == "${out}" ]]; then
|
|
| 91 | 91 |
# There is not directive specified |
| 92 | 92 |
directive=0 |
| 93 | 93 |
fi |
| ... | ... |
@@ -101,22 +101,36 @@ __%[1]s_process_completion_results() {
|
| 101 | 101 |
local shellCompDirectiveNoFileComp=%[5]d |
| 102 | 102 |
local shellCompDirectiveFilterFileExt=%[6]d |
| 103 | 103 |
local shellCompDirectiveFilterDirs=%[7]d |
| 104 |
+ local shellCompDirectiveKeepOrder=%[8]d |
|
| 104 | 105 |
|
| 105 |
- if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then |
|
| 106 |
+ if (((directive & shellCompDirectiveError) != 0)); then |
|
| 106 | 107 |
# Error code. No completion. |
| 107 | 108 |
__%[1]s_debug "Received error from custom completion go code" |
| 108 | 109 |
return |
| 109 | 110 |
else |
| 110 |
- if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then |
|
| 111 |
- if [[ $(type -t compopt) = "builtin" ]]; then |
|
| 111 |
+ if (((directive & shellCompDirectiveNoSpace) != 0)); then |
|
| 112 |
+ if [[ $(type -t compopt) == builtin ]]; then |
|
| 112 | 113 |
__%[1]s_debug "Activating no space" |
| 113 | 114 |
compopt -o nospace |
| 114 | 115 |
else |
| 115 | 116 |
__%[1]s_debug "No space directive not supported in this version of bash" |
| 116 | 117 |
fi |
| 117 | 118 |
fi |
| 118 |
- if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then |
|
| 119 |
- if [[ $(type -t compopt) = "builtin" ]]; then |
|
| 119 |
+ if (((directive & shellCompDirectiveKeepOrder) != 0)); then |
|
| 120 |
+ if [[ $(type -t compopt) == builtin ]]; then |
|
| 121 |
+ # no sort isn't supported for bash less than < 4.4 |
|
| 122 |
+ if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then
|
|
| 123 |
+ __%[1]s_debug "No sort directive not supported in this version of bash" |
|
| 124 |
+ else |
|
| 125 |
+ __%[1]s_debug "Activating keep order" |
|
| 126 |
+ compopt -o nosort |
|
| 127 |
+ fi |
|
| 128 |
+ else |
|
| 129 |
+ __%[1]s_debug "No sort directive not supported in this version of bash" |
|
| 130 |
+ fi |
|
| 131 |
+ fi |
|
| 132 |
+ if (((directive & shellCompDirectiveNoFileComp) != 0)); then |
|
| 133 |
+ if [[ $(type -t compopt) == builtin ]]; then |
|
| 120 | 134 |
__%[1]s_debug "Activating no file completion" |
| 121 | 135 |
compopt +o default |
| 122 | 136 |
else |
| ... | ... |
@@ -130,7 +144,7 @@ __%[1]s_process_completion_results() {
|
| 130 | 130 |
local activeHelp=() |
| 131 | 131 |
__%[1]s_extract_activeHelp |
| 132 | 132 |
|
| 133 |
- if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then |
|
| 133 |
+ if (((directive & shellCompDirectiveFilterFileExt) != 0)); then |
|
| 134 | 134 |
# File extension filtering |
| 135 | 135 |
local fullFilter filter filteringCmd |
| 136 | 136 |
|
| ... | ... |
@@ -143,13 +157,12 @@ __%[1]s_process_completion_results() {
|
| 143 | 143 |
filteringCmd="_filedir $fullFilter" |
| 144 | 144 |
__%[1]s_debug "File filtering command: $filteringCmd" |
| 145 | 145 |
$filteringCmd |
| 146 |
- elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then |
|
| 146 |
+ elif (((directive & shellCompDirectiveFilterDirs) != 0)); then |
|
| 147 | 147 |
# File completion for directories only |
| 148 | 148 |
|
| 149 |
- # Use printf to strip any trailing newline |
|
| 150 | 149 |
local subdir |
| 151 |
- subdir=$(printf "%%s" "${completions[0]}")
|
|
| 152 |
- if [ -n "$subdir" ]; then |
|
| 150 |
+ subdir=${completions[0]}
|
|
| 151 |
+ if [[ -n $subdir ]]; then |
|
| 153 | 152 |
__%[1]s_debug "Listing directories in $subdir" |
| 154 | 153 |
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return |
| 155 | 154 |
else |
| ... | ... |
@@ -164,7 +177,7 @@ __%[1]s_process_completion_results() {
|
| 164 | 164 |
__%[1]s_handle_special_char "$cur" = |
| 165 | 165 |
|
| 166 | 166 |
# Print the activeHelp statements before we finish |
| 167 |
- if [ ${#activeHelp[*]} -ne 0 ]; then
|
|
| 167 |
+ if ((${#activeHelp[*]} != 0)); then
|
|
| 168 | 168 |
printf "\n"; |
| 169 | 169 |
printf "%%s\n" "${activeHelp[@]}"
|
| 170 | 170 |
printf "\n" |
| ... | ... |
@@ -184,21 +197,21 @@ __%[1]s_process_completion_results() {
|
| 184 | 184 |
# Separate activeHelp lines from real completions. |
| 185 | 185 |
# Fills the $activeHelp and $completions arrays. |
| 186 | 186 |
__%[1]s_extract_activeHelp() {
|
| 187 |
- local activeHelpMarker="%[8]s" |
|
| 187 |
+ local activeHelpMarker="%[9]s" |
|
| 188 | 188 |
local endIndex=${#activeHelpMarker}
|
| 189 | 189 |
|
| 190 | 190 |
while IFS='' read -r comp; do |
| 191 |
- if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then
|
|
| 191 |
+ if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then
|
|
| 192 | 192 |
comp=${comp:endIndex}
|
| 193 | 193 |
__%[1]s_debug "ActiveHelp found: $comp" |
| 194 |
- if [ -n "$comp" ]; then |
|
| 194 |
+ if [[ -n $comp ]]; then |
|
| 195 | 195 |
activeHelp+=("$comp")
|
| 196 | 196 |
fi |
| 197 | 197 |
else |
| 198 | 198 |
# Not an activeHelp line but a normal completion |
| 199 | 199 |
completions+=("$comp")
|
| 200 | 200 |
fi |
| 201 |
- done < <(printf "%%s\n" "${out}")
|
|
| 201 |
+ done <<<"${out}"
|
|
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
__%[1]s_handle_completion_types() {
|
| ... | ... |
@@ -254,7 +267,7 @@ __%[1]s_handle_standard_completion_case() {
|
| 254 | 254 |
done < <(printf "%%s\n" "${completions[@]}")
|
| 255 | 255 |
|
| 256 | 256 |
# If there is a single completion left, remove the description text |
| 257 |
- if [ ${#COMPREPLY[*]} -eq 1 ]; then
|
|
| 257 |
+ if ((${#COMPREPLY[*]} == 1)); then
|
|
| 258 | 258 |
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
|
| 259 | 259 |
comp="${COMPREPLY[0]%%%%$tab*}"
|
| 260 | 260 |
__%[1]s_debug "Removed description from single completion, which is now: ${comp}"
|
| ... | ... |
@@ -271,8 +284,8 @@ __%[1]s_handle_special_char() |
| 271 | 271 |
if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
|
| 272 | 272 |
local word=${comp%%"${comp##*${char}}"}
|
| 273 | 273 |
local idx=${#COMPREPLY[*]}
|
| 274 |
- while [[ $((--idx)) -ge 0 ]]; do |
|
| 275 |
- COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
|
|
| 274 |
+ while ((--idx >= 0)); do |
|
| 275 |
+ COMPREPLY[idx]=${COMPREPLY[idx]#"$word"}
|
|
| 276 | 276 |
done |
| 277 | 277 |
fi |
| 278 | 278 |
} |
| ... | ... |
@@ -298,7 +311,7 @@ __%[1]s_format_comp_descriptions() |
| 298 | 298 |
|
| 299 | 299 |
# Make sure we can fit a description of at least 8 characters |
| 300 | 300 |
# if we are to align the descriptions. |
| 301 |
- if [[ $maxdesclength -gt 8 ]]; then |
|
| 301 |
+ if ((maxdesclength > 8)); then |
|
| 302 | 302 |
# Add the proper number of spaces to align the descriptions |
| 303 | 303 |
for ((i = ${#comp} ; i < longest ; i++)); do
|
| 304 | 304 |
comp+=" " |
| ... | ... |
@@ -310,8 +323,8 @@ __%[1]s_format_comp_descriptions() |
| 310 | 310 |
|
| 311 | 311 |
# If there is enough space for any description text, |
| 312 | 312 |
# truncate the descriptions that are too long for the shell width |
| 313 |
- if [ $maxdesclength -gt 0 ]; then |
|
| 314 |
- if [ ${#desc} -gt $maxdesclength ]; then
|
|
| 313 |
+ if ((maxdesclength > 0)); then |
|
| 314 |
+ if ((${#desc} > maxdesclength)); then
|
|
| 315 | 315 |
desc=${desc:0:$(( maxdesclength - 1 ))}
|
| 316 | 316 |
desc+="…" |
| 317 | 317 |
fi |
| ... | ... |
@@ -332,9 +345,9 @@ __start_%[1]s() |
| 332 | 332 |
# Call _init_completion from the bash-completion package |
| 333 | 333 |
# to prepare the arguments properly |
| 334 | 334 |
if declare -F _init_completion >/dev/null 2>&1; then |
| 335 |
- _init_completion -n "=:" || return |
|
| 335 |
+ _init_completion -n =: || return |
|
| 336 | 336 |
else |
| 337 |
- __%[1]s_init_completion -n "=:" || return |
|
| 337 |
+ __%[1]s_init_completion -n =: || return |
|
| 338 | 338 |
fi |
| 339 | 339 |
|
| 340 | 340 |
__%[1]s_debug |
| ... | ... |
@@ -361,7 +374,7 @@ fi |
| 361 | 361 |
# ex: ts=4 sw=4 et filetype=sh |
| 362 | 362 |
`, name, compCmd, |
| 363 | 363 |
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, |
| 364 |
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, |
|
| 364 |
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, |
|
| 365 | 365 |
activeHelpMarker)) |
| 366 | 366 |
} |
| 367 | 367 |
|
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -167,8 +167,8 @@ func appendIfNotPresent(s, stringToAppend string) string {
|
| 167 | 167 |
|
| 168 | 168 |
// rpad adds padding to the right of a string. |
| 169 | 169 |
func rpad(s string, padding int) string {
|
| 170 |
- template := fmt.Sprintf("%%-%ds", padding)
|
|
| 171 |
- return fmt.Sprintf(template, s) |
|
| 170 |
+ formattedString := fmt.Sprintf("%%-%ds", padding)
|
|
| 171 |
+ return fmt.Sprintf(formattedString, s) |
|
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
// tmpl executes the given template text on data, writing the result to w. |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -35,7 +35,7 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" |
| 35 | 35 |
// FParseErrWhitelist configures Flag parse errors to be ignored |
| 36 | 36 |
type FParseErrWhitelist flag.ParseErrorsWhitelist |
| 37 | 37 |
|
| 38 |
-// Structure to manage groups for commands |
|
| 38 |
+// Group Structure to manage groups for commands |
|
| 39 | 39 |
type Group struct {
|
| 40 | 40 |
ID string |
| 41 | 41 |
Title string |
| ... | ... |
@@ -47,7 +47,7 @@ type Group struct {
|
| 47 | 47 |
// definition to ensure usability. |
| 48 | 48 |
type Command struct {
|
| 49 | 49 |
// Use is the one-line usage message. |
| 50 |
- // Recommended syntax is as follow: |
|
| 50 |
+ // Recommended syntax is as follows: |
|
| 51 | 51 |
// [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required. |
| 52 | 52 |
// ... indicates that you can specify multiple values for the previous argument. |
| 53 | 53 |
// | indicates mutually exclusive information. You can use the argument to the left of the separator or the |
| ... | ... |
@@ -321,7 +321,7 @@ func (c *Command) SetHelpCommand(cmd *Command) {
|
| 321 | 321 |
c.helpCommand = cmd |
| 322 | 322 |
} |
| 323 | 323 |
|
| 324 |
-// SetHelpCommandGroup sets the group id of the help command. |
|
| 324 |
+// SetHelpCommandGroupID sets the group id of the help command. |
|
| 325 | 325 |
func (c *Command) SetHelpCommandGroupID(groupID string) {
|
| 326 | 326 |
if c.helpCommand != nil {
|
| 327 | 327 |
c.helpCommand.GroupID = groupID |
| ... | ... |
@@ -330,7 +330,7 @@ func (c *Command) SetHelpCommandGroupID(groupID string) {
|
| 330 | 330 |
c.helpCommandGroupID = groupID |
| 331 | 331 |
} |
| 332 | 332 |
|
| 333 |
-// SetCompletionCommandGroup sets the group id of the completion command. |
|
| 333 |
+// SetCompletionCommandGroupID sets the group id of the completion command. |
|
| 334 | 334 |
func (c *Command) SetCompletionCommandGroupID(groupID string) {
|
| 335 | 335 |
// completionCommandGroupID is used if no completion command is defined by the user |
| 336 | 336 |
c.Root().completionCommandGroupID = groupID |
| ... | ... |
@@ -655,20 +655,44 @@ Loop: |
| 655 | 655 |
|
| 656 | 656 |
// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like |
| 657 | 657 |
// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). |
| 658 |
-func argsMinusFirstX(args []string, x string) []string {
|
|
| 659 |
- for i, y := range args {
|
|
| 660 |
- if x == y {
|
|
| 661 |
- ret := []string{}
|
|
| 662 |
- ret = append(ret, args[:i]...) |
|
| 663 |
- ret = append(ret, args[i+1:]...) |
|
| 664 |
- return ret |
|
| 658 |
+// Special care needs to be taken not to remove a flag value. |
|
| 659 |
+func (c *Command) argsMinusFirstX(args []string, x string) []string {
|
|
| 660 |
+ if len(args) == 0 {
|
|
| 661 |
+ return args |
|
| 662 |
+ } |
|
| 663 |
+ c.mergePersistentFlags() |
|
| 664 |
+ flags := c.Flags() |
|
| 665 |
+ |
|
| 666 |
+Loop: |
|
| 667 |
+ for pos := 0; pos < len(args); pos++ {
|
|
| 668 |
+ s := args[pos] |
|
| 669 |
+ switch {
|
|
| 670 |
+ case s == "--": |
|
| 671 |
+ // -- means we have reached the end of the parseable args. Break out of the loop now. |
|
| 672 |
+ break Loop |
|
| 673 |
+ case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): |
|
| 674 |
+ fallthrough |
|
| 675 |
+ case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): |
|
| 676 |
+ // This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip |
|
| 677 |
+ // over the next arg, because that is the value of this flag. |
|
| 678 |
+ pos++ |
|
| 679 |
+ continue |
|
| 680 |
+ case !strings.HasPrefix(s, "-"): |
|
| 681 |
+ // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, |
|
| 682 |
+ // return the args, excluding the one at this position. |
|
| 683 |
+ if s == x {
|
|
| 684 |
+ ret := []string{}
|
|
| 685 |
+ ret = append(ret, args[:pos]...) |
|
| 686 |
+ ret = append(ret, args[pos+1:]...) |
|
| 687 |
+ return ret |
|
| 688 |
+ } |
|
| 665 | 689 |
} |
| 666 | 690 |
} |
| 667 | 691 |
return args |
| 668 | 692 |
} |
| 669 | 693 |
|
| 670 | 694 |
func isFlagArg(arg string) bool {
|
| 671 |
- return ((len(arg) >= 3 && arg[1] == '-') || |
|
| 695 |
+ return ((len(arg) >= 3 && arg[0:2] == "--") || |
|
| 672 | 696 |
(len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) |
| 673 | 697 |
} |
| 674 | 698 |
|
| ... | ... |
@@ -686,7 +710,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
| 686 | 686 |
|
| 687 | 687 |
cmd := c.findNext(nextSubCmd) |
| 688 | 688 |
if cmd != nil {
|
| 689 |
- return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) |
|
| 689 |
+ return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd)) |
|
| 690 | 690 |
} |
| 691 | 691 |
return c, innerArgs |
| 692 | 692 |
} |
| ... | ... |
@@ -1272,7 +1296,7 @@ func (c *Command) AllChildCommandsHaveGroup() bool {
|
| 1272 | 1272 |
return true |
| 1273 | 1273 |
} |
| 1274 | 1274 |
|
| 1275 |
-// ContainGroups return if groupID exists in the list of command groups. |
|
| 1275 |
+// ContainsGroup return if groupID exists in the list of command groups. |
|
| 1276 | 1276 |
func (c *Command) ContainsGroup(groupID string) bool {
|
| 1277 | 1277 |
for _, x := range c.commandgroups {
|
| 1278 | 1278 |
if x.ID == groupID {
|
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -77,6 +77,10 @@ const ( |
| 77 | 77 |
// obtain the same behavior but only for flags. |
| 78 | 78 |
ShellCompDirectiveFilterDirs |
| 79 | 79 |
|
| 80 |
+ // ShellCompDirectiveKeepOrder indicates that the shell should preserve the order |
|
| 81 |
+ // in which the completions are provided |
|
| 82 |
+ ShellCompDirectiveKeepOrder |
|
| 83 |
+ |
|
| 80 | 84 |
// =========================================================================== |
| 81 | 85 |
|
| 82 | 86 |
// All directives using iota should be above this one. |
| ... | ... |
@@ -159,6 +163,9 @@ func (d ShellCompDirective) string() string {
|
| 159 | 159 |
if d&ShellCompDirectiveFilterDirs != 0 {
|
| 160 | 160 |
directives = append(directives, "ShellCompDirectiveFilterDirs") |
| 161 | 161 |
} |
| 162 |
+ if d&ShellCompDirectiveKeepOrder != 0 {
|
|
| 163 |
+ directives = append(directives, "ShellCompDirectiveKeepOrder") |
|
| 164 |
+ } |
|
| 162 | 165 |
if len(directives) == 0 {
|
| 163 | 166 |
directives = append(directives, "ShellCompDirectiveDefault") |
| 164 | 167 |
} |
| ... | ... |
@@ -169,7 +176,7 @@ func (d ShellCompDirective) string() string {
|
| 169 | 169 |
return strings.Join(directives, ", ") |
| 170 | 170 |
} |
| 171 | 171 |
|
| 172 |
-// Adds a special hidden command that can be used to request custom completions. |
|
| 172 |
+// initCompleteCmd adds a special hidden command that can be used to request custom completions. |
|
| 173 | 173 |
func (c *Command) initCompleteCmd(args []string) {
|
| 174 | 174 |
completeCmd := &Command{
|
| 175 | 175 |
Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd),
|
| ... | ... |
@@ -727,7 +734,7 @@ to enable it. You can execute the following once: |
| 727 | 727 |
|
| 728 | 728 |
To load completions in your current shell session: |
| 729 | 729 |
|
| 730 |
- source <(%[1]s completion zsh); compdef _%[1]s %[1]s |
|
| 730 |
+ source <(%[1]s completion zsh) |
|
| 731 | 731 |
|
| 732 | 732 |
To load completions for every new session, execute once: |
| 733 | 733 |
|
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -53,7 +53,7 @@ function __%[1]s_perform_completion |
| 53 | 53 |
__%[1]s_debug "last arg: $lastArg" |
| 54 | 54 |
|
| 55 | 55 |
# Disable ActiveHelp which is not supported for fish shell |
| 56 |
- set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg" |
|
| 56 |
+ set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg" |
|
| 57 | 57 |
|
| 58 | 58 |
__%[1]s_debug "Calling $requestComp" |
| 59 | 59 |
set -l results (eval $requestComp 2> /dev/null) |
| ... | ... |
@@ -89,6 +89,60 @@ function __%[1]s_perform_completion |
| 89 | 89 |
printf "%%s\n" "$directiveLine" |
| 90 | 90 |
end |
| 91 | 91 |
|
| 92 |
+# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result |
|
| 93 |
+function __%[1]s_perform_completion_once |
|
| 94 |
+ __%[1]s_debug "Starting __%[1]s_perform_completion_once" |
|
| 95 |
+ |
|
| 96 |
+ if test -n "$__%[1]s_perform_completion_once_result" |
|
| 97 |
+ __%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion" |
|
| 98 |
+ return 0 |
|
| 99 |
+ end |
|
| 100 |
+ |
|
| 101 |
+ set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion) |
|
| 102 |
+ if test -z "$__%[1]s_perform_completion_once_result" |
|
| 103 |
+ __%[1]s_debug "No completions, probably due to a failure" |
|
| 104 |
+ return 1 |
|
| 105 |
+ end |
|
| 106 |
+ |
|
| 107 |
+ __%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result" |
|
| 108 |
+ return 0 |
|
| 109 |
+end |
|
| 110 |
+ |
|
| 111 |
+# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run |
|
| 112 |
+function __%[1]s_clear_perform_completion_once_result |
|
| 113 |
+ __%[1]s_debug "" |
|
| 114 |
+ __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" |
|
| 115 |
+ set --erase __%[1]s_perform_completion_once_result |
|
| 116 |
+ __%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result" |
|
| 117 |
+end |
|
| 118 |
+ |
|
| 119 |
+function __%[1]s_requires_order_preservation |
|
| 120 |
+ __%[1]s_debug "" |
|
| 121 |
+ __%[1]s_debug "========= checking if order preservation is required ==========" |
|
| 122 |
+ |
|
| 123 |
+ __%[1]s_perform_completion_once |
|
| 124 |
+ if test -z "$__%[1]s_perform_completion_once_result" |
|
| 125 |
+ __%[1]s_debug "Error determining if order preservation is required" |
|
| 126 |
+ return 1 |
|
| 127 |
+ end |
|
| 128 |
+ |
|
| 129 |
+ set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) |
|
| 130 |
+ __%[1]s_debug "Directive is: $directive" |
|
| 131 |
+ |
|
| 132 |
+ set -l shellCompDirectiveKeepOrder %[9]d |
|
| 133 |
+ set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2) |
|
| 134 |
+ __%[1]s_debug "Keeporder is: $keeporder" |
|
| 135 |
+ |
|
| 136 |
+ if test $keeporder -ne 0 |
|
| 137 |
+ __%[1]s_debug "This does require order preservation" |
|
| 138 |
+ return 0 |
|
| 139 |
+ end |
|
| 140 |
+ |
|
| 141 |
+ __%[1]s_debug "This doesn't require order preservation" |
|
| 142 |
+ return 1 |
|
| 143 |
+end |
|
| 144 |
+ |
|
| 145 |
+ |
|
| 92 | 146 |
# This function does two things: |
| 93 | 147 |
# - Obtain the completions and store them in the global __%[1]s_comp_results |
| 94 | 148 |
# - Return false if file completion should be performed |
| ... | ... |
@@ -99,17 +153,17 @@ function __%[1]s_prepare_completions |
| 99 | 99 |
# Start fresh |
| 100 | 100 |
set --erase __%[1]s_comp_results |
| 101 | 101 |
|
| 102 |
- set -l results (__%[1]s_perform_completion) |
|
| 103 |
- __%[1]s_debug "Completion results: $results" |
|
| 102 |
+ __%[1]s_perform_completion_once |
|
| 103 |
+ __%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result" |
|
| 104 | 104 |
|
| 105 |
- if test -z "$results" |
|
| 105 |
+ if test -z "$__%[1]s_perform_completion_once_result" |
|
| 106 | 106 |
__%[1]s_debug "No completion, probably due to a failure" |
| 107 | 107 |
# Might as well do file completion, in case it helps |
| 108 | 108 |
return 1 |
| 109 | 109 |
end |
| 110 | 110 |
|
| 111 |
- set -l directive (string sub --start 2 $results[-1]) |
|
| 112 |
- set --global __%[1]s_comp_results $results[1..-2] |
|
| 111 |
+ set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1]) |
|
| 112 |
+ set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2] |
|
| 113 | 113 |
|
| 114 | 114 |
__%[1]s_debug "Completions are: $__%[1]s_comp_results" |
| 115 | 115 |
__%[1]s_debug "Directive is: $directive" |
| ... | ... |
@@ -205,13 +259,17 @@ end |
| 205 | 205 |
# Remove any pre-existing completions for the program since we will be handling all of them. |
| 206 | 206 |
complete -c %[2]s -e |
| 207 | 207 |
|
| 208 |
+# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global |
|
| 209 |
+complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result' |
|
| 208 | 210 |
# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results |
| 209 | 211 |
# which provides the program's completion choices. |
| 210 |
-complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' |
|
| 211 |
- |
|
| 212 |
+# If this doesn't require order preservation, we don't use the -k flag |
|
| 213 |
+complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' |
|
| 214 |
+# otherwise we use the -k flag |
|
| 215 |
+complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results' |
|
| 212 | 216 |
`, nameForVar, name, compCmd, |
| 213 | 217 |
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, |
| 214 |
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) |
|
| 218 |
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) |
|
| 215 | 219 |
} |
| 216 | 220 |
|
| 217 | 221 |
// GenFishCompletion generates fish completion file and writes to the passed writer. |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -77,6 +77,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
| 77 | 77 |
$ShellCompDirectiveNoFileComp=%[6]d |
| 78 | 78 |
$ShellCompDirectiveFilterFileExt=%[7]d |
| 79 | 79 |
$ShellCompDirectiveFilterDirs=%[8]d |
| 80 |
+ $ShellCompDirectiveKeepOrder=%[9]d |
|
| 80 | 81 |
|
| 81 | 82 |
# Prepare the command to request completions for the program. |
| 82 | 83 |
# Split the command at the first space to separate the program and arguments. |
| ... | ... |
@@ -106,13 +107,22 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
| 106 | 106 |
# If the last parameter is complete (there is a space following it) |
| 107 | 107 |
# We add an extra empty parameter so we can indicate this to the go method. |
| 108 | 108 |
__%[1]s_debug "Adding extra empty parameter" |
| 109 |
-`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+` |
|
| 110 |
-`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` |
|
| 109 |
+ # PowerShell 7.2+ changed the way how the arguments are passed to executables, |
|
| 110 |
+ # so for pre-7.2 or when Legacy argument passing is enabled we need to use |
|
| 111 |
+`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+` |
|
| 112 |
+ if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or |
|
| 113 |
+ ($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or
|
|
| 114 |
+ (($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and
|
|
| 115 |
+ $PSNativeCommandArgumentPassing -eq 'Legacy')) {
|
|
| 116 |
+`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+` |
|
| 117 |
+ } else {
|
|
| 118 |
+ $RequestComp="$RequestComp" + ' ""' |
|
| 119 |
+ } |
|
| 111 | 120 |
} |
| 112 | 121 |
|
| 113 | 122 |
__%[1]s_debug "Calling $RequestComp" |
| 114 | 123 |
# First disable ActiveHelp which is not supported for Powershell |
| 115 |
- $env:%[9]s=0 |
|
| 124 |
+ $env:%[10]s=0 |
|
| 116 | 125 |
|
| 117 | 126 |
#call the command store the output in $out and redirect stderr and stdout to null |
| 118 | 127 |
# $Out is an array contains each line per element |
| ... | ... |
@@ -137,7 +147,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
$Longest = 0 |
| 140 |
- $Values = $Out | ForEach-Object {
|
|
| 140 |
+ [Array]$Values = $Out | ForEach-Object {
|
|
| 141 | 141 |
#Split the output in name and description |
| 142 | 142 |
`+" $Name, $Description = $_.Split(\"`t\",2)"+` |
| 143 | 143 |
__%[1]s_debug "Name: $Name Description: $Description" |
| ... | ... |
@@ -182,6 +192,11 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
| 182 | 182 |
} |
| 183 | 183 |
} |
| 184 | 184 |
|
| 185 |
+ # we sort the values in ascending order by name if keep order isn't passed |
|
| 186 |
+ if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) {
|
|
| 187 |
+ $Values = $Values | Sort-Object -Property Name |
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 185 | 190 |
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
| 186 | 191 |
__%[1]s_debug "ShellCompDirectiveNoFileComp is called" |
| 187 | 192 |
|
| ... | ... |
@@ -267,7 +282,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
| 267 | 267 |
Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock |
| 268 | 268 |
`, name, nameForVar, compCmd, |
| 269 | 269 |
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, |
| 270 |
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name))) |
|
| 270 |
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) |
|
| 271 | 271 |
} |
| 272 | 272 |
|
| 273 | 273 |
func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error {
|
| ... | ... |
@@ -1,11 +1,13 @@ |
| 1 | 1 |
## Projects using Cobra |
| 2 | 2 |
|
| 3 | 3 |
- [Allero](https://github.com/allero-io/allero) |
| 4 |
+- [Arewefastyet](https://benchmark.vitess.io) |
|
| 4 | 5 |
- [Arduino CLI](https://github.com/arduino/arduino-cli) |
| 5 | 6 |
- [Bleve](https://blevesearch.com/) |
| 6 | 7 |
- [Cilium](https://cilium.io/) |
| 7 | 8 |
- [CloudQuery](https://github.com/cloudquery/cloudquery) |
| 8 | 9 |
- [CockroachDB](https://www.cockroachlabs.com/) |
| 10 |
+- [Constellation](https://github.com/edgelesssys/constellation) |
|
| 9 | 11 |
- [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) |
| 10 | 12 |
- [Datree](https://github.com/datreeio/datree) |
| 11 | 13 |
- [Delve](https://github.com/derekparker/delve) |
| ... | ... |
@@ -25,7 +27,7 @@ |
| 25 | 25 |
- [Istio](https://istio.io) |
| 26 | 26 |
- [Kool](https://github.com/kool-dev/kool) |
| 27 | 27 |
- [Kubernetes](https://kubernetes.io/) |
| 28 |
-- [Kubescape](https://github.com/armosec/kubescape) |
|
| 28 |
+- [Kubescape](https://github.com/kubescape/kubescape) |
|
| 29 | 29 |
- [KubeVirt](https://github.com/kubevirt/kubevirt) |
| 30 | 30 |
- [Linkerd](https://linkerd.io/) |
| 31 | 31 |
- [Mattermost-server](https://github.com/mattermost/mattermost-server) |
| ... | ... |
@@ -51,10 +53,12 @@ |
| 51 | 51 |
- [Random](https://github.com/erdaltsksn/random) |
| 52 | 52 |
- [Rclone](https://rclone.org/) |
| 53 | 53 |
- [Scaleway CLI](https://github.com/scaleway/scaleway-cli) |
| 54 |
+- [Sia](https://github.com/SiaFoundation/siad) |
|
| 54 | 55 |
- [Skaffold](https://skaffold.dev/) |
| 55 | 56 |
- [Tendermint](https://github.com/tendermint/tendermint) |
| 56 | 57 |
- [Twitch CLI](https://github.com/twitchdev/twitch-cli) |
| 57 | 58 |
- [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli) |
| 59 |
+- [Vitess](https://vitess.io) |
|
| 58 | 60 |
- VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework) |
| 59 | 61 |
- [Werf](https://werf.io/) |
| 60 | 62 |
- [ZITADEL](https://github.com/zitadel/zitadel) |
| ... | ... |
@@ -71,7 +71,7 @@ PowerShell: |
| 71 | 71 |
`,cmd.Root().Name()), |
| 72 | 72 |
DisableFlagsInUseLine: true, |
| 73 | 73 |
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
| 74 |
- Args: cobra.ExactValidArgs(1), |
|
| 74 |
+ Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), |
|
| 75 | 75 |
Run: func(cmd *cobra.Command, args []string) {
|
| 76 | 76 |
switch args[0] {
|
| 77 | 77 |
case "bash": |
| ... | ... |
@@ -162,16 +162,7 @@ cmd := &cobra.Command{
|
| 162 | 162 |
} |
| 163 | 163 |
``` |
| 164 | 164 |
|
| 165 |
-The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by |
|
| 166 |
-the completion algorithm if entered manually, e.g. in: |
|
| 167 |
- |
|
| 168 |
-```bash |
|
| 169 |
-$ kubectl get rc [tab][tab] |
|
| 170 |
-backend frontend database |
|
| 171 |
-``` |
|
| 172 |
- |
|
| 173 |
-Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of |
|
| 174 |
-replication controllers following `rc`. |
|
| 165 |
+The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`. |
|
| 175 | 166 |
|
| 176 | 167 |
### Dynamic completion of nouns |
| 177 | 168 |
|
| ... | ... |
@@ -237,6 +228,10 @@ ShellCompDirectiveFilterFileExt |
| 237 | 237 |
// return []string{"themes"}, ShellCompDirectiveFilterDirs
|
| 238 | 238 |
// |
| 239 | 239 |
ShellCompDirectiveFilterDirs |
| 240 |
+ |
|
| 241 |
+// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order |
|
| 242 |
+// in which the completions are provided |
|
| 243 |
+ShellCompDirectiveKeepOrder |
|
| 240 | 244 |
``` |
| 241 | 245 |
|
| 242 | 246 |
***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function. |
| ... | ... |
@@ -385,6 +380,19 @@ or |
| 385 | 385 |
```go |
| 386 | 386 |
ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"}
|
| 387 | 387 |
``` |
| 388 |
+ |
|
| 389 |
+If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like: |
|
| 390 |
+ |
|
| 391 |
+```bash |
|
| 392 |
+$ source <(helm completion bash) |
|
| 393 |
+$ helm completion [tab][tab] |
|
| 394 |
+bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell) |
|
| 395 |
+fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh) |
|
| 396 |
+ |
|
| 397 |
+$ source <(helm completion bash --no-descriptions) |
|
| 398 |
+$ helm completion [tab][tab] |
|
| 399 |
+bash fish powershell zsh |
|
| 400 |
+``` |
|
| 388 | 401 |
## Bash completions |
| 389 | 402 |
|
| 390 | 403 |
### Dependencies |
| ... | ... |
@@ -188,6 +188,37 @@ var versionCmd = &cobra.Command{
|
| 188 | 188 |
} |
| 189 | 189 |
``` |
| 190 | 190 |
|
| 191 |
+### Organizing subcommands |
|
| 192 |
+ |
|
| 193 |
+A command may have subcommands which in turn may have other subcommands. This is achieved by using |
|
| 194 |
+`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in |
|
| 195 |
+its own go package. |
|
| 196 |
+ |
|
| 197 |
+The suggested approach is for the parent command to use `AddCommand` to add its most immediate |
|
| 198 |
+subcommands. For example, consider the following directory structure: |
|
| 199 |
+ |
|
| 200 |
+```text |
|
| 201 |
+├── cmd |
|
| 202 |
+│  ├── root.go |
|
| 203 |
+│  └── sub1 |
|
| 204 |
+│  ├── sub1.go |
|
| 205 |
+│  └── sub2 |
|
| 206 |
+│  ├── leafA.go |
|
| 207 |
+│  ├── leafB.go |
|
| 208 |
+│  └── sub2.go |
|
| 209 |
+└── main.go |
|
| 210 |
+``` |
|
| 211 |
+ |
|
| 212 |
+In this case: |
|
| 213 |
+ |
|
| 214 |
+* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command. |
|
| 215 |
+* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command. |
|
| 216 |
+* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the |
|
| 217 |
+ sub2 command. |
|
| 218 |
+ |
|
| 219 |
+This approach ensures the subcommands are always included at compile time while avoiding cyclic |
|
| 220 |
+references. |
|
| 221 |
+ |
|
| 191 | 222 |
### Returning and handling errors |
| 192 | 223 |
|
| 193 | 224 |
If you wish to return an error to the caller of a command, `RunE` can be used. |
| ... | ... |
@@ -313,8 +344,8 @@ rootCmd.MarkFlagsRequiredTogether("username", "password")
|
| 313 | 313 |
You can also prevent different flags from being provided together if they represent mutually |
| 314 | 314 |
exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: |
| 315 | 315 |
```go |
| 316 |
-rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON") |
|
| 317 |
-rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML") |
|
| 316 |
+rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") |
|
| 317 |
+rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") |
|
| 318 | 318 |
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
|
| 319 | 319 |
``` |
| 320 | 320 |
|
| ... | ... |
@@ -349,7 +380,7 @@ shown below: |
| 349 | 349 |
```go |
| 350 | 350 |
var cmd = &cobra.Command{
|
| 351 | 351 |
Short: "hello", |
| 352 |
- Args: MatchAll(ExactArgs(2), OnlyValidArgs), |
|
| 352 |
+ Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), |
|
| 353 | 353 |
Run: func(cmd *cobra.Command, args []string) {
|
| 354 | 354 |
fmt.Println("Hello, World!")
|
| 355 | 355 |
}, |
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-// Copyright 2013-2022 The Cobra Authors |
|
| 1 |
+// Copyright 2013-2023 The Cobra Authors |
|
| 2 | 2 |
// |
| 3 | 3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | 4 |
// you may not use this file except in compliance with the License. |
| ... | ... |
@@ -90,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) {
|
| 90 | 90 |
compCmd = ShellCompNoDescRequestCmd |
| 91 | 91 |
} |
| 92 | 92 |
WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s |
| 93 |
+compdef _%[1]s %[1]s |
|
| 93 | 94 |
|
| 94 | 95 |
# zsh completion for %-36[1]s -*- shell-script -*- |
| 95 | 96 |
|
| ... | ... |
@@ -108,8 +109,9 @@ _%[1]s() |
| 108 | 108 |
local shellCompDirectiveNoFileComp=%[5]d |
| 109 | 109 |
local shellCompDirectiveFilterFileExt=%[6]d |
| 110 | 110 |
local shellCompDirectiveFilterDirs=%[7]d |
| 111 |
+ local shellCompDirectiveKeepOrder=%[8]d |
|
| 111 | 112 |
|
| 112 |
- local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace |
|
| 113 |
+ local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder |
|
| 113 | 114 |
local -a completions |
| 114 | 115 |
|
| 115 | 116 |
__%[1]s_debug "\n========= starting completion logic ==========" |
| ... | ... |
@@ -177,7 +179,7 @@ _%[1]s() |
| 177 | 177 |
return |
| 178 | 178 |
fi |
| 179 | 179 |
|
| 180 |
- local activeHelpMarker="%[8]s" |
|
| 180 |
+ local activeHelpMarker="%[9]s" |
|
| 181 | 181 |
local endIndex=${#activeHelpMarker}
|
| 182 | 182 |
local startIndex=$((${#activeHelpMarker}+1))
|
| 183 | 183 |
local hasActiveHelp=0 |
| ... | ... |
@@ -227,6 +229,11 @@ _%[1]s() |
| 227 | 227 |
noSpace="-S ''" |
| 228 | 228 |
fi |
| 229 | 229 |
|
| 230 |
+ if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then |
|
| 231 |
+ __%[1]s_debug "Activating keep order." |
|
| 232 |
+ keepOrder="-V" |
|
| 233 |
+ fi |
|
| 234 |
+ |
|
| 230 | 235 |
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then |
| 231 | 236 |
# File extension filtering |
| 232 | 237 |
local filteringCmd |
| ... | ... |
@@ -262,7 +269,7 @@ _%[1]s() |
| 262 | 262 |
return $result |
| 263 | 263 |
else |
| 264 | 264 |
__%[1]s_debug "Calling _describe" |
| 265 |
- if eval _describe "completions" completions $flagPrefix $noSpace; then |
|
| 265 |
+ if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then |
|
| 266 | 266 |
__%[1]s_debug "_describe found some completions" |
| 267 | 267 |
|
| 268 | 268 |
# Return the success of having called _describe |
| ... | ... |
@@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then |
| 296 | 296 |
fi |
| 297 | 297 |
`, name, compCmd, |
| 298 | 298 |
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, |
| 299 |
- ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, |
|
| 299 |
+ ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, |
|
| 300 | 300 |
activeHelpMarker)) |
| 301 | 301 |
} |
| ... | ... |
@@ -549,7 +549,7 @@ github.com/in-toto/in-toto-golang/in_toto |
| 549 | 549 |
github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common |
| 550 | 550 |
github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1 |
| 551 | 551 |
github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2 |
| 552 |
-# github.com/inconshreveable/mousetrap v1.0.1 |
|
| 552 |
+# github.com/inconshreveable/mousetrap v1.1.0 |
|
| 553 | 553 |
## explicit; go 1.18 |
| 554 | 554 |
github.com/inconshreveable/mousetrap |
| 555 | 555 |
# github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 |
| ... | ... |
@@ -908,7 +908,7 @@ github.com/spdx/tools-golang/json |
| 908 | 908 |
github.com/spdx/tools-golang/spdx/common |
| 909 | 909 |
github.com/spdx/tools-golang/spdx/v2_2 |
| 910 | 910 |
github.com/spdx/tools-golang/spdx/v2_3 |
| 911 |
-# github.com/spf13/cobra v1.6.1 |
|
| 911 |
+# github.com/spf13/cobra v1.7.0 |
|
| 912 | 912 |
## explicit; go 1.15 |
| 913 | 913 |
github.com/spf13/cobra |
| 914 | 914 |
# github.com/spf13/pflag v1.0.5 |