MCPcopy Index your code
hub / github.com/akamensky/argparse

github.com/akamensky/argparse @v1.4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.4.0 ↗ · + Follow
244 symbols 1,468 edges 24 files 65 documented · 27% 3 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Golang argparse

GoDoc 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

Extension points exported contracts — how you extend this code

Arg (Interface)
Arg interface provides exporting of arg structure, while exposing it [1 implementers]
argument.go

Core symbols most depended-on inside this repo

Error
called by 198
errors.go
NewParser
called by 135
argparse.go
Parse
called by 120
argparse.go
NewCommand
called by 53
argparse.go
Flag
called by 46
argparse.go
Int
called by 39
argparse.go
Happened
called by 32
argparse.go
name
called by 28
argument.go

Shape

Function 146
Method 84
Struct 11
TypeAlias 2
Interface 1

Languages

Go100%

Modules by API surface

argparse_test.go122 symbols
argument.go41 symbols
argparse.go40 symbols
examples/commands-advanced/zoo/zoo.go11 symbols
command.go6 symbols
errors.go3 symbols
argparse_examples_test.go3 symbols
extras.go2 symbols
misc_test.go1 symbols
misc.go1 symbols
examples/validation/validation.go1 symbols
examples/sleep/sleep.go1 symbols

Used by 3 indexed graphs manifest dependencies, hub-wide

For agents

$ claude mcp add argparse \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact