Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
[![Build Status](https://travis-ci.org/ogier/pflag.png?branch=master)](https://travis-ci.org/ogier/pflag)

## Description

pflag is a drop-in replacement for Go's flag package, implementing
Expand All @@ -20,11 +18,11 @@ pflag is available using the standard `go get` command.

Install by running:

go get github.com/ogier/pflag
go get github.com/gdm85/pflag

Run tests by running:

go test github.com/ogier/pflag
go test github.com/gdm85/pflag

## Usage

Expand All @@ -33,7 +31,7 @@ pflag under the name "flag" then all code should continue to function
with no changes.

``` go
import flag "github.com/ogier/pflag"
import flag "github.com/gdm85/pflag"
```

There is one exception to this: if you directly instantiate the Flag struct
Expand Down Expand Up @@ -150,8 +148,8 @@ Duration flags accept any input valid for time.ParseDuration.
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/ogier/pflag][2] after
[http://localhost:6060/pkg/github.com/gdm85/pflag][2] after
installation.

[2]: http://localhost:6060/pkg/github.com/ogier/pflag
[3]: http://godoc.org/github.com/ogier/pflag
[2]: http://localhost:6060/pkg/github.com/gdm85/pflag
[3]: http://godoc.org/github.com/gdm85/pflag
2 changes: 1 addition & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"strings"
"time"

flag "github.com/ogier/pflag"
flag "github.com/gdm85/pflag"
)

// Example 1: A single string flag called "species" with default value "gopher".
Expand Down
1 change: 1 addition & 0 deletions export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func ResetForTesting(usage func()) {
name: os.Args[0],
errorHandling: ContinueOnError,
output: ioutil.Discard,
actual: map[string]*Flag{},
}
Usage = usage
}
Expand Down
209 changes: 110 additions & 99 deletions flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,98 +3,111 @@
// license that can be found in the LICENSE file.

/*
pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.
pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.

pflag is compatible with the GNU extensions to the POSIX recommendations
for command-line options. See
http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
pflag is compatible with the GNU extensions to the POSIX recommendations
for command-line options. See
http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html

Usage:
Usage:

pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function
with no changes.
pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function
with no changes.

import flag "github.com/ogier/pflag"
import flag "github.com/gdm85/pflag"

There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore
unaffected.
There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore
unaffected.

Define flags using flag.String(), Bool(), Int(), etc.
Define flags using flag.String(), Bool(), Int(), etc.

This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
var ip = flag.Int("flagname", 1234, "help message for flagname")
If you like, you can bind the flag to a variable using the Var() functions.
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
flag.Var(&flagVal, "name", "help message for flagname")
For such flags, the default value is just the initial value of the variable.

After all flags are defined, call
flag.Parse()
to parse the command line into the defined flags.

Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.

The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP("boolname", "b", true, "help message")
}
flag.VarP(&flagVar, "varname", "v", 1234, "help message")
Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.

Command line flag syntax:
--flag // boolean flags only
--flag=x

Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags.
// boolean flags
-f
-abc
// non-boolean flags
-n 1234
-Ifile
// mixed
-abcs "hello"
-abcn1234

Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.

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.
Duration flags accept any input valid for time.ParseDuration.

The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.

var ip = flag.Int("flagname", 1234, "help message for flagname")

If you like, you can bind the flag to a variable using the Var() functions.

var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by

flag.Var(&flagVal, "name", "help message for flagname")

For such flags, the default value is just the initial value of the variable.

After all flags are defined, call

flag.Parse()

to parse the command line into the defined flags.

Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.

The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.

var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP("boolname", "b", true, "help message")
}
flag.VarP(&flagVar, "varname", "v", 1234, "help message")

Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.

Command line flag syntax:

--flag // boolean flags only
--flag=x

Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags.

// boolean flags
-f
-abc
// non-boolean flags
-n 1234
-Ifile
// mixed
-abcs "hello"
-abcn1234

Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.

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.
Duration flags accept any input valid for time.ParseDuration.

The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
*/
package pflag

Expand Down Expand Up @@ -215,6 +228,17 @@ func Lookup(name string) *Flag {
return CommandLine.formal[name]
}

// IsSpecified returns true if the named flag was specified via command-line flags.
func (f *FlagSet) IsSpecified(name string) bool {
_, ok := f.actual[name]
return ok
}

// IsSpecified returns true if the named flag was specified via command-line flags.
func IsSpecified(name string) bool {
return CommandLine.IsSpecified(name)
}

// Set sets the value of the named flag.
func (f *FlagSet) Set(name, value string) error {
flag, ok := f.formal[name]
Expand All @@ -225,9 +249,6 @@ func (f *FlagSet) Set(name, value string) error {
if err != nil {
return err
}
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
return nil
}
Expand Down Expand Up @@ -465,9 +486,6 @@ func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {
return f.failf("invalid argument %q for %s: %v", value, origArg, err)
}
// mark as visited for Visit()
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[flag.Name] = flag

return nil
Expand Down Expand Up @@ -606,6 +624,7 @@ func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
name: name,
errorHandling: errorHandling,
interspersed: true,
actual: map[string]*Flag{},
}
return f
}
Expand All @@ -614,11 +633,3 @@ func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
func (f *FlagSet) SetInterspersed(interspersed bool) {
f.interspersed = interspersed
}

// Init sets the name and error handling property for a flag set.
// By default, the zero FlagSet uses an empty name and the
// ContinueOnError error handling policy.
func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
f.name = name
f.errorHandling = errorHandling
}
28 changes: 24 additions & 4 deletions flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ func (f *flagVar) Set(value string) error {
}

func TestUserDefined(t *testing.T) {
var flags FlagSet
flags.Init("test", ContinueOnError)
flags := NewFlagSet("test", ContinueOnError)
var v flagVar
flags.VarP(&v, "v", "v", "usage")
if err := flags.Parse([]string{"--v=1", "-v2", "-v", "3"}); err != nil {
Expand All @@ -259,10 +258,9 @@ func TestUserDefined(t *testing.T) {
}

func TestSetOutput(t *testing.T) {
var flags FlagSet
flags := NewFlagSet("test", ContinueOnError)
var buf bytes.Buffer
flags.SetOutput(&buf)
flags.Init("test", ContinueOnError)
flags.Parse([]string{"--unknown"})
if out := buf.String(); !strings.Contains(out, "--unknown") {
t.Logf("expected output mentioning unknown; got %q", out)
Expand Down Expand Up @@ -348,3 +346,25 @@ func TestNoInterspersed(t *testing.T) {
t.Fatal("expected interspersed options/non-options to fail")
}
}

func TestIsSpecified(t *testing.T) {
f := NewFlagSet("test", ContinueOnError)
f.SetInterspersed(false)
f.Bool("alpha", true, "always true")
f.Bool("beta", false, "always false")
err := f.Parse([]string{"--beta"})
if err != nil {
t.Fatal("expected no error; got ", err)
}
args := f.Args()
if len(args) != 0 {
t.Fatal("expected no extra args")
}

if !f.IsSpecified("beta") {
t.Fatal("expected beta to be specified")
}
if f.IsSpecified("alpha") {
t.Fatal("expected alpha to not be specified")
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gdm85/pflag

go 1.24.0