build(deps): bump github.com/spf13/pflag from 1.0.10 to 1.1.0

Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.10 to 1.1.0.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.10...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/pflag
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] authored and GitHub committed 2026-11-06 14:43:27 +00:00
1 parent 2edb3e1c7b
commit 8d6de2bc4a
38 files changed
+589 -229

No files matched your search

+1 -1
View File
@@ -84,7 +84,7 @@ require (
github.com/sirupsen/logrus v1.10.2
github.com/spf13/afero v1.15.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/spf13/pflag v1.1.0
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.12.1
github.com/test-go/testify v1.1.4
+2 -2
View File
@@ -913,8 +913,8 @@ github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qq
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.1.0 h1:6W6MbVUrnMb8PEhjkqwsVLY7ryuzRfFHF4mQd7L94ag=
github.com/spf13/pflag v1.1.0/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+23 -1
View File
@@ -1,4 +1,26 @@
version: "2"
linters:
disable-all: true
enable:
- errorlint
- nolintlint
- revive
- unconvert
- unparam
settings:
govet:
disable:
# Suggests reflect.Pointer over reflect.Ptr, which needs Go 1.18.
# This module still builds and tests on Go 1.12 (see go.mod).
- inline
staticcheck:
# Enable all options, with some exceptions.
# For defaults, see https://golangci-lint.run/usage/linters/#staticcheck
checks:
- all
- -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008
- -ST1003 # Poorly chosen identifier; https://staticcheck.dev/docs/checks/#ST1003
formatters:
enable:
- gofmt
+65 -18
View File
@@ -1,6 +1,7 @@
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
[![Build Status](https://github.com/spf13/pflag/actions/workflows/ci.yaml/badge.svg)](https://github.com/spf13/pflag/actions/workflows/ci.yaml)
![GitHub License](https://img.shields.io/github/license/spf13/pflag)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/spf13/pflag)](https://pkg.go.dev/github.com/spf13/pflag)
## Description
@@ -11,7 +12,7 @@ pflag is compatible with the [GNU extensions to the POSIX recommendations
for command-line options][1]. For a more precise description, see the
"Command-line flag syntax" section below.
[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
[1]: https://sourceware.org/glibc/manual/latest/html_node/Argument-Syntax.html
pflag is available under the same style of BSD license as the Go language,
which can be found in the LICENSE file.
@@ -22,7 +23,7 @@ pflag is available using the standard `go get` command.
Install by running:
go get github.com/spf13/pflag
go get github.com/spf13/pflag@latest
Run tests by running:
@@ -179,6 +180,25 @@ Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.
To stop parsing at the first non-flag argument, call
`flag.SetInterspersed(false)` before `flag.Parse()`, or use
`flags.SetInterspersed(false)` on a `FlagSet`. This is useful for wrappers
that pass a command and its remaining arguments through unchanged:
```go
flags := flag.NewFlagSet("wrapper", flag.ContinueOnError)
verbose := flags.Bool("verbose", false, "verbose output")
flags.SetInterspersed(false)
if err := flags.Parse([]string{"--verbose", "echo", "--verbose", "hello"}); err != nil {
panic(err)
}
fmt.Println(*verbose) // true
fmt.Println(flags.Args()) // [echo --verbose hello]
```
The second `--verbose` belongs to `echo`, so it is left in `flags.Args()`
along with every argument after the command, even if it names a known flag.
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
TRUE, FALSE, True, False.
@@ -249,13 +269,35 @@ flags.MarkHidden("secretFlag")
## Disable sorting of flags
`pflag` allows you to disable sorting of flags for help and usage message.
`SortFlags` is a field on `FlagSet`, not a package-level variable. To disable
sorting on the default `CommandLine` flag set, use `pflag.CommandLine.SortFlags`.
**Example**:
```go
flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()
package main
import (
"fmt"
"github.com/spf13/pflag"
)
func main() {
flags := pflag.NewFlagSet("example", pflag.ContinueOnError)
flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()
fmt.Println()
}
```
For the default `CommandLine` flag set:
```go
pflag.CommandLine.SortFlags = false
pflag.PrintDefaults()
```
**Output**:
```
@@ -271,12 +313,15 @@ to support flags defined by third-party dependencies (e.g. `golang/glog`).
**Example**: You want to add the Go flags to the `CommandLine` flagset
```go
package main
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
var ip = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
@@ -296,17 +341,22 @@ will result in the `-v` flag being ignored. This happens because of the way pfla
To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
```go
package main
import (
goflag "flag"
"os"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
var ip = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
flag.Parse()
}
```
@@ -314,10 +364,7 @@ func main() {
## More info
You can see the full reference documentation of the pflag package
[at godoc.org][3], or through go's standard documentation system by
running `godoc -http=:6060` and browsing to
[http://localhost:6060/pkg/github.com/spf13/pflag][2] after
installation.
at [pkg.go.dev][2], or through go's standard documentation system by
cloning the repository and running `go doc -http` in it.
[2]: http://localhost:6060/pkg/github.com/spf13/pflag
[3]: http://godoc.org/github.com/spf13/pflag
[2]: https://pkg.go.dev/github.com/spf13/pflag
+31
View File
@@ -0,0 +1,31 @@
# Releasing pflag
This document describes how to create a new pflag release.
## Method 1: GitHub UI (recommended by maintainers)
1. Go to the [releases page](https://github.com/spf13/pflag/releases)
2. Click **"Draft a new release"**
3. Click **"Generate release notes"** — this shows the merged PRs since the last tag, which helps determine the next version (minor vs patch)
4. Choose the tag version (e.g., `v1.0.8`) — the tag will be created when the release is published
5. Review the generated notes, then publish
This method has the advantage that the tag and release are published atomically, and the PR list helps pick the right version number before tagging.
## Method 2: GitHub CLI
```bash
git checkout master
git pull origin master
# Tag and push
git tag v1.0.8
git push origin v1.0.8
# Create release with auto-generated notes
gh release create v1.0.8 --generate-notes
```
## Notes
pflag follows [Semantic Versioning](https://semver.org/). Check the [releases page](https://github.com/spf13/pflag/releases) for the latest tag.
+15 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// optional interface to indicate boolean flags that can be
// supplied without "=value" text
@@ -9,6 +12,13 @@ type boolFlag interface {
IsBoolFlag() bool
}
func isNoOptBoolValue(v Value) bool {
if bf, ok := v.(boolFlag); ok {
return bf.IsBoolFlag()
}
return false
}
// -- bool Value
type boolValue bool
@@ -19,8 +29,11 @@ func newBoolValue(val bool, p *bool) *boolValue {
func (b *boolValue) Set(s string) error {
v, err := strconv.ParseBool(s)
if err != nil {
return errors.New("must be true or false")
}
*b = boolValue(v)
return err
return nil
}
func (b *boolValue) Type() string {
+1 -3
View File
@@ -22,13 +22,12 @@ func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
func (s *boolSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12
return err
}
@@ -60,7 +59,6 @@ func (s *boolSliceValue) Type() string {
// String defines a "native" format for this boolean slice flag value.
func (s *boolSliceValue) String() string {
boolStrSlice := make([]string, len(*s.value))
for i, b := range *s.value {
boolStrSlice[i] = strconv.FormatBool(b)
+2 -8
View File
@@ -18,7 +18,6 @@ func (bytesHex bytesHexValue) String() string {
// Set implements pflag.Value.Set.
func (bytesHex *bytesHexValue) Set(value string) error {
bin, err := hex.DecodeString(strings.TrimSpace(value))
if err != nil {
return err
}
@@ -39,20 +38,18 @@ func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue {
}
func bytesHexConv(sval string) (interface{}, error) {
bin, err := hex.DecodeString(sval)
if err == nil {
return bin, nil
}
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err.Error())
}
// GetBytesHex return the []byte value of a flag with the given name
func (f *FlagSet) GetBytesHex(name string) ([]byte, error) {
val, err := f.getFlagType(name, "bytesHex", bytesHexConv)
if err != nil {
return []byte{}, err
}
@@ -119,7 +116,6 @@ func (bytesBase64 bytesBase64Value) String() string {
// Set implements pflag.Value.Set.
func (bytesBase64 *bytesBase64Value) Set(value string) error {
bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value))
if err != nil {
return err
}
@@ -140,19 +136,17 @@ func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value {
}
func bytesBase64ValueConv(sval string) (interface{}, error) {
bin, err := base64.StdEncoding.DecodeString(sval)
if err == nil {
return bin, nil
}
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err.Error())
}
// GetBytesBase64 return the []byte value of a flag with the given name
func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) {
val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv)
if err != nil {
return []byte{}, err
}
+5 -2
View File
@@ -13,12 +13,15 @@ func newCountValue(val int, p *int) *countValue {
func (i *countValue) Set(s string) error {
// "+1" means that no specific value was passed, so increment
if s == "+1" {
*i = countValue(*i + 1)
*i = *i + 1
return nil
}
v, err := strconv.ParseInt(s, 0, 0)
if err != nil {
return err
}
*i = countValue(v)
return err
return nil
}
func (i *countValue) Type() string {
+5 -1
View File
@@ -1,6 +1,7 @@
package pflag
import (
"errors"
"time"
)
@@ -14,8 +15,11 @@ func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
func (d *durationValue) Set(s string) error {
v, err := time.ParseDuration(s)
if err != nil {
return errors.New(`must be a duration like "30s" or "5m"`)
}
*d = durationValue(v)
return err
return nil
}
func (d *durationValue) Type() string {
+2 -3
View File
@@ -1,7 +1,6 @@
package pflag
import (
"fmt"
"strings"
"time"
)
@@ -46,7 +45,7 @@ func (s *durationSliceValue) Type() string {
func (s *durationSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%s", d)
out[i] = d.String()
}
return "[" + strings.Join(out, ",") + "]"
}
@@ -56,7 +55,7 @@ func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
}
func (s *durationSliceValue) toString(val time.Duration) string {
return fmt.Sprintf("%s", val)
return val.String()
}
func (s *durationSliceValue) Append(val string) error {
+1 -5
View File
@@ -10,7 +10,6 @@ type notExistErrorMessageType int
const (
flagNotExistMessage notExistErrorMessageType = iota
flagNotDefinedMessage
flagNoSuchFlagMessage
flagUnknownFlagMessage
flagUnknownShorthandFlagMessage
@@ -30,9 +29,6 @@ func (e *NotExistError) Error() string {
case flagNotExistMessage:
return fmt.Sprintf("flag %q does not exist", e.name)
case flagNotDefinedMessage:
return fmt.Sprintf("flag accessed but not defined: %s", e.name)
case flagNoSuchFlagMessage:
return fmt.Sprintf("no such flag -%v", e.name)
@@ -142,7 +138,7 @@ func (e *InvalidSyntaxError) Error() string {
return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
}
// GetSpecifiedName returns the exact flag (with dashes) as it
// GetSpecifiedFlag returns the exact flag (with dashes) as it
// appeared in the parsed arguments.
func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
return e.specifiedFlag
+185 -53
View File
@@ -137,10 +137,29 @@ const (
PanicOnError
)
// UnknownFlagsHandling decides how to handle unknown flags
type UnknownFlagsHandling int
const (
// ErrorOnUnknownFlag will return an error if an unknown flag is found
ErrorOnUnknownFlag UnknownFlagsHandling = iota
// IgnoreUnknownFlag will ignore unknown flags and continue parsing rest of the flags
IgnoreUnknownFlag
// PassUnknownFlagToArgs will treat unknown flags as non-flag arguments.
// Combined shorthand flags mixed with known ones and unknown ones results
// combined flags only with unknown ones.
// E.g. -fghi results -gh if only `f` and `i` are known.
PassUnknownFlagToArgs
)
// ParseErrorsAllowlist defines the parsing errors that can be ignored
type ParseErrorsAllowlist struct {
// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
// Deprecated: Use UnknownFlagsHandling instead
UnknownFlags bool
// UnknownFlagsHandling decides how to handle unknown flags. Defaults to UnknownFlagsHandlingErrorOnUnknown.
UnknownFlagsHandling UnknownFlagsHandling
}
// ParseErrorsWhitelist defines the parsing errors that can be ignored.
@@ -270,7 +289,7 @@ func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedNam
if f.normalizeNameFunc != nil {
return f.normalizeNameFunc
}
return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) }
return func(_ *FlagSet, name string) NormalizedName { return NormalizedName(name) }
}
func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
@@ -337,6 +356,35 @@ func (f *FlagSet) HasAvailableFlags() bool {
return false
}
// getUnknownFlagsHandling returns the UnknownFlagsHandling value,
// considering deprecated ParseErrorsWhitelist and UnknownFlags field
// After removing ParseErrorsWhitelist, this function can be simplified
// and moved to ParseErrorsAllowlist.getUnknownFlagsHandling()
func (f *FlagSet) getUnknownFlagsHandling() UnknownFlagsHandling {
// first check ParseErrorsAllowlist:
// if UnknownFlagsHandling is set, use it
if f.ParseErrorsAllowlist.UnknownFlagsHandling != ErrorOnUnknownFlag {
return f.ParseErrorsAllowlist.UnknownFlagsHandling
}
if f.ParseErrorsAllowlist.UnknownFlags {
return IgnoreUnknownFlag
}
// then, check deprecated ParseErrorsWhitelist:
// if UnknownFlagsHandling is set, use it
if f.ParseErrorsWhitelist.UnknownFlagsHandling != ErrorOnUnknownFlag {
return f.ParseErrorsWhitelist.UnknownFlagsHandling
}
if f.ParseErrorsWhitelist.UnknownFlags {
return IgnoreUnknownFlag
}
// Otherwise, return the default value
return ErrorOnUnknownFlag
}
// VisitAll visits the command-line flags in lexicographical order or
// in primordial order if f.SortFlags is false, calling fn for each.
// It visits all flags, even those not set.
@@ -388,7 +436,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.Output(), msg)
_, _ = fmt.Fprint(f.Output(), msg)
panic(msg)
}
c := name[0]
@@ -400,11 +448,16 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
return f.formal[name]
}
// func to return a given type for a given flag name
// getFlagType performs a lookup of a flag with the given name and ftype. The flag is stringified and passed through
// convFunc before being returned to enforce flag immutablility.
//
// convFunc may be nil, in which case the raw flag value is returned directly and no immutability is enforced. This is
// particularly useful when users need to access the pointer of the underlying flag value for manipulation (e.g.
// resetting flag values in tests).
func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
flag := f.Lookup(name)
if flag == nil {
err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
err := &NotExistError{name: name, messageType: flagNotExistMessage}
return nil, err
}
@@ -413,6 +466,10 @@ func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval stri
return nil, err
}
if convFunc == nil {
return flag.Value, nil
}
sval := flag.Value.String()
result, err := convFunc(sval)
if err != nil {
@@ -510,7 +567,7 @@ func (f *FlagSet) Set(name, value string) error {
}
if flag.Deprecated != "" {
fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
_, _ = fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", name, flag.Deprecated)
}
return nil
}
@@ -551,15 +608,16 @@ func Set(name, value string) error {
// otherwise, the default values of all defined flags in the set.
func (f *FlagSet) PrintDefaults() {
usages := f.FlagUsages()
fmt.Fprint(f.Output(), usages)
_, _ = fmt.Fprint(f.Output(), usages)
}
// defaultIsZeroValue returns true if the default value for this flag represents
// a zero value.
func (f *Flag) defaultIsZeroValue() bool {
switch f.Value.(type) {
case boolFlag:
if isNoOptBoolValue(f.Value) {
return f.DefValue == "false" || f.DefValue == ""
}
switch f.Value.(type) {
case *durationValue:
// Beginning in Go 1.7, duration zero values are "0s"
return f.DefValue == "0" || f.DefValue == "0s"
@@ -608,6 +666,9 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
}
name = flag.Value.Type()
if isNoOptBoolValue(flag.Value) {
name = ""
}
switch name {
case "bool", "boolfunc":
name = ""
@@ -635,7 +696,9 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
// Splits the string `s` on whitespace into an initial substring up to
// `i` runes in length and the remainder. Will go `slop` over `i` if
// that encompasses the entire string (which allows the caller to
// avoid short orphan words on the final line).
// avoid short orphan words on the final line). If the next word is
// wider than `i`, it is returned on its own and wrapping continues
// after it.
func wrapN(i, slop int, s string) (string, string) {
if i+slop > len(s) {
return s, ""
@@ -643,7 +706,13 @@ func wrapN(i, slop int, s string) (string, string) {
w := strings.LastIndexAny(s[:i], " \t\n")
if w <= 0 {
return s, ""
// No break in the first i bytes. Emit the over-wide word
// alone and keep wrapping whatever follows.
next := strings.IndexAny(s, " \t\n")
if next <= 0 {
return s, ""
}
return s[:next], s[next+1:]
}
nlPos := strings.LastIndex(s[:i], "\n")
if nlPos > 0 && nlPos < w {
@@ -657,7 +726,7 @@ func wrapN(i, slop int, s string) (string, string) {
// caller). Pass `w` == 0 to do no wrapping
func wrap(i, w int, s string) string {
if w == 0 {
return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
return strings.ReplaceAll(s, "\n", "\n"+strings.Repeat(" ", i))
}
// space between indent i and end of line width w into which
@@ -675,7 +744,7 @@ func wrap(i, w int, s string) string {
}
// If still not enough space then don't even try to wrap.
if wrap < 24 {
return strings.Replace(s, "\n", r, -1)
return strings.ReplaceAll(s, "\n", r)
}
// Try to avoid short orphan words on the final line, by
@@ -687,18 +756,17 @@ func wrap(i, w int, s string) string {
// Handle first line, which is indented by the caller (or the
// special case above)
l, s = wrapN(wrap, slop, s)
r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
r = r + strings.ReplaceAll(l, "\n", "\n"+strings.Repeat(" ", i))
// Now wrap the rest
for s != "" {
var t string
t, s = wrapN(wrap, slop, s)
r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
r = r + "\n" + strings.Repeat(" ", i) + strings.ReplaceAll(t, "\n", "\n"+strings.Repeat(" ", i))
}
return r
}
// FlagUsagesWrapped returns a string containing the usage information
@@ -723,9 +791,12 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
}
varname, usage := UnquoteUsage(flag)
if varname != "" {
if isNoOptBoolValue(flag.Value) && flag.Value.Type() == "bool" {
line += "[=true|false]"
} else if varname != "" {
line += " " + varname
}
if flag.NoOptDefVal != "" {
switch flag.Value.Type() {
case "string":
@@ -769,7 +840,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
sidx := strings.Index(line, "\x00")
spacing := strings.Repeat(" ", maxlen-sidx)
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
_, _ = fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
}
return buf.String()
@@ -788,7 +859,7 @@ func PrintDefaults() {
// defaultUsage is the default function to print a usage message.
func defaultUsage(f *FlagSet) {
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
_, _ = fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
f.PrintDefaults()
}
@@ -796,12 +867,13 @@ func defaultUsage(f *FlagSet) {
// because it serves (via godoc flag Usage) as the example
// for how to write your own usage function.
// Usage prints to standard error a usage message documenting all defined command-line flags.
// The function is a variable that may be changed to point to a custom function.
// By default it prints a simple header and calls PrintDefaults; for details about the
// format of the output and how to control it, see the documentation for PrintDefaults.
// Usage prints, to the set destination, a usage message documenting all defined
// command-line flags. The function is a variable that may be changed to point to a
// custom function. By default it prints a simple header and calls PrintDefaults; for
// details about the format of the output and how to control it, see the documentation
// for PrintDefaults.
var Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
_, _ = fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
PrintDefaults()
}
@@ -874,7 +946,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
_, alreadyThere := f.formal[normalizedFlagName]
if alreadyThere {
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
fmt.Fprintln(f.Output(), msg)
_, _ = fmt.Fprintln(f.Output(), msg)
panic(msg) // Happens only if flags are declared with identical names
}
if f.formal == nil {
@@ -882,6 +954,9 @@ func (f *FlagSet) AddFlag(flag *Flag) {
}
flag.Name = string(normalizedFlagName)
if flag.NoOptDefVal == "" && isNoOptBoolValue(flag.Value) {
flag.NoOptDefVal = "true"
}
f.formal[normalizedFlagName] = flag
f.orderedFormal = append(f.orderedFormal, flag)
@@ -890,7 +965,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
}
if len(flag.Shorthand) > 1 {
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
fmt.Fprintf(f.Output(), msg)
_, _ = fmt.Fprint(f.Output(), msg)
panic(msg)
}
if f.shorthands == nil {
@@ -900,7 +975,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
used, alreadyThere := f.shorthands[c]
if alreadyThere {
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
fmt.Fprintf(f.Output(), msg)
_, _ = fmt.Fprint(f.Output(), msg)
panic(msg)
}
f.shorthands[c] = flag
@@ -960,23 +1035,34 @@ func (f *FlagSet) usage() {
// --unknown arg ... (args will be arg ...)
func stripUnknownFlagValue(args []string) []string {
if len(args) == 0 {
//--unknown
// --unknown
return args
}
first := args[0]
if len(first) > 0 && first[0] == '-' {
//--unknown --next-flag ...
// --unknown --next-flag ...
return args
}
//--unknown arg ... (args will be arg ...)
// --unknown arg ... (args will be arg ...)
if len(args) > 1 {
return args[1:]
}
return nil
}
// errUnknownFlag is used for internal unknown flag handling.
type unknownFlagError struct {
// UnknownFlags is flags that are unknown and unprocessed.
// It depends on the context whether this has a prefix like '-' or '--'.
UnknownFlags string
}
func (e *unknownFlagError) Error() string {
return fmt.Sprintf("unknown flag: %v", e.UnknownFlags)
}
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
a = args
name := s[2:]
@@ -988,15 +1074,14 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
split := strings.SplitN(name, "=", 2)
name = split[0]
flag, exists := f.formal[f.normalizeFlagName(name)]
unknownFlagsHandling := f.getUnknownFlagsHandling()
if !exists {
switch {
case name == "help":
f.usage()
return a, ErrHelp
case f.ParseErrorsWhitelist.UnknownFlags:
fallthrough
case f.ParseErrorsAllowlist.UnknownFlags:
case unknownFlagsHandling == IgnoreUnknownFlag:
// --unknown=unknownval arg ...
// we do not want to lose arg in this case
if len(split) >= 2 {
@@ -1004,6 +1089,10 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
}
return stripUnknownFlagValue(a), nil
case unknownFlagsHandling == PassUnknownFlagToArgs:
return a, &unknownFlagError{
UnknownFlags: s,
}
default:
err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
return
@@ -1030,9 +1119,11 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
return
}
err = fn(flag, value)
// Pass the name the user actually typed so a deprecation message reports
// it rather than the canonical name a NormalizeFunc may have mapped it to.
err = fn(flag, name, value)
if err != nil {
f.fail(err)
err = f.fail(err)
}
return
}
@@ -1049,14 +1140,14 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
flag, exists := f.shorthands[c]
if !exists {
unknownFlagsHandling := f.getUnknownFlagsHandling()
switch {
case c == 'h':
f.usage()
err = ErrHelp
return
case f.ParseErrorsWhitelist.UnknownFlags:
fallthrough
case f.ParseErrorsAllowlist.UnknownFlags:
case unknownFlagsHandling == IgnoreUnknownFlag:
// '-f=arg arg ...'
// we do not want to lose arg in this case
if len(shorthands) > 2 && shorthands[1] == '=' {
@@ -1066,6 +1157,20 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
outArgs = stripUnknownFlagValue(outArgs)
return
case unknownFlagsHandling == PassUnknownFlagToArgs:
// '-f=arg': pass all the argument
if len(shorthands) > 2 && shorthands[1] == '=' {
outShorts = ""
err = &unknownFlagError{
UnknownFlags: shorthands,
}
return
}
// '-fgh': pass only the first switch
err = &unknownFlagError{
UnknownFlags: shorthands[0:1],
}
return
default:
err = f.fail(&NotExistError{
name: string(c),
@@ -1103,12 +1208,12 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
}
if flag.ShorthandDeprecated != "" {
fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
_, _ = fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
err = fn(flag, value)
err = fn(flag, flag.Name, value)
if err != nil {
f.fail(err)
err = f.fail(err)
}
return
}
@@ -1116,14 +1221,31 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
a = args
shorthands := s[1:]
var errUnknownFlagAll *unknownFlagError
// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
for len(shorthands) > 0 {
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
if err != nil {
return
if errUnknownFlag, ok := err.(*unknownFlagError); ok { //nolint:errorlint
// this means f.ParseErrorsAllowlist.UnknownFlagsHandling is set to UnknownFlagsHandlingPassUnknownToArgs
if errUnknownFlagAll == nil {
errUnknownFlagAll = &unknownFlagError{
UnknownFlags: "-",
}
}
errUnknownFlagAll.UnknownFlags = errUnknownFlagAll.UnknownFlags +
errUnknownFlag.UnknownFlags
err = nil
} else {
return
}
}
}
if errUnknownFlagAll != nil {
err = errUnknownFlagAll
}
return
}
@@ -1153,7 +1275,13 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
args, err = f.parseShortArg(s, args, fn)
}
if err != nil {
return
if errUnknownFlag, ok := err.(*unknownFlagError); ok { //nolint:errorlint
// this means f.ParseErrorsAllowlist.UnknownFlagsHandling is set to UnknownFlagsHandlingPassUnknownToArgs
f.args = append(f.args, errUnknownFlag.UnknownFlags)
err = nil
} else {
return
}
}
}
return
@@ -1166,7 +1294,7 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
func (f *FlagSet) Parse(arguments []string) error {
if f.addedGoFlagSets != nil {
for _, goFlagSet := range f.addedGoFlagSets {
goFlagSet.Parse(nil)
_ = goFlagSet.Parse(nil)
}
}
f.parsed = true
@@ -1177,8 +1305,8 @@ func (f *FlagSet) Parse(arguments []string) error {
return nil
}
set := func(flag *Flag, value string) error {
return f.Set(flag.Name, value)
set := func(_ *Flag, name, value string) error {
return f.Set(name, value)
}
err := f.parseArgs(arguments, set)
@@ -1187,10 +1315,10 @@ func (f *FlagSet) Parse(arguments []string) error {
case ContinueOnError:
return err
case ExitOnError:
if err == ErrHelp {
if err == ErrHelp { //nolint:errorlint // not using errors.Is for compatibility with go1.12
os.Exit(0)
}
fmt.Fprintln(f.Output(), err)
_, _ = fmt.Fprintln(f.Output(), err)
os.Exit(2)
case PanicOnError:
panic(err)
@@ -1199,7 +1327,7 @@ func (f *FlagSet) Parse(arguments []string) error {
return nil
}
type parseFunc func(flag *Flag, value string) error
type parseFunc func(flag *Flag, name, value string) error
// ParseAll parses flag definitions from the argument list, which should not
// include the command name. The arguments for fn are flag and value. Must be
@@ -1210,16 +1338,20 @@ func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string)
f.parsed = true
f.args = make([]string, 0, len(arguments))
err := f.parseArgs(arguments, fn)
set := func(flag *Flag, _, value string) error {
return fn(flag, value)
}
err := f.parseArgs(arguments, set)
if err != nil {
switch f.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
if err == ErrHelp {
if err == ErrHelp { //nolint:errorlint // not using errors.Is for compatibility with go1.12
os.Exit(0)
}
fmt.Fprintln(f.Output(), err)
_, _ = fmt.Fprintln(f.Output(), err)
os.Exit(2)
case PanicOnError:
panic(err)
@@ -1237,7 +1369,7 @@ func (f *FlagSet) Parsed() bool {
// after all flags are defined and before flags are accessed by the program.
func Parse() {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.Parse(os.Args[1:])
_ = CommandLine.Parse(os.Args[1:])
}
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
@@ -1245,7 +1377,7 @@ func Parse() {
// defined and before flags are accessed by the program.
func ParseAll(fn func(flag *Flag, value string) error) {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.ParseAll(os.Args[1:], fn)
_ = CommandLine.ParseAll(os.Args[1:], fn)
}
// SetInterspersed sets whether to support interspersed option/non-option arguments.
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- float32 Value
type float32Value float32
@@ -12,8 +15,11 @@ func newFloat32Value(val float32, p *float32) *float32Value {
func (f *float32Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 32)
if err != nil {
return errors.New("must be a number")
}
*f = float32Value(v)
return err
return nil
}
func (f *float32Value) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- float64 Value
type float64Value float64
@@ -12,8 +15,11 @@ func newFloat64Value(val float64, p *float64) *float64Value {
func (f *float64Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 64)
if err != nil {
return errors.New("must be a number")
}
*f = float64Value(v)
return err
return nil
}
func (f *float64Value) Type() string {
+3 -4
View File
@@ -71,14 +71,14 @@ func (v *flagValueWrapper) Type() string {
// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei
// with both `-v` and `--v` in flags. If the golang flag was more than a single
// character (ex: `verbose`) it will only be accessible via `--verbose`
func PFlagFromGoFlag(goflag *goflag.Flag) *Flag {
func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { //nolint:revive // ignore "func name will be used as pflag.PFlagFromGoFlag by other packages, and that stutters"
// Remember the default value as a string; it won't change.
flag := &Flag{
Name: goflag.Name,
Usage: goflag.Usage,
Value: wrapFlagValue(goflag.Value),
// Looks like golang flags don't set DefValue correctly :-(
//DefValue: goflag.DefValue,
// DefValue: goflag.DefValue,
DefValue: goflag.Value.String(),
}
// Ex: if the golang flag was -v, allow both -v and --v to work
@@ -127,7 +127,7 @@ func (f *FlagSet) CopyToGoFlagSet(newSet *goflag.FlagSet) {
switch value := flag.Value.(type) {
case *stringValue:
newSet.StringVar((*string)(value), flag.Name, flag.DefValue, usage)
newSet.StringVar((*string)(value), flag.Name, *(*string)(value), usage)
case *intValue:
newSet.IntVar((*int)(value), flag.Name, *(*int)(value), usage)
case *int64Value:
@@ -158,4 +158,3 @@ func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
}
return goFlagSet.Parse(skippedFlags)
}
+9 -3
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- int Value
type intValue int
@@ -11,9 +14,12 @@ func newIntValue(val int, p *int) *intValue {
}
func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
v, err := strconv.ParseInt(s, 0, 0)
if err != nil {
return errors.New("must be an integer")
}
*i = intValue(v)
return err
return nil
}
func (i *intValue) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- int16 Value
type int16Value int16
@@ -12,8 +15,11 @@ func newInt16Value(val int16, p *int16) *int16Value {
func (i *int16Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 16)
if err != nil {
return errors.New("must be an integer")
}
*i = int16Value(v)
return err
return nil
}
func (i *int16Value) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- int32 Value
type int32Value int32
@@ -12,8 +15,11 @@ func newInt32Value(val int32, p *int32) *int32Value {
func (i *int32Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 32)
if err != nil {
return errors.New("must be an integer")
}
*i = int32Value(v)
return err
return nil
}
func (i *int32Value) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- int64 Value
type int64Value int64
@@ -12,8 +15,11 @@ func newInt64Value(val int64, p *int64) *int64Value {
func (i *int64Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
if err != nil {
return errors.New("must be an integer")
}
*i = int64Value(v)
return err
return nil
}
func (i *int64Value) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- int8 Value
type int8Value int8
@@ -12,8 +15,11 @@ func newInt8Value(val int8, p *int8) *int8Value {
func (i *int8Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 8)
if err != nil {
return errors.New("must be an integer")
}
*i = int8Value(v)
return err
return nil
}
func (i *int8Value) Type() string {
+3
View File
@@ -32,6 +32,9 @@ func (i *ipValue) Type() string {
}
func ipConv(sval string) (interface{}, error) {
if sval == "" || sval == "<nil>" {
return net.IP(nil), nil
}
ip := net.ParseIP(sval)
if ip != nil {
return ip, nil
+10 -8
View File
@@ -23,13 +23,12 @@ func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
func (s *ipSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12
return err
}
@@ -61,7 +60,6 @@ func (s *ipSliceValue) Type() string {
// String defines a "native" format for this net.IP slice flag value.
func (s *ipSliceValue) String() string {
ipStrSlice := make([]string, len(*s.value))
for i, ip := range *s.value {
ipStrSlice[i] = ip.String()
@@ -73,7 +71,11 @@ func (s *ipSliceValue) String() string {
}
func (s *ipSliceValue) fromString(val string) (net.IP, error) {
return net.ParseIP(strings.TrimSpace(val)), nil
ip := net.ParseIP(strings.TrimSpace(val))
if ip == nil {
return nil, fmt.Errorf("invalid string being converted to IP address: %s", val)
}
return ip, nil
}
func (s *ipSliceValue) toString(val net.IP) string {
@@ -81,22 +83,22 @@ func (s *ipSliceValue) toString(val net.IP) string {
}
func (s *ipSliceValue) Append(val string) error {
i, err := s.fromString(val)
ip, err := s.fromString(val)
if err != nil {
return err
}
*s.value = append(*s.value, i)
*s.value = append(*s.value, ip)
return nil
}
func (s *ipSliceValue) Replace(val []string) error {
out := make([]net.IP, len(val))
for i, d := range val {
var err error
out[i], err = s.fromString(d)
ip, err := s.fromString(d)
if err != nil {
return err
}
out[i] = ip
}
*s.value = out
return nil
+5 -1
View File
@@ -53,7 +53,11 @@ func ParseIPv4Mask(s string) net.IPMask {
return nil
}
}
return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15])
mask = mask.To4()
if mask == nil {
return nil
}
return net.IPv4Mask(mask[0], mask[1], mask[2], mask[3])
}
func parseIPv4Mask(sval string) (interface{}, error) {
+1 -3
View File
@@ -23,13 +23,12 @@ func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
func (s *ipNetSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12
return err
}
@@ -61,7 +60,6 @@ func (s *ipNetSliceValue) Type() string {
// String defines a "native" format for this net.IPNet slice flag value.
func (s *ipNetSliceValue) String() string {
ipNetStrSlice := make([]string, len(*s.value))
for i, n := range *s.value {
ipNetStrSlice[i] = n.String()
+1
View File
@@ -12,6 +12,7 @@ func (s *stringValue) Set(val string) error {
*s = stringValue(val)
return nil
}
func (s *stringValue) Type() string {
return "string"
}
+2 -6
View File
@@ -30,18 +30,14 @@ func (s *stringArrayValue) Append(val string) error {
func (s *stringArrayValue) Replace(val []string) error {
out := make([]string, len(val))
for i, d := range val {
out[i] = d
}
copy(out, val)
*s.value = out
return nil
}
func (s *stringArrayValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = d
}
copy(out, *s.value)
return out
}
+20 -8
View File
@@ -98,9 +98,12 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
// The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" --ss="v3"
//
// --ss="v1,v2" --ss="v3"
//
// will result in
// []string{"v1", "v2", "v3"}
//
// []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
f.VarP(newStringSliceValue(value, p), name, "", usage)
}
@@ -114,9 +117,12 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
// The argument p points to a []string variable in which to store the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" --ss="v3"
//
// --ss="v1,v2" --ss="v3"
//
// will result in
// []string{"v1", "v2", "v3"}
//
// []string{"v1", "v2", "v3"}
func StringSliceVar(p *[]string, name string, value []string, usage string) {
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
}
@@ -130,9 +136,12 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
// The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" --ss="v3"
//
// --ss="v1,v2" --ss="v3"
//
// will result in
// []string{"v1", "v2", "v3"}
//
// []string{"v1", "v2", "v3"}
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
p := []string{}
f.StringSliceVarP(&p, name, "", value, usage)
@@ -150,9 +159,12 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
// The return value is the address of a []string variable that stores the value of the flag.
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
// For example:
// --ss="v1,v2" --ss="v3"
//
// --ss="v1,v2" --ss="v3"
//
// will result in
// []string{"v1", "v2", "v3"}
//
// []string{"v1", "v2", "v3"}
func StringSlice(name string, value []string, usage string) *[]string {
return CommandLine.StringSliceP(name, "", value, usage)
}
+98 -62
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/csv"
"fmt"
"io"
"sort"
"strings"
)
@@ -21,7 +22,7 @@ func newStringToStringValue(val map[string]string, p *map[string]string) *string
return ssv
}
// Format: a=1,b=2
// Set updates the flag value from the given string, adding additional mappings or updating existing ones.
func (s *stringToStringValue) Set(val string) error {
var ss []string
n := strings.Count(val, "=")
@@ -37,6 +38,9 @@ func (s *stringToStringValue) Set(val string) error {
if err != nil {
return err
}
if _, err := r.Read(); err != io.EOF {
return fmt.Errorf("must be a single CSV record; quote fields containing newlines")
}
}
out := make(map[string]string, len(ss))
@@ -47,13 +51,20 @@ func (s *stringToStringValue) Set(val string) error {
}
out[kv[0]] = kv[1]
}
// clear out any default flag values
if !s.changed {
*s.value = out
} else {
for k, v := range out {
(*s.value)[k] = v
for k := range *s.value {
delete(*s.value, k)
}
}
if *s.value == nil {
*s.value = make(map[string]string, len(out))
}
for k, v := range out {
(*s.value)[k] = v
}
s.changed = true
return nil
}
@@ -81,88 +92,113 @@ func (s *stringToStringValue) String() string {
panic(err)
}
w.Flush()
return "[" + strings.TrimSpace(buf.String()) + "]"
return "[" + strings.TrimSuffix(buf.String(), "\n") + "]"
}
func stringToStringConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
return map[string]string{}, nil
}
r := csv.NewReader(strings.NewReader(val))
ss, err := r.Read()
if err != nil {
return nil, err
}
out := make(map[string]string, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
}
out[kv[0]] = kv[1]
}
return out, nil
}
// GetStringToString return the map[string]string value of a flag with the given name
// GetStringToString return the map value of a flag with the given name from f. The returned map shares memory with the
// internal flag value [Flag.Value].
func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
val, err := f.getFlagType(name, "stringToString", stringToStringConv)
val, err := f.getFlagType(name, "stringToString", nil)
if err != nil {
return map[string]string{}, err
}
return val.(map[string]string), nil
fv, ok := val.(*stringToStringValue)
if !ok {
panic(fmt.Errorf("illegal state: unspected internal type for stringToString flag '%s'", name))
}
if fv.value == nil {
return nil, nil
}
return *fv.value, nil
}
// StringToStringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
// StringToStringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a map[string]string variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
// StringToString defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
// StringToString defines a map flag with specified name, default value, and usage string.
//
// StringToString flags are used to pass key=value pairs to applications. The same flag can be provided more than once
// with all key=value pairs being merged into a final map. Multiple key=value pairs may be provided in a single arg,
// separated by commas. A few simple examples include:
//
// --arg a=1 -> map[string]string{ "a": "1" }
// --arg a=1 --arg b=2 -> map[string]string{ "a": "1", "b": "2" }
// --arg a=1,b=2 -> map[string]string{ "a": "1", "b": "2" }
// --arg=a=1 -> map[string]string{ "a": "1" }
//
// As a special case, a single key=value pair whose value contains a comma will be interpreted as shown below:
//
// --arg a=1,2 -> map[string]string{ "a": "1,2" }
//
// Arguments containing multiple '=' characters are parsed as one CSV record.
// Quote the entire key=value field to preserve commas, quotes, or newlines in
// its value. When invoking a command from a shell, preserve the CSV quotes,
// for example by enclosing the argument in single quotes:
//
// --arg '"a=first,second=value"' -> map[string]string{ "a": "first,second=value" }
//
// Multiple unquoted CSV records in one argument are rejected rather than
// silently discarding mappings after the first record.
//
// Returns a pointer to the map which will be updated upon invocation of [FlagSet.Parse], [Flag.Value.Set], and others.
func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
p := map[string]string{}
f.StringToStringVarP(&p, name, "", value, usage)
return &p
}
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
// StringToStringP is like [FlagSet.StringToString], but also accepts a shorthand letter that can be used after a single
// dash.
//
// See [FlagSet.StringToString].
func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
p := map[string]string{}
f.StringToStringVarP(&p, name, shorthand, value, usage)
return &p
}
// StringToStringVar is like [FlagSet.StringToString], but also accepts a map pointer argument p which is updated with
// the parsed key-value pairs.
//
// See [FlagSet.StringToString].
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like [FlagSet.StringToString], but also accepts a map pointer argument p which is updated with
// the parsed key-value pairs, and a shorthand letter that can be used after a single dash.
//
// See [FlagSet.StringToString].
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
// StringToString defines a string flag with specified name, default value, and usage string.
// The return value is the address of a map[string]string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
//
// See [FlagSet.StringToString].
func StringToString(name string, value map[string]string, usage string) *map[string]string {
return CommandLine.StringToStringP(name, "", value, usage)
}
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
// StringToStringP is like [FlagSet.StringToString], but also accepts a shorthand letter that can be used after a single
// dash.
//
// See [FlagSet.StringToString].
func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
return CommandLine.StringToStringP(name, shorthand, value, usage)
}
// StringToStringVar is like [FlagSet.StringToString], but also accepts a map pointer argument p which is updated with
// the parsed key-value pairs.
//
// See [FlagSet.StringToString].
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
}
// StringToStringVarP is like [FlagSet.StringToString], but also accepts a map pointer argument p which is updated with
// the parsed key-value pairs, and a shorthand letter that can be used after a single dash.
//
// See [FlagSet.StringToString].
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
}
+4 -5
View File
@@ -42,10 +42,9 @@ func (v textValue) String() string {
return ""
}
//end of copy
// end of copy
func (v textValue) Type() string {
return reflect.ValueOf(v.p).Type().Name()
return reflect.TypeOf(v.p).String()
}
// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
@@ -54,8 +53,8 @@ func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
if flag == nil {
return fmt.Errorf("flag accessed but not defined: %s", name)
}
if flag.Value.Type() != reflect.TypeOf(out).Name() {
return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
if flag.Value.Type() != reflect.TypeOf(out).String() {
return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).String(), flag.Value.Type())
}
return out.UnmarshalText([]byte(flag.Value.String()))
}
+1 -2
View File
@@ -51,9 +51,8 @@ func (d *timeValue) Type() string {
func (d *timeValue) String() string {
if d.Time.IsZero() {
return ""
} else {
return d.Time.Format(time.RFC3339Nano)
}
return d.Time.Format(time.RFC3339Nano)
}
// GetTime return the time value of a flag with the given name
+9 -3
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- uint Value
type uintValue uint
@@ -11,9 +14,12 @@ func newUintValue(val uint, p *uint) *uintValue {
}
func (i *uintValue) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
v, err := strconv.ParseUint(s, 0, 0)
if err != nil {
return errors.New("must be a non-negative integer")
}
*i = uintValue(v)
return err
return nil
}
func (i *uintValue) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- uint16 value
type uint16Value uint16
@@ -12,8 +15,11 @@ func newUint16Value(val uint16, p *uint16) *uint16Value {
func (i *uint16Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 16)
if err != nil {
return errors.New("must be a non-negative integer")
}
*i = uint16Value(v)
return err
return nil
}
func (i *uint16Value) Type() string {
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- uint32 value
type uint32Value uint32
@@ -12,8 +15,11 @@ func newUint32Value(val uint32, p *uint32) *uint32Value {
func (i *uint32Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 32)
if err != nil {
return errors.New("must be a non-negative integer")
}
*i = uint32Value(v)
return err
return nil
}
func (i *uint32Value) Type() string {
+9 -3
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- uint64 Value
type uint64Value uint64
@@ -12,8 +15,11 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
if err != nil {
return errors.New("must be a non-negative integer")
}
*i = uint64Value(v)
return err
return nil
}
func (i *uint64Value) Type() string {
@@ -27,7 +33,7 @@ func uint64Conv(sval string) (interface{}, error) {
if err != nil {
return 0, err
}
return uint64(v), nil
return v, nil
}
// GetUint64 return the uint64 value of a flag with the given name
+8 -2
View File
@@ -1,6 +1,9 @@
package pflag
import "strconv"
import (
"errors"
"strconv"
)
// -- uint8 Value
type uint8Value uint8
@@ -12,8 +15,11 @@ func newUint8Value(val uint8, p *uint8) *uint8Value {
func (i *uint8Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 8)
if err != nil {
return errors.New("must be a non-negative integer")
}
*i = uint8Value(v)
return err
return nil
}
func (i *uint8Value) Type() string {
+3 -3
View File
@@ -23,7 +23,7 @@ func (s *uintSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
u, err := strconv.ParseUint(d, 0, 0)
if err != nil {
return err
}
@@ -51,7 +51,7 @@ func (s *uintSliceValue) String() string {
}
func (s *uintSliceValue) fromString(val string) (uint, error) {
t, err := strconv.ParseUint(val, 10, 0)
t, err := strconv.ParseUint(val, 0, 0)
if err != nil {
return 0, err
}
@@ -101,7 +101,7 @@ func uintSliceConv(val string) (interface{}, error) {
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
u, err := strconv.ParseUint(d, 0, 0)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -2001,7 +2001,7 @@ github.com/spf13/cast/internal
# github.com/spf13/cobra v1.10.2
## explicit; go 1.15
github.com/spf13/cobra
# github.com/spf13/pflag v1.0.10
# github.com/spf13/pflag v1.1.0
## explicit; go 1.12
github.com/spf13/pflag
# github.com/spf13/viper v1.21.0