{"id":25882865,"url":"https://github.com/dax89/cl","last_synced_at":"2025-03-02T16:19:23.835Z","repository":{"id":205669309,"uuid":"714797331","full_name":"Dax89/cl","owner":"Dax89","description":"Easy command line parsing with EDSL","archived":false,"fork":false,"pushed_at":"2024-01-08T18:39:53.000Z","size":37,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-01-08T20:09:49.727Z","etag":null,"topics":["argument-parser","c-plus-plus","cli-parser","cpp17","header-only","mit-license","no-dependencies","option-parser","positional-arguments"],"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/Dax89.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}},"created_at":"2023-11-05T20:45:30.000Z","updated_at":"2023-11-12T11:20:43.000Z","dependencies_parsed_at":"2023-11-11T19:31:24.631Z","dependency_job_id":"7fc72523-895b-4426-9ef0-581edbde0cf4","html_url":"https://github.com/Dax89/cl","commit_stats":null,"previous_names":["dax89/cl"],"tags_count":2,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dax89%2Fcl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dax89%2Fcl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dax89%2Fcl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dax89%2Fcl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dax89","download_url":"https://codeload.github.com/Dax89/cl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241533995,"owners_count":19977893,"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":["argument-parser","c-plus-plus","cli-parser","cpp17","header-only","mit-license","no-dependencies","option-parser","positional-arguments"],"created_at":"2025-03-02T16:19:23.447Z","updated_at":"2025-03-02T16:19:23.827Z","avatar_url":"https://github.com/Dax89.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"CL: Command Line parsing for C++\n-----\n\nCL is a C++17 single header library that provides an Embedded Domain Specific Language (EDSL) by exploiting C++ features for command line argument parsing.\u003cbr\u003e\nNo regex, grammars, lexers and parsers required!\n\nQuick Start\n-----\n\n```cpp\n#include \u003ccl/cl.h\u003e\n\nint main(int argc, char** argv[]) {\n    // Needed later for _p operator\n    using namespace cl::string_literals;\n\n    // Set some application info (optional)\n    cl::set_program(\"cl_app\");\n    cl::set_name(\"CL Application\");\n    cl::set_description(\"CL App Description\");\n    cl::set_version(\"1.0\");\n\n    // Define options (needed if you use options later)\n    cl::Options{\n        cl::opt(\"o1\", \"opt1\", \"I'm the option 1\"),\n        cl::opt(\"o2\", \"opt2\", \"I'm the option 2\"),\n        cl::opt(\"o3\", \"opt3\"_o, \"I'm the option 3\"),\n    };\n\n    // Create parsing rules (for options, the short name can also be used)\n    cl::Usage{\n      cl::cmd(\"command1\", \"pos1\", *\"pos2\"_p, --\"opt1\"_p, *--\"opt2\"_p),\n      cl::cmd(\"command2\", \"pos1\", \"pos2\"_p, --\"opt1\"_p, --\"opt2\"_p),\n      cl::cmd(\"command3\", \"pos1\", cl::one(\"val1\", \"val2\", \"val3\")),\n      cl::cmd(\"command4\", \"pos1\", *cl::one(\"val1\", \"val2\", \"val3\"), *--\"opt3\"_p),\n      cl::cmd(\"command5\"_a, \"pos1\"),\n      cl::cmd(\"command6\"_a)\n      \n    };\n\n    cl::Args args = cl::parse(argc, argv);\n    // ... parse 'args'\n    return 0;\n}\n```\n\n* `cl::Options`: defines a list of command line options, they are shared between all rules (if you only need positional arguments you can skip this step).\n* `cl::Usage`: this is the most important statement, here we define the rules needed to parse command line arguments (positionals, options, optional arguments, etc)\n* String literal operators adds some sugar to the code, here is their meaning:\n  * `_p` creates a `cl::Param` object (more info below)\n    * `_a` creates an 'any-type' command (more info below)\n  * `_o` create a _k=v_ option, if you don't pass this operator, options are just flags (_true/false_ boolean)\n* The operator `_p` create a `cl::Param` that overloads some C++ operators, these are their meaning:\n  * `--\"myarg\"_p` creates a **required option**.\n  * if the `*` is present the argument/option becomes optional (eg. `*\"pos\"_p`, `*--\"opt\"_p`)\n* The operator `_a` allows any command to be passed (these rules are quite permissive: add them at the end of usage list)\n* `cl::one(\"a\", \"b\", \"c\", ...)`: is for positional arguments where only one of the provided values are valid (by adding a `*` makes this argument optional)\n\nHelp is autogenerated, for the sample code above.\u003cbr\u003e\n**NOTE:** `cl_app --help` and `cl_app --version` are builtin.\n```\nCL App 1.0\nApp Description\n\nUsage:\n  cl_app command1 \u003cpos1\u003e [pos2] --opt1 [--opt2]\n  cl_app command2 \u003cpos1\u003e \u003cpos2\u003e --opt1 --opt2\n  cl_app command3 \u003cpos1\u003e (val1|val2|val3)\n  cl_app command4 \u003cpos1\u003e [(val1|val2|val3)] [--opt3=ARG]\n  cl_app {command5} \u003cpos1\u003e\n  cl_app {command6} \u003cpos1\u003e\n  cl_app --version\n  cl_app --help\n\nOptions:\n  -h  --help         Show this screen\n  -v  --version      Show version\n  -o1 --opt1         I'm the option 1\n  -o2 --opt2         I'm the option 2\n  -o3 --opt3=ARG     I'm the option 3\n```\n\nExtract argument information (explained)\n-----\nThis part is inspired by [docopt.cpp](https://github.com/docopt/docopt.cpp).\u003cbr\u003e\nCalling `cl::parse()` function returns a `cl::Args` object, which is simply an `std::unordered_map\u003cstd::string_view, cl::Value\u003e`\u003cbr\u003e\nHere are some examples:\n\nCase 1\n-------\ncl_app called as `cl_app command4 val1 val2`\n\n```ruby\nopt3 = null\ncommand1 = false\npos1 = \"arg1\"          # The 1st positional argument for this command\npos2 = null\ncommand2 = false\ncommand3 = false\nopt2 = false\nval1 = false\nval2 = true            # We have selected 'val2' for cl::one() param\nval3 = false\ncommand4 = \"command4\"  # We called this command\ncommand5 = false\ncommand6 = false\nhelp = false\nversion = false\nopt1 = false\n```\n\nCase 2\n-------\ncl_app called as `cl_app command2 arg1 arg2 -o1 --opt2`\n\n```ruby\nopt3 = null\ncommand1 = false\npos1 = \"arg1\"          # The 1st positional argument for this command\npos2 = \"arg2\"          # The 2nd positional argument for this command\ncommand2 = \"command2\"  # We called this command\ncommand3 = false\nopt2 = true            # opt2 is set\nval1 = false\nval2 = false\nval3 = false\ncommand4 = false\ncommand5 = false\ncommand6 = false\nhelp = false\nversion = false\nopt1 = true            # opt1 is set\n```\n\nExtract argument information (C++ code)\n----\nIn C++ the code looks like this:\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003ccl/cl.h\u003e\n\nint main(int argc, char** argv[]) {\n    //... create rules \u0026 options\n\n    cl::Args args = cl::parse(argc, argv);\n\n    if(args[\"command2\"]) {\n        std::cout \u003c\u003c \"Called command2\" \u003c\u003c std::endl;\n        std::cout \u003c\u003c \"Positionals: \" \u003c\u003c args[\"pos1\"] \u003c\u003c \", \" \u003c\u003c args[\"pos2\"] \u003c\u003c std::endl;\n        std::cout \u003c\u003c \"Options: \" \u003c\u003c args[\"opt1\"] \u003c\u003c \", \" \u003c\u003c args[\"opt2\"] \u003c\u003c std::endl;\n    }\n    else if(args[\"command4\"]) {\n        std::cout \u003c\u003c \"Called command4\" \u003c\u003c std::endl;\n        std::cout \u003c\u003c \"Positionals: \" \u003c\u003c args[\"pos1\"] \u003c\u003c std::endl;\n\n      if(args[\"val2\"].to_bool() == true)\n          std::cout \u003c\u003c \"Val2 is set\" \u003c\u003c std::endl;\n      else\n          std::cout \u003c\u003c \"Val2 is NOT set\" \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdax89%2Fcl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdax89%2Fcl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdax89%2Fcl/lists"}