This commit is contained in:
Bruno Franca dos Reis 2023-08-06 23:36:40 +00:00 committed by GitHub
commit 0c471a4dd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 275 additions and 344 deletions

View File

@ -199,13 +199,13 @@ func Example_helpPlaceholder() {
MustParse(&args)
// output:
//
// Usage: example [--optimize LEVEL] [--maxjobs N] SRC [DST [DST ...]]
//
// Positional arguments:
// SRC
// DST
//
// Options:
// --optimize LEVEL, -O LEVEL
// optimization level
@ -501,7 +501,9 @@ func Example_envVarOnly() {
os.Args = split("./example")
_ = os.Setenv("AUTH_KEY", "my_key")
defer os.Unsetenv("AUTH_KEY")
defer func() {
_ = os.Unsetenv("AUTH_KEY")
}()
var args struct {
AuthKey string `arg:"--,env:AUTH_KEY"`

8
go.mod
View File

@ -1,14 +1,14 @@
module github.com/alexflint/go-arg
go 1.18
require (
github.com/alexflint/go-scalar v1.2.0
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.4
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
go 1.18

10
go.sum
View File

@ -1,15 +1,13 @@
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -11,7 +11,7 @@ import (
"reflect"
"strings"
scalar "github.com/alexflint/go-scalar"
"github.com/alexflint/go-scalar"
)
// path represents a sequence of steps to find the output location for an
@ -94,7 +94,7 @@ func mustParse(config Config, dest ...interface{}) *Parser {
p, err := NewParser(config, dest...)
if err != nil {
fmt.Fprintln(config.Out, err)
_, _ = fmt.Fprintln(config.Out, err)
config.Exit(-1)
return nil
}
@ -141,6 +141,9 @@ type Config struct {
// Out is where help text, usage text, and failure messages are printed (defaults to os.Stdout)
Out io.Writer
// Environment is a map of environment variables to override those in the process environment, or provide values to those not in the process environment.
Environment map[string]string
}
// Parser represents a set of command line options with destination values
@ -513,11 +516,11 @@ func (p *Parser) Parse(args []string) error {
func (p *Parser) MustParse(args []string) {
err := p.Parse(args)
switch {
case err == ErrHelp:
case errors.Is(err, ErrHelp):
p.writeHelpForSubcommand(p.config.Out, p.lastCmd)
p.config.Exit(0)
case err == ErrVersion:
fmt.Fprintln(p.config.Out, p.version)
case errors.Is(err, ErrVersion):
_, _ = fmt.Fprintln(p.config.Out, p.version)
p.config.Exit(0)
case err != nil:
p.failWithSubcommand(err.Error(), p.lastCmd)
@ -531,7 +534,17 @@ func (p *Parser) captureEnvVars(specs []*spec, wasPresent map[*spec]bool) error
continue
}
value, found := os.LookupEnv(spec.env)
var value string
var found bool
if !p.config.IgnoreEnv {
value, found = os.LookupEnv(spec.env)
}
if p.config.Environment != nil {
value, found = p.config.Environment[spec.env]
}
if !found {
continue
}
@ -584,7 +597,7 @@ func (p *Parser) process(args []string) error {
copy(specs, curCmd.specs)
// deal with environment vars
if !p.config.IgnoreEnv {
if !p.config.IgnoreEnv || p.config.Environment != nil {
err := p.captureEnvVars(specs, wasPresent)
if err != nil {
return err
@ -640,7 +653,7 @@ func (p *Parser) process(args []string) error {
}
// capture environment vars for these new options
if !p.config.IgnoreEnv {
if !p.config.IgnoreEnv || p.config.Environment != nil {
err := p.captureEnvVars(subcmd.specs, wasPresent)
if err != nil {
return err

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ import (
"unicode"
"unicode/utf8"
scalar "github.com/alexflint/go-scalar"
"github.com/alexflint/go-scalar"
)
var textUnmarshalerType = reflect.TypeOf([]encoding.TextUnmarshaler{}).Elem()

View File

@ -59,7 +59,7 @@ func TestCardinalityOf(t *testing.T) {
type implementsTextUnmarshaler struct{}
func (*implementsTextUnmarshaler) UnmarshalText(text []byte) error {
func (*implementsTextUnmarshaler) UnmarshalText(_ []byte) error {
return nil
}

View File

@ -5,7 +5,7 @@ import (
"reflect"
"strings"
scalar "github.com/alexflint/go-scalar"
"github.com/alexflint/go-scalar"
)
// setSliceOrMap parses a sequence of strings into a slice or map. If clear is

View File

@ -42,8 +42,7 @@ func TestMinimalSubcommand(t *testing.T) {
var args struct {
List *listCmd `arg:"subcommand"`
}
p, err := pparse("list", &args)
require.NoError(t, err)
p := pparse(t, "list", &args)
assert.NotNil(t, args.List)
assert.Equal(t, args.List, p.Subcommand())
assert.Equal(t, []string{"list"}, p.SubcommandNames())
@ -66,7 +65,7 @@ func TestNoSuchSubcommand(t *testing.T) {
var args struct {
List *listCmd `arg:"subcommand"`
}
_, err := pparse("invalid", &args)
_, err := parseWithEnvErr(t, "invalid", nil, &args)
assert.Error(t, err)
}
@ -76,8 +75,7 @@ func TestNamedSubcommand(t *testing.T) {
var args struct {
List *listCmd `arg:"subcommand:ls"`
}
p, err := pparse("ls", &args)
require.NoError(t, err)
p := pparse(t, "ls", &args)
assert.NotNil(t, args.List)
assert.Equal(t, args.List, p.Subcommand())
assert.Equal(t, []string{"ls"}, p.SubcommandNames())
@ -89,8 +87,7 @@ func TestEmptySubcommand(t *testing.T) {
var args struct {
List *listCmd `arg:"subcommand"`
}
p, err := pparse("", &args)
require.NoError(t, err)
p := pparse(t, "", &args)
assert.Nil(t, args.List)
assert.Nil(t, p.Subcommand())
assert.Empty(t, p.SubcommandNames())
@ -105,8 +102,7 @@ func TestTwoSubcommands(t *testing.T) {
Get *getCmd `arg:"subcommand"`
List *listCmd `arg:"subcommand"`
}
p, err := pparse("list", &args)
require.NoError(t, err)
p := pparse(t, "list", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
assert.Equal(t, args.List, p.Subcommand())
@ -128,16 +124,14 @@ func TestSubcommandsWithOptions(t *testing.T) {
{
var args cmd
err := parse("list", &args)
require.NoError(t, err)
parse(t, "list", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
}
{
var args cmd
err := parse("list --limit 3", &args)
require.NoError(t, err)
parse(t, "list --limit 3", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
assert.Equal(t, args.List.Limit, 3)
@ -145,8 +139,7 @@ func TestSubcommandsWithOptions(t *testing.T) {
{
var args cmd
err := parse("list --limit 3 --verbose", &args)
require.NoError(t, err)
parse(t, "list --limit 3 --verbose", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
assert.Equal(t, args.List.Limit, 3)
@ -155,8 +148,7 @@ func TestSubcommandsWithOptions(t *testing.T) {
{
var args cmd
err := parse("list --verbose --limit 3", &args)
require.NoError(t, err)
parse(t, "list --verbose --limit 3", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
assert.Equal(t, args.List.Limit, 3)
@ -165,8 +157,7 @@ func TestSubcommandsWithOptions(t *testing.T) {
{
var args cmd
err := parse("--verbose list --limit 3", &args)
require.NoError(t, err)
parse(t, "--verbose list --limit 3", &args)
assert.Nil(t, args.Get)
assert.NotNil(t, args.List)
assert.Equal(t, args.List.Limit, 3)
@ -175,16 +166,14 @@ func TestSubcommandsWithOptions(t *testing.T) {
{
var args cmd
err := parse("get", &args)
require.NoError(t, err)
parse(t, "get", &args)
assert.NotNil(t, args.Get)
assert.Nil(t, args.List)
}
{
var args cmd
err := parse("get --name test", &args)
require.NoError(t, err)
parse(t, "get --name test", &args)
assert.NotNil(t, args.Get)
assert.Nil(t, args.List)
assert.Equal(t, args.Get.Name, "test")
@ -207,8 +196,7 @@ func TestSubcommandsWithEnvVars(t *testing.T) {
{
var args cmd
setenv(t, "LIMIT", "123")
err := parse("list", &args)
require.NoError(t, err)
parse(t, "list", &args)
require.NotNil(t, args.List)
assert.Equal(t, 123, args.List.Limit)
}
@ -216,7 +204,7 @@ func TestSubcommandsWithEnvVars(t *testing.T) {
{
var args cmd
setenv(t, "LIMIT", "not_an_integer")
err := parse("list", &args)
_, err := parseWithEnvErr(t, "list", nil, &args)
assert.Error(t, err)
}
}
@ -235,8 +223,7 @@ func TestNestedSubcommands(t *testing.T) {
{
var args root
p, err := pparse("grandparent parent child", &args)
require.NoError(t, err)
p := pparse(t, "grandparent parent child", &args)
require.NotNil(t, args.Grandparent)
require.NotNil(t, args.Grandparent.Parent)
require.NotNil(t, args.Grandparent.Parent.Child)
@ -246,8 +233,7 @@ func TestNestedSubcommands(t *testing.T) {
{
var args root
p, err := pparse("grandparent parent", &args)
require.NoError(t, err)
p := pparse(t, "grandparent parent", &args)
require.NotNil(t, args.Grandparent)
require.NotNil(t, args.Grandparent.Parent)
require.Nil(t, args.Grandparent.Parent.Child)
@ -257,8 +243,7 @@ func TestNestedSubcommands(t *testing.T) {
{
var args root
p, err := pparse("grandparent", &args)
require.NoError(t, err)
p := pparse(t, "grandparent", &args)
require.NotNil(t, args.Grandparent)
require.Nil(t, args.Grandparent.Parent)
assert.Equal(t, args.Grandparent, p.Subcommand())
@ -267,8 +252,7 @@ func TestNestedSubcommands(t *testing.T) {
{
var args root
p, err := pparse("", &args)
require.NoError(t, err)
p := pparse(t, "", &args)
require.Nil(t, args.Grandparent)
assert.Nil(t, p.Subcommand())
assert.Empty(t, p.SubcommandNames())
@ -286,16 +270,14 @@ func TestSubcommandsWithPositionals(t *testing.T) {
{
var args cmd
err := parse("list", &args)
require.NoError(t, err)
parse(t, "list", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "", args.List.Pattern)
}
{
var args cmd
err := parse("list --format json", &args)
require.NoError(t, err)
parse(t, "list --format json", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "", args.List.Pattern)
assert.Equal(t, "json", args.Format)
@ -303,16 +285,14 @@ func TestSubcommandsWithPositionals(t *testing.T) {
{
var args cmd
err := parse("list somepattern", &args)
require.NoError(t, err)
parse(t, "list somepattern", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "somepattern", args.List.Pattern)
}
{
var args cmd
err := parse("list somepattern --format json", &args)
require.NoError(t, err)
parse(t, "list somepattern --format json", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "somepattern", args.List.Pattern)
assert.Equal(t, "json", args.Format)
@ -320,8 +300,7 @@ func TestSubcommandsWithPositionals(t *testing.T) {
{
var args cmd
err := parse("list --format json somepattern", &args)
require.NoError(t, err)
parse(t, "list --format json somepattern", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "somepattern", args.List.Pattern)
assert.Equal(t, "json", args.Format)
@ -329,8 +308,7 @@ func TestSubcommandsWithPositionals(t *testing.T) {
{
var args cmd
err := parse("--format json list somepattern", &args)
require.NoError(t, err)
parse(t, "--format json list somepattern", &args)
assert.NotNil(t, args.List)
assert.Equal(t, "somepattern", args.List.Pattern)
assert.Equal(t, "json", args.Format)
@ -338,8 +316,7 @@ func TestSubcommandsWithPositionals(t *testing.T) {
{
var args cmd
err := parse("--format json", &args)
require.NoError(t, err)
parse(t, "--format json", &args)
assert.Nil(t, args.List)
assert.Equal(t, "json", args.Format)
}
@ -355,16 +332,14 @@ func TestSubcommandsWithMultiplePositionals(t *testing.T) {
{
var args cmd
err := parse("get", &args)
require.NoError(t, err)
parse(t, "get", &args)
assert.NotNil(t, args.Get)
assert.Empty(t, args.Get.Items)
}
{
var args cmd
err := parse("get --limit 5", &args)
require.NoError(t, err)
parse(t, "get --limit 5", &args)
assert.NotNil(t, args.Get)
assert.Empty(t, args.Get.Items)
assert.Equal(t, 5, args.Limit)
@ -372,24 +347,21 @@ func TestSubcommandsWithMultiplePositionals(t *testing.T) {
{
var args cmd
err := parse("get item1", &args)
require.NoError(t, err)
parse(t, "get item1", &args)
assert.NotNil(t, args.Get)
assert.Equal(t, []string{"item1"}, args.Get.Items)
}
{
var args cmd
err := parse("get item1 item2 item3", &args)
require.NoError(t, err)
parse(t, "get item1 item2 item3", &args)
assert.NotNil(t, args.Get)
assert.Equal(t, []string{"item1", "item2", "item3"}, args.Get.Items)
}
{
var args cmd
err := parse("get item1 --limit 5 item2", &args)
require.NoError(t, err)
parse(t, "get item1 --limit 5 item2", &args)
assert.NotNil(t, args.Get)
assert.Equal(t, []string{"item1", "item2"}, args.Get.Items)
assert.Equal(t, 5, args.Limit)

View File

@ -32,7 +32,7 @@ func (p *Parser) FailSubcommand(msg string, subcommand ...string) error {
// failWithSubcommand prints usage information for the given subcommand to stderr and exits with non-zero status
func (p *Parser) failWithSubcommand(msg string, cmd *command) {
p.writeUsageForSubcommand(p.config.Out, cmd)
fmt.Fprintln(p.config.Out, "error:", msg)
_, _ = fmt.Fprintln(p.config.Out, "error:", msg)
p.config.Exit(-1)
}
@ -74,7 +74,7 @@ func (p *Parser) writeUsageForSubcommand(w io.Writer, cmd *command) {
}
if p.version != "" {
fmt.Fprintln(w, p.version)
_, _ = fmt.Fprintln(w, p.version)
}
// make a list of ancestor commands so that we print with full context
@ -86,33 +86,33 @@ func (p *Parser) writeUsageForSubcommand(w io.Writer, cmd *command) {
}
// print the beginning of the usage string
fmt.Fprint(w, "Usage:")
_, _ = fmt.Fprint(w, "Usage:")
for i := len(ancestors) - 1; i >= 0; i-- {
fmt.Fprint(w, " "+ancestors[i])
_, _ = fmt.Fprint(w, " "+ancestors[i])
}
// write the option component of the usage message
for _, spec := range shortOptions {
// prefix with a space
fmt.Fprint(w, " ")
_, _ = fmt.Fprint(w, " ")
if !spec.required {
fmt.Fprint(w, "[")
_, _ = fmt.Fprint(w, "[")
}
fmt.Fprint(w, synopsis(spec, "-"+spec.short))
_, _ = fmt.Fprint(w, synopsis(spec, "-"+spec.short))
if !spec.required {
fmt.Fprint(w, "]")
_, _ = fmt.Fprint(w, "]")
}
}
for _, spec := range longOptions {
// prefix with a space
fmt.Fprint(w, " ")
_, _ = fmt.Fprint(w, " ")
if !spec.required {
fmt.Fprint(w, "[")
_, _ = fmt.Fprint(w, "[")
}
fmt.Fprint(w, synopsis(spec, "--"+spec.long))
_, _ = fmt.Fprint(w, synopsis(spec, "--"+spec.long))
if !spec.required {
fmt.Fprint(w, "]")
_, _ = fmt.Fprint(w, "]")
}
}
@ -130,40 +130,40 @@ func (p *Parser) writeUsageForSubcommand(w io.Writer, cmd *command) {
// REQUIRED1 REQUIRED2 [OPTIONAL1 [REPEATEDOPTIONAL [REPEATEDOPTIONAL ...]]]
var closeBrackets int
for _, spec := range positionals {
fmt.Fprint(w, " ")
_, _ = fmt.Fprint(w, " ")
if !spec.required {
fmt.Fprint(w, "[")
_, _ = fmt.Fprint(w, "[")
closeBrackets += 1
}
if spec.cardinality == multiple {
fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder)
_, _ = fmt.Fprintf(w, "%s [%s ...]", spec.placeholder, spec.placeholder)
} else {
fmt.Fprint(w, spec.placeholder)
_, _ = fmt.Fprint(w, spec.placeholder)
}
}
fmt.Fprint(w, strings.Repeat("]", closeBrackets))
_, _ = fmt.Fprint(w, strings.Repeat("]", closeBrackets))
// if the program supports subcommands, give a hint to the user about their existence
if len(cmd.subcommands) > 0 {
fmt.Fprint(w, " <command> [<args>]")
_, _ = fmt.Fprint(w, " <command> [<args>]")
}
fmt.Fprint(w, "\n")
_, _ = fmt.Fprint(w, "\n")
}
func printTwoCols(w io.Writer, left, help string, defaultVal string, envVal string) {
lhs := " " + left
fmt.Fprint(w, lhs)
_, _ = fmt.Fprint(w, lhs)
if help != "" {
if len(lhs)+2 < colWidth {
fmt.Fprint(w, strings.Repeat(" ", colWidth-len(lhs)))
_, _ = fmt.Fprint(w, strings.Repeat(" ", colWidth-len(lhs)))
} else {
fmt.Fprint(w, "\n"+strings.Repeat(" ", colWidth))
_, _ = fmt.Fprint(w, "\n"+strings.Repeat(" ", colWidth))
}
fmt.Fprint(w, help)
_, _ = fmt.Fprint(w, help)
}
bracketsContent := []string{}
var bracketsContent []string
if defaultVal != "" {
bracketsContent = append(bracketsContent,
@ -178,9 +178,9 @@ func printTwoCols(w io.Writer, left, help string, defaultVal string, envVal stri
}
if len(bracketsContent) > 0 {
fmt.Fprintf(w, " [%s]", strings.Join(bracketsContent, ", "))
_, _ = fmt.Fprintf(w, " [%s]", strings.Join(bracketsContent, ", "))
}
fmt.Fprint(w, "\n")
_, _ = fmt.Fprint(w, "\n")
}
// WriteHelp writes the usage string followed by the full help string for each option
@ -224,13 +224,13 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
}
if p.description != "" {
fmt.Fprintln(w, p.description)
_, _ = fmt.Fprintln(w, p.description)
}
p.writeUsageForSubcommand(w, cmd)
// write the list of positionals
if len(positionals) > 0 {
fmt.Fprint(w, "\nPositional arguments:\n")
_, _ = fmt.Fprint(w, "\nPositional arguments:\n")
for _, spec := range positionals {
printTwoCols(w, spec.placeholder, spec.help, "", "")
}
@ -238,7 +238,7 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
// write the list of options with the short-only ones first to match the usage string
if len(shortOptions)+len(longOptions) > 0 || cmd.parent == nil {
fmt.Fprint(w, "\nOptions:\n")
_, _ = fmt.Fprint(w, "\nOptions:\n")
for _, spec := range shortOptions {
p.printOption(w, spec)
}
@ -260,7 +260,7 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
// write the list of global options
if len(globals) > 0 {
fmt.Fprint(w, "\nGlobal options:\n")
_, _ = fmt.Fprint(w, "\nGlobal options:\n")
for _, spec := range globals {
p.printOption(w, spec)
if spec.long == "version" {
@ -286,7 +286,7 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
// write the list of environment only variables
if len(envOnlyOptions) > 0 {
fmt.Fprint(w, "\nEnvironment variables:\n")
_, _ = fmt.Fprint(w, "\nEnvironment variables:\n")
for _, spec := range envOnlyOptions {
p.printEnvOnlyVar(w, spec)
}
@ -294,14 +294,14 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
// write the list of subcommands
if len(cmd.subcommands) > 0 {
fmt.Fprint(w, "\nCommands:\n")
_, _ = fmt.Fprint(w, "\nCommands:\n")
for _, subcmd := range cmd.subcommands {
printTwoCols(w, subcmd.name, subcmd.help, "", "")
}
}
if p.epilogue != "" {
fmt.Fprintln(w, "\n"+p.epilogue)
_, _ = fmt.Fprintln(w, "\n"+p.epilogue)
}
}

View File

@ -97,12 +97,12 @@ Environment variables:
type MyEnum int
func (n *MyEnum) UnmarshalText(b []byte) error {
func (n *MyEnum) UnmarshalText(_ []byte) error {
return nil
}
func (n *MyEnum) MarshalText() ([]byte, error) {
return nil, errors.New("There was a problem")
return nil, errors.New("there was a problem")
}
func TestUsageWithDefaults(t *testing.T) {
@ -142,7 +142,7 @@ func TestUsageCannotMarshalToString(t *testing.T) {
v := MyEnum(42)
args.Name = &v
_, err := NewParser(Config{Program: "example"}, &args)
assert.EqualError(t, err, `args.Name: error marshaling default value to string: There was a problem`)
assert.EqualError(t, err, `args.Name: error marshaling default value to string: there was a problem`)
}
func TestUsageLongPositionalWithHelp_legacyForm(t *testing.T) {
@ -455,7 +455,8 @@ Global options:
assert.Equal(t, expectedHelp[1:], help.String())
var help2 bytes.Buffer
p.WriteHelpForSubcommand(&help2, "child", "nested")
err = p.WriteHelpForSubcommand(&help2, "child", "nested")
require.NoError(t, err)
assert.Equal(t, expectedHelp[1:], help2.String())
var usage bytes.Buffer
@ -463,7 +464,8 @@ Global options:
assert.Equal(t, expectedUsage, strings.TrimSpace(usage.String()))
var usage2 bytes.Buffer
p.WriteUsageForSubcommand(&usage2, "child", "nested")
err = p.WriteUsageForSubcommand(&usage2, "child", "nested")
require.NoError(t, err)
assert.Equal(t, expectedUsage, strings.TrimSpace(usage2.String()))
}