Coder Social home page Coder Social logo

go-flags's Introduction

go-flags: a go library for parsing command line arguments

GoDoc Build Status Coverage Status

This library provides similar functionality to the builtin flag library of go, but provides much more functionality and nicer formatting. From the documentation:

Package flags provides an extensive command line option parser. The flags package is similar in functionality to the go builtin flag package but provides more options and uses reflection to provide a convenient and succinct way of specifying command line options.

Supported features:

  • Options with short names (-v)
  • Options with long names (--verbose)
  • Options with and without arguments (bool v.s. other type)
  • Options with optional arguments and default values
  • Multiple option groups each containing a set of options
  • Generate and print well-formatted help message
  • Passing remaining command line arguments after -- (optional)
  • Ignoring unknown command line options (optional)
  • Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification
  • Supports multiple short options -aux
  • Supports all primitive go types (string, int{8..64}, uint{8..64}, float)
  • Supports same option multiple times (can store in slice or last option counts)
  • Supports maps
  • Supports function callbacks
  • Supports namespaces for (nested) option groups

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"`
}

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 will be appended to the Verbose field. e.g. when specifying -vvv, the 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 flag restricted to a pre-defined set of strings
	Animal string `long:"animal" choice:"cat" choice:"dog"`

	// 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",
	"--animal", "dog", // anything other than "cat" or "dog" will raise an error
	"-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)
}

fmt.Printf("Verbosity: %v\n", opts.Verbose)
fmt.Printf("Offset: %d\n", opts.Offset)
fmt.Printf("Name: %s\n", opts.Name)
fmt.Printf("Animal: %s\n", opts.Animal)
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

go-flags's People

Contributors

bboozzoo avatar bengadbois avatar blampe avatar chipaca avatar davecgh avatar elwinar avatar fabiokung avatar farbodsalimi avatar gebi avatar hchargois avatar jessevdk avatar jkieboom avatar kkolman avatar lrstanley avatar mnm678 avatar mpobrien avatar peterebden avatar pierrec avatar piranha avatar rupertchen avatar shirayu avatar sqs avatar tg123 avatar timabell avatar titusjaka avatar tonyabbott avatar vito avatar xenophex avatar zimmski avatar zyga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-flags's Issues

Bool should be able to be set false.

If you have a bool option that defaults to true, there is no way of disabling it from the command line.

You should be able to do this by ./somecommand --boolflag=0

Right now running this results in: "bool flag boolflag cannot have an argument"

Supporting auto-completion

It's nice to have autocompletion to your CLI, and go-flags is in a good position to support that.

What I suggest is a method like

parser.Complete([]string{"foo", "--version"})

that would return all possible words that could come after foo --version.

How is that determined?

Well, in the simplest case - where you're in a position in which any option and command is valid - let it return all possibles commands and options, so if I have

type opts struct {
    verbose bool `short:"v"`
    num int `long:"num"
}

and I issue parser.Complete(&opts{}, []string{"foo"}), I'll get [-v --num].

If I issue parser.Complete(&opts{}, []string{"foo", "--num"}), go-flags will try to call opts.num.FlagComplete() []string and will return the result.

So for example to get autocompletion right, I'll have

type opts struct {
    num IntBetween3And10 `long:"num"`
}
func (IntBetween3And8) FlagComplete() []string {
    return []{"3","4","5","6","7","8"}
}
func (i*IntBetween3And8) UnmarshalFlag(s string) {
    *i = strconv.Atoi(s)
}

Likewise, every command can implement FlagComplete interface, to get completion right.

I'll be glad for feedback.

Documentation on the format for the various argument types

I am using go-flags for my project gocog. It was kind of trial and error to figure out how the user needs to specify the fields so they'll get picked up correctly.

Strings are easy, obviously, but things like maps and slices are more difficult... I think that deserves some documentation. For example, I don't know how to specify values for a map for go-flags.

Command line args don't play nice with ini files

It seems that I can use command line args or ini files, but not both. In my case specifically I have a command line option that specifies where to find the ini file and several other (required) options that should be able to be satisfied by command line args or the ini file.

Consider the following

type Options struct {
    ConfigFile     string `short:"c"`
    DatabaseDriver string `short:"d" long:"db-driver" required:"true"`
}

var opt Options

func main() {
    p := flags.NewParser(&opt, flags.Default)
    _, err := p.Parse()
    if err != nil {
        return
    }

    ini := flags.NewIniParser(p)
    buf := bytes.NewBufferString("[Application Options]\ndb-driver = mock")
    err = ini.Parse(buf)
    if err != nil {
        println(err.Error())
        return
    }
    fmt.Printf("%v\n", opt)
}

This suffers from the following problems:

  1. db-driver emits an error that it is required even though it is in the ini file. (Because it happens before IniParser's Parse, it has no knowledge of the ini file)

  2. If I specify db-parse on the command line IniParser overwrites the command line option. (Presumably because IniParser's Parse happens last)

I can do it in reverse:

    p := flags.NewParser(&opt, flags.Default)
    ini := flags.NewIniParser(p)
    buf := bytes.NewBufferString("[Application Options]\ndb-driver = mock")
    err := ini.Parse(buf)
    if err != nil {
        return
    }
    _, err = p.Parse()
    if err != nil {
        return
    }
    fmt.Printf("%v\n", opt)

This seems to solve issue # 2, but issue # 1 remains. I also have no way of getting the configuration filename doing it this way (chicken & the egg).

If I use just IniParser's Parse, it doesn't seem to parse the command line at all.

Ideally what I'd like to see is something like this:

type Options struct {
    ConfigFile     string `short:"c" ini-file:"true"`
    DatabaseDriver string `short:"d" long:"db-driver" required:"true"`
}

var opt Options

func main() {
    _, err := flags.Parse(&opt)
    if err != nil {
        return
    }
    fmt.Printf("%v\n", opt)
}

Where "ini-file" would indicate a user-specified ini file to be read. Requirements would be resolved by either command line args, or through the configuration file. Command line args would have precedence over ini options.

Ability to customize help

Subject, basically. Maybe provide some functions which will returns parts of help? I need to inject some text between usage and options description and right now it seems there is no way to do that.

undefined: getTerminalColumns

Hi,

Seems go-flags does not build anymore for raspberry pi on linux amd64.

GOARM=5 GOARCH=arm GOOS=linux go build -o passhash_arm5 passhash.go
# github.com/jessevdk/go-flags
../../../go/src/github.com/jessevdk/go-flags/help.go:28: undefined: getTerminalColumns

It's imho because of 412dcc0.
This commit removes cross compile ability for ALL programs using go-flags!

quickfix patch:

diff --git a/convert_unix.go b/convert_unix.go
index f6be109..c748b79 100644
--- a/convert_unix.go
+++ b/convert_unix.go
@@ -1,4 +1,4 @@
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin,cgo freebsd,cgo linux,cgo netbsd,cgo openbsd,cgo

 package flags

diff --git a/convert_unixcross.go b/convert_unixcross.go
new file mode 100644
index 0000000..2b6ae57
--- /dev/null
+++ b/convert_unixcross.go
@@ -0,0 +1,24 @@
+// +build darwin,!cgo freebsd,!cgo linux,!cgo netbsd,!cgo openbsd,!cgo
+
+package flags
+
+import (
+       "syscall"
+       "unsafe"
+)
+
+type winsize struct {
+       ws_row, ws_col       uint16
+       ws_xpixel, ws_ypixel uint16
+}
+
+func getTerminalColumns() int {
+       ws := winsize{}
+
+       syscall.Syscall(syscall.SYS_IOCTL,
+               uintptr(0),
+               uintptr(0x5413),
+               uintptr(unsafe.Pointer(&ws)))
+
+       return int(ws.ws_col)
+}

base, the field tag, could be clearer

I didn't understand what this tag meant without browsing the source. Could I suggest changing the wording in documentation slightly, to something like:
a base (radix) used to convert strings to integer values

Otherwise, great work, I love it!

Problems with argument slices

I have the following Options struct:

type Options struct {
    Debug bool     `short:"d" long:"debug" description:"Run in debug mode."`
    Pipes []string `short:"p" long:"pipes" description:"List of filenames for the pipes to write to."`
}

I parse my command-line options with the following code:

Opts = new(Options)
parser := flags.NewParser(Opts, flags.Default)
_, err := parser.Parse()
if err != nil {
    os.Exit(1)
}

Calling at the cli like this:

./my-program -p test

Or:

./my-program -p test1 -p test2

Results in this:

fmt.Println(len(Opts.Pipes))
>> 0

Is there something I'm missing about the feature to have multiple values for a single argument?

How about allowing shortcuts for commands?

When there is no bash_completion, its difficult to use a tool's commands especially if we are going to use it a lot of times.

So, How about shortcuts (aliases) for sub commands? It would be nice if we can define them.

$ hub issues comment "Will fix it soon."
$ hub i c "Will fix it soon."

I also realized I am unable to set the long-description of a command when I am using a struct to define it. (Not using AddCommand). Would be nice to have a Description() similiar to Usage() which we have.


Apparently, the default usage for a command prints [cmdname-options] even if there are no options defined for the command. Can you make it not print that? This frees me up a bit since I dont have to define Usage() to return empty strings.

Feature request: add "required" field tag

It would be useful to have a "required" field tag to denote that an argument must be provided; for example:

type Options struct {
   Server string `short:"s" description:"The server name" required:true`
}

When parsed, if this option is missing, go-flag could report this as an error.

A useful variation of this feature would be if the required tag took a string to define an option group, such that at least one flag in the group would be required:

type Options struct {
   Add bool `short:"a" description:"Add a foo" required:"command"`
   Del bool `short:"d" description:"Delete a foo" required:"command"`
}

In this case, go-flag would ensure that the parsed argument contain -a or -d, or both (if this is an error, the calling program should handle it).

Command line arguements after -- are mistaken for blank options

Just built my program with the latest version (from go get) and with no changes in my program it now doesn't like anything after "--". I'm getting the following error:

unknown flag `'

I'm simply running my program with a couple of command line options and then a command to be passed into my program:

<my_program> --debug -- echo hello
<my_program> --debug --log ${PWD} -- echo hello

Thanks

Optional value not set for an option unless it is the last option specified. Parses the next option

From the code / documentation, it seems that to set a default value for an optional argument, both optional-value should be used. e.g.
Check string long:"check" description:"description" optional:"true" optional-value:"foo"

When this option is used without arguments, the (i.e. --check) the value of the argument is set to "foo" only if it is the last option on the command line. Otherwise, the next option is parsed as the argument.

More GNU-looking output

Right now options formatter formats options in such a way:

  -x, --exclude [RE]      exclude files that match the regexp from search ([])

I would love to have more usual-looking output:

  -x RE --exclude=RE      exclude files that match the regexp from search

if you're willing to accept such changes I'll be glad to make them.

Show help while ignoring unknowns

HelpFlag | PrintErrors | IgnoreUnknown doesn't seem to work. I'm currently doing something like this as a workaround:

func showHelp(args []string, err error, parser *flags.Parser) {
    var showHelp bool
    for _, arg := range args {
        switch arg {
        case "-h", "--help":
            showHelp = true
            break
        default:
            showHelp = false
        }
    }
    var msg string
    if showHelp {
        var b bytes.Buffer
        parser.WriteHelp(&b)
        msg = b.String()
    } else if err != nil {
        msg = err.Error()
    }
    if len(msg) > 0 {
        fmt.Fprintln(os.Stderr, msg)
        os.Exit(1)
    }
}

type Cmd struct {
    parser *flags.Parser
}

func (c *Cmd) Execute(args []string) error {
    showHelp(args, nil, c.parser)
    println("Not yet implemented")
    return nil
}

In main:

parser := flags.NewNamedParser(os.Args[0], flags.IgnoreUnknown)
parser.AddCommand("cmd", "", "", &Cmd{parser: parser})
args, err := parser.ParseArgs(os.Args[1:])
showHelp(os.Args[1:], err, parser)

This probably ain't the best way to go about it. Am I missing something?

There is no way to specify multiple values from a config file for slices

The following code, configuration file, and output illustrate the issue:

package main

import (
    "fmt"
    "github.com/jessevdk/go-flags"
)

type config struct {
    StringSlice []string `long:"stringslice" description:"A slice of strings"`
}

func main() {
    cfg := config{}

    // Load config from file.
    parser := flags.NewParser(&cfg, flags.Default)
    err := parser.ParseIniFile("test.conf")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("Num:", len(cfg.StringSlice), "Entries:", cfg.StringSlice)
}

The config file:

[Application Options]

stringslice=one
stringslice=two

Output:

$ ./cfg
Num: 1 Entries: [two]

The expected result is 2 entries in the slice. I have tried several variations in the config file such as commas, colons, spaces to no avail.

Realistically, I think the example config file I provided should be the way it works. That is to say, multiple entries (lines) in the config file for an underlying slice type leads to multiple entries in the slice. For non-slice types, the current mechanics would be the same (the most recent entry is the one that takes effect). Trying to use some type of punctuation as a separator would either mean there would be no way to specify the values including whatever punctuation is used as a separator, or it would require escaping which seems a bit cumbersome for non-programmer types..

Expected arguments for slices flags

When using flags with multiple options:

type Options struct {
    Debug bool     `short:"d" long:"debug" description:"Run in debug mode."`
    MyList []string `short:"l" long:"list" description:"List of stuff"`
}

This works correctly,

./my-program --list test1 --list test2 --debug

But, when a required argument is missing, it assumes the other flag is the argument to the list option.

./my-program --list test1 --list --debug

space between flag and argument

(whoops, pressed enter accidentally, updating issue now...)

Works:

my-app --file="config.yml"
my-app -f=config.yml
my-app -fconfig.yml

Doesn't work:

my-app -f config.yml

Is this intended behaviour? I personally prefer leaving a space, which is why I hit this behaviour.

flags.IgnoreUnknown strips flags assignments

When I'm using the IgnoreUnkown parser flag, I expect unkown variables will be given to me verbatime, however, flags strips everything after the =. For example --foo=bar will appear as --foo in the reurned arguments.

package main

import (
    "github.com/jessevdk/go-flags"
)

func main() {
    var o struct {
        S string `short:"s"`
    }
    parser := flags.NewParser(&o, flags.IgnoreUnknown)
    args, _ := parser.ParseArgs([]string{"--foo=bar"})
    println(args[0]) // expect --foo=bar
                     // got    --foo
}

Make automatic display of errors optional?

Currently, when there is an error such as a missing required parameters, the library automatically prints a message. However, in some cases the caller might want to display a custom message (or no message at all), or display a localized message.

To allow this, I would suggest making the automatic messages optional. Perhaps there could be a boolean such as flag.autoPrintMessages. Defaults to true for backward compatibility. If set to false the library won't print any message. What do you think?

By the way, assuming your are okay with this feature, I'd be glad to implement it in a pull request.

Feature Request: Allow option to mask default values for sensitive fields

The following code, configuration file, and output illustrate the reasoning:

package main

import (
    "fmt"
    "github.com/jessevdk/go-flags"
)

type config struct {
    Password string `short:"p" long:"password" description:"Specify password for foobar"`
}

func main() {
    cfg := config{}

    // Load config from file.
    parser := flags.NewParser(&cfg, flags.Default)
    err := parser.ParseIniFile("test.conf")
    if err != nil {
        fmt.Println(err)
        return
    }

    // Parse command line options to allow CLI override of options
    // in config file.
    parser.Parse()
}

The config file:

[Application Options]
password=secret

Output:

$ ./cfg -h
Usage:
  cfg.exe [OPTIONS]

Help Options:
  -h, --help=     Show this help message

Application Options:
  -p, --password= Specify password for foobar (secret)

Notice how the password in the config file shows up as the default value in the command line help.

I think a mask:"true" tag on the struct field would do the trick. It could mask the input with *** (length should not match the sensitive data length). This approach allows the user to tell the difference between nothing specified (missing default altogether) and simply a masked value.

Desired Output:

$ ./cfg -h
Usage:
  cfg.exe [OPTIONS]

Help Options:
  -h, --help=     Show this help message

Application Options:
  -p, --password= Specify password for foobar (***)

Slight problem with boolean options

It seems []bool options are set to 'false' rather than 'true', at least with Go 1.0.3 on OS X 10.8.2.
Reproduce by adding a line to example_test.go, to print the Verbose bools:

fmt.Printf("Verbosity: %d\n", len(opts.Verbose)) 
>> fmt.Println(opts.Verbose)
fmt.Printf("Offset: %d\n", opts.Offset)

Testing this results in 'false' where 'true' would be expected:

$ go test example_test.go 
--- FAIL: Example (0.00 seconds)
got:
Verbosity: 2
[false false]
Offset: 5
Name: Me
Remaining args: arg1 arg2 arg3
want:
Verbosity: 2
Offset: 5
Name: Me
Remaining args: arg1 arg2 arg3
FAIL
FAIL    command-line-arguments  0.027s

Missing usage string for subcommands

It would be nice if it was possible to set a usage string for subcommands of the application, much like it is on the main application. The use case is for subcommands that take non-option (positional) parameters, such as for example a mandatory filename. I.e. with an application app and command cmd where app cmd --help today renders as

Usage:
  app [OPTIONS] cmd [cmd-OPTIONS]

it would be nice to be able to instead produce

Usage:
  app [OPTIONS] cmd <filename> <age> <whatever> [cmd-OPTIONS]

and similar.

No way to specify a name for a field in help?

I'd like help to be able to print out something like this:

-o [OUTPUT] Send the results to the file OUTPUT

I'm not sure if this is possible right now... if it is, it probably needs better documentation :) if it's not, it would be nice if it could be added.

Let me know if I missed this functionality somewhere.

Command options from ini files

I could not find the documentation pertaining to having command options set in ini files. I tried specifying the options at the same default level than the application, but it didn't work. Specifying a "group" in the option tag served me no better.

Is it possible to do this?

Option to make headings optional in ini files

Command line options are unique, so they cannot reoccur across sections. Thus it would make sense to make headings in ini files optional. At least, have an option to specify the group that belongs to the headless section at the top of the ini file.

Compile failure on NetBSD and OpenBSD

As the title indicates, this will not compile on NetBSD or OpenBSD as of commit 3e06beb.

The issue is a result of the termsize_unix.go and termsize_other.go files causing a conflict on NetBSD and OpenBSD due to the build constraints not matching.

The following is the error:

# github.com/jessevdk/go-flags
./termsize_unix.go:6: TIOCGWINSZ redeclared in this block
        previous declaration at ./termsize_other.go:6

The following patch resolves the issue for NetBSD and OpenBSD by ensuring the negative of all build constraints specified in termsize_*.go are specified in termsize_other.go:

diff --git a/termsize_other.go b/termsize_other.go
index f9c0d99..3bf804a 100644
--- a/termsize_other.go
+++ b/termsize_other.go
@@ -1,4 +1,4 @@
-// +build !darwin,!freebsd,!linux
+// +build !darwin,!freebsd,!netbsd,!openbsd,!linux

 package flags

Positional arguments

Have you ever thought of implemented a mapping for positional arguments?

Something like

LocalPath string   `arg:"0"`
RemoteUrl string   `arg:"1"`
Tags      []string `arg:"2..."`

Calling a program with -h/--help sets error in Parse(opts) ?

I might be missing something, but why would -h/--help set Error in Parse func ? It doesn't make much sense to me.

var opts struct {}

func main() {
    args, err := flags.Parse(&opts)

    if err != nil {
          fmt.Printf("Error: %v", err)
    }
}
$ ./test -h
Usage:
  test [OPTIONS]

Help Options:
  -h, --help  Show this help message

Error: Usage:
  test [OPTIONS]

Help Options:
  -h, --help  Show this help message

Solaris/SmartOS compatibility

Compiling the terminal.go fails under smartOS since it tries to syscall.SYS_IOCTL in https://github.com/jessevdk/go-flags/blob/master/termsize.go#L19 which does not exist there.

(transscript)

[16:10:46]  <Licenser>   Aram ah just having trouble to compiling the terminalize (let me check what it was exactly)
[16:13:04]  <Licenser>   https://github.com/jessevdk/go-flags/blob/master/termsize.go#L19 is where it crapped otu seems that syscall.SYS_IOCTL is not exported
[16:13:20]  <Aram>   hmm
[16:13:35]  <Aram>   well it isn't exported because on Solaris, the indirect system call is not stable.
[16:13:45]  <Licenser>   that makes sense
[16:14:13]  <Aram>   what that code should do is call syscall.Ioctl (if it exists), instead of doing syscall.Syscall(syscall.SYS_IOCTL, ...)
[16:14:38]  <Licenser>   so not a sunos issue but a library thing
[16:14:46]  <Aram>   yeah.
[16:15:02]  <Licenser>   okay :)
[16:15:59]  <Aram>   ther's no syscall.Ioctly ATM, and there's no syscall.Mmap either. I will all these if people need them.
[16:15:59]  <Aram>   s/will/will add/
[16:17:46]  <Licenser>   *nods*

Example for usage of bash completion

So I am playing around with the new bash completion and it works great (except two things I will correct with pull requests). But I am missing an example for using it in a program. Is this the idiomatic way?

p := flags.NewParser(&opts, flags.Default)

if _, err := p.Parse(); err != nil {
    panic(err)
}

if len(os.Getenv("GO_FLAGS_COMPLETION")) != 0 {
    os.Exit(123)
}

// and now the code of the program

If yes, I think we should add a flag or method to indicate that the completion code ran and that the user should stop the program.

Documentation for groups and commands

Some documentation explaining the basics of groups and commands would be greatly appreciated.

I am considering using go-flags for my project, and I need something like the "go" program command line processing. That is, writing myproject command ...options... with different options available for different commands. Top-level help should list the commands, each command's help should list its options. Some options are universal, some are shared by several commands, some are unique to specific commands.

It seems that go-flags will do exactly what I want in a very nice way - if I knew how to use groups/commands properly. Since there's no documentation for that, I am looking at the code to reverse-engineer the proper way to use it, which may take longer than just hacking an application solution myself :-(

Tests fail on Windows

As the title indicates, the tests fail on Windows running the current master 8ec9564.

This is because all of the tests are expecting - and -- for the emitted short and long options, respectively, but Windows shows short options with / and long options with /foo:. There are a lot of errors, but here is a sample of one of them:

$ go test
--- FAIL: TestRequiredOnCommand (0.00 seconds)
        assert_test.go:71: Expected error message "the required flag `-v' was not specified", but got "the required flag `/v' was not specified"

Also, I'd like to point out that the use of all of those assert_foo functions in the tests is not a good idea because, as you can see, it hides the real source of the error. Every error shows up as assert_test.go:## instead of the actual test file/line number where the error occurred.

subcommands-optional question

This is more of a "golang newbie" question but: How the heck do I tag a Command struct with subcommands-optional? I've tried plopping subcommands-optional:"true" in various positions of the type BlahCommand struct {} but just couldn't figure it out. For now, I've achieved what I want with the following, but I'd rather do it the "right" way.

func init() {
    subc, err := parser.AddCommand("blah", "short", "long", &blahCommand)
    if err == nil {
        subc.SubcommandsOptional = true
    }
}

required flag and issue with printing a version

I am trying to use the required flag functionality, but aslo want to support printing a version with "foo -V". However, as expected, I get output listing the missing required flags.

How would I go about making a specific flag take precedence and behave similarly to how 'help' does, in that regard?
Would the recommendation be to use a Callback and print the version and exit?

Use the assert package of "testify"

The comment of #78 about how the asserts in the test code work, made we wonder if we could improve the situation. So I am suggesting to refactor the test code to use the assert package of https://github.com/stretchr/testify/ which has a nice assertion API http://godoc.org/github.com/stretchr/testify/assert

  1. Refactor and remove old assertions where possible
  2. Use assert.CallerInfo for the remaining asserts
  3. Add common test code as additional asserts

This would reduce the test code dramatically and improve the readability.

For example this construct can be seen throughout the test code

if !opts.Value {
    t.Errorf("Expected Value to be true")
}

can be reduced to

assert.True(opts.Value)

Feature Request: Support `no-cli` tag to mirror `no-ini` tag

There are certain parameters such as passwords which are almost never a good idea to specify via the command line since they show up in shell history, ps, etc. I noticed there is a no-ini tag to specify the option only applies to the command line, but I didn't see a no-cli variant. While I realize the main purpose of this package is command line flag parsing, it also doubles as a config file reader, so it seems like being able to support ini-only flags fits in nicely.

Edit:

To elaborate a bit, the no-cli tag would make it so the usage doesn't display the flag and it would be treated as an invalid flag if specified on the command line, but it would still be parsed from the ini file and populated into the target config struct.

Feature Request: Use Stringer for time.Duration arguments

The following code and output illustrate the reasoning:

package main

import (
    "fmt"
    "github.com/jessevdk/go-flags"
    "time"
)

type config struct {
    BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers.  Valid time units are {us, ms, s, m, h}"`
}

func main() {
    cfg := config{
        BanDuration: time.Hour,
    }

    // Print the time.Duration value using the default Stringer to
    // illustrate the difference.
    fmt.Println("BanDuration when invoking Stringer:", cfg.BanDuration)

    parser := flags.NewParser(&cfg, flags.Default)
    parser.Parse()
}

Output:

$ ./cfg -h
BanDuration when invoking Stringer: 1h0m0s
Usage:
  cfg.exe [OPTIONS]

Help Options:
  -h, --help         Show this help message

Application Options:
      --banduration= How long to ban misbehaving peers.  Valid time
                     units are {us, ms, s, m, h} (3600000000000)

Notice how the duration in the usage is shown in nanoseconds instead of the nicer 1h0m0s printed by the time.Duration Stringer above the 'Usage:' line by the fmt.Println statement.

Desired Output:

$ ./cfg -h
Usage:
  cfg.exe [OPTIONS]

Help Options:
  -h, --help=     Show this help message

Application Options:
      --banduration= How long to ban misbehaving peers.  Valid time
                     units are {us, ms, s, m, h} (1h0m0s)

Instead of only checking specifically for time.Duration, it might make more sense to simply check if the type has a Stringer in general and invoke it. That way the same code can work with any type that implements a fmt.Stringer. Something like the following should work:

displayStr := theValue
if stringer, ok := theValue.(fmt.Stringer); ok {
    displayStr = stringer()
}

Required on command should only trigger error when the command is specified

When you set required:"true" on an argument in a command, you get an error that you didn't include the required flag even when you don't provide the command argument.

type Cmd struct {
   Test bool `short:"t" required:"true"`
}

type opts struct {
    Foo bool `short:"b"`
}

parser := flags.NewParser(&opts{}, flags.Default)
parser.AddCommand("command", "", "", &Cmd{})

When you run this program like this:

go run src\main.go -b

Result:
the required flag -t was not specified

Expected result:
You don't get this error. The error only displays when you run like this:

go run src\main.go -b command

Default values and slices

  1. If you set no default value for a slice, ([]) will be printed at the end anyway.
  2. Default values have no real slice support, and only support a single string. So if you have a slice where you want the default values to be []string{"opt1", "opt2"}, you can't do that in the struct tag. The best you can do is something like default:"opt1, opt2", and then programmically check if Opt.Key[0] == "opt1, opt2" and then set it to the real slice.

Nested struct / namespaced args

Hi,

I'm thinking about implementing my own command line parser because I want a feature that none of those I investigate have. But given the advancement of your project and its quality, I'd like to base my effort on your code.
What Id' like to implement is the ability the fill nested struct with command line args; something alog these lines :

type ServerConfig struct {
    Port uint32
    Ssl SslConfig
}

type SslConfig struct {
    Certificate string
    CertificateKey string
}

And the program could be called that way :

./server -port 8000 -ssl.certificate=PATH_TO_CERTIFICATE -ssl.certificate_key=PATH_TO_CERTIFICATE_KEY

Do you think this would required a lot of changes to the code, and could you advise me on where to start ?

Thx in advance.

Command Execute error not returned to parser.

Is there any way to call the Execute function on a command so that it will exit with an error? Currently, it just prints the error but does not result in a non-zero exit status for the process. See https://github.com/jessevdk/go-flags/blob/master/parser.go#L198

Otherwise, is there some way to use the Command interface to get an error back? From the documentation, it would seem that way (https://github.com/jessevdk/go-flags/blob/master/command.go#L21) but I don't think it actually does this.

Help Group Options in Nested Commands

Can't we be satisfied with a single one?

The code is at https://github.com/pksunkara/hub

$  hub -h
Usage:
  hub [options]

Application Options:
  -p, --private  Use private url for the repository
  -V, --verbose  Show verbose debug information

Help Options:
  -h, --help     Show this help message

Available commands:
  auth     Manage github access modes
  version  Display program version

$  hub auth -h
Usage:
  hub [options] auth

Application Options:
  -p, --private  Use private url for the repository
  -V, --verbose  Show verbose debug information

Help Options:
  -h, --help     Show this help message

Help Options:
  -h, --help     Show this help message

Available commands:
  destroy  Destroy authorization and delete username
  private  Give access to your private data
  user     Set an username to use their public data

$  hub auth destroy -h
Usage:
  hub [options] auth destroy

Application Options:
  -p, --private  Use private url for the repository
  -V, --verbose  Show verbose debug information

Help Options:
  -h, --help     Show this help message

Help Options:
  -h, --help     Show this help message

Help Options:
  -h, --help     Show this help message

And shouldn't the Usage for hub auth -h be shown as hub [options] auth <command> ??

Allow specifying custom deserialization

When you have your own type you want to serialize from the options, it would be great if I could do something like:

type Coord struct {
    X, Y string
}
func CoordFromString(s string) (Coord, error) {
    xs := strings.Split()
    return Coord{xs[0], xs[1]}
}
type Opts struct {
    Coords Coord `short:"s"`
}
flags.AddSerializers(CoordFromString)
flags.ParseArgs(&opt, os.Args[1:])

where flags would recognize that CoordFromString converts a string to Coord, and will use it to convert argument to Coord struct.

Would you accept pull request?

Current command

So, this is a mix of question that depending on the answer is an issue :)

Unless I'm missing something there is no way to get the current command that was parsed out of the flags..?

If that is so, can we add a way of doing that? Otherwise, how can one act based on the command?

Cheers

Cross compiling to windows from linux

Hey,

I am using this package for development of a command line tool. I am doing cross compile using goxc for darwin, linux, freebsd, openbsd.

I was not able to compile for windows because it is complaining about syscall.SYS_IOCTL

Can you fix this?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.