Coder Social home page Coder Social logo

argparse's Introduction

Golang argparse

Go Reference Go Report Card Coverage Status Build Status

Let's be honest -- Go's standard command line arguments parser flag terribly sucks. It cannot come anywhere close to the Python's argparse module. This is why this project exists.

The goal of this project is to bring ease of use and flexibility of argparse to Go. Which is where the name of this package comes from.

Installation

To install and start using argparse simply do:

$ go get -u -v github.com/akamensky/argparse

You are good to go to write your first command line tool! See Usage and Examples sections for information how you can use it

Usage

To start using argparse in Go see above instructions on how to install. From here on you can start writing your first program. Please check out examples from examples/ directory to see how to use it in various ways.

Here is basic example of print command (from examples/print/ directory):

package main

import (
	"fmt"
	"github.com/akamensky/argparse"
	"os"
)

func main() {
	// Create new parser object
	parser := argparse.NewParser("print", "Prints provided string to stdout")
	// Create string flag
	s := parser.String("s", "string", &argparse.Options{Required: true, Help: "String to print"})
	// Parse input
	err := parser.Parse(os.Args)
	if err != nil {
		// In case of error print error and print usage
		// This can also be done by passing -h or --help flags
		fmt.Print(parser.Usage(err))
	}
	// Finally print the collected string
	fmt.Println(*s)
}

Basic options

Create your parser instance and pass it program name and program description. Program name if empty will be taken from os.Args[0] (which is okay in most cases). Description can be as long as you wish and will be used in --help output

parser := argparse.NewParser("progname", "Description of my awesome program. It can be as long as I wish it to be")

String will allow you to get a string from arguments, such as $ progname --string "String content"

var myString *string = parser.String("s", "string", ...)

Positional arguments can be used like this $ progname value1. See Basic Option Structure and Positionals.

var myString *string = parser.StringPositional(nil)
var myString *string = parser.FilePositional(nil)
var myString *string = parser.FloatPositional(nil)
var myString *string = parser.IntPositional(nil)
var myString *string = parser.SelectorPositional([]string{"a", "b"}, nil)
var myString1 *string = parser.StringPositional(Options{Default: "beep"})

Selector works same as a string, except that it will only allow specific values. For example like this $ progname --debug-level WARN

var mySelector *string = parser.Selector("d", "debug-level", []string{"INFO", "DEBUG", "WARN"}, ...)

StringList allows to collect multiple string values into the slice of strings by repeating same flag multiple times. Such as $ progname --string hostname1 --string hostname2 -s hostname3

var myStringList *[]string = parser.StringList("s", "string", ...)

List allows to collect multiple values into the slice of strings by repeating same flag multiple times (at fact - it is an Alias of StringList). Such as $ progname --host hostname1 --host hostname2 -H hostname3

var myList *[]string = parser.List("H", "hostname", ...)

Flag will tell you if a simple flag was set on command line (true is set, false is not). For example $ progname --force

var myFlag *bool = parser.Flag("f", "force", ...)

FlagCounter will tell you the number of times that simple flag was set on command line (integer greater than or equal to 1 or 0 if not set). For example $ progname -vv --verbose

var myFlagCounter *int = parser.FlagCounter("v", "verbose", ...)

Int will allow you to get a decimal integer from arguments, such as $ progname --integer "42"

var myInteger *int = parser.Int("i", "integer", ...)

IntList allows to collect multiple decimal integer values into the slice of integers by repeating same flag multiple times. Such as $ progname --integer 42 --integer +51 -i -1

var myIntegerList *[]int = parser.IntList("i", "integer", ...)

Float will allow you to get a floating point number from arguments, such as $ progname --float "37.2"

var myFloat *float64 = parser.Float("f", "float", ...)

FloatList allows to collect multiple floating point number values into the slice of floats by repeating same flag multiple times. Such as $ progname --float 42 --float +37.2 -f -1.0

var myFloatList *[]float64 = parser.FloatList("f", "float", ...)

File will validate that file exists and will attempt to open it with provided privileges. To be used like this $ progname --log-file /path/to/file.log

var myLogFile *os.File = parser.File("l", "log-file", os.O_RDWR, 0600, ...)

FileList allows to collect files into the slice of files by repeating same flag multiple times. FileList will validate that files exists and will attempt to open them with provided privileges. To be used like this $ progname --log-file /path/to/file.log --log-file /path/to/file_cpy.log -l /another/path/to/file.log

var myLogFiles *[]os.File = parser.FileList("l", "log-file", os.O_RDWR, 0600, ...)

You can implement sub-commands in your CLI using parser.NewCommand() or go even deeper with command.NewCommand(). Addition of a sub-command implies that a subcommand is required. Sub-commands are always parsed before arguments. If a command has Positional arguments and sub-commands then sub-commands take precedence. Since parser inherits from command, every command supports exactly same options as parser itself, thus allowing to add arguments specific to that command or more global arguments added on parser itself!

You can also dynamically retrieve argument values and if they were parsed:

var myInteger *int = parser.Int("i", "integer", ...)
parser.Parse()
fmt.Printf("%d", *parser.GetArgs()[0].GetResult().(*int))
fmt.Printf("%v", *parser.GetArgs()[0].GetParsed())

Basic Option Structure

The Option structure is declared at argparse.go:

type Options struct {
	Required bool
	Validate func(args []string) error
	Help     string
	Default  interface{}
}

You can set Required to let it know if it should ask for arguments. Or you can set Validate as a lambda function to make it know while value is valid. Or you can set Help for your beautiful help document. Or you can set Default will set the default value if user does not provide a value.

Example:

dirpath := parser.String("d", "dirpath",
			 &argparse.Options{
			 	Required: false,
				Help: "the input files' folder path",
				Default: "input",
			})

Caveats

There are a few caveats (or more like design choices) to know about:

  • Shorthand arguments MUST be a single character. Shorthand arguments are prepended with single dash "-"
  • If not convenient shorthand argument can be completely skipped by passing empty string "" as first argument
  • Shorthand arguments ONLY for parser.Flag() and parser.FlagCounter() can be combined into single argument same as ps -aux, rm -rf or lspci -vvk
  • Long arguments must be specified and cannot be empty. They are prepended with double dash "--"
  • You cannot define two same arguments. Only first one will be used. For example doing parser.Flag("t", "test", nil) followed by parser.String("t", "test2", nil) will not work as second String argument will be ignored (note that both have "t" as shorthand argument). However since it is case-sensitive library, you can work arounf it by capitalizing one of the arguments
  • There is a pre-defined argument for -h|--help, so from above attempting to define any argument using h as shorthand will fail
  • parser.Parse() returns error in case of something going wrong, but it is not expected to cover ALL cases
  • Any arguments that left un-parsed will be regarded as error
Positionals
  • Positional args have a set of effects and conditions:
    • Always parsed after subcommands and non-positional args
    • Always set Required=False
    • Default is only used if the command or subcommand owning the arg Happened
    • Parsed in Command root->leaf left->right order (breadth-first)
      • Top level cmd consumes as many positionals as it can, from left to right
      • Then in a descendeding loop for any command which Happened it repeats
      • Positionals which are not satisfied (due to lack of input args) are not errors

Contributing

Can you write in Go? Then this projects needs your help!

Take a look at open issues, specially the ones tagged as help-wanted. If you have any improvements to offer, please open an issue first to ensure this improvement is discussed.

There are following tasks to be done:

  • Add more examples
  • Improve code quality (it is messy right now and could use a major revamp to improve gocyclo report)
  • Add more argument options (such as numbers parsing)
  • Improve test coverage
  • Write a wiki for this project

However note that the logic outlined in method comments must be preserved as the the library must stick with backward compatibility promise!

Acknowledgments

Thanks to Python developers for making a great argparse which inspired this package to match for greatness of Go

argparse's People

Contributors

abathargh avatar akamensky avatar alecbakholdin avatar densestvoid avatar drewwalters96 avatar goofinator avatar jaikrishnats avatar jhughes1153 avatar josegonzalez avatar look avatar peterlitszo avatar rsheasby avatar silversoldier avatar thegreyd avatar vsachs avatar zuoxiaofeng 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

argparse's Issues

SelectorList flag

We should enable a SelectorList argument type which accepts a list of strings which match the Selector criteria

Usage(err interface{}) only uses values of type error

Regarding func (*Command) Usage(err interface{}) string, only values of err with types subCommandError and error are used by the function. Because subCommandError is an implementation of error, the argument should really be of type error.

It would be nice if it also accounted for string and fmt.Stringer, but I think documentation should at least note what the supported types are.

shorthand argument creation check

If i do some thing like this ("pp" on shorthand argument ):
parser.Int("pp","port",&argparse.Options{Required: false,Default: 10000, Help: "Work in dummy mode"})
there is no error on parser.Parse, and default value became 0. Are long name as shorthand allowed? If no, maybe it should be error value on this situation? If Yes - why default value differs from expectation.

Combining a shorthand arguments with a parameter with flags

Hello!
Interesting: how critical is the design requirement:
"Shorthand arguments ONLY for parser.Flag () can be combined into single argument same as ps -aux or rm -rf"
It seems to me that it would be a good idea to give the opportunity to combine a shorthand arguments with a parameter with flags if it is written after them. I mean some thing like this:
tar -cvaf foo.tar.gz foo

Thoughts on a Lists

There is a question.
There are arguments with a parameter for different types (String, Float, Int).
There is also an argument of type List, which allows you to create a list of parameters of type String.
Wouldn't it be logical to make StringList, FloatList, IntList?

Add support for positional arguments

For some tools it makes more sense to use positional arguments instead of randomly located named arguments. The positional arguments must work as follows:

  1. Positional arguments can be placed only after named arguments and cannot mixed up with them
  2. Positional arguments order should be clearly defined in the code (possibly by order in which they are added)
  3. Positional argument parsing should account for shell expansions (namely wildcard in path arguments, which expands to multiple arguments)

Error when trying to run example in README.md

The example in README.md gives the following error when I try to run it:

./main.go:23:25: not enough arguments in call to parser.Command.Usage
	have ()
	want (interface {})

After checking the source code, I passed the err variable to parser.Usage, which resulted in the error being printed twice. So, I presume the fmt.Println call is redundant.

Running: go1.10 on Ubuntu 17.10.1 Linux 64-bit.

[bug] Commands not required

Hello, I have following code

parser := argparse.NewParser("...", "...")

verbose := parser.FlagCounter("v", "verbose", &argparse.Options{})
hosts := parser.StringList("", "host", &argparse.Options{Required: true})
username := parser.String("u", "user", &argparse.Options{Required: true})
password := parser.String("p", "password", &argparse.Options{Required: true})

// preset cmd
presetCmd := parser.NewCommand("preset", "Get and modify radio presets")
// get preset cmd
getPresetCmd := presetCmd.NewCommand("get", "Get the current radio preset")
// set preset cmd
setPresetCmd := presetCmd.NewCommand("set", "Set the current radio preset")
setPresetID := setPresetCmd.Int("", "id", &argparse.Options{Required: true})

// user cmd
userCmd := parser.NewCommand("user", "User")
getUserCmd := userCmd.NewCommand("get", "Get all users")

err := parser.Parse(os.Args)
if err != nil {
    fmt.Println(parser.Usage(err))
    return
}

When I start this with no arguments, I get the expected error message [sub]Command required.
When I start the program with just hosts, username and password, the subcommand is suddenly not needed.

EDIT: After reviewing your example code, the advanced-command example has the exact same bug. Start the example with just the --name argument and you reach

// This should be unreachable
log.Fatal("Uh-oh, something weird happened")

testFunction

I thought it would be nice to include a test function in the options.
If it is defined, when creating the argument, you should test the received value of the argument with its help. If it fails, finish processing with an error. This will help the user to handle a wide range of situations when the list of values โ€‹โ€‹is limited, not providing for all cases in the library itself.

Too many loops and cycling references

While this code works, it was something made over the weekend, just because I needed good library for this asap.

Might need to re-thinking the code to avoid cycling dependencies in the code as well as reduce number of loops in it.

Write Wiki documentation for this project

Apparently GoDoc cannot show documentation for exported methods of un-exported structs, and it makes no sense to export parser and/or command, thus this project should provide its own documentation page.

subparser not implemented

So, I am trying to follow wyag tutorial. I am trying this with golang. So far so good. I found all equivalent go packages. But the parser in the tutorial uses subparser. I think I can do it without it too, But I noticed it's not implemented here.

Thanks for this package.

How do I make a hidden argument?

For example, the user can define a hidden argument that is not shown on the help. I can't find an argument type to do this or any option field to set. How do I make a hidden one?

Can't have duplicate switches in different commands?

If different commands both have switches that share the same short or long value, it errors with unable to add String: short name {} occurs more than once. This completely renders this library unusable for me unfortunately as many of my sub-commands do share the same switches (with different uses). Is this something that would be easy to fix or should I look for another library?

`sdtin / stdout` default values for File?

I'm not quite sure of the size of my request, but here goes.

Looking at the implementation I see that the default should be a string, it being the path to the file to open, but I can't seem to make that point to the "real" standard streams. Perhaps it could be hardcoded that the strings "stdin", "stdout", "stderr" in the Option's Default for the File trigger that the file pointer points to os.Stdin / Stderr / Stdout?

Allow parser.ParseKnownArgs(...)

Using your library is nice, but I'd really like to be able to pass through additional arguments so I can wrap scripts and forward args I don't care about to them.

The error returned would then only check that required arguments are there. Setting all others as ignored

Question about returned parameters (not a bug report)

Congratulations on porting the ArgParse concept from Python. ArgParse is one of the Python packages that I have used heavily so this was quite welcome to find. If I find any bugs or suggestions for enhancements, I'll write up a separate issue.

  1. Since Parser.X is returning something, why return a pointer to the something? Why not simply return the something itself? Yes, argparse is consistent which is always a good thing.

  2. When will argparse be part of the standard package library? i.e. import argparse without the github references.

Allow unambiguous shortened long-options

With GNU getopt and friends (I believe Python argparse included, but I haven't tested it to write this issue report), long options may be abbreviated to the shortest unambiguous version and needn't be typed in full.

For example, in a program that has both --verbose and --version, --ver cannot work since it would match either of them, but --vers would act the same as --version, and --verb would act the same as --verbose.

Provide <META> fields and Author Information in usage string

First of all thanks for the awesome work. I noticed a few discrepancies and usage issues which can make this package better.

  1. Python's argparse provides a metavar field which adds a description, a META field for the argument which is missing from this package. So say if a field is a filename then it would show up as,
  -x  --export      <filename> Export all entries to <filename>

I could not find a way to do that with this package.

  1. Author information - I want to add a copyright plus author email field in my help string which is not possible with this package as it has an exact idea of how a usage string should be like.

I liked your package enough to use it for my project, but since these were missing I have added this in my fork of the package. If these changes make sense feel free to engage me in this issue.

Usage string using default argparse.

$ ./varuh -h
usage: varuh [-h|--help] [-e|--encrypt] [-A|--add] [-p|--path] [-a|--list-all]
             [-s|--show] [-c|--copy] [-v|--version] [-I|--init "<value>"]
             [-d|--decrypt "<value>"] [-C|--clone "<value>"] [-R|--remove
             "<value>"] [-U|--use-db "<value>"] [-f|--find "<value>"]
             [-E|--edit "<value>"] [-l|--list-entry "<value>"] [-x|--export
             "<value>"] [-g|--genpass "<value>"]

             Password manager for the command line for Unix like operating
             systems

Arguments:

  -h  --help        Print help information
  -e  --encrypt     Encrypt the current database
  -A  --add         Add a new entry
  -p  --path        Show current database path
  -a  --list-all    List all entries in current database
  -s  --show        Show passwords when listing entries
  -c  --copy        Copy password to clipboard
  -v  --version     Show version information and exit
  -I  --init        Initialize a new database
  -d  --decrypt     Decrypt password database
  -C  --clone       Clone an entry with <id>
  -R  --remove      Remove an entry with <id>
  -U  --use-db      Set <path> as active database
  -f  --find        Search entries with <term>
  -E  --edit        Edit entry by <id>
  -l  --list-entry  List entry by <id>
  -x  --export      Export all entries to <filename>
  -g  --genpass     Generate password of given <length>

Usage string after my changes,

$ ./varuh -h
usage: varuh [-h|--help] [-I|--init "<value>"] [-d|--decrypt "<value>"]
             [-C|--clone "<value>"] [-R|--remove "<value>"] [-U|--use-db
             "<value>"] [-f|--find "<value>"] [-E|--edit "<value>"]
             [-l|--list-entry "<value>"] [-x|--export "<value>"] [-g|--genpass
             "<value>"] [-e|--encrypt] [-A|--add] [-p|--path] [-a|--list-all]
             [-s|--show] [-c|--copy] [-v|--version]

             Password manager for the command line for Unix like operating
             systems

Options:

  -h  --help                   Print help information
  -I  --init        <path>     Initialize a new database
  -d  --decrypt     <path>     Decrypt password database
  -C  --clone       <id>       Clone an entry with <id>
  -R  --remove      <id>       Remove an entry with <id>
  -U  --use-db      <path>     Set <path> as active database
  -f  --find        <term>     Search entries with <term>
  -E  --edit        <id>       Edit entry by <id>
  -l  --list-entry  <id>       List entry by <id>
  -x  --export      <filename> Export all entries to <filename>
  -g  --genpass     <length>   Generate password of given <length>
  -e  --encrypt                Encrypt the current database
  -A  --add                    Add a new entry
  -p  --path                   Show current database path
  -a  --list-all               List all entries in current database
  -s  --show                   Show passwords when listing entries
  -c  --copy                   Copy password to clipboard
  -v  --version                Show version information and exit


AUTHORS
    Copyright (C) 2021 Anand B Pillai <[email protected]>

Handle better newlines in help message

Hello,

I want to add a list to help message, so each item should be on a new line. Now this looks not very good:

      --input          Possible values:
not set - read from stdin;
gs://<path to file gzipped file> - read from
                       GCS;
pubsub://projects/<project>/subscriptions/<subscription> - fetch input value
                       from PubSub

While the original help string looks like:

	Help: "Possible values:\n" +
		"not set - read from stdin;\n" +
		"gs://<path to file gzipped file> - read from GCS;\n" +
		"pubsub://projects/<project>/subscriptions/<subscription> - fetch input value from PubSub"

Add support for nargs functionality

  1. Take constant or variable number of arguments that follow
  2. Important for optional arguments
  3. Does not make much sense for positional arguments

Validation error messages should go to stderr not stdout

I'm using argparse as part of go-procfile-util, and capturing output of that command. Unfortunately, if flags are passed in, the command will exit non-zero but will have some output, which can be a bit confusing if you expect no output on error (my project doesn't have stdout unless there are no errors).

Would be great if all errors went to stderr instead of stdout.

Options.Default should be ignored for Flag

package main

import (
	"fmt"
	"github.com/akamensky/argparse"
	"os"
)

func main() {
   parser := argparse.NewParser("accounts", "Prints provided string to stdout")
   noTest := parser.Flag("n", "no-test", &argparse.Options{Help: "boolean true/false", Default: true})

   err := parser.Parse(os.Args)
   if err != nil {
      fmt.Print(parser.Usage(err))
   }
   fmt.Println(*noTest)
}

why is this always true? the second should be false?

$ go run main.go 
true
$ go run main.go -n
true
$

Getting: import cycle not allowed using the example.

package main

import (
"fmt"
"github.com/akamensky/argparse"
"os"
)

func main() {
// Create new parser object
parser := argparse.NewParser("print", "Prints provided string to stdout")
// Create string flag
s := parser.String("s", "string", &argparse.Options{Required: true, Help: "String to print"})
// Parse input
err := parser.Parse(os.Args)
if err != nil {
// In case of error print error and print usage
// This can also be done by passing -h or --help flags
fmt.Print(parser.Usage(err))
}
// Finally print the collected string
fmt.Println(*s)
}

above is the source

go build first_argparse.go
output:
imports github.com/akamensky/argparse
imports github.com/akamensky/argparse: import cycle not allowed

~/go/src/cmdline_argparse $ go version
go version go1.17.1 darwin/amd64

support "h" custom argument

If I define

host := parser.String("h", "host", &argparse.Options{Required: false, Help: "listening host", Default: "127.0.0.1"})
// ...

I'll get a panic ->

panic: unable to add String: short name h occurs more than once

This is because there's a built-in -h/--help already occupied it.

For now I can workaround it by using a different letter, but It would be a nice to have support for h ๐Ÿ˜

[bug] Unable to detect if file flag was actually provided?

Hi There.

This has been my go-to library for argument parsing, and I recently tried to use this to parse file arguments. However, it seems impossible to determine if a flag was actually provided. For example:

configFile := parser.File("c", "config", etc)
parser.Parse()
if configFile != nil {
    // Do stuff with the file
}
// Do stuff if -c wasn't provided

This does not work, because the configFile is always non-nil, as the parser seems to work by overwriting the internal structures of os.File, and if the argument isn't provided, the configFile will still be non-nil. Furthermore, the standard library doesn't help in this regard, since all the regular functions assume that the file object is valid, so if I try something like configFile.Name(), it just panics.

Is there something I'm missing here, or is there no way to distinguish if the -c flag was provided, without reflection nonsense or panic handling?

Missing Features

While I'm not entirely convinced that all features of argparse are useful, a few are really nifty.

Making a list of few features that I think could be added:

  • Positional arguments
    • Take arguments based on the position.
  • nargs functionality
    • Take constant or variable number of arguments that follow
    • Important for optional arguments
    • Does not make much sense for positional arguments
  • Repeated flags/options
    • Allow to repeat flags or optional arguments to specify more inputs
    • Support for multiple levels like -vvv

[Suggestion] Improve doc of the File type parameter

The flag and perm arguments are a bit confusing. Some clarifications and examples might help.
On my mac, I find the even when I specify a non existing file I get a non nil File *. I am not sure if this is an issue or a bug in my usage:

pubkeyfile := registercmd.File("p", "public-key-file", os.O_RDONLY, 0, &argparse.Options{Help: "Public Key filename (.pem)"})
parser.Parse(os.Args)
if pubkeyfile == nil {
	log.Println("Invalid public key file")
} else {
	log.Println("Opened public key file")
}

BTW - This is my second project with argparse. Thanks for your efforts.

My first use (one a fork of the other) is at:

https://github.com/RajaSrinivasan/srctrace.git
https://github.com/RajaSrinivasan/repotrace.git

They can be viewed as basic and simple applications of argparse.

srini

Repeated text in sub-command usage text

Thank you for the great library! As a former python argparse user this has helped getting a CLI together for some go work.

Working on a program with two levels of sub-commands I noticed the help info repeats with incorrect/incomplete argument usage. This is the not the case with doing -h on the sub-command.

This does not seem to be the same issue as #5 but might be related?

The command-advanced in examples shows this same behavior:

Repeated:

user@vubuntu:~/code/argparse/examples/commands-advanced$ ./commands-advanced dog
[sub]Command required
usage: zooprog dog <Command> [--wiggle] [-h|--help] --name "<value>"

               We are going to see dog

Commands:

  speak   Make the dog speak
  feed    Make the dog eat
  summon  Make the dog come over
  play    Make the dog play

Arguments:

      --wiggle  Makes the dog to wiggle its tail
  -h  --help    Print help information
      --name    Provide an optional name for the animal

usage: zooprog dog <Command> [--wiggle] [-h|--help] --name "<value>"

               We are going to see dog

Commands:

  speak   Make the dog speak
  feed    Make the dog eat
  summon  Make the dog come over
  play    Make the dog play

Arguments:

      --wiggle  Makes the dog to wiggle its tail
  -h  --help    Print help information
      --name    Provide an optional name for the animal

OK:

user@vubuntu:~/code/argparse/examples/commands-advanced$ ./commands-advanced dog -h
usage: zooprog dog <Command> [--wiggle] [-h|--help] --name "<value>"

               We are going to see dog

Commands:

  speak   Make the dog speak
  feed    Make the dog eat
  summon  Make the dog come over
  play    Make the dog play

Arguments:

      --wiggle  Makes the dog to wiggle its tail
  -h  --help    Print help information
      --name    Provide an optional name for the animal

Add more examples

Need examples to cover following topics:

  • Flag and Flag shorthand combining
  • String, Selector and List
  • Int and Float
  • File
  • Required vs Optional arguments
  • Argument validation functions
  • Commands simple
  • Commands with sub-commands and arguments
  • Default values example

Each example must be independent and fully functional program

FlagCounter display unexpectedly

Given a FlagCounter arg definition as following

verboseCounter = parser.FlagCounter("v", "verbose", &argparse.Options{
  Required: false,
  Validate: nil,
  Help:     "",
  Default:  0,
})

the help message displays it in the same style as an Int arg.

 [-v|--verbose <integer>]

however, it can not be used in the same way as an Int arg

-v 1
-v 2
-v 3

instead it should be used in the flag way.

-v
-vv
-vvv

[vote] Should sub-commands be required?

Right now if command has a sub-command (e.g. $ progname command <sub-command> or $ progname <command>) that sub-command is automatically required and not providing any will generate error response on parser.Parse(). This vote is consideration whether sub-commands must be always required, or they do not have to be required (do not generate err on parser.Parse() and instead delegate sub-command require/not-required decision to the developer who uses package.

Thumbs up - required, thumbs down - not required.

Argparse variables as Global variable

  1. Is there a way to set the argparse variables as GLOBAL one. Currently, the scope of argparse variables are confined only to main().
  2. Is there a way to declare it in var ( )?

Golang Argparse not picking correct value for multiple flags

I have a golang binary named test. I have two flags -p and -s. I want user to pass them like below scenarios:

  1. ./test -p
  2. ./test -s serviceName
  3. ./test -p -s serviceName

Means -p should be passed with empty value and -s should be passed with any service name. 1 and 2 are working fine but in third -p flag is taking value "-s". What i want from 3rd is -p should be empty value ("") and -s should be "serviceName"

Help Command closes Program - undesirable in web chat app parsing

Hi i am trying to build a discord chat bot, and leveraging this package has been awesome for that, however when the parser is created a non overridable help argument is added which os.Exit(0) when triggered which is meaning users chatting the bot can make it close. I know this is probably a unexpected use case, i am willing to fork the project and workout a solution if you would like to give my guidance on how the end state should look.

expect File arg to take standard input / output stream as a value

When I define a File arg (like following) to specify an input file,

-i <input-file>

I wish we can specify the - value to input from the standard input stream. However, it will report error now.

if it's defined with a String arg, the help message will display like -i "<value>"(cannot tell this should be a file), not as expected very much.

It is the same case for the output file. I wish to specify the - value to output to standard output stream.

enable required for positionals

Positionals (added in 1.4) currently ignore the Required option. It should be supported, with these basic requirements:

  • Required positionals must have a value supplied by the user (not by Default) or an error is thrown
  • If a positional is set to required, throw an error if there are already any positionals on this command which are NOT required
    -- This is necessary in order to avoid ambiguity of positional argument satisfaction: Say you have two positionals, the first is optional and the second is required. The user gives one value on the CLI. Which positional gets the value? Does the required positional get it IFF the optional has a default?
    -- Do not throw an error if there are optional positionals on a parent command of the command which has had Required positionals added
  • Allow optional positionals to follow Required positionals
  • Do not throw an error if there are Required positionals on commands which did not Happen

Some discussion of the problem is warranted before coding begins. This may not be an exhaustive list of requirements.

panic: runtime error: slice bounds out of range

If you use an argument and pass no value, the go program panics with panic: runtime error: slice bounds out of range.
PoC:

parser := argparse.NewParser("download", "Downloads URL matching provided string")
// Create string flag
searchQuery = parser.String("q", "query", &argparse.Options{Required: true, Help: "URL to download"})
// Parse input
err := parser.Parse(os.Args)
if err != nil {
	// In case of error print error and print usage
	// This can also be done by passing -h or --help flags
	fmt.Println(err.Error())
	fmt.Print(parser.Usage(parser))
}
go run main.go -q

[doc] the sub-command example in README

I'd like to add some examples in README.md, it will be helpful in my opinion.

If it is OK, I will try to update README tomorrow or someday I do not have homework....

Mutually exclusive groups

As Python's argparse implementation, is possible to have a mutually exclusive groups for arguments

support of equals from cli

It seems like it would be useful to be able to specify --path=/home/path/to/file like you can in the python version of argparse. Currently to get around this one has to specify --path /home/path/to/file with the space and it wont parse if there is an equal sign. It took some time before I realized that I needed to have spaces instead of an equal sign before it would parse it correctly.

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.