Browse code

vendor: github.com/spf13/cobra v1.7.0

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>

Sebastiaan van Stijn authored on 2023/05/19 08:52:30
Showing 26 changed files
... ...
@@ -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,3 +1,4 @@
1
+//go:build !windows
1 2
 // +build !windows
2 3
 
3 4
 package mousetrap
... ...
@@ -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
-}
... ...
@@ -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.
... ...
@@ -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
-![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png)
1
+![cobra logo](assets/CobraMain.png)
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://img.shields.io/github/workflow/status/spf13/cobra/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
9
+[![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
10 10
 [![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra)
11 11
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra)
12 12
 [![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](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.
... ...
@@ -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.
... ...
@@ -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.
... ...
@@ -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.
... ...
@@ -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)
... ...
@@ -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.
... ...
@@ -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