Compare commits

..

10 Commits

Author SHA1 Message Date
Nir Soffer
78bfc837fe
Test also with go 1.23 (#2182)
Some checks are pending
Test / lic-headers (push) Waiting to run
Test / golangci-lint (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (17, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (17, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (18, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (18, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (19, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (19, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (20, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (20, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (21, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (21, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (22, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (22, ubuntu) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (23, macOS) (push) Waiting to run
Test / ${{ matrix.platform }} | 1.${{ matrix.go }}.x (23, ubuntu) (push) Waiting to run
Test / MINGW64 (push) Waiting to run
2024-08-24 19:02:44 -04:00
Nir Soffer
511af59cb3
Replace deprecated ioutil usage (#2181)
Fixing golangci-lint errors[1]:

    Error: SA1019: "io/ioutil" has been deprecated since Go 1.19: As of
    Go 1.16, the same functionality is now provided by package [io] or
    package [os], and those implementations should be preferred in new
    code. See the specific function documentation for details.
    (staticcheck)

[1] https://github.com/spf13/cobra/actions/runs/10535452454/job/29194442289?pr=2180
2024-08-24 07:05:26 -04:00
Gabe Cook
756ba6dad6
fix(completions): Complete map flags multiple times (#2174) 2024-07-28 12:18:07 -04:00
Sebastiaan van Stijn
371ae25d2c
Fix deprecation comment for Command.SetOutput (#2172)
Deprecation comments should be at the start of a paragraph [1], and because
of that have a whitespace above them [2];

> To signal that an identifier should not be used, add a paragraph to its
> doc comment that begins with Deprecated: followed by some information
> about the deprecation (...)

With the whitespace missing, some tools, including pkg.go.dev [3] don't
detect it to be deprecated.

[1]: https://go.dev/wiki/Deprecated
[2]: https://go.dev/doc/comment#paragraphs
[3]: https://pkg.go.dev/github.com/spf13/cobra@v1.8.1#Command.SetOutput

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-16 19:36:29 -04:00
Ville Skyttä
e94f6d0dd9
Address golangci-lint deprecation warnings, enable some more linters (#2152)
* Address golangci-lint linter deprecation warnings

1.59.0 outputs:

WARN [lintersdb] The name "gas" is deprecated. The linter has been renamed to: gosec.
WARN [lintersdb] The linter named "megacheck" is deprecated. It has been split into: gosimple, staticcheck, unused.

* Enable some more linters, address finding
2024-06-01 06:31:11 -04:00
Nir Soffer
8003b74a10
Remove fully inactivated linters (#2148)
* Remove fully inactivated linters

Currently golangci-lint fails with these errors:

ERRO [linters_context] golint: This linter is fully inactivated: it will not produce any reports.
ERRO [linters_context] interfacer: This linter is fully inactivated: it will not produce any reports.
ERRO [linters_context] maligned: This linter is fully inactivated: it will not produce any reports.

I could not find any docs explaining what "fully inactivated" mean, but
based this PR[1] it seems that these linters do nothing now. Removing
the linters fixes this issue without changing linting, as they did not
produce any report.

Looking in the linters docs[2] I did not find a replacement for
"interfacer" and "malinged" linters. "stylecheck" seems to be a
replacement for "golint", but we need to fix the code to enable it.

[1] https://github.com/golangci/golangci-lint/pull/4436
[2] https://golangci-lint.run/usage/linters/

* Add stylecheck linter, replacement for golint

This revealed 2 capitalized error messages.

https://golangci-lint.run/usage/linters/#stylecheck
2024-05-18 22:12:02 -04:00
Nir Soffer
5c2c1d627d
Consistent annotation names (#2140)
Add `Annotation` suffix to the private annotations to allow nicer code
using the constants.

For example one can use the current annotation names as a temporary
variable instead of unclear shortcut. Instead of this:

    rag := flagsFromAnnotation(c, f, requiredAsGroup)
    me := flagsFromAnnotation(c, f, mutuallyExclusive)
    or := flagsFromAnnotation(c, f, oneRequired)

We can use now:

    requiredAsGrop := flagsFromAnnotation(c, f, requiredAsGroupAnnotation)
    mutuallyExclusive := flagsFromAnnotation(c, f, mutuallyExclusiveAnnotation)
    oneRequired := flagsFromAnnotation(c, f, oneRequiredAnnotation)

Example taken from #2105.
2024-05-18 09:41:31 -04:00
dependabot[bot]
5a1acea321
build(deps): bump github.com/cpuguy83/go-md2man/v2 from 2.0.3 to 2.0.4 (#2127) 2024-04-13 02:21:03 +00:00
Xinwei Xiong
0fc86c2ffd
docs: update user guide (#2128) 2024-04-08 06:47:35 -04:00
Ville Skyttä
6b5f577ebc
More linting (#2099)
* Address gocritic findings, enable it

* Enable gosimple, no new findings to address
2024-04-01 08:42:08 -04:00
20 changed files with 68 additions and 72 deletions

View File

@ -67,6 +67,7 @@ jobs:
- 20 - 20
- 21 - 21
- 22 - 22
- 23
name: '${{ matrix.platform }} | 1.${{ matrix.go }}.x' name: '${{ matrix.platform }} | 1.${{ matrix.go }}.x'
runs-on: ${{ matrix.platform }}-latest runs-on: ${{ matrix.platform }}-latest
steps: steps:

View File

@ -26,33 +26,28 @@ linters:
- errcheck - errcheck
#- exhaustive #- exhaustive
#- funlen #- funlen
- gas
#- gochecknoinits #- gochecknoinits
- goconst - goconst
#- gocritic - gocritic
#- gocyclo #- gocyclo
#- gofmt - gofmt
- goimports - goimports
- golint
#- gomnd #- gomnd
#- goprintffuncname #- goprintffuncname
#- gosec - gosec
#- gosimple - gosimple
- govet - govet
- ineffassign - ineffassign
- interfacer
#- lll #- lll
- maligned - misspell
- megacheck
#- misspell
#- nakedret #- nakedret
#- noctx #- noctx
#- nolintlint - nolintlint
#- rowserrcheck #- rowserrcheck
#- scopelint #- scopelint
#- staticcheck - staticcheck
#- structcheck ! deprecated since v1.49.0; replaced by 'unused' #- structcheck ! deprecated since v1.49.0; replaced by 'unused'
#- stylecheck - stylecheck
#- typecheck #- typecheck
- unconvert - unconvert
#- unparam #- unparam

View File

@ -597,9 +597,7 @@ func writeRequiredFlag(buf io.StringWriter, cmd *Command) {
if nonCompletableFlag(flag) { if nonCompletableFlag(flag) {
return return
} }
for key := range flag.Annotations { if _, ok := flag.Annotations[BashCompOneRequiredFlag]; ok {
switch key {
case BashCompOneRequiredFlag:
format := " must_have_one_flag+=(\"--%s" format := " must_have_one_flag+=(\"--%s"
if flag.Value.Type() != "bool" { if flag.Value.Type() != "bool" {
format += "=" format += "="
@ -611,7 +609,6 @@ func writeRequiredFlag(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand))
} }
} }
}
}) })
} }

View File

@ -281,6 +281,7 @@ func (c *Command) SetArgs(a []string) {
// SetOutput sets the destination for usage and error messages. // SetOutput sets the destination for usage and error messages.
// If output is nil, os.Stderr is used. // If output is nil, os.Stderr is used.
//
// Deprecated: Use SetOut and/or SetErr instead // Deprecated: Use SetOut and/or SetErr instead
func (c *Command) SetOutput(output io.Writer) { func (c *Command) SetOutput(output io.Writer) {
c.outWriter = output c.outWriter = output
@ -875,7 +876,7 @@ func (c *Command) ArgsLenAtDash() int {
func (c *Command) execute(a []string) (err error) { func (c *Command) execute(a []string) (err error) {
if c == nil { if c == nil {
return fmt.Errorf("Called Execute() on a nil Command") return fmt.Errorf("called Execute() on a nil Command")
} }
if len(c.Deprecated) > 0 { if len(c.Deprecated) > 0 {
@ -1460,7 +1461,6 @@ func (c *Command) UseLine() string {
// DebugFlags used to determine which flags have been assigned to which commands // DebugFlags used to determine which flags have been assigned to which commands
// and which persist. // and which persist.
// nolint:goconst
func (c *Command) DebugFlags() { func (c *Command) DebugFlags() {
c.Println("DebugFlags called on", c.Name()) c.Println("DebugFlags called on", c.Name())
var debugflags func(*Command) var debugflags func(*Command)

View File

@ -2777,7 +2777,7 @@ func TestFind(t *testing.T) {
func TestUnknownFlagShouldReturnSameErrorRegardlessOfArgPosition(t *testing.T) { func TestUnknownFlagShouldReturnSameErrorRegardlessOfArgPosition(t *testing.T) {
testCases := [][]string{ testCases := [][]string{
//{"--unknown", "--namespace", "foo", "child", "--bar"}, // FIXME: This test case fails, returning the error `unknown command "foo" for "root"` instead of the expected error `unknown flag: --unknown` // {"--unknown", "--namespace", "foo", "child", "--bar"}, // FIXME: This test case fails, returning the error `unknown command "foo" for "root"` instead of the expected error `unknown flag: --unknown`
{"--namespace", "foo", "--unknown", "child", "--bar"}, {"--namespace", "foo", "--unknown", "child", "--bar"},
{"--namespace", "foo", "child", "--unknown", "--bar"}, {"--namespace", "foo", "child", "--unknown", "--bar"},
{"--namespace", "foo", "child", "--bar", "--unknown"}, {"--namespace", "foo", "child", "--bar", "--unknown"},

View File

@ -298,7 +298,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
} }
if err != nil { if err != nil {
// Unable to find the real command. E.g., <program> someInvalidCmd <TAB> // Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs) return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs)
} }
finalCmd.ctx = c.ctx finalCmd.ctx = c.ctx
@ -401,8 +401,9 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
doCompleteFlags := func(flag *pflag.Flag) { doCompleteFlags := func(flag *pflag.Flag) {
if !flag.Changed || if !flag.Changed ||
strings.Contains(flag.Value.Type(), "Slice") || strings.Contains(flag.Value.Type(), "Slice") ||
strings.Contains(flag.Value.Type(), "Array") { strings.Contains(flag.Value.Type(), "Array") ||
// If the flag is not already present, or if it can be specified multiple times (Array or Slice) strings.HasPrefix(flag.Value.Type(), "stringTo") {
// If the flag is not already present, or if it can be specified multiple times (Array, Slice, or stringTo)
// we suggest it as a completion // we suggest it as a completion
completions = append(completions, getFlagNameCompletions(flag, toComplete)...) completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
} }

View File

@ -133,7 +133,7 @@ func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error {
} }
header.Date = &now header.Date = &now
} }
header.date = (*header.Date).Format("Jan 2006") header.date = header.Date.Format("Jan 2006")
if header.Source == "" && !disableAutoGen { if header.Source == "" && !disableAutoGen {
header.Source = "Auto generated by spf13/cobra" header.Source = "Auto generated by spf13/cobra"
} }

View File

@ -18,7 +18,6 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -168,7 +167,7 @@ func TestManPrintFlagsHidesShortDeprecated(t *testing.T) {
func TestGenManTree(t *testing.T) { func TestGenManTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"} c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
header := &GenManHeader{Section: "2"} header := &GenManHeader{Section: "2"}
tmpdir, err := ioutil.TempDir("", "test-gen-man-tree") tmpdir, err := os.MkdirTemp("", "test-gen-man-tree")
if err != nil { if err != nil {
t.Fatalf("Failed to create tmpdir: %s", err.Error()) t.Fatalf("Failed to create tmpdir: %s", err.Error())
} }
@ -219,7 +218,7 @@ func assertNextLineEquals(scanner *bufio.Scanner, expectedLine string) error {
} }
func BenchmarkGenManToFile(b *testing.B) { func BenchmarkGenManToFile(b *testing.B) {
file, err := ioutil.TempFile("", "") file, err := os.CreateTemp("", "")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }

View File

@ -16,7 +16,6 @@ package doc
import ( import (
"bytes" "bytes"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -94,7 +93,7 @@ func TestGenMdNoTag(t *testing.T) {
func TestGenMdTree(t *testing.T) { func TestGenMdTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"} c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
tmpdir, err := ioutil.TempDir("", "test-gen-md-tree") tmpdir, err := os.MkdirTemp("", "test-gen-md-tree")
if err != nil { if err != nil {
t.Fatalf("Failed to create tmpdir: %v", err) t.Fatalf("Failed to create tmpdir: %v", err)
} }
@ -110,7 +109,7 @@ func TestGenMdTree(t *testing.T) {
} }
func BenchmarkGenMarkdownToFile(b *testing.B) { func BenchmarkGenMarkdownToFile(b *testing.B) {
file, err := ioutil.TempFile("", "") file, err := os.CreateTemp("", "")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }

View File

@ -16,7 +16,6 @@ package doc
import ( import (
"bytes" "bytes"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -81,7 +80,7 @@ func TestGenRSTNoTag(t *testing.T) {
func TestGenRSTTree(t *testing.T) { func TestGenRSTTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"} c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
tmpdir, err := ioutil.TempDir("", "test-gen-rst-tree") tmpdir, err := os.MkdirTemp("", "test-gen-rst-tree")
if err != nil { if err != nil {
t.Fatalf("Failed to create tmpdir: %s", err.Error()) t.Fatalf("Failed to create tmpdir: %s", err.Error())
} }
@ -97,7 +96,7 @@ func TestGenRSTTree(t *testing.T) {
} }
func BenchmarkGenReSTToFile(b *testing.B) { func BenchmarkGenReSTToFile(b *testing.B) {
file, err := ioutil.TempFile("", "") file, err := os.CreateTemp("", "")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }

View File

@ -40,7 +40,7 @@ func hasSeeAlso(cmd *cobra.Command) bool {
// that do not contain \n. // that do not contain \n.
func forceMultiLine(s string) string { func forceMultiLine(s string) string {
if len(s) > 60 && !strings.Contains(s, "\n") { if len(s) > 60 && !strings.Contains(s, "\n") {
s = s + "\n" s += "\n"
} }
return s return s
} }

View File

@ -17,7 +17,6 @@ package doc
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -58,7 +57,7 @@ func TestGenYamlNoTag(t *testing.T) {
func TestGenYamlTree(t *testing.T) { func TestGenYamlTree(t *testing.T) {
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"} c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
tmpdir, err := ioutil.TempDir("", "test-gen-yaml-tree") tmpdir, err := os.MkdirTemp("", "test-gen-yaml-tree")
if err != nil { if err != nil {
t.Fatalf("Failed to create tmpdir: %s", err.Error()) t.Fatalf("Failed to create tmpdir: %s", err.Error())
} }
@ -85,7 +84,7 @@ func TestGenYamlDocRunnable(t *testing.T) {
} }
func BenchmarkGenYamlToFile(b *testing.B) { func BenchmarkGenYamlToFile(b *testing.B) {
file, err := ioutil.TempFile("", "") file, err := os.CreateTemp("", "")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }

View File

@ -23,9 +23,9 @@ import (
) )
const ( const (
requiredAsGroup = "cobra_annotation_required_if_others_set" requiredAsGroupAnnotation = "cobra_annotation_required_if_others_set"
oneRequired = "cobra_annotation_one_required" oneRequiredAnnotation = "cobra_annotation_one_required"
mutuallyExclusive = "cobra_annotation_mutually_exclusive" mutuallyExclusiveAnnotation = "cobra_annotation_mutually_exclusive"
) )
// MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors // MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors
@ -37,7 +37,7 @@ func (c *Command) MarkFlagsRequiredTogether(flagNames ...string) {
if f == nil { if f == nil {
panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v)) panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v))
} }
if err := c.Flags().SetAnnotation(v, requiredAsGroup, append(f.Annotations[requiredAsGroup], strings.Join(flagNames, " "))); err != nil { if err := c.Flags().SetAnnotation(v, requiredAsGroupAnnotation, append(f.Annotations[requiredAsGroupAnnotation], strings.Join(flagNames, " "))); err != nil {
// Only errs if the flag isn't found. // Only errs if the flag isn't found.
panic(err) panic(err)
} }
@ -53,7 +53,7 @@ func (c *Command) MarkFlagsOneRequired(flagNames ...string) {
if f == nil { if f == nil {
panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a one-required flag group", v)) panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a one-required flag group", v))
} }
if err := c.Flags().SetAnnotation(v, oneRequired, append(f.Annotations[oneRequired], strings.Join(flagNames, " "))); err != nil { if err := c.Flags().SetAnnotation(v, oneRequiredAnnotation, append(f.Annotations[oneRequiredAnnotation], strings.Join(flagNames, " "))); err != nil {
// Only errs if the flag isn't found. // Only errs if the flag isn't found.
panic(err) panic(err)
} }
@ -70,7 +70,7 @@ func (c *Command) MarkFlagsMutuallyExclusive(flagNames ...string) {
panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v)) panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v))
} }
// Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed. // Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed.
if err := c.Flags().SetAnnotation(v, mutuallyExclusive, append(f.Annotations[mutuallyExclusive], strings.Join(flagNames, " "))); err != nil { if err := c.Flags().SetAnnotation(v, mutuallyExclusiveAnnotation, append(f.Annotations[mutuallyExclusiveAnnotation], strings.Join(flagNames, " "))); err != nil {
panic(err) panic(err)
} }
} }
@ -91,9 +91,9 @@ func (c *Command) ValidateFlagGroups() error {
oneRequiredGroupStatus := map[string]map[string]bool{} oneRequiredGroupStatus := map[string]map[string]bool{}
mutuallyExclusiveGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{}
flags.VisitAll(func(pflag *flag.Flag) { flags.VisitAll(func(pflag *flag.Flag) {
processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus)
processFlagForGroupAnnotation(flags, pflag, oneRequired, oneRequiredGroupStatus) processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus)
processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus)
}) })
if err := validateRequiredFlagGroups(groupStatus); err != nil { if err := validateRequiredFlagGroups(groupStatus); err != nil {
@ -232,9 +232,9 @@ func (c *Command) enforceFlagGroupsForCompletion() {
oneRequiredGroupStatus := map[string]map[string]bool{} oneRequiredGroupStatus := map[string]map[string]bool{}
mutuallyExclusiveGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{}
c.Flags().VisitAll(func(pflag *flag.Flag) { c.Flags().VisitAll(func(pflag *flag.Flag) {
processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus)
processFlagForGroupAnnotation(flags, pflag, oneRequired, oneRequiredGroupStatus) processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus)
processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus)
}) })
// If a flag that is part of a group is present, we make all the other flags // If a flag that is part of a group is present, we make all the other flags

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/spf13/cobra
go 1.15 go 1.15
require ( require (
github.com/cpuguy83/go-md2man/v2 v2.0.3 github.com/cpuguy83/go-md2man/v2 v2.0.4
github.com/inconshreveable/mousetrap v1.1.0 github.com/inconshreveable/mousetrap v1.1.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=

View File

@ -28,8 +28,8 @@ import (
func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) { func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) {
// Variables should not contain a '-' or ':' character // Variables should not contain a '-' or ':' character
nameForVar := name nameForVar := name
nameForVar = strings.Replace(nameForVar, "-", "_", -1) nameForVar = strings.ReplaceAll(nameForVar, "-", "_")
nameForVar = strings.Replace(nameForVar, ":", "_", -1) nameForVar = strings.ReplaceAll(nameForVar, ":", "_")
compCmd := ShellCompRequestCmd compCmd := ShellCompRequestCmd
if !includeDesc { if !includeDesc {

View File

@ -35,7 +35,7 @@ package main
import ( import (
"log" "log"
"io/ioutil" "io"
"os" "os"
"k8s.io/kubernetes/pkg/kubectl/cmd" "k8s.io/kubernetes/pkg/kubectl/cmd"
@ -45,7 +45,7 @@ import (
) )
func main() { func main() {
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, io.Discard, io.Discard)
err := doc.GenMarkdownTree(kubectl, "./") err := doc.GenMarkdownTree(kubectl, "./")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -35,7 +35,7 @@ package main
import ( import (
"log" "log"
"io/ioutil" "io"
"os" "os"
"k8s.io/kubernetes/pkg/kubectl/cmd" "k8s.io/kubernetes/pkg/kubectl/cmd"
@ -45,7 +45,7 @@ import (
) )
func main() { func main() {
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, io.Discard, io.Discard)
err := doc.GenReSTTree(kubectl, "./") err := doc.GenReSTTree(kubectl, "./")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -34,7 +34,7 @@ This program can actually generate docs for the kubectl command in the kubernete
package main package main
import ( import (
"io/ioutil" "io"
"log" "log"
"os" "os"
@ -45,7 +45,7 @@ import (
) )
func main() { func main() {
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, io.Discard, io.Discard)
err := doc.GenYamlTree(kubectl, "./") err := doc.GenYamlTree(kubectl, "./")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -3,7 +3,7 @@
While you are welcome to provide your own organization, typically a Cobra-based While you are welcome to provide your own organization, typically a Cobra-based
application will follow the following organizational structure: application will follow the following organizational structure:
``` ```test
▾ appName/ ▾ appName/
▾ cmd/ ▾ cmd/
add.go add.go
@ -301,6 +301,7 @@ command := cobra.Command{
### Bind Flags with Config ### Bind Flags with Config
You can also bind your flags with [viper](https://github.com/spf13/viper): You can also bind your flags with [viper](https://github.com/spf13/viper):
```go ```go
var author string var author string
@ -320,12 +321,14 @@ More in [viper documentation](https://github.com/spf13/viper#working-with-flags)
Flags are optional by default. If instead you wish your command to report an error Flags are optional by default. If instead you wish your command to report an error
when a flag has not been set, mark it as required: when a flag has not been set, mark it as required:
```go ```go
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region") rootCmd.MarkFlagRequired("region")
``` ```
Or, for persistent flags: Or, for persistent flags:
```go ```go
rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)") rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkPersistentFlagRequired("region") rootCmd.MarkPersistentFlagRequired("region")
@ -335,6 +338,7 @@ rootCmd.MarkPersistentFlagRequired("region")
If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then
Cobra can enforce that requirement: Cobra can enforce that requirement:
```go ```go
rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
@ -343,6 +347,7 @@ rootCmd.MarkFlagsRequiredTogether("username", "password")
You can also prevent different flags from being provided together if they represent mutually You can also prevent different flags from being provided together if they represent mutually
exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: exclusive options such as specifying an output format as either `--json` or `--yaml` but never both:
```go ```go
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
@ -351,6 +356,7 @@ rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
If you want to require at least one flag from a group to be present, you can use `MarkFlagsOneRequired`. If you want to require at least one flag from a group to be present, you can use `MarkFlagsOneRequired`.
This can be combined with `MarkFlagsMutuallyExclusive` to enforce exactly one flag from a given group: This can be combined with `MarkFlagsMutuallyExclusive` to enforce exactly one flag from a given group:
```go ```go
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
@ -428,7 +434,7 @@ by not providing a 'Run' for the 'rootCmd'.
We have only defined one flag for a single command. We have only defined one flag for a single command.
More documentation about flags is available at https://github.com/spf13/pflag More documentation about flags is available at https://github.com/spf13/pflag.
```go ```go
package main package main
@ -722,7 +728,7 @@ command.SuggestionsMinimumDistance = 1
You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but make sense in your set of commands but for which You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but make sense in your set of commands but for which
you don't want aliases. Example: you don't want aliases. Example:
``` ```bash
$ kubectl remove $ kubectl remove
Error: unknown command "remove" for "kubectl" Error: unknown command "remove" for "kubectl"
@ -787,7 +793,7 @@ func main() {
Example run as a kubectl plugin: Example run as a kubectl plugin:
``` ```bash
$ kubectl myplugin $ kubectl myplugin
Usage: Usage:
kubectl myplugin [command] kubectl myplugin [command]