akamensky / argparse Goto Github PK
View Code? Open in Web Editor NEWArgparse for golang. Just because `flag` sucks
License: MIT License
Argparse for golang. Just because `flag` sucks
License: MIT License
We should enable a SelectorList argument type which accepts a list of strings which match the Selector criteria
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.
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.
When will argparse be part of the standard package library? i.e. import argparse
without the github references.
First of all thanks for the awesome work. I noticed a few discrepancies and usage issues which can make this package better.
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.
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]>
The usage helptext is currently very cramped, at 80 maximum characters ( https://github.com/akamensky/argparse/blob/master/argparse.go#L647 ):
It would be great if this were configurable
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.
argparse
variables as GLOBAL one. Currently, the scope of argparse variables are confined only to main()
.var ( )
?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"
See examples/commands-advanced
for example. It has help message issues with calling $ go run main.go dog
Should print list of dog's subcommands, but prints dog
and cat
top level commands.
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
i.e. progname command --help
will yield error message instead of printing entire help message.
Help message should be printed whenever -h|--help
is provided regardless whether on top level or on sub-command.
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.
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.
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
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
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.
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.
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.
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)
}
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
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
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.
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.
According to Effective Go getter methods should be named based on the object and shouldn't include the get prefix.
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.
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....
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
π
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.
Positionals (added in 1.4) currently ignore the Required option. It should be supported, with these basic requirements:
Some discussion of the problem is warranted before coding begins. This may not be an exhaustive list of requirements.
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:
nargs
functionality
-vvv
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")
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
$
Hi.
Is it possible to enable auto complete subcommands like git?
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?
As Python's argparse implementation, is possible to have a mutually exclusive groups for arguments
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
?
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?
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.
Possibly need two separate arguments. One for int
and one for float
types.
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
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?
Need examples to cover following topics:
Each example must be independent and fully functional program
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
.
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?
See https://docs.python.org/3/library/argparse.html#default.
I would expect something like:
parser.String("s", "string", &argparse.Options{Default: "The default string value."})
For some tools it makes more sense to use positional arguments instead of randomly located named arguments. The positional arguments must work as follows:
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.
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
-vvv
I have a golang binary named test. I have two flags -p and -s. I want user to pass them like below scenarios:
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"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.