{"id":26633623,"url":"https://github.com/ahajha/cli151","last_synced_at":"2025-03-24T15:15:52.741Z","repository":{"id":255964457,"uuid":"851290106","full_name":"Ahajha/cli151","owner":"Ahajha","description":"A C++20 reflection based CLI parsing library with parser built at compile time ","archived":false,"fork":false,"pushed_at":"2024-10-19T04:38:48.000Z","size":101,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-19T06:21:11.664Z","etag":null,"topics":["cli","compile-time","compile-time-reflection","exceptionless","no-dynamic-allocations","parser"],"latest_commit_sha":null,"homepage":"","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/Ahajha.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":"2024-09-02T20:01:25.000Z","updated_at":"2024-10-04T03:38:58.000Z","dependencies_parsed_at":"2024-09-08T06:37:44.007Z","dependency_job_id":"d6c90343-15e0-4a43-ad40-c0422dc808b4","html_url":"https://github.com/Ahajha/cli151","commit_stats":null,"previous_names":["ahajha/cli151"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahajha%2Fcli151","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahajha%2Fcli151/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahajha%2Fcli151/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ahajha%2Fcli151/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ahajha","download_url":"https://codeload.github.com/Ahajha/cli151/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245294719,"owners_count":20591909,"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":["cli","compile-time","compile-time-reflection","exceptionless","no-dynamic-allocations","parser"],"created_at":"2025-03-24T15:15:52.177Z","updated_at":"2025-03-24T15:15:52.699Z","avatar_url":"https://github.com/Ahajha.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CLI151\n\nA header-only C++20 library for constructing CLI parsers at compile time. CLI151 supports reflection of field names, has no dynamic memory allocation, and works without exceptions.\n\nCLI151 is still early in development, but actively worked on. Expect bugs, but also expect issues to be responded to.\n\n## How to use\n\n```c++\n#include \u003ccli151/cli151.hpp\u003e\nnamespace cli = cli151;\n\n#include \u003coptional\u003e\n#include \u003cstring_view\u003e\n\n// Define the struct\nstruct mycli\n{\n    int number;\n    std::optional\u003cstd::string_view\u003e author;\n    bool cool_flag = false;\n};\n\n// Define the meta information\ntemplate \u003c\u003e\nstruct cli::meta\u003cmycli\u003e\n{\n    using T = mycli;\n    constexpr static auto value = args{\n        // Anything up to the first std::optional or bool is positional and required\n        \u0026T::number,\n        // From the first std::optional or bool onward, the options are keyword and optional\n        \u0026T::author,\n        \u0026T::cool_flag,\n    };\n    // The order is not required to be the same as in the struct, but it is generally assumed they are.\n};\n\n// Parse\nint main(int argc, char* argv[])\n{\n    // Returns a cli151::expected\u003cmycli\u003e\n    const auto result = cli::parse\u003cmycli\u003e(argc, argv);\n\n    if (result)\n    {\n        const auto [number, author, cool_flag] = result.value();\n\n        // Use the result\n    }\n    else\n    {\n        // Error!\n    }\n}\n```\n\nThere also exists a convenience macro in a separate header. The following is an equivalent way to define the meta information (T is automatically added as an alias to the given type):\n\n```c++\n#include \u003ccli151/macros.hpp\u003e\n\nCLI151_CLI(mycli, \u0026T::number, \u0026T::author, \u0026T::cool_flag)\n```\n\nPass the arguments as:\n`./program 123 --author Ahajha --cool-flag`\n- `cool_flag` is flipped when specified\n- Note that underscores are converted to hyphens in field names\n\nIt also supports short keywords:\n`./program 123 -a Ahajha -c`\n\nSupports out of order args:\n`./program -a Ahajha 123 -c`\n\nOptional args aren't necessary:\n`./program 123`\n- `cool_flag` is kept as the default, author is `std::nullopt`\n\nArgs can also be specified with `=`\n`./program 123 --author=Ahajha`\n`./program 123 -a=Ahajha`\n\n## Notes\n\n- Prefer `std::string_view` (or `const char*`) over `std::string` in your cli structs, unless you plan to do additional modifications to the argument after parsing. If using these types, they will reference the contents of `argv` directly, with no intermediate allocations.\n\n## Including in your project\n\nWork in progress - Future goals are to directly support FetchContent and Conan.\n\n## Compiler support\n\nGCC 10+\nClang 10+ (with libstdc++ or libc++)\nMSVC 2019+\nApple clang 13+ (12 _might_ work, but is untested)\n\n## Advanced usage\n\nAdditional information for each field can be given:\n```c++\ntemplate \u003c\u003e\nstruct cli::meta\u003cmycli\u003e\n{\n    using T = mycli;\n    constexpr static auto value = args{\n        // Member pointers and `arg` structs can be mixed and matched\n        \u0026T::number,\n        \u0026T::author,\n        arg{\u0026T::cool_flag, { // Note that this is a substruct\n            // Help text\n            .help = \"This program is really cool if you pass this in!\",\n            // Short name - by default is the first letter of arg_name\n            // (which in turn defaults to the field name).\n            .abbr = \"f\",\n            // Override the field name, also note that this overrides the underscore-to-hyphen conversion.\n            .arg_name = \"really_cool_flag\",\n        }},\n    };\n};\n```\n`abbr` and `arg_name` can be set to `\"\"` to disable it, this is useful if you want a keyword arg that only accepts a long or short form, for example allowing `--cool-flag` but disallowing `-c`.\n\n## Troubleshooting\n\nIf you're getting cryptic template errors about constexpr recursion depth, it's likely you have duplicate short field names. See [frozen's troubleshooting guide](https://github.com/serge-sans-paille/frozen?tab=readme-ov-file#troubleshooting).\n\nFor example, the struct\n```c++\nstruct mycli\n{\n    std::string_view name;\n    int number;\n};\n```\nwould cause this error since both fields abbreviate to `-n`.\n\n## Dependencies\n\n- `frozen` for compile time hash maps\n- `tl::expected` when `std::expected` isn't available (either if the compiler doesn't support it or if in C++20 mode)\n- `fast_float` when `std::from_chars` isn't available\n- `fmt` when `std::format` or `std::print(ln)` isn't available (either if the compiler doesn't support it or if in C++20 mode)\n- `doctest` for unit tests\n\n## Inspirations\n\n- [structopt](https://github.com/p-ranav/structopt) - For the idea of specifying CLI information declaratively rather than constructing a parser iteratively.\n- [glaze](https://github.com/stephenberry/glaze) - For the idea of using `meta` structs to add information about a struct at compile time.\n- [reflect-cpp](https://github.com/getml/reflect-cpp) - For the idea of how to implement compile time reflection of field names from member function pointers.\n\n## Future plans\n\n- Supporting more types (tuple, vector, set, map, array, enums(!), etc.)\n- Autogenerated help text\n- Compile time, runtime, and memory footprint improvements benchmarks (A cli parser doesn't _need_ to be fast, but why not?)\n- More convenience functions and macros\n- More configuration options\n- Testing, testing, testing\n- Likely more to come!\n\nContributions are welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahajha%2Fcli151","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fahajha%2Fcli151","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahajha%2Fcli151/lists"}