{"id":17115028,"url":"https://github.com/tdewolff/argp","last_synced_at":"2025-05-16T07:03:54.206Z","repository":{"id":57565060,"uuid":"336797785","full_name":"tdewolff/argp","owner":"tdewolff","description":"GNU command line argument parser","archived":false,"fork":false,"pushed_at":"2025-04-30T13:52:18.000Z","size":80,"stargazers_count":320,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-30T15:05:20.106Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tdewolff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-02-07T13:48:44.000Z","updated_at":"2025-04-30T13:52:21.000Z","dependencies_parsed_at":"2022-08-23T12:30:47.603Z","dependency_job_id":"6ec37392-7ae0-4002-8201-e6303f504d26","html_url":"https://github.com/tdewolff/argp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdewolff%2Fargp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdewolff%2Fargp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdewolff%2Fargp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdewolff%2Fargp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tdewolff","download_url":"https://codeload.github.com/tdewolff/argp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485053,"owners_count":22078767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T17:21:18.432Z","updated_at":"2025-05-16T07:03:54.186Z","avatar_url":"https://github.com/tdewolff.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# GNU command line argument parser\nCommand line argument parser following the GNU standard.\n\n    ./test -vo out.png --size 256 input.txt\n\nwith the following features:\n\n- build-in help (`-h` and `--help`) message\n- scan arguments into struct fields with configuration in tags\n- scan into composite field types (arrays, slices, structs)\n- allow for nested sub commands\n\nGNU command line argument rules:\n\n- arguments are options when they begin with a hyphen `-`\n- multiple options can be combined: `-abc` is the same as `-a -b -c`\n- long options start with two hyphens: `--abc` is one option\n- option names are alphanumeric characters\n- options can have a value: `-a 1` means that `a` has value `1`\n- option values can be separated by a space, equal sign, or nothing: `-a1 -a=1 -a 1` are all equal\n- options and non-options can be interleaved\n- options may appear in any order\n- the argument `--` terminates all options so that all following arguments are treated as non-options\n- an argument value of `-` is allowed, usually used to mean standard in or out streams\n- options may be specified multiple times, only the last one determines its value\n\nAdditional features:\n\n- counting options: `-vvv` sets `v = 3`\n- appending options: `-v 1 -v 2` sets `v = []int{1, 2}`\n- boolean options: `--var` enables and `--no-var` disables a boolean\n- options can be composite types, such as structs, slices, or maps:\n  - `-v 1,2,3` sets `v = []int{1, 2, 3}`\n  - `-v [1 2 3]` sets `v = []int{1, 2, 3}`\n  - `-v {1:one 2:two}` sets `map[int]string{1:\"one\", 2:\"two\"}`\n  - `-v {string 42 [0 1]}` sets `struct{S string, I int, B [2]bool}{\"string\", 42, false, true}`\n- options can retrieve their list/dict values from a source (such as SQL):\n  - `-v file:email-addresses.txt` sets `v = []string{ /* lines in email-addresses.txt */ }`\n  - `-v file:email-addresses.txt` sets `v = map[string]string{ /* key=value in email-addresses.txt lines */ }`\n\n*See also [github.com/tdewolff/prompt](https://github.com/tdewolff/prompt) for a command line prompter.*\n\n## Installation\nMake sure you have [Git](https://git-scm.com/) and [Go](https://golang.org/dl/) (1.22 or higher) installed, run\n```\nmkdir Project\ncd Project\ngo mod init\ngo get -u github.com/tdewolff/argp\n```\n\nThen add the following import\n``` go\nimport (\n    \"github.com/tdewolff/argp\"\n)\n```\n\n## Examples\n### Default usage\nA regular command with short and long options.\nSee [`cmd/test/main.go`](cmd/test/main.go).\n\n```go\npackage main\n\nimport \"github.com/tdewolff/argp\"\n\nfunc main() {\n    var verbose int\n    var input string\n    var output string\n    var files []string\n    size := 512 // default value\n\n    cmd := argp.New(\"CLI tool description\")\n    cmd.AddOpt(argp.Count{\u0026verbose}, \"v\", \"verbose\", \"Increase verbosity, eg. -vvv\")\n    cmd.AddOpt(\u0026output, \"o\", \"output\", \"Output file name\")\n    cmd.AddOpt(\u0026size, \"\", \"size\", \"Image size\")\n    cmd.AddArg(\u0026input, \"input\", \"Input file name\")\n    cmd.AddRest(\u0026files, \"files\", \"Additional files\")\n    cmd.Parse()\n\n    // ...\n}\n```\n\nwith help output\n\n```\nUsage: test [options] input files...\n\nOptions:\n  -h, --help          Help\n  -o, --output string Output file name\n      --size=512 int  Image size\n  -v, --verbose int   Increase verbosity, eg. -vvv\n\nArguments:\n  input     Input file name\n  files     Additional files\n```\n\n### Sub commands\nExample with sub commands using a main command for when no sub command is used, and a sub command named \"cmd\". For the main command we can also use `New` and `AddOpt` instead and process the command after `argp.Parse()`.\n\n```go\npackage main\n\nimport \"github.com/tdewolff/argp\"\n\nfunc main() {\n    cmd := argp.NewCmd(\u0026Main{}, \"CLI tool description\")\n    cmd.AddCmd(\u0026Command{}, \"cmd\", \"Sub command\")\n    cmd.Parse()\n}\n\ntype Main struct {\n    Version bool `short:\"v\"`\n}\n\nfunc (cmd *Main) Run() error {\n    // ...\n}\n\ntype Command struct {\n    Verbose bool `short:\"v\" name:\"\"`\n    Output string `short:\"o\" desc:\"Output file name\"`\n    Size int `default:\"512\" desc:\"Image size\"`\n}\n\nfunc (cmd *Command) Run() error {\n    // ...\n}\n```\n\n### Arguments\n```go\nvar input string\ncmd.AddArg(\u0026input, \"input\", \"Input file name\")\n\nvar files []string\ncmd.AddRest(\u0026files, \"files\", \"Additional input files\")\n```\n\n### Options\nBasic types\n```go\nvar v string = \"default\"\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n\nvar v bool = true\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n\nvar v int = 42 // also: int8, int16, int32, int64\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n\nvar v uint = 42 // also: uint8, uint16, uint32, uint64\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n\nvar v float64 = 4.2 // also: float32\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n```\n\nComposite types\n```go\nv := [2]int{4, 2} // element can be any valid basic or composite type\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n// --var [4 2]  =\u003e  [2]int{4, 2}\n// or: --var 4,2  =\u003e  [2]int{4, 2}\n\nv := []int{4, 2, 1} // element can be any valid basic or composite type\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n// --var [4 2 1]  =\u003e  []int{4, 2, 1}\n// or: --var 4,2,1  =\u003e  []int{4, 2, 1}\n\nv := map[int]string{1:\"one\", 2:\"two\"} // key and value can be any valid basic or composite type\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n// --var {1:one 2:two}  =\u003e  map[int]string{1:\"one\", 2:\"two\"}\n\nv := struct { // fields can be any valid basic or composite type\n    S string\n    I int\n    B [2]bool\n}{\"string\", 42, [2]bool{0, 1}}\ncmd.AddOpt(\u0026v, \"v\", \"var\", \"description\")\n// --var {string 42 [0 1]}  =\u003e  struct{S string, I int, B [2]bool}{\"string\", 42, false, true}\n```\n\n#### Count\nCount the number of time a flag has been passed.\n\n```go\nvar c int\ncmd.AddOpt(argp.Count{\u0026c}, \"c\", \"count\", \"Count\")\n// Count the number of times flag is present\n// -c -c / -cc / --count --count  =\u003e  2\n// or: -c 5  =\u003e  5\n```\n\n#### Append\nAppend each flag to a list.\n\n```go\nvar v []int\ncmd.AddOpt(argp.Append{\u0026v}, \"v\", \"value\", \"Values\")\n// Append values for each flag\n// -v 1 -v 2  =\u003e  [1 2]\n```\n\n#### Config\nLoad all arguments from a configuration file. Currently only TOML is supported.\n\n```go\ncmd.AddOpt(\u0026argp.Config{cmd, \"config.toml\"}, \"\", \"config\", \"Configuration file\")\n```\n\n#### List\nUse a list source specified as type:list. Default supported types are: inline.\n- Inline takes a []string, e.g. `inline:[foo bar]`\n\n```go\nlist := argp.NewList(il)\ndefer list.Close()\n\ncmd.AddOpt(\u0026list, \"\", \"list\", \"List\")\n```\n\nYou can add a MySQL source:\n```\ntype mysqlList struct {\n\tHosts    string\n\tUser     string\n\tPassword string\n\tDbname   string\n\tQuery    string\n}\n\nfunc newMySQLList(s []string) (argp.ListSource, error) {\n\tif len(s) != 1 {\n\t\treturn nil, fmt.Errorf(\"invalid path\")\n\t}\n\n\tt := mysqlList{}\n\tif err := argp.LoadConfigFile(\u0026t, s[0]); err != nil {\n\t\treturn nil, err\n\t}\n\n\turi := fmt.Sprintf(\"%s:%s@%s/%s\", t.User, t.Password, t.Hosts, t.Dbname)\n\tdb, err := sqlx.Open(\"mysql\", uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdb.SetConnMaxLifetime(time.Minute)\n\tdb.SetConnMaxIdleTime(time.Minute)\n\tdb.SetMaxOpenConns(10)\n\tdb.SetMaxIdleConns(10)\n\treturn argp.NewSQLList(db, t.Query, \"\")\n}\n\n// ...\nlist.AddSource(\"mysql\", newMySQLList)\n// ...\n```\nUse as `./bin -list mysql:list-config.toml`.\n\n#### Dict\nUse a dict source specified as type:dict. Default supported types are: static and inline.\n- Static takes a string and will return that as a value for all keys, e.g. `static:foobar`\n- Inline takes a map[string]string, e.g. `inline:{foo:1 bar:2}`\n\n```go\ndict := argp.NewDict([]string{\"static:value\"})\ndefer dict.Close()\n\ncmd.AddOpt(\u0026dict, \"\", \"dict\", \"Dict\")\n```\n\nYou can add custom sources must like the mysqlList example above.\n\n### Option tags\nThe following struct will accept the following options and arguments:\n- `-v` or `--var` with a default value of 42\n- The first argument called `first` with a default value of 4.2\n- The other arguments called `rest`\n\n```go\ntype Command struct {\n    Var1 int `short:\"v\" name:\"var\" default:\"42\" desc:\"Description\"`\n    Var2 float64 `name:\"first\" index:\"0\" default:\"4.2\"`\n    Var3 []string `name:\"rest\" index:\"*\"`\n}\n\nfunc (cmd *Command) Run() error {\n    // run command\n    return nil\n}\n```\n\n## License\nReleased under the [MIT license](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdewolff%2Fargp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftdewolff%2Fargp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdewolff%2Fargp/lists"}