Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync Upstream #3

Open
wants to merge 50 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5f175cd
test IniParser.WriteFile with no-ini option
zimmski Dec 28, 2014
43c5f3c
Merge pull request #123 from zimmski/test-write-of-noini
jessevdk Jan 24, 2015
eee67de
Fix docs typo
Jan 25, 2015
1c0255a
Use positional-arg-name tag
Jan 25, 2015
e27a44a
Add test for value-name tag
Jan 25, 2015
15347ef
Merge pull request #125 from ggilder/add-positional-arg-name-docs
jessevdk Jan 25, 2015
3f36317
Updating the go get path for vet and cover
sergiusens Feb 14, 2015
5e11878
Merge pull request #127 from sergiusens/vet_location
jessevdk Feb 15, 2015
3c2a20f
expose isSet
mattes Mar 26, 2015
f59c328
Add "Hidden" option to comamnds and options
mvo5 Mar 31, 2015
f25cb1a
Merge pull request #134 from mattes/expose-isset-via-getter
jessevdk Jun 27, 2015
b77ba87
Add default, optional values in man page output
jessevdk Jun 27, 2015
1b89bf7
Allow specifying parent options after subcommands
jessevdk Jun 28, 2015
c104d9a
Accept arguments which start with '-' if the next character is a digit
shirayu Jul 14, 2015
a22c114
Fix typos
shirayu Aug 16, 2015
4a954c8
Reverted the function argumentIsOption
shirayu Aug 16, 2015
adb660f
Added tests for a numeric flag like -3
shirayu Aug 16, 2015
1acbbaf
Merge pull request #144 from shirayu/floatarg
jessevdk Aug 16, 2015
1d02749
Implement support for limiting argument values to a certain set
jessevdk Oct 10, 2015
f412642
Prefix default value in help with default:
jessevdk Oct 10, 2015
1c008c1
Store default literal value before parsing
jessevdk Oct 10, 2015
5631e09
Improve documentation of 'optional'
jessevdk Oct 10, 2015
eff4073
Output a blank .TP section after usage to fix rendering issue
tmc May 30, 2015
2e3d1bd
Lookup options in all parent commands
jessevdk Oct 14, 2015
741647f
Remove help flag from rest args
jessevdk Oct 18, 2015
85383eb
Allow customized completion handling
jessevdk Oct 18, 2015
ded79de
Exit after completion by default
jessevdk Oct 18, 2015
6e4f416
Make wrapText newline aware
jessevdk Oct 18, 2015
59aa546
Merge remote-tracking branch 'mvo5/master'
jessevdk Oct 18, 2015
a15da34
Set and respect Hidden on group
jessevdk Oct 18, 2015
2e55b6d
Add hidden tests
jessevdk Oct 18, 2015
2497690
Clear slice and map option values before set the first time
jessevdk Oct 18, 2015
05e133d
Merge _private files
jessevdk Oct 18, 2015
31c5fc5
Do not apply defaults if option value was set from ini
jessevdk Oct 18, 2015
64336ff
Add required minimum rest arguments constraint
jessevdk Oct 18, 2015
4047bd7
Add doc for required rest positional arguments
jessevdk Oct 18, 2015
fc93116
Add FindOptionByLongName and FindOptionByShortName
jessevdk Oct 28, 2015
e1bd911
check err before using subc
cppforlife Nov 15, 2015
0a28dbe
Merge pull request #152 from cppforlife/err_check_before_subc
jessevdk Nov 15, 2015
cfa9457
Highlight code examples as Go
stevenwilkin Dec 10, 2015
aa34304
Merge pull request #153 from stevenwilkin/patch-1
jessevdk Dec 10, 2015
46e39c7
Parse unexported embedded option struct fields in Go 1.6 (consistent …
sqs Dec 22, 2015
d91b7c5
Merge pull request #156 from sourcegraph/go16-embedded-unexported-fields
jessevdk Dec 22, 2015
36760f6
ini: allow specifying group opts directly on subcommands
sqs Dec 31, 2015
97448c9
Merge pull request #158 from sqs/ini-flag-equiv
jessevdk Feb 7, 2016
8b13cca
Don't display description-less positional args in --help
zyga Feb 8, 2016
7f2ab82
Do not allow default tag on boolean flags
jessevdk Feb 27, 2016
1f0c485
Merge pull request #161 from zyga/skip-help-2
jessevdk Feb 27, 2016
6b9493b
Fix error message for invalid use of default tag
jessevdk Feb 27, 2016
7481a63
Sync Upstream
davecgh May 6, 2016
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
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ install:
- go build -v ./...

# linting
- go get code.google.com/p/go.tools/cmd/vet
- go get golang.org/x/tools/cmd/vet
- go get github.com/golang/lint
- go install github.com/golang/lint/golint

# code coverage
- go get code.google.com/p/go.tools/cmd/cover
- go get golang.org/x/tools/cmd/cover
- go get github.com/onsi/ginkgo/ginkgo
- go get github.com/modocache/gover
- if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi
Expand Down
176 changes: 90 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ The flags package uses structs, reflection and struct field tags
to allow users to specify command line options. This results in very simple
and concise specification of your application options. For example:

type Options struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
}
```go
type Options struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
}
```

This specifies one option with a short name -v and a long name --verbose.
When either -v or --verbose is found on the command line, a 'true' value
Expand All @@ -44,88 +46,90 @@ resulting value of Verbose will be {[true, true, true]}.

Example:
--------
var opts struct {
// Slice of bool will append 'true' each time the option
// is encountered (can be set multiple times, like -vvv)
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`

// Example of automatic marshalling to desired type (uint)
Offset uint `long:"offset" description:"Offset"`

// Example of a callback, called each time the option is found.
Call func(string) `short:"c" description:"Call phone number"`

// Example of a required flag
Name string `short:"n" long:"name" description:"A name" required:"true"`

// Example of a value name
File string `short:"f" long:"file" description:"A file" value-name:"FILE"`

// Example of a pointer
Ptr *int `short:"p" description:"A pointer to an integer"`

// Example of a slice of strings
StringSlice []string `short:"s" description:"A slice of strings"`

// Example of a slice of pointers
PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"`

// Example of a map
IntMap map[string]int `long:"intmap" description:"A map from string to int"`
}

// Callback which will invoke callto:<argument> to call a number.
// Note that this works just on OS X (and probably only with
// Skype) but it shows the idea.
opts.Call = func(num string) {
cmd := exec.Command("open", "callto:"+num)
cmd.Start()
cmd.Process.Release()
}

// Make some fake arguments to parse.
args := []string{
"-vv",
"--offset=5",
"-n", "Me",
"-p", "3",
"-s", "hello",
"-s", "world",
"--ptrslice", "hello",
"--ptrslice", "world",
"--intmap", "a:1",
"--intmap", "b:5",
"arg1",
"arg2",
"arg3",
}

// Parse flags from `args'. Note that here we use flags.ParseArgs for
// the sake of making a working example. Normally, you would simply use
// flags.Parse(&opts) which uses os.Args
args, err := flags.ParseArgs(&opts, args)

if err != nil {
panic(err)
os.Exit(1)
}

fmt.Printf("Verbosity: %v\n", opts.Verbose)
fmt.Printf("Offset: %d\n", opts.Offset)
fmt.Printf("Name: %s\n", opts.Name)
fmt.Printf("Ptr: %d\n", *opts.Ptr)
fmt.Printf("StringSlice: %v\n", opts.StringSlice)
fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"])
fmt.Printf("Remaining args: %s\n", strings.Join(args, " "))

// Output: Verbosity: [true true]
// Offset: 5
// Name: Me
// Ptr: 3
// StringSlice: [hello world]
// PtrSlice: [hello world]
// IntMap: [a:1 b:5]
// Remaining args: arg1 arg2 arg3
```go
var opts struct {
// Slice of bool will append 'true' each time the option
// is encountered (can be set multiple times, like -vvv)
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`

// Example of automatic marshalling to desired type (uint)
Offset uint `long:"offset" description:"Offset"`

// Example of a callback, called each time the option is found.
Call func(string) `short:"c" description:"Call phone number"`

// Example of a required flag
Name string `short:"n" long:"name" description:"A name" required:"true"`

// Example of a value name
File string `short:"f" long:"file" description:"A file" value-name:"FILE"`

// Example of a pointer
Ptr *int `short:"p" description:"A pointer to an integer"`

// Example of a slice of strings
StringSlice []string `short:"s" description:"A slice of strings"`

// Example of a slice of pointers
PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"`

// Example of a map
IntMap map[string]int `long:"intmap" description:"A map from string to int"`
}

// Callback which will invoke callto:<argument> to call a number.
// Note that this works just on OS X (and probably only with
// Skype) but it shows the idea.
opts.Call = func(num string) {
cmd := exec.Command("open", "callto:"+num)
cmd.Start()
cmd.Process.Release()
}

// Make some fake arguments to parse.
args := []string{
"-vv",
"--offset=5",
"-n", "Me",
"-p", "3",
"-s", "hello",
"-s", "world",
"--ptrslice", "hello",
"--ptrslice", "world",
"--intmap", "a:1",
"--intmap", "b:5",
"arg1",
"arg2",
"arg3",
}

// Parse flags from `args'. Note that here we use flags.ParseArgs for
// the sake of making a working example. Normally, you would simply use
// flags.Parse(&opts) which uses os.Args
args, err := flags.ParseArgs(&opts, args)

if err != nil {
panic(err)
os.Exit(1)
}

fmt.Printf("Verbosity: %v\n", opts.Verbose)
fmt.Printf("Offset: %d\n", opts.Offset)
fmt.Printf("Name: %s\n", opts.Name)
fmt.Printf("Ptr: %d\n", *opts.Ptr)
fmt.Printf("StringSlice: %v\n", opts.StringSlice)
fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"])
fmt.Printf("Remaining args: %s\n", strings.Join(args, " "))

// Output: Verbosity: [true true]
// Offset: 5
// Name: Me
// Ptr: 3
// StringSlice: [hello world]
// PtrSlice: [hello world]
// IntMap: [a:1 b:5]
// Remaining args: arg1 arg2 arg3
```

More information can be found in the godocs: <http://godoc.org/github.com/jessevdk/go-flags>
3 changes: 3 additions & 0 deletions arg.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ type Arg struct {
// A description of the positional argument (used in the help)
Description string

// Whether a positional argument is required
Required int

value reflect.Value
tag multiTag
}
Expand Down
80 changes: 80 additions & 0 deletions arg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,83 @@ func TestPositionalRequired(t *testing.T) {

assertError(t, err, ErrRequired, "the required argument `Filename` was not provided")
}

func TestPositionalRequiredRest1Fail(t *testing.T) {
var opts = struct {
Value bool `short:"v"`

Positional struct {
Rest []string `required:"yes"`
} `positional-args:"yes"`
}{}

p := NewParser(&opts, None)
_, err := p.ParseArgs([]string{})

assertError(t, err, ErrRequired, "the required argument `Rest (at least 1 argument)` was not provided")
}

func TestPositionalRequiredRest1Pass(t *testing.T) {
var opts = struct {
Value bool `short:"v"`

Positional struct {
Rest []string `required:"yes"`
} `positional-args:"yes"`
}{}

p := NewParser(&opts, None)
_, err := p.ParseArgs([]string{"rest1"})

if err != nil {
t.Fatalf("Unexpected error: %v", err)
return
}

if len(opts.Positional.Rest) != 1 {
t.Fatalf("Expected 1 positional rest argument")
}

assertString(t, opts.Positional.Rest[0], "rest1")
}

func TestPositionalRequiredRest2Fail(t *testing.T) {
var opts = struct {
Value bool `short:"v"`

Positional struct {
Rest []string `required:"2"`
} `positional-args:"yes"`
}{}

p := NewParser(&opts, None)
_, err := p.ParseArgs([]string{"rest1"})

assertError(t, err, ErrRequired, "the required argument `Rest (at least 2 arguments, but got only 1)` was not provided")
}

func TestPositionalRequiredRest2Pass(t *testing.T) {
var opts = struct {
Value bool `short:"v"`

Positional struct {
Rest []string `required:"2"`
} `positional-args:"yes"`
}{}

p := NewParser(&opts, None)
_, err := p.ParseArgs([]string{"rest1", "rest2", "rest3"})

if err != nil {
t.Fatalf("Unexpected error: %v", err)
return
}

if len(opts.Positional.Rest) != 3 {
t.Fatalf("Expected 3 positional rest argument")
}

assertString(t, opts.Positional.Rest[0], "rest1")
assertString(t, opts.Positional.Rest[1], "rest2")
assertString(t, opts.Positional.Rest[2], "rest3")
}
Loading