{"id":15663066,"url":"https://github.com/ethomson/adopt","last_synced_at":"2025-04-30T16:07:45.983Z","repository":{"id":15718194,"uuid":"18456270","full_name":"ethomson/adopt","owner":"ethomson","description":"A portable command-line argument parser","archived":false,"fork":false,"pushed_at":"2024-11-06T13:44:27.000Z","size":123,"stargazers_count":19,"open_issues_count":2,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-30T17:44:44.293Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","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/ethomson.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}},"created_at":"2014-04-05T00:08:30.000Z","updated_at":"2024-10-26T13:37:55.000Z","dependencies_parsed_at":"2024-05-13T10:49:18.668Z","dependency_job_id":null,"html_url":"https://github.com/ethomson/adopt","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethomson%2Fadopt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethomson%2Fadopt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethomson%2Fadopt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethomson%2Fadopt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ethomson","download_url":"https://codeload.github.com/ethomson/adopt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251739054,"owners_count":21635891,"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-03T13:35:23.183Z","updated_at":"2025-04-30T16:07:45.920Z","avatar_url":"https://github.com/ethomson.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"Adopt\n=====\n\nA portable command-line argument parser for C that handles short\n(`-a`, `-b foo`, etc) and long (`--arg-a`, `--arg-b=foo`) style \noptions.  It is meant to be compatible with GNU getopt in\ncommand-line usage (though not as an API) and available under an\nMIT license.\n\nAdopt can also produces help syntax and usage messages based on\nthe arguments you accept, so that you don't need to remember to\nupdate your usage messages when you add a new option.\n\nTypes of options\n----------------\n\n* Boolean values are options that do not take a value, and are\n  either set or unset, for example `-v` or `--verbose`.  If a\n  boolean has a long name (eg `--verbose`) then it implicitly has\n  a negation prefixed by `no-` (in this case, `--no-verbose`).\n  The given value will be set to `1` when the boolean is given on\n  the command line and `0` when its negation is given.\n* Accumulators are options that can be provided multiple times to\n  increase its value.  For example, `-v` will set verbosity to `1`,\n  but `-vvv` will set verbosity to `3`.\n* Switches are options that do not take a value on the command\n  line, for example `--long` or `--short`.  When a switch is present\n  on the command line, a variable will be set to a predetermined value.\n  This is useful for (say) having a `length` variable that both\n  `--long` and `--short` will update.\n* Values are options that take a value, for example `-m 2` or\n  `--level=2`.\n* Literal separators are bare double-dashes, `--` as a lone\n  word, indicating that further words will be treated as\n  arguments (even if they begin with a dash).\n* Arguments are bare words, not prefixed with a single or double dash,\n  for example `filename.txt`.\n* Argument lists are the remainder of arguments, not prefixed\n  with dashes.  For example, an array: `file1.txt`, `file2.txt`,\n  ...\n\nSpecifying command-line options\n-------------------------------\n\nOptions should be specified as an array of `adopt_spec` elements,\nelements, terminated with an `adopt_spec` initialized to zeroes.\n\n```c\nint debug = 0;\nint verbose = 0;\nint volume = 1;\nchar *channel = \"default\";\nchar *filename1 = NULL;\nchar *filename2 = NULL;\n\nadopt_spec opt_specs[] = {\n    /* `verbose`, above, will increment each time `-v` is specified. */\n    { ADOPT_ACCUMULATOR, \"verbose\", 'v', \u0026verbose },\n\n    /* `debug`, above, will be set to `1` when `--debug` is specified,\n     * or to `0` if `--no-debug` is specified.\n     */\n    { ADOPT_BOOL, \"debug\", 'd', \u0026debug },\n\n    /* `volume` will be set to `0` when `--quiet` is specified, and\n     * set to `2` when `--loud` is specified.  if neither is specified,\n     * it will retain its default value of `1`, defined above.\n     */\n    { ADOPT_SWITCH, \"quiet\", 'q', \u0026volume, 0 },\n    { ADOPT_SWITCH, \"loud\", 'l', \u0026volume, 2 },\n\n    /* `channel` will be set to the given argument if an argument is\n     * provided to `--channel`, or will be set to `NULL` if no argument\n     * was specified.\n     */\n    { ADOPT_VALUE, \"channel\", 'c', \u0026channel, NULL },\n\n    /* A double dash (`--`) may be specified to indicate that the parser\n     * should stop treated arguments as possible options and treat\n     * remaining arguments as literal arguments; which allows a user\n     * to specify `--loud` as an actual literal filename (below).\n     */\n    { ADOPT_LITERAL },\n\n    /* `filename` will be set to the first bare argument */\n    { ADOPT_ARG, NULL, 0, \u0026filename1 },\n\n    /* `filename2` will be set to the first bare argument */\n    { ADOPT_ARG, NULL, 0, \u0026filename2 },\n\n    /* End of the specification list. */\n    { 0 },\n};\n```\n\nParsing arguments\n-----------------\n\nThe simplest way to parse arguments is by calling `adopt_parse`.\nThis will parse the arguments given to it, will set the given\n`spec-\u003evalue`s to the appropriate arguments, and will stop and\nreturn an error on any invalid input.  If there are errors, you\ncan display that information with `adopt_status_fprint`.\n\n```c\nint main(int argc, const char **argv)\n{\n    adopt_parser parser;\n    adopt_opt result;\n    const char *value;\n    const char *file;\n    \n    if (adopt_parse(\u0026result, opt_specs, argv + 1, argc - 1, ADOPT_PARSE_DEFAULT) \u003c 0) {\n            adopt_status_fprint(stderr, \u0026opt);\n            adopt_usage_fprint(stderr, argv[0], opt_specs);\n            return 129;\n    }\n}\n```\n\nParsing arguments individually\n-------------------------------\n\nFor more control over your parsing, you may iterate over the\nparser in a loop.  After initializing the parser by calling\n`adopt_parser_init` with the `adopt_spec`s and the command-line\narguments given to your program, you can call `adopt_parser_next`\nin a loop to handle each option.\n   \n```c\nint main(int argc, const char **argv)\n{\n    adopt_parser parser;\n    adopt_opt opt;\n    const char *value;\n    const char *file;\n    \n    adopt_parser_init(\u0026parser, opt_specs, argv + 1, argc - 1);\n    \n    while (adopt_parser_next(\u0026opt, \u0026parser)) {\n        /*\n         * Although regular practice would be to simply let the parser\n         * set the variables for you, there is information about the\n         * parsed argument available in the `opt` struct.  For example,\n         * `opt.spec` will point to the `adopt_spec` that was parsed,\n         * or `NULL` if it did not match a specification.\n         */\n        if (!opt.spec) {\n            fprintf(stderr, \"Unknown option: %s\\n\", opt.arg);\n            return 129;\n        }\n    }\n}\n```\n\nRequired arguments\n------------------\n\nSome value options may require arguments, and it would be an error for\ncallers to omit those.  \n\nThe simplest way to detect unspecified values is to inspect for `NULL`.\nFirst, set a variable to a default value, like with `channel` above.  If\nthe `--channel` option is specified without a value, then `channel` will\nbe set to `NULL` when it is read.  This can be detected either during the\nprocessing loop, or after.  For example:\n\n```c\nif (!channel) {\n    fprintf(stderr, \"Option: %s requires an argument\\n\", opt.arg);\n    return 129;\n}\n```\n\n### Inspecting the `opt` struct\n\nIf you cannot use a sentinal value, perhaps because `NULL` is a useful\nvalue, you can also inspect the `opt` struct.  For example:\n\n```c\nif (opt.spec-\u003evalue == \u0026channel \u0026\u0026 !channel) {\n    fprintf(stderr, \"Option: %s requires an argument\\n\", opt.arg);\n    return 129;\n}\n```\n\nDisplaying usage\n----------------\n\nIf you provide additional usage information in your `adopt_spec`s, you\ncan have adopt print this usage information for you based on the options\nyou accept.  This allows you to define a single structure for both\nargument parsing _and_ help information, which keeps your help in sync\nwith the code automatically.\n\nSimply set the three additional structure members:  `value_name` is the\none-word description of the argument (for options of type `ADOPT_VALUE`),\n`help` is a short description of the option, and `usage` is a set of\nflags that determine whether all or part of the option is required.\n\n(Specifying an option or a value does not affect parsing, it only affects\nhow help is displayed.  If an option or value is not required, its help\nwill display it within square brackets.)\n\nAdding these to the above example:\n\n```c\nadopt_spec opt_specs[] = {\n    /* For bools and switches, you probably only want to set the help.\n     * There is no value to describe, and these are unlikely to be\n     * required.\n     */\n    { ADOPT_BOOL, \"verbose\", 'v', \u0026verbose,\n      NULL, \"Turn on verbose mode\", 0 },\n\n    /* Specifying that an option is an `ADOPT_USAGE_CHOICE` indicates\n     * that it is orthogonal to the previous entry.  These two options\n     * will be rendered together in help output as `[-q|-l]`.\n     */\n    { ADOPT_SWITCH, \"quiet\", 'q', \u0026volume, 0,\n      NULL, \"Emit no output\", 0 },\n    { ADOPT_SWITCH, \"loud\", 'l', \u0026volume, 2 },\n      NULL, \"Emit louder than usual output\", ADOPT_USAGE_CHOICE },\n\n    /* Set the `value_name` and specify that the value is required.\n     * This will be rendered in help output as `-c \u003cchannel\u003e`;\n     * if it was not required, it would be rendered as `-c [\u003cchannel\u003e]`.\n     */\n    { ADOPT_VALUE, \"channel\", 'c', \u0026channel, NULL,\n      \"channel\", \"Set the channel number\", ADOPT_USAGE_VALUE_REQUIRED },\n\n    { ADOPT_LITERAL },\n\n    /* `filename` is required.  It will be rendered in help output as\n     * `\u003cfile1\u003e`.\n     */\n    { ADOPT_ARG, NULL, 0, \u0026filename1, NULL,\n      \"file1\", \"The first filename\", ADOPT_USAGE_REQUIRED },\n\n    /* `filename` is not required.  It will be rendered in help output\n     * as `[\u003cfile2\u003e]`.\n     */\n    { ADOPT_ARG, NULL, 0, \u0026filename2, NULL,\n      \"file2\", \"The second (optional) filename\", 0 },\n\n    /* End of the specification list. */\n    { 0 },\n};\n```\n\nIf you call `adopt_usage_fprint` with the above specifications, it will emit:\n\n```\nusage: ./example [-v] [-q] [-l] [-c \u003cchannel\u003e] -- \u003cfile1\u003e [\u003cfile2\u003e]\n```\n\nInclusion in your product\n-------------------------\n\nIf you loathe additional namespaces, and want to use adopt inside your\nproduct without using the `adopt_` prefix, you can use the included\n`rename.pl` script to give the functions and structs your own prefix.\n\nFor example:\n\n```bash\n% ./rename.pl ed_opt\n```\n\nWill product `ed_opt.c` and `ed_opt.h` that can be included in an\napplication, with the variables renamed to `ed_opt` (instead of `adopt`)\nand enum names renamed to `ED_OPT` (instead of `ADOPT`).\n\nOr simply:\n\n```bash\n% ./rename.pl opt\n```\n\nTo produce `opt.c` and `opt.h`, with variables prefixed with `opt`.\n\nAbout Adopt\n-----------\nAdopt was written by Edward Thomson \u003cethomson@edwardthomson.com\u003e\nand is available under the MIT License.  Please see the\nincluded file `LICENSE` for more information.\n\nAdopt takes its name from the only entry in `/usr/dict/words`\nthat ends in the letters **opt**.  But if you happen to like adopt,\nconsider a donation to your local pet shelter or human society.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethomson%2Fadopt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fethomson%2Fadopt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethomson%2Fadopt/lists"}