Fully featured Go (golang) command line option parser with built-in auto-completion support.

go-getoptions

Quick overview

  1. Define your command line specification:

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    	"log"
    	"os"
    
    	"github.com/DavidGamba/go-getoptions"
    )
    
    var logger = log.New(ioutil.Discard, "DEBUG: ", log.LstdFlags)
    
    func main() {
    	var debug bool
    	var greetCount int
    	var list map[string]string
    	opt := getoptions.New()
    	opt.Bool("help", false, opt.Alias("h", "?"))
    	opt.BoolVar(&debug, "debug", false)
    	opt.IntVar(&greetCount, "greet", 0,
    		opt.Required(),
    		opt.Description("Number of times to greet."))
    	opt.StringMapVar(&list, "list", 1, 99,
    		opt.Description("Greeting list by language."))
    	remaining, err := opt.Parse(os.Args[1:])
    	if opt.Called("help") {
    		fmt.Fprintf(os.Stderr, opt.Help())
    		os.Exit(1)
    	}
    	if err != nil {
    		fmt.Fprintf(os.Stderr, "ERROR: %s\n\n", err)
    		fmt.Fprintf(os.Stderr, opt.Help(getoptions.HelpSynopsis))
    		os.Exit(1)
    	}
    
    	// Use the passed command line options... Enjoy!
    	if debug {
    		logger.SetOutput(os.Stderr)
    	}
    	logger.Printf("Unhandled CLI args: %v\n", remaining)
    
    	// Use the int variable
    	for i := 0; i < greetCount; i++ {
    		fmt.Println("Hello World, from go-getoptions!")
    	}
    
    	// Use the map[string]string variable
    	if len(list) > 0 {
    		fmt.Printf("Greeting List:\n")
    		for k, v := range list {
    			fmt.Printf("\t%s=%s\n", k, v)
    		}
    	}
    }
  2. Call it:

    Show help
    $ ./myscript --help
    SYNOPSIS:
        myscript --greet <int> [--debug] [--help|-h|-?] [--list <key=value>...]...
    
    REQUIRED PARAMETERS:
        --greet <int>                Number of times to greet.
    
    OPTIONS:
        --debug                      (default: false)
    
        --help|-h|-?                 (default: false)
    
        --list <key=value>...        Greeting list by language. (default: {})
    Show errors
    $ ./myscript
    ERROR: Missing required option 'greet'!
    
    SYNOPSIS:
        myscript --greet <int> [--debug] [--help|-h|-?] [--list <key=value>...]...
    Show errors
    $ ./myscript -g
    ERROR: Missing argument for option 'greet'!
    
    SYNOPSIS:
        myscript --greet <int> [--debug] [--help|-h|-?] [--list <key=value>...]...
    Use of int option
    $ ./myscript -g 3
    Hello World, from go-getoptions!
    Hello World, from go-getoptions!
    Hello World, from go-getoptions!
    Use of bool option
    $ ./myscript --debug -g 1 other stuff
    DEBUG: 2019/07/14 23:20:22 Unhandled CLI args: [other stuff]
    Hello World, from go-getoptions!
    Use of map option
    ./myscript -g 0 -l en='Hello World' es='Hola Mundo'
    Greeting List:
            en=Hello World
            es=Hola Mundo

Examples

Simple script

A simple script ./examples/myscript/main.go

To use the autocompletion, cd to the ./examples/myscript dir and run: source sourceme.bash The run go build and ./myscript.

Tab completion for this script is triggered for options only, so you need to have a dash - to trigger it: ./myscript -<tab><tab>

Program with multiple commands separated in multiple packages

This is the other extreme, a large program that can separate each command in a separate go package.

The base is located at ./examples/mygit/main.go

The commands are located at:

To use the autocompletion, cd to the ./examples/mygit dir and run: source sourceme.bash The run go build and ./mygit.

Tab completion without arguments triggers completion for commands, for option completion add a dash - and trigger it: ./mygit -<tab><tab>

The slow command shows an example of an slow command that can be cancelled with Ctrl+C. The cancellation is passed to the command through context.Context and it is handled at the command to stop taking new work and trigger a cleanup routine. Running Ctrl+C twice cancels the cancellation routine and fully cancels the program.

Directed Acyclic Graph Build System

This example shows task dependency orchestration and parallelization ./examples/dag/main.go.

To use the autocompletion, cd to the ./examples/dag dir and run: source sourceme.bash The run go build and ./dag.

Tab completion without arguments triggers completion for commands, for option completion add a dash - and trigger it: ./dag -<tab><tab>

DAG Build System

For an overview of the Directed Acyclic Graph Build System see ./dag/README.adoc

Features

  • Built in auto completion. A single line of bash is all it takes.

  • Allow passing options and non-options in any order.

  • Support for --long options.

  • Support for short (-s) options with flexible behaviour (see the Operation Modes section for details):

    • Normal (default)

    • Bundling

    • SingleDash

  • Called() method indicates if the option was passed on the command line.

  • Multiple aliases for the same option. e.g. help, man.

  • CalledAs() method indicates what alias was used to call the option on the command line.

  • Simple synopsis and option list automated help.

  • Boolean, String, Int, Float64, Slice and Map type options.

  • Negatable Boolean options.

    For example: --verbose, --no-verbose or --noverbose.

  • Options with Array arguments. The same option can be used multiple times with different arguments. The list of arguments will be saved into an Slice.

  • Options with array arguments and multiple entries.

    For example, instead of writing: color --r 10 --g 20 --b 30 --next-option or color --rgb 10 --rgb 20 --rgb 30 --next-option the input could be: color --rgb 10 20 30 --next-option

  • When using integer array options with multiple arguments, positive integer ranges are allowed.

    For example, Instead of writing: csv --columns 1 2 3 or csv --columns 1 --columns 2 --columns 3 The input could be: csv --columns 1..3

  • Options with Key Value arguments. This allows the same option to be used multiple times with arguments of key value type.

    For example: rpmbuild --define name=myrpm --define version=123

  • Options with key value arguments and multiple entries.

    For example, instead of writing: connection --server hostname=serverIP --server port=123 --client hostname=localhost --client port=456 the input could be: connection --server hostname=serverIP port=123 --client hostname=localhost port=456

  • Supports command line options with '='.

    For example: You can use --string=mystring and --string mystring.

  • Allows passing arguments to options that start with dash - when passed after equal.

    For example: --string=--hello and --int=-123.

  • Supports passing -- to stop parsing arguments (everything after will be left in the remaining []string).

  • Options with optional arguments. If the default argument is not passed the default is set.

    For example: You can call --int 123 which yields 123 or --int which yields the given default.

  • Allows abbreviations when the provided option is not ambiguous.

    For example: An option called build can be called with --b, --bu, --bui, --buil and --build as long as there is no ambiguity. In the case of ambiguity, the shortest non ambiguous combination is required.

  • Support for the lonesome dash "-". To indicate, for example, when to read input from STDIO.

  • Incremental options. Allows the same option to be called multiple times to increment a counter.

  • Supports case sensitive options. For example, you can use v to define verbose and V to define Version.

  • Support indicating if an option is required and allows overriding default error message.

  • Errors exposed as public variables to allow overriding them for internationalization.

  • Supports program commands (when a command is passed a command function is triggered to handle the command logic).

  • Built in opt.Dispatch function calls commands and propagates context, options, arguments and cancellation signals.

  • Multiple ways of managing unknown options:

    • Fail on unknown (default).

    • Warn on unknown.

    • Pass through, allows for commands and can be combined with Require Order.

  • Require order: Allows for commands. Stop parsing arguments when the first non-option is found. When mixed with Pass through, it also stops parsing arguments when the first unmatched option is found.

  • Set options by reading Environment Variables.

How to install it

  1. Get it from github:

    go get github.com/DavidGamba/go-getoptions

  2. Then import it:

    import "github.com/DavidGamba/go-getoptions" // As getoptions

  3. Enjoy!

Dependencies

Go 1.14+

Only the last two versions of Go will be supported.

Introduction

Note
For a Quick overview, jump to that section in the TOC or review the GoDoc Documentation.

Option parsing is the act of taking command line arguments and converting them into meaningful structures within the program.

An option parser should support, at least, the following:

Boolean options

True when passed on the command line. For example:

ls --all

In go-getoptions this is accomplished with:

  • ptr := opt.Bool(name, default_value).

  • opt.BoolVar(&ptr, name, default_value).

  • Additionally, if all you want to know is if the option was passed you can use: opt.Bool(name, default_value) (without capturing its return value) and then check opt.Called(name).

  • Also, you can get the value with v, ok := opt.Value(name).(bool).

Options with String arguments

The option will accept a string argument. For example:

grepp --ignore .txt

Additionally, arguments to options can be passed with the = symbol.

grepp --ignore=.txt

In go-getoptions this is accomplished with:

  • ptr := opt.String(name, default_value).

  • opt.StringVar(&ptr, name, default_value).

The features listed above are enough to create basic programs but an option parser should do better:

Options with Integer arguments

Parse an option string argument into an Integer and provide an user error if the string provided is not an integer. For example:

grepp --contex-lines 3

and:

grepp --context-lines string

Error: 'string' is not a valid integer.

In go-getoptions this is accomplished with:

  • ptr := opt.Int(name, default_value).

  • opt.IntVar(&ptr, name, default_value).

Options with Floating point arguments

Parse an option string argument into a Floating point value and provide an user error if the string provided is not a valid floating point. For example:

program --approximation 3.5

and:

$ program --approximation string

Error: 'string' is not a valid floating point value.

In go-getoptions this is accomplished with:

  • ptr := opt.Float64(name, default_value).

  • opt.Float64Var(&ptr, name, default_value).

The features listed above relieve the programmer from the cumbersome task of converting the option argument into the expected type.

That covers the most basic set of features, but still it is not enough to get past a basic program. The following features will allow for a more complete interface.

Options with array arguments

This allows the same option to be used multiple times with different arguments. The list of arguments will be saved into a Slice inside the program. For example:

list-files --exclude .txt --exclude .html --exclude .pdf

In go-getoptions this is accomplished with:

  • ptr := opt.StringSlice(name, 1, 1).

  • opt.StringSliceVar(&ptr, name, 1, 1).

  • ptr := opt.IntSlice(name, 1, 1).

  • opt.IntSliceVar(&ptr, name, 1, 1).

go-getoptions has only implemented this feature for string and int.

Options with Key Value arguments

This allows the same option to be used multiple times with arguments of key value type. For example:

rpmbuild --define name=myrpm --define version=123

In go-getoptions this is accomplished with:

  • strMap := opt.StringMap(name, 1, 1).

  • opt.StringMapVar(&ptr, name, 1, 1).

go-getoptions has only implemented this feature for string.

The features above are useful when you have a variable amount of arguments, but it becomes cumbersome for the user when the number of entries is always the same. The features described below are meant to handle the cases when each option has a known number of multiple entries.

Options with array arguments and multiple entries

This allows the user to save typing. For example:

Instead of writing: color --r 10 --g 20 --b 30 --next-option or color --rgb 10 --rgb 20 --rgb 30 --next-option

The input could be: color --rgb 10 20 30 --next-option.

The setup for this feature should allow for the user to continue using both versions of the input, that is passing one argument at a time or passing the 3 arguments at once, or allow the setup to force the user to have to use the 3 arguments at once version. This is accomplished with the minimum and maximum setup parameters.

The minimum setup parameter indicates the minimum amount of parameters the user can pass at a time. For the example above, the parameter could be set to 3 to force the user to have to pass the 3 arguments at once. When set to 1, the user will be able to pass a single parameter per option call.

The maximum setup parameter indicates the maximum amount of parameters the user can pass at a time. The option parser will leave any non option argument after the maximum in the remaining slice.

In go-getoptions this is accomplished with:

  • strSlice := opt.StringSlice(name, minArgs, maxArgs).

  • opt.StringSliceVar(&ptr, name, minArgs, maxArgs).

  • intSlice := opt.IntSlice(name, minArgs, maxArgs).

  • opt.IntSliceVar(&ptr, name, minArgs, maxArgs).

Additionally, in the case of integers, positive integer ranges are allowed. For example:

Instead of writing: csv --columns 1 2 3 or csv --columns 1 --columns 2 --columns 3

The input could be: csv --columns 1..3.

In go-getoptions this is currently enabled by default when using:

  • intSlice := opt.IntSlice(name, minArgs, maxArgs)

  • opt.IntSliceVar(&ptr, name, minArgs, maxArgs).

Options with key value arguments and multiple entries

This allows the user to save typing. For example:

Instead of writing: connection --server hostname=serverIP --server port=123 --client hostname=localhost --client port=456

The input could be: connection --server hostname=serverIP port=123 --client hostname=localhost port=456

In go-getoptions this is accomplished with:

  • strMap := opt.StringMap(name, minArgs, maxArgs).

  • opt.StringMapVar(&ptr, name, minArgs, maxArgs).

That covers a complete user interface that is flexible enough to accommodate most programs. The following are advanced features:

Stop parsing options when -- is passed

Useful when arguments start with dash - and you don’t want them interpreted as options.

In go-getoptions this is the default behaviour.

Stop parsing options when a command is passed

A command is assumed to be the first argument that is not an option or an argument to an option. When a command is found, stop parsing arguments and let a command handler handle the remaining arguments. For example:

program --opt arg command --subopt subarg

In the example above, --opt is an option and arg is an argument to an option, making command the first non option argument.

Additionally, when mixed with pass through, it will also stop parsing arguments when it finds the first unmatched option.

In go-getoptions this is accomplished with:

  • opt.SetUnknownMode(getoptions.Pass).

And can be combined with:

  • opt.SetRequireOrder().

Allow passing options and non-options in any order

Some option parsers force you to put the options before or after the arguments. That is really annoying!

In go-getoptions this is the default behaviour.

Allow pass through

Have an option to pass through unmatched options. Useful when writing programs with multiple options depending on the main arguments. The initial parser will only capture the help or global options and pass through everything else. Additional argument parsing calls are invoked on the remaining arguments based on the initial input.

In go-getoptions this is accomplished with:

  • opt.SetUnknownMode(getoptions.Pass).

Fail on unknown

The opposite of the above option. Useful if you want to ensure there are no input mistakes and force the application to stop.

In go-getoptions this is the default behaviour.

It can be explicitly set with:

opt.SetUnknownMode(getoptions.Fail).

Warn on unknown

Less strict parsing of options. This will warn the user that the option used is not a valid option but it will not stop the rest of the program.

In go-getoptions this is accomplished with:

  • opt.SetUnknownMode(getoptions.Warn).

Option aliases

Options should be allowed to have different aliases. For example, the same option could be invoked with --address or --hostname.

In go-getoptions, pass opt.Alias("my-alias") to any option. For example:

opt.BoolVar(&flag, "flag", false, opt.Alias("alias", "alias-2"))

Finally, to know with what alias an option was called with used opt.CalledAs(<name>).

Required options

Mark an option as required. Return an error if the option is not called.

In go-getoptions, pass opt.Required() to any option. For example:

opt.BoolVar(&flag, "flag", false, opt.Required())

Optionally, override the default error message with opt.Required(msg). For example:

opt.BoolVar(&flag, "flag", false, opt.Required("Missing --flag!"))

Incremental option

Some options can be passed more than once to increment an internal counter. For example:

command --v --v --v

Could increase the verbosity level each time the option is passed.

In go-getoptions this is accomplished with:

  • ptr := opt.Increment(name, default_value).

  • opt.IncrementVar(&ptr, name, default_value).

Additional types

The option parser could provide converters to additional types. The disadvantage of providing non basic types is that the option parser grows in size.

Not yet implemented in go-getoptions.

Options with optional arguments

With regular options, when the argument is not passed (for example: --level instead of --level=debug) you will get a Missing argument error. When using options with optional arguments, If the argument is not passed, the option will set the default value for the option type. For this feature to be fully effective in strong typed languages where types have defaults, there must be a means to query the option parser to determine whether or not the option was called or not.

In go-getoptions this is accomplished with:

  • ptr := opt.StringOptional(name, default_value).

  • ptr := opt.IntOptional(name, default_value).

  • ptr := opt.Float64Optional(name, default_value).

  • The above should be used in combination with opt.Called(name).

For example, for the following definition:

ptr := opt.StringOptional("level", "info")

  • If the option level is called with just --level, the value of *ptr is the default "info" and querying opt.Called("level") returns true.

  • If the option level is called with --level=debug, the value of *ptr is "debug" and querying opt.Called("level") returns true.

  • Finally, If the option level is not called, the value of *ptr is the default "info" and querying opt.Called("level") returns false.

Option flags that call a method internally

If all the flag is doing is call a method or function when present, then having a way to call that function directly saves the programmer some time.

Not yet implemented in go-getoptions.

Operation Modes

Notice how so far only long options (options starting with double dash --) have been mentioned. There are 3 main ways to handle short options (options starting with only one dash -).

The behaviour for long options (options starting with double dash --) is consistent across operation modes. The behaviour for short options (options starting with only one dash -) depends on the operation mode. The sections below show the different operation modes.

Normal Mode (default)

Given argument Interpretation

--opt

option: "opt", argument: nil

--opt=arg

option: "opt", argument: "arg" [1]


1. Argument gets type casted depending on option definition.

-opt

option: "opt", argument: nil

-opt=arg

option: "opt", argument: "arg" [2]


2. Argument gets type casted depending on option definition.

Bundling Mode

Set by defining opt.SetMode(getoptions.Bundling).

Given option Interpretation

--opt

option: "opt", argument: nil

--opt=arg

option: "opt", argument: "arg" [3]


3. Argument gets type casted depending on option definition.

-opt

option: "o", argument: nil
option: "p", argument: nil
option: "t", argument: nil

-opt=arg

option: "o", argument: nil
option: "p", argument: nil
option: "t", argument: "arg" [4]


4. Argument gets type casted depending on option definition.

Enforce Single Dash Mode

Set by defining opt.SetMode(getoptions.SingleDash).

Given option Interpretation

--opt

option: "opt", argument: nil

--opt=arg

option: "opt", argument: "arg" [5]


5. Argument gets type casted depending on option definition.

-opt

option: "o", argument: "pt" [6]


6. Argument gets type casted depending on option definition.

-opt=arg

option: "o", argument: "pt=arg" [7]


7. Argument gets type casted depending on option definition.

Biggest option parser misfeature - Automatically generate help

The biggest misfeature an option parser can have is to automatically generate the help message for the programmer. This seemingly helpful feature has caused most tools not to have proper man pages anymore and to have all verbose descriptions mixed in the help synopsis.

If you are writing a mid to large tool, don’t be lazy, write a man page for your program! If you are looking for options, asciidoctor has a manpage backend that can generate manpages written in the Asciidoc markup.

For the help synopsis, however, use the automated help. It even shows when an option can be set with environment variables.

For example, the following is a script using the built in help:

$ ./aws-configure -h
NAME:
    aws-configure - Generate default ~/.aws/config and ~/.aws/credentials configuration.

        When a role is passed, it allows the use of the role in the default profile.

        NOTE: Remember to unset AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY after use.

SYNOPSIS:
    aws-configure --access-key-id <string> --region <string>
                  --secret-access-key <string> [--debug] [--help|-?]
                  [--output-dir <string>] [--role-arn <string>] [--version|-V]
                  [<args>]

REQUIRED PARAMETERS:
    --access-key-id <string>        AWS Access Key ID. (env: AWS_ACCESS_KEY_ID)

    --region <string>               Default Region. (env: AWS_DEFAULT_REGION)

    --secret-access-key <string>    AWS Secret Access Key. (env: AWS_SECRET_ACCESS_KEY)

OPTIONS:
    --debug                         (default: false)

    --help|-?                       (default: false)

    --output-dir <string>           Where to place the config and credentials file. (default: "/home/david/.aws")

    --role-arn <string>             Role ARN. (default: "", env: AWS_ROLE_ARN)

    --version|-V                    (default: false)

And below is the output of the automated help of a program with multiple commands:

$ menu
SYNOPSIS:
    menu [--config <string>] [--debug] [--help|-?] [--profile <string>]
         [--region <string>] [--role <string>] [--version|-V] <command> [<args>]

COMMANDS:
    docker       docker tasks
    help         Use 'menu help <command>' for extra details.
    instance     Actions on your deployed instances
    terraform    Run terraform commands from inside the container

OPTIONS:
    --config <string>     (default: "config.yml")

    --debug               (default: false)

    --help|-?             (default: false)

    --profile <string>    (default: "default")

    --region <string>     (default: "us-west-2")

    --role <string>       (default: "")

    --version|-V          (default: false)

Use 'menu help <command>' for extra details.

Command behaviour

This section describes how the parser resolves ambiguities between the program and the command.

Given a definition like:

func main() {
	var profile, password string
	opt := New()
	opt.SetUnknownMode(Pass)
	opt.StringVar(&profile, "profile", "")
	command := NewCommand()
	command.StringVar(&password, "password", "")
	opt.Command(command.Self("command", "").SetCommandFn(commandFn))
	remaining, err := opt.Parse(os.Args[1:])
	...
	err = opt.Dispatch("help", remaining)
	...
}
func commandFn(opt *getoptions.GetOpt, args []string) error {
	args, err := opt.Parse(remaining)
	...
}

There is an option at the parent, profile and one at the command, password. Passing --p <arg> is ambiguous and results in an error. At minimum, --pr <arg> and --pa <arg> are required.

Given a definition like:

func main() {
	var profile, password string
	opt := New()
	opt.SetUnknownMode(Pass)
	opt.StringVar(&profile, "profile", "")
	command := NewCommand()
	command.StringVar(&password, "password", "", opt.Alias("p"))
	opt.Command(command.Self("command", "").SetCommandFn(commandFn))
	remaining, err := opt.Parse(os.Args[1:])
	...
	err = opt.Dispatch("help", remaining)
	...
}
func commandFn(opt *getoptions.GetOpt, args []string) error {
	args, err := opt.Parse(remaining)
	...
}

There is an option at the parent, profile and one at the command, password with alias p. Passing --p <arg> at the parent results in the parent opt.Parse call to leave the --p <arg> option unhandled and leave it in the remaining slice. The opt.Dispatch call gets the -p <arg> option and throws an error. At minimum, --pr <arg> is required to call profile at the parent and command options must be passed after the command declaration.

For example, the calls below is correct:

$ ./program -pr <profile> command -p <password>
$ ./program command -pr <profile> -p <password>

But the following one is incorrect:

./program -pr <profile> -p <password> command

Environment Variables Support

Initial support for environment variables has been added.

Currently, only: - opt.Bool and opt.BoolVar - opt.String, opt.StringVar, opt.StringOptional, and opt.StringVarOptional - opt.Int, opt.IntVar, opt.IntOptional, and opt.IntVarOptional - opt.Float64, opt.Float64Var, opt.Float64Optional, and opt.Float64VarOptional

To use it, set the option modify function to opt.GetEnv. For example:

var profile string
opt.StringVar(&profile, "profile", "default", opt.GetEnv("AWS_PROFILE"))

Or:

profile := opt.String("profile", "default", opt.GetEnv("AWS_PROFILE"))
Note
Non supported option types behave with a No-Op when opt.GetEnv is defined.

When using opt.GetEnv with opt.Bool or opt.BoolVar, only the words "true" or "false" are valid. They can be provided in any casing, for example: "true", "True" or "TRUE".

Note
For numeric values, opt.Int and opt.Float64 and their derivatives, environment variable string conversion errors are ignored and the default value is assigned.

Possible Env Variable Roadmap

The Roadmap isn’t clear given that there might not be enough value in implementing all of them.

  • Handle opt.Int and opt.Float64 errors.

    StringSlice and StringSliceVar

    Comma separated? ← Most likely

    Comma space separated? Proper CSV parsing to allow comma escaping?

    IntSlice and IntSliceVar

    Comma separated?

    StringMap and StringMapVar

    Comma separated key=value?

ROADMAP

  • Create new error description for errors when parsing integer ranges (1..3).

  • Option that runs a function?

  • Case insensitive matching.

  • Option values in the bundle: -h1024w800-h 1024 -w 800

  • prefix and prefix_pattern. The string that starts options. Defaults to "--" and "-" but could include "/" to support Win32 style argument handling.

  • Supports argument dividers other than '='. For example: You could define ':' and use --string=mystring, --string:mystring and --string mystring.

  • All other Perl’s Getopt::Long goodies that seem reasonable to add!

  • Remove need for opt.HelpCommand("") when dispatch is defined.

    Currently we have to define the opt.Bool("help", false) flag, then opt.HelpCommand(""), and finally opt.Dispatch(ctx, "help", remaining). opt.HelpCommand is redundant. Additionally opt.HelpCommand has the help command name hardcoded in it.

License

This file is part of go-getoptions.

Copyright © 2015-2020 David Gamba Rios

This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

Comments
  • Question: Possible to add sub commands to sub commands?

    Question: Possible to add sub commands to sub commands?

    Is it possible to add NewCommand to a NewCommand

    to create a command line interface like that

    mytool make new -h
    mytool make init -s=whatever
    
    mytool do check -h
    mytool do run --program=whatever
    

    I hope that explains what I would like to achive

  • help aliases ignored when Required() option is set

    help aliases ignored when Required() option is set

    I'm getting some weird help functionality when Required() is included on an option. Here's the playground link demonstrating this:

    https://go.dev/play/p/6Wma6dc3HbA

    Calling with "--help", or "help " calls, getoptions.Parse() fails due to the required option missing... But only in those cases; just using "help" alone doesn't fail the parse.

    Thoughts?

  • Running a program with `--help`/`-h` option  should not result in an exit-code other than 0

    Running a program with `--help`/`-h` option should not result in an exit-code other than 0

    When asking for command line arguments help, the program exits with an exit-code other than 0 , most likely always 1.

    I think this is not correct, since the program did exactly what was asked for.

    Example from my toy program

    -> go run . --help
    NAME:
        cmdargs - A toy program to lear go command line processing
    
    SYNOPSIS:
        cmdargs [--help|-h|-?] <command> [<args>]
    
    COMMANDS:
        command1    This is the first command
        command2    This is the second command
        command3    The third command
        help        Use 'cmdargs help <command>' for extra details.
    
    OPTIONS:
        --help|-h|-?    (default: false)
    
    Use 'cmdargs help <command>' for extra details.
    exit status 1
    
    
    -> go run . command3  --help
    NAME:
        cmdargs command3 - The third command
    
    SYNOPSIS:
        cmdargs command3 [--help|-h|-?] <command> [<args>]
    
    COMMANDS:
        sub-cmd    
    
    OPTIONS:
        --help|-h|-?    (default: false)
    
    Use 'cmdargs command3 help <command>' for extra details.
    exit status 1
    
    -> echo $?
    1
    

    but programs should always return 0 when executed with some help option, see for example

    -> go help
    ...
    -> echo $?
    0
    

    or any other tool with --help/-h options

    -> xcode-select --help
    Usage: xcode-select [options]
    
    Print or change the path to the active developer directory. This directory
    controls which tools are used for the Xcode command line tools (for example,
    xcodebuild) as well as the BSD development commands (such as cc and make).
    
    Options:
      -h, --help                  print this help message and exit
      -p, --print-path            print the path of the active developer directory
      -s <path>, --switch <path>  set the path for the active developer directory
      --install                   open a dialog for installation of the command line developer tools
      -v, --version               print the xcode-select version
      -r, --reset                 reset to the default command line tools path
    
    -> echo $?
    0
    

    It would be nice if go-getoptions would behave per default likewise it is expected to behave when the --help/-h is processed, and only produces other exitcodes than 0 when the help is shown due to unknown arguments

  • Readme missing section

    Readme missing section

    README file leaves me hanging: https://github.com/DavidGamba/go-getoptions/blame/master/README.adoc#L357 Using blame view because GitHub doesn't support show correct line when trying to view file normally https://github.com/DavidGamba/go-getoptions/blob/master/README.adoc#L357

  • [question] How to do positional arguments?

    [question] How to do positional arguments?

    First of all, thanks for this library, I am super new to go, but your docs and example make it pretty easy to get started creating some app that takes commands and arguments, and it's fun!

    One issue though, I could not figure out how to get something like pythons argparse positional argument https://docs.python.org/3/howto/argparse.html#introducing-positional-arguments

    Specifying the name(s) of argument values that are not passed via a flag, but at the end of a command.

    I could of course use the remaining args from opt.Parse, but then there is no help entry... Did I miss something in the docs, or is it not mentioned?

  • Fix spelling mistake on DepthFirstSort mispelled as DephFirstSort

    Fix spelling mistake on DepthFirstSort mispelled as DephFirstSort

    Hello David :). Was snooping around and saw a spelling mistake. Thought I'd go ahead and make a PR. Let me know if anything needs to be changed.

    I've run the tests locally and it looks good, and I've compiled some of your examples (dag, mygit) and they seem to work.

  • question about non dash argument

    question about non dash argument

    Hi, is there a way to allow a commandline with a first argument without a dash ? For exemple : ./myprogram init -v 4 -d --long something or ./myprogram build -v 5 [...] ?

  • Making StringMap/StringMapVar optional?

    Making StringMap/StringMapVar optional?

    Greetings, this is my favorite of the Go command-line parsing mechanisms. One question though: I noticed that StringMap/StringMapVar have a minimum of 1 entry. In my case I intend to fall back to a configuration file for map[string]string values that aren't explicitly provided on the command-line. Does this sound reasonable or am I making an incorrect usage assumption?

  • Startup panic when alias matches the beginning of preexisting option

    Startup panic when alias matches the beginning of preexisting option

    Code to reproduce it:

        opt = New()
        opt.Bool("fleg", false)
        opt.Bool("flag", false, "f")
        _, err = opt.Parse([]string{})
    

    Output:

    panic: Alias 'f' is already defined for option 'fleg'

    Workaround: Define the option with the alias before the one without.

        opt = New()
        opt.Bool("flag", false, "f")
        opt.Bool("fleg", false)
        _, err = opt.Parse([]string{})
    
  • single purpose help vs complex help

    single purpose help vs complex help

    I'm liking the project so far, but trying to figure out the context for help information with regards to the single purpose script vs the complex script referenced here

    In the single purpose script, help is handled by opt.Bool("help", ... ) and if opt.Called("help") { fmt.Println(opt.Help() }

    In the complex script, help is defined by opt.HelpCommand("help", ... ), handled within the Dispatch() call, returning ErrHelpCalled.

    I just want to verify that this is correct; that these two methods of handling help are essentially exclusive (shouldn't be mixed). To me, it seems inconsistent having two different methods for handling help depending on the complexity; could help be handled within parse() returning ErrHelpCalled to make things more consistent?

    Just a thought..

A flexible command and option parser for Go

Writ Overview Writ is a flexible option parser with thorough test coverage. It's meant to be simple and "just work". Applications using writ look and

Dec 27, 2022
A command line parser written in Go

go-cmdline Introduction cmdline is a Go library to parse command line options (with optional default values), arguments and subcommands. Usage The fol

Oct 9, 2022
A command-line arguments parser that will make you smile.

docopt-go An implementation of docopt in the Go programming language. docopt helps you create beautiful command-line interfaces easily: package main

Jan 7, 2023
A Go library for implementing command-line interfaces.

Go CLI Library cli is a library for implementing powerful command-line interfaces in Go. cli is the library that powers the CLI for Packer, Serf, Cons

Jan 1, 2023
Permits a Go application to implement subcommands support similar to what is supported by the 'go' tool.

subcommands golang library This package permits a Go application to implement subcommands support similar to what is supported by the 'go' tool. The l

Jul 28, 2022
getopt-like flags package for golang,

goopt A getopt-like processor of command-line flags. It works much like the "flag" package, only it processes arguments in a way that is compatible wi

Oct 5, 2022
Fully featured Go (golang) command line option parser with built-in auto-completion support.

go-getoptions Go option parser inspired on the flexibility of Perl’s GetOpt::Long. Table of Contents Quick overview Examples Simple script Program wit

Dec 14, 2022
bash completion written in go + bash completion for go command

complete Package complete is everything for bash completion and Go. The main development is done on the master branch, please follow the link to see a

Dec 20, 2022
DeSo is a blockchain built from the ground up to support a fully-featured social network

DeSo is a blockchain built from the ground up to support a fully-featured social network. Its architecture is similar to Bitcoin, only it supports complex social network data like profiles, posts, follows, creator coin transactions, and more.

Dec 22, 2022
DeSo: a blockchain built from the ground up to support a fully-featured social network

About DeSo DeSo is a blockchain built from the ground up to support a fully-feat

Dec 18, 2021
Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.
  Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.

gore Yet another Go REPL that works nicely. Featured with line editing, code completion, and more. (Screencast taken with cho45/KeyCast) Usage gore Af

Jan 2, 2023
Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.
  Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.

gore Yet another Go REPL that works nicely. Featured with line editing, code completion, and more. (Screencast taken with cho45/KeyCast) Usage gore Af

Jan 7, 2023
Focus is a fully featured productivity timer for the command line, based on the Pomodoro Technique. Supports Linux, Windows, and macOS.
Focus is a fully featured productivity timer for the command line, based on the Pomodoro Technique. Supports Linux, Windows, and macOS.

Focus is a cross-platform productivity timer for the command line. It is based on the Pomodoro Technique, a time management method developed by Francesco Cirillo in the late 1980s.

Dec 26, 2022
go command line option parser

go-flags: a go library for parsing command line arguments This library provides similar functionality to the builtin flag library of go, but provides

Jan 4, 2023
go command line option parser

go-flags: a go library for parsing command line arguments This library provides similar functionality to the builtin flag library of go, but provides

Dec 22, 2022
Flag is a simple but powerful command line option parsing library for Go support infinite level subcommand

Flag Flag is a simple but powerful commandline flag parsing library for Go. Documentation Documentation can be found at Godoc Supported features bool

Sep 26, 2022
Fully featured and highly configurable SFTP server with optional FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob

SFTPGo Fully featured and highly configurable SFTP server with optional FTP/S and WebDAV support, written in Go. Several storage backends are supporte

Jan 9, 2023
SFTPGo - Fully featured and highly configurable SFTP server with optional FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob

SFTPGo - Fully featured and highly configurable SFTP server with optional FTP/S and WebDAV support - S3, Google Cloud Storage, Azure Blob

Jan 4, 2023
Simple trie based auto-completion engine implementation in golang.
Simple trie based auto-completion engine implementation in golang.

Simple auto-complete engine implementation in golang. Quick start $ git clone https://github.com/benbarron/trie-auto-completion-engine $ cd trie-auto-

Jul 12, 2022
This is a simple text completion/editing/auto-correction tool I created in Go.
This is a simple text completion/editing/auto-correction tool I created in Go.

Auto Text Completion Tool This is a simple text completion/editing/auto-correction tool I created in Go. The tool receives the following arguments: Th

Oct 25, 2022