{"id":20355899,"url":"https://github.com/hedzr/cmdr-cxx","last_synced_at":"2025-08-25T01:34:16.848Z","repository":{"id":45788330,"uuid":"335521944","full_name":"hedzr/cmdr-cxx","owner":"hedzr","description":"cmdr cxx version, a C++17/20 header-only command-line parser with hierarchical config data manager here","archived":false,"fork":false,"pushed_at":"2025-07-24T08:18:14.000Z","size":1684,"stargazers_count":17,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-24T12:00:53.134Z","etag":null,"topics":["argument-parser","argument-parsing","cli","cmdr","cmdr-cxx","command-line","command-line-interface","command-line-parser","cxx17","cxx20","hierarchical-data","jaro-winkler-distance","parser","posix-compliant"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hedzr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":"https://paypal.me/hezr/5"}},"created_at":"2021-02-03T05:51:54.000Z","updated_at":"2025-07-24T08:18:14.000Z","dependencies_parsed_at":"2025-07-24T10:20:22.574Z","dependency_job_id":null,"html_url":"https://github.com/hedzr/cmdr-cxx","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/hedzr/cmdr-cxx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr-cxx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr-cxx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr-cxx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr-cxx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hedzr","download_url":"https://codeload.github.com/hedzr/cmdr-cxx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hedzr%2Fcmdr-cxx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271991288,"owners_count":24854746,"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","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","argument-parsing","cli","cmdr","cmdr-cxx","command-line","command-line-interface","command-line-parser","cxx17","cxx20","hierarchical-data","jaro-winkler-distance","parser","posix-compliant"],"created_at":"2024-11-14T23:14:25.925Z","updated_at":"2025-08-25T01:34:16.842Z","avatar_url":"https://github.com/hedzr.png","language":"C++","funding_links":["https://paypal.me/hezr/5"],"categories":[],"sub_categories":[],"readme":"# cmdr-cxx {#mainpage}\n\n![CMake Build Matrix](https://github.com/hedzr/cmdr-cxx/workflows/CMake%20Build%20Matrix/badge.svg) \u003c!-- \n![CMake Build Matrix](https://github.com/hedzr/cmdr-cxx/workflows/CMake%20Build%20Matrix/badge.svg?event=release) \n--\u003e [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/hedzr/cmdr-cxx.svg?label=release)](https://github.com/hedzr/cmdr-cxx/releases)\n\n`cmdr-cxx` is a C++17/20 *header-only* command-line arguments parser, config manager, and application\nframework. As a member of [#cmdr series](https://github.com/topics/cmdr), it provides a\nfully-functional `Option Store` (Configuration Manager) for your hierarchical configuration data.\n\nSee also golang version: [cmdr](https://github.com/hedzr/cmdr).\n\n![cover](https://user-images.githubusercontent.com/12786150/108625941-8fb04400-7488-11eb-8403-afc79825745c.png)\n\n## Features\n\n- POSIX-Compliant command-line argument parser\n\n  - supports long flag (REQUIRED, `--help`, short flag (`-h`), and aliases (`--usage`, `--info`, ...)\n  - supports multi-level sub-commands\n  - supports short flag compat: `-vab` == `-v -a -b`, `-r3ap1zq` == `-r 3 -ap 1 -z -q`\n  - supports passthrough flag: `--` will terminate the parsing\n  - supports lots of data types for a flag: bool, int, uint, float, string, array, chrono duration, ...\n    - allows user-custom data types\n  - automated help-screen printing (*`-hhh` to print the hidden items*)\n\n- Robust Interfaces\n\n  - Hooks or Actions:\n\n    - global: pre/post-invoke\n    - flags: on_hit\n    - commands: on_hit, pre/post-invoke, invoke\n\n  - Supports non-single-char short flag: `-ap 1`\n\n  - Supports for `-D+`, `-D-` to enable/disable a bool option\n\n  - Supports sortable command/flag groups\n\n  - Supports toggleable flags - just like a radio button group\n\n  - Free style flags arrangements: `$ app main sub4 bug-bug2 zero-sub3 -vqb2r1798b2r 234 --sub4-retry1 913 --bug-bug2-shell-name=fish ~~debug --int 67 -DDD --string 'must-be' --long 789`\n\n  - Smart suggestions for wrong command and flags\n\n    based on [Jaro-Winkler distance](https://en.wikipedia.org/wiki/Jaro–Winkler_distance). See [Snapshot](https://github.com/hedzr/cmdr-cxx/issues/1)\n\n  - Builtin commands and flags\n\n    - Help: `-h`, `-?`, `--help`, `--info`, `--usage`, ...\n      - `help` command: `app help server pause` == `app server pause --help`.\n    - Version \u0026 Build Info: `--version`/`--ver`/`-V`, `--build-info`/`-#`\n    - `version`/`versions` command available.\n    - Simulating version at runtime with `—-version-sim 1.9.1`\n\n  - `~~tree`: lists all commands and sub-commands.\n\n    - `~~debug`: print the debugging info\n    - `--no-color`: disable terminal color in outputting\n    - `--config \u003clocation\u003e`: specify the location of the root config file. [only for yaml-loader]\n\n  - Verbose \u0026 Debug: `—verbose`/`-v`, `—debug`/`-D`, `—quiet`/`-q`\n\n  - Supports `-I/usr/include -I=/usr/include` `-I /usr/include -I:/usr` option argument specifications Automatically allows those formats (applied to long option too):\n\n    - `-I file`, `-Ifile`, and `-I=files`\n    - `-I 'file'`, `-I'file'`, and `-I='files'`\n    - `-I \"file\"`, `-I\"file\"`, and `-I=\"files\"`\n\n  - Envvars overrides: `HELP=1 ./bin/test-app2-c2 server pause` is the equivalent of `./bin/test-app2-c2 server pause --help`\n\n  - Extensible external loaders: `cli.set_global_on_loading_externals(...);`\n\n  - Extending internal actions for special operations auch as printing help screen...\n\n- Hierarchical Data Manager - `Option Store`\n\n  - various data types supports\n  - accusing the item with its dotted path key (such as `server.tls.certs.cert-bundle`)\n  - See also [Fast Doc](#fast-document) section.\n\n## Status / History / CHANGELOGs\n\n- See [CHANGELOG](https://github.com/hedzr/cmdr-cxx/blob/master/CHANGELOG)\n\n### CXX 17/20 Compilers\n\n- gcc 10+: passed\n- clang 12+: passed\n- msvc build tool:\n  - 17.2.32505.173 (VS2022 or Build Tool) passed\n  - OLD: 16.7.2, 16.8.5 (VS2019 or Build Tool) passed\n  - NEW: VS2022 passed\n\n\n### Snapshots\n\n`cmdr-cxx` prints an evident, clear, and logical help-screen. Please proceed the more snapshots\nat [#1 - Gallery](https://github.com/hedzr/cmdr-cxx/issues/1).\n\n### Bonus\n\n- golang: [cmdr](https://github.com/hedzr/cmdr)\n- .netCore: [Cmdr.Core](https://github.com/hedzr/Cmdr.Core)\n\n\n\n\n\n## Usages\n\n\n### Local Deployment\n\n#### Homebrew\n\ncmdr-cxx can be installed from homebrew:\n\n```bash\nbrew install hedzr/brew/cmdr-cxx\n```\n\n#### CMake Standard\n\ncmdr-cxx is findable via CMake Modules.\n\nYou could install cmdr-cxx manually:\n\n```bash\ngit clone https://github.com/hedzr/cmdr-cxx.git\ncd cmdr-cxx\ncmake -DCMAKE_VERBOSE_DEBUG=ON -DCMAKE_AUTOMATE_TESTS=OFF -S . -B build/ -G Ninja\n# Or:\n#    cmake -S . -B build/\ncmake --build build/\ncmake --install build/\n# Or:\n#   cmake --build build/ --target install\n#\n# Sometimes sudo it:\n#   sudo cmake --build build/ --target install\n# Or:\n#   cmake --install build/ --prefix ./dist/install --strip\n#   sudo cp -R ./dist/install/include/* /usr/local/include/\n#   sudo cp -R ./dist/install/lib/cmake/cmdr11 /usr/local/lib/cmake/\n#\n# macOS users could install to Homebrew directly without super privilidges:\n#   cmake --install build/ --prefix $(brew --prefix) --strip\n#\nrm -rf ./build\ncd ..\n```\n\nMore cmake commands:\n\n```bash\n# clean (all targets files, but the immedieted files)\ncmake --build build/ --target clean\n# clean and build (just relinking all targets without recompiling)\ncmake --build build/ --clean-first\n\n# clean deeply\nrm -rf build/\n\n# clean deeply since cmake 3.24.0\n# (your custom settings from command-line will lost.\n#   For example, if you ever run `cmake -DCMAKE_VERBOSE_DEBUG=ON -S . -B build',\n#   and now cmake --fresh -B build/ will ignore `CMAKE_VERBOSE_DEBUG = ON' \n#   and reconfigure to default state.\n# )\ncmake --fresh -B build/\n\n# recompiling and relinking (simply passing `-B' to `make')\ncmake --build build/ -- -B\n\n# reconfigure\nrm ./build/CMakeCache.txt \u0026\u0026 cmake -DENABLE_AUTOMATE_TESTS=OFF -S . -B build/\n\n# print compiling command before exeuting them\ncmake --build build/ -- VERBOSE=1\n# Or:\nVERBOSE=1 cmake --build build/\n# Or:\ncmake --build build --verbose\n```\n\n##### dependencies\n\nTo build cmdr-cxx, please install these components at first:\n\n- yaml-cpp\n\nThe typical install command could be `brew install yaml-cpp`,\nFor more information, please refer to the chapter [Others](#others).\n\n\u003e It can be disabled by `CMDR_NO_3RDPARTY` while building cmdr-cxx:\n\u003e\n\u003e ```bash\n\u003e cmake -DCMDR_NO_3RDPARTY:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=Release -S . -B build-release/\n\u003e ```\n\n#### CMake ExternalProject\n\nAdding cmdr11 with `ExternalProject` is possible. A `load-cmdr-cxx.cmake` was provided to make integrating `cmdr-cxx` easier.\n\nExtract `cmake/load-cmdr-cxx.cmake` into your project, load it and use `add-cmdr-cxx-to` macro. For example, your cli-app could be:\n\n```cmake\n#\tdefine_cxx_executable_target(myapp\n# \t\tPREFIX myapp\n# \t\tLIBRARIES ${myapp_libs}\n# \t\tSOURCES ${myapp_source_files}\n# \t\tINCLUDE_DIRECTORIES ${myapp_INCDIR}\n#\t)\n#\tenable_version_increaser(myapp-cli myapp my MY_)\n\nproject(cmdr-cli-demo)\nadd_executable(${PROJECT_NAME} cmdr_main.cc)\ntarget_include_directories(${PROJECT_NAME} PRIVATE\n\t$\u003cBUILD_INTERFACE:${CMAKE_GENERATED_DIR}\u003e\n)\n\ninclude(load-cmdr-cxx)   # load ME here.\nadd_cmdr_cxx_to(myapp)   # attach cmdr11::cmdr11\n```\n\nIt works.\n\n### Integrate to your cmake script\n\nAfter installed at local cmake repository (Modules), `cmdr-cxx` can be integrated as your CMake module. So we might find\nand use it:\n\n```cmake\nfind_package(cmdr11 REQUIRED)\n\nadd_executable(my-app)\ntarget_link_libraries(my-app PRIVATE cmdr11::cmdr11)\nset_target_properties(${PROJECT_NAME}  PROPERTIES\n    CXX_STANDARD 20\n    CXX_STANDARD_REQUIRED ON\n    CXX_EXTENSIONS ON\n    )\n```\n\nOr you can download [load-cmdr-cxx.cmake](https://github.com/hedzr/cmdr-cxx/blob/master/cmake/load-cmdr-cxx.cmake) and\ninclude it:\n\n```cmake\nadd_executable(my-app)\n\ninclude(deps-cmdr11)     # put deps-cmdr11.cmake into your cmake module path at first\nadd_cmdr_cxx_to(my-app)\n```\n\n\n\n\n\n### Short example\n\n```cpp\n#include \u003ccmdr11/cmdr11.hh\u003e\n#include \"version.h\" // xVERSION_STRING\n\nint main(int argc, char *argv[]) {\n\n  auto \u0026cli = cmdr::cli(\"app2\", xVERSION_STRING, \"hedzr\",\n                        \"Copyright © 2021 by hedzr, All Rights Reserved.\",\n                        \"A demo app for cmdr-cxx library.\",\n                        \"$ ~ --help\");\n\n  try {\n    using namespace cmdr::opt;\n\n    cli += sub_cmd{}(\"server\", \"s\", \"svr\")\n      .description(\"server operations for listening\")\n      .group(\"TCP/UDP/Unix\");\n    {\n      auto \u0026t1 = *cli.last_added_command();\n\n      t1 += opt{(int16_t)(8)}(\"retry\", \"r\")\n      .description(\"set the retry times\");\n\n      t1 += opt{(uint64_t) 2}(\"count\", \"c\")\n      .description(\"set counter value\");\n\n      t1 += opt{\"localhost\"}(\"host\", \"H\", \"hostname\", \"server-name\")\n      .description(\"hostname or ip address\")\n        .group(\"TCP\")\n        .placeholder(\"HOST[:IP]\")\n        .env_vars(\"HOST\");\n\n      t1 += opt{(int16_t) 4567}(\"port\", \"p\")\n      .description(\"listening port number\")\n        .group(\"TCP\")\n        .placeholder(\"PORT\")\n        .env_vars(\"PORT\", \"SERVER_PORT\");\n\n      t1 += sub_cmd{}(\"start\", \"s\", \"startup\", \"run\")\n      .description(\"start the server as a daemon service, or run it at foreground\")\n        .on_invoke([](cmdr::opt::cmd const \u0026c, string_array const \u0026remain_args) -\u003e int {\n          UNUSED(c, remain_args);\n          std::cout \u003c\u003c c.title() \u003c\u003c \" invoked.\\n\";\n          return 0;\n        });\n      auto \u0026s1 = *t1.last_added_command();\n      s1 += cmdr::opt::opt{}(\"foreground\", \"f\")\n      .description(\"run at fg\");\n\n      t1 += sub_cmd{}(\"stop\", \"t\", \"shutdown\")\n      .description(\"stop the daemon service, or stop the server\");\n\n      t1 += sub_cmd{}(\"pause\", \"p\")\n      .description(\"pause the daemon service\");\n\n      t1 += sub_cmd{}(\"resume\", \"re\")\n      .description(\"resume the paused daemon service\");\n      t1 += sub_cmd{}(\"reload\", \"r\")\n      .description(\"reload the daemon service\");\n      t1 += sub_cmd{}(\"hot-reload\", \"hr\")\n      .description(\"hot-reload the daemon service without stopping the process\");\n      t1 += sub_cmd{}(\"status\", \"st\", \"info\", \"details\")\n      .description(\"display the running status of the daemon service\");\n    }\n\n  } catch (std::exception \u0026e) {\n    std::cerr \u003c\u003c \"Exception caught for duplicated cmds/args: \" \u003c\u003c e.what() \u003c\u003c '\\n';\n    CMDR_DUMP_STACK_TRACE(e);\n  }\n\n  return cli.run(argc, argv);\n}\n```\n\nIt is a simple program.\n\n\n\n## Fast Document\n\n\n\n### Lookup a command and its flags\n\nThe operator `()` (`cli(\"cmd1.sub-cmd2.sub-sub-cmd\")` ) could be used for retrieving a command (`cmdr::opt::cmd\u0026 cc`)\nfrom `cli`:\n\n```cpp\nauto \u0026cc = cli(\"server\");\nCMDR_ASSERT(cc.valid());\nCMDR_ASSERT(cc[\"count\"].valid());     // the flag of 'server'\nCMDR_ASSERT(cc[\"host\"].valid());\nCMDR_ASSERT(cc(\"status\").valid());    // the sub-command of 'server'\nCMDR_ASSERT(cc(\"start\").valid());     // sub-command: 'start'\nCMDR_ASSERT(cc(\"run\", true).valid()); // or alias: 'run'\n```\n\nOnce `cc` is valid, use `[]` to extract its flags.\n\nThe dotted key is allowed. For example: `cc[\"start.port\"].valid()`.\n\n```cpp\nCMDR_ASSERT(cli(\"server.start\").valid());\nCMDR_ASSERT(cli(\"server.start.port\").valid());\n\n// get flag 'port' of command 'server.start':\nCMDR_ASSERT(cc[\"start.port\"].valid());\n```\n\n\n\n\n\n### Extract the matched information of a flag\n\nWhile a flag given from command-line is matched ok, it holds some hit info. Such as:\n\n```cpp\nauto \u0026cc = cli(\"server\");  // get 'server' command object\nCMDR_ASSERT(cc.valid());   // got ok?\n\nCMDR_ASSERT(cc[\"count\"].valid());\nCMDR_ASSERT(cc[\"count\"].hit_long()); \t          // if `--count` given\nCMDR_ASSERT(cc[\"count\"].hit_long() == false); \t// if `-c` given\nCMDR_ASSERT(cc[\"count\"].hit_count() == 1);     \t// if `--count` given\nCMDR_ASSERT(cc[\"count\"].hit_title() == \"c\");   \t// if `-c` given\n\nCMDR_ASSERT(cli[\"verbose\"].hit_count() == 3);   // if `-vvv` given\n\n// hit_xxx are available for a command too\nCMDR_ASSERT(cc.hit_title() == \"server\");        // if 'server' command given\n\n```\n\nThe value of a flag from command-line will be saved into `Option Store`, and extracted by shortcut `cmdr::get_for_cli()`\n. For example:\n\n```cpp\nauto verbose = cmdr::get_for_cli\u003cbool\u003e(\"verbose\");\nauto hostname = cmdr::get_for_cli\u003cstd::string\u003e(\"server.host\");\n```\n\nIn `Option Store`, the flag value will be prefixed by `\"app.cli.\"`, and get_for_cli wraps transparently.\n\n\u003e The normal entries in `Options Store` are prefixed by string `\"app.\"`. You could define another one of course.\n\nTo extract the normal configuration data, `cmdr::set` and `cmdr::get` are best choices. They will wrap and unwrap the\nprefix `app` transparently.\n\n```cpp\nauto verbose = cmdr::get\u003cbool\u003e(\"cli.verbose\");\nauto hostname = cmdr::get\u003cstd::string\u003e(\"cli.server.host\");\n```\n\nIf you wanna extract them directly:\n\n```cpp\nauto verbose = cmdr::get_store().get_raw\u003cbool\u003e(\"app.cli.verbose\");\nauto hostname = cmdr::get_store().get_raw\u003cstd::string\u003e(\"app.cli.server.host\");\n\nauto verbose = cmdr::get_store().get_raw_p\u003cbool\u003e(\"app.cli\", \"verbose\");\nauto hostname = cmdr::get_store().get_raw_p\u003cstd::string\u003e(\"app.cli\", \"server.host\");\n```\n\n\n\n### Set the value of a config item\n\nEvery entry in `Option Store` that we call it a config item. The entries are hierarchical. So we locate it with a dotted\nkey path string.\n\nA config item is free for data type dynamically. That is saying, you could change the data type of a item at runtime.\nSuch as setting one entry to integer array, from integer originally.\n\n\u003e But it is hard for coding while you're working for a c++ program.\n\n```cpp\ncmdr::set(\"wudao.count\", 1);\ncmdr::set(\"wudao.string\", \"str\");\ncmdr::set(\"wudao.float\", 3.14f);\ncmdr::set(\"wudao.double\", 2.7183);\ncmdr::set(\"wudao.array\", std::vector{\"a\", \"b\", \"c\"});\ncmdr::set(\"wudao.bool\", false);\n\nstd::cout \u003c\u003c cmdr::get\u003cint\u003e(\"wudao.count\") \u003c\u003c '\\n';\nauto const \u0026aa = cmdr::get\u003c std::vector\u003cchar const*\u003e \u003e(\"wudao.array\");\nstd::cout \u003c\u003c cmdr::string::join(aa, \", \", \"[\", \"]\") \u003c\u003c '\\n';\n\n// Or: maybe you will like to stream out a `variable` with standard format.\ncmdr::vars::variable\u0026 ab = cmdr::get_app().get(\"wudao.array\");\nstd::cout \u003c\u003c ab \u003c\u003c '\\n';\n```\n\n\n\n### `cmdr::vars::variable`\n\n`cmdr-cxx` provides stream-io on lots of types via `cmdr::vars::variable`, take a look for further.\n\n\n\n### Bundled Utilities or Helpers\n\nThere are some common cross-platform helper classes. Its can be found in these headers:\n\n- cmdr_defs.hh\n\n- cmdr_types.hh\n\n- cmdr_type_checks.hh\n\n- cmdr_utils.hh\n\n---\n\n- cmdr_dbg.hh\n\n- cmdr_log.gg\n\n---\n\n- cmdr_chrono.hh\n\n- cmdr_if.hh\n\n- cmdr_ios.hh\n\n- cmdr_mmap.hh\n\n- cmdr_os_io_redirect.hh\n\n- cmdr_path.hh\n\n- cmdr_process.hh\n\n- cmdr_pool.hh\n\n- cmdr_priority_queue.hh\n\n- cmdr_string.hh\n\n- cmdr_terminal.hh\n\n\n\n\n\n## Features to improve your app arch\n\n`cmdr-cxx` provides some debugging features or top view to improve you design at CLI-side.\n\n### Default Action\n\nWe've been told that we can bind an action (via `on_invoke`) to a (sub-)command:\n\n```cpp\nt1 += sub_cmd{}(\"start\", \"s\", \"startup\", \"run\")\n  .description(\"start the server as a daemon service, or run it at foreground\")\n  .on_invoke([](cmdr::opt::cmd const \u0026c, string_array const \u0026remain_args) -\u003e int {\n    UNUSED(c, remain_args);\n    std::cout \u003c\u003c c.title() \u003c\u003c \" invoked.\\n\";\n    return 0;\n  });\n```\n\nFor those commands without binding to `on_invoke`, `cmdr-cxx` will invoke a default one, For example:\n\n```cpp\nt1 += sub_cmd{}(\"pause\", \"p\")\n  .description(\"pause the daemon service\");\n```\n\nWhile the end-user is typing and they will got:\n\n```bash\n❯ ./bin/test-app2-c2 server pause\nINVOKING: \"pause, p\", remains: .\ncommand \"pause, p\" hit.\n```\n\nSimple naive? Dislike it? The non-hooked action can be customized.\n\n#### User-custom non-hooked action\n\nYes you can:\n\n```cpp\n#if CMDR_TEST_ON_COMMAND_NOT_HOOKED\ncli.set_global_on_command_not_hooked([](cmdr::opt::cmd const \u0026, string_array const \u0026) {\n  cmdr::get_store().dump_full_keys(std::cout);\n  cmdr::get_store().dump_tree(std::cout);\n  return 0;\n});\n#endif\n```\n\n\n\n### `~~debug`\n\nSpecial flag has the leading sequence chars `~~`.\n\n`~~debug` can disable the command action and print the internal hitting information.\n\n```bash\n❯ ./bin/test-app2-c2 server pause -r 5 -c 3 -p 1357 -vvv ~~debug\ncommand \"pause, p\" hit.\n - 1 hits: \"--port=PORT, -p\" (hit title: \"p\", spec:0, long:0, env:0) =\u003e 1357\n - 1 hits: \"--retry, -r\" (hit title: \"r\", spec:0, long:0, env:0) =\u003e 5\n - 1 hits: \"--count, -c\" (hit title: \"c\", spec:0, long:0, env:0) =\u003e 3\n - 3 hits: \"--verbose, -v\" (hit title: \"v\", spec:0, long:0, env:0) =\u003e true\n - 1 hits: \"--debug, -D, --debug-mode\" (hit title: \"debug\", spec:true, long:true, env:false) =\u003e true\n\n```\n\nAnother one in [Gallary](https://github.com/hedzr/cmdr-cxx/issues/1):\n\n![image-20210217161825139](https://user-images.githubusercontent.com/12786150/108175867-39679c00-713c-11eb-8ef2-4d363d37755e.png)\n\n#### `-DDD`\n\nTriple `D` means `--debug --debug --debug`. In `~~debug` mode, triple `D` can dump more underlying value structure\ninside `Option Store`.\n\n\u003e The duplicated-flag exception there among others, is expecting because we're in testing.\n\n![image-20210211184120423](https://user-images.githubusercontent.com/12786150/107626849-5a8e3f80-6c99-11eb-8e7b-278a50702c8c.png)\n\n\n\n#### `~~debug --cli -DDD`\n\nThe values of CLI flags are ignored but `~~cli` can make them raised when dumping. See the snapshot\nat [#1 - Gallary](https://github.com/hedzr/cmdr-cxx/issues/1).\n\n\n\n\n### `~~tree`\n\nThis flag will print the command hierarchical structure:\n\n![image-20210222130046734](https://user-images.githubusercontent.com/12786150/108664649-2246f680-750e-11eb-8e6d-0437f9797e63.png)\n\n\n\n### Remove the cmdr-cxx tail line\n\nBy default a citation line(s) will be printed at the ends of help screen:\n\n![image-20210215100547030](https://user-images.githubusercontent.com/12786150/107898103-da582a80-6f75-11eb-9ffc-02cdd2af249d.png)\n\nI knew this option is what you want:\n\n```cpp\n    auto \u0026cli = cmdr::cli(\"app2\", CMDR_VERSION_STRING, \"hedzr\",\n                         \"Copyright © 2021 by hedzr, All Rights Reserved.\",\n                         \"A demo app for cmdr-c11 library.\",\n                         \"$ ~ --help\")\n            // remove \"Powered by cmdr-cxx\" line\n            .set_no_cmdr_endings(true)\n            // customize the last line except cmdr endings\n            // .set_tail_line(\"\")\n            .set_no_tail_line(true);\n```\n\nThe \"Type `...` ...\" line could be customized by `set_tail_line(str)`, so called `tail line`,. Or, you can disable\nthe `tail line`  by `set_no_tail_line(bool)`.\n\nThe `Powered by ...` line can be disabled by `set_no_cmdr_ending`, so-called `cmdr-ending` line.\n\n## External Loaders\n\nThere is a builtin addon `yaml-loader` for loading the external config files in the pre-defined directory locations. As\na sample to show you how to write a external loader, `yaml-loader` will load and parse the yaml config file and merge it\ninto `Option Store`.\n\n\u003e TODO: `conf.d` not processed now.\n\n`test-app-c1` demonstrates how to use it:\n\n```cpp\n{\n  using namespace cmdr::addons::loaders;\n  cli.set_global_on_loading_externals(yaml_loader{}());\n}\n```\n\nThe coresponding cmake fragment might be:\n\n```cmake\n#\n# For test-app-c1, loading the dependency to yaml-cpp\n#\ninclude(loaders/yaml_loader)\nadd_yaml_loader(test-app2-c1)\n```\n\n\u003e This add-on needs a third-part library,`yaml-cpp`, presented.\n\n## Specials\n\nInside `cmdr-cxx`, there are many optimizable points and some of them in working.\n\n- [x] enable dim text in terminal\n\n  ```bash\n  CMDR_DIM=1 ./bin/test-app2-c2 main sub4 bug-bug2\n  ```\n\n- [x] `--no-color`: do NOT print colorful text\n  with [Terminal Escaped Sequences](https://en.wikipedia.org/wiki/ANSI_escape_code), envvars `PLAIN` or `NO_COLOR`\n  available too.\n\n  ```bash\n  ./bin/test-app2-c2 --no-color\n  PLAIN=1 ./bin/test-app-c2\n  ```\n\n- [x] enable very verbose debugging\n\n  ```cpp\n  #define CMDR_ENABLE_VERBOSE_LOG 1\n  #include \u003ccmdr11/cmdr11.hh\u003e\n  ```\n\n- [x] enable unhandled exception handler\n\n  ```cpp\n  cmdr::debug::UnhandledExceptionHookInstaller _ueh{}; // for c++ exceptions\n  cmdr::debug::SigSegVInstaller _ssi{};                // for SIGSEGV ...\n  return cli.run(argc, argv);\n  ```\n\n- [x] `-hhh` (i.e. `--help --help --help`) will print the help screen with those invisible items (the hidden commands\n  and flags).\n\n- [x] Tab-stop position is adjustable based the options automatically\n\n- [x] The right-side of a line, in the help screen, command/flag decriptions usually, can be wrapped and aligned along\n  the tab-stop width.\n\n- [ ] More...\n\n\n\n## Use `cmdr-cxx` As A New App Skeletion\n\nThat's very appreciated!\n\n### PROs\n\n- [cmdr](https://github.com/hedzr/cmdr)-like programmatical interface.\n  - See also [Short example](#short-example) and [Fast Document](#fast-document)\n  - See also test app sources\n- A fully functional Hierarchical Configurable Data Management Mechanism (so called `Option Store`) is ready for box.\n- Uses debug outputting macros: `cmdr_print`, `cmdr_debug`, `cmdr_trace` (while `CMDR_ENABLE_VERBOSE_LOG` defined),\n  see [cmdr_log.hh](https://github.com/hedzr/cmdr-cxx/blob/master/libs/cmdr11/include/cmdr11/cmdr_log.hh)\n-\n\n\n\n\n\n## Contributions\n\n\n\n### Build\n\n\u003e gcc 10+: passed\n\u003e\n\u003e clang 12+: passed\n\u003e\n\u003e msvc build tool 16.7.2, 16.8.5 (VS2019 or Build Tool) passed\n\n```bash\n# configure\ncmake -DENABLE_AUTOMATE_TESTS=OFF -S . -B build/\n# build\ncmake --build build/\n# install\ncmake --build build/ --target install\n# sometimes maybe sudo: sudo cmake --build build/ --target install\n```\n\nFor msvs build tool, vcpkg should be present, so cmake configure command is:\n\n```bash\ncmake -DENABLE_AUTOMATE_TESTS=OFF -S . -B build/ -DCMAKE_TOOLCHAIN_FILE=%USERPROFILE%/work/vcpkg/scripts/buildsystems/vcpkg.cmake\n```\n\n\u003e If you clone vcvpkg source and bootstrap it at: `%USERPROFILE%/work/vcpkg`.\n\n#### Windows Server 2019 Core \u0026 VSBT\n\n```powershell\nset VCPKG_DEFAULT_TRIPLET=x64-windows\n\nmkdir %USERPROFILE%/work\ncd %USERPROFILE%/work\ngit clone ...\n\nREM launch `vsbt` build env\nSETX PATH \"%PATH%;C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\Common7\\Tools\"\nLaunchDevCmd.bat\n\ncd cmdr-cxx\ncmake -DENABLE_AUTOMATE_TESTS=OFF -S . -B build/ -DCMAKE_TOOLCHAIN_FILE=%USERPROFILE%/work/vcpkg/scripts/buildsystems/vcpkg.cmake\ncmake --build build/\n```\n\n### ninja, [Optional]\n\nWe use ninja for faster building. That's safe to build cmdr-cxx without it.\n\n### ccache, [Optional]\n\nWe use ccache for faster building. That's safe to build cmdr-cxx without it.\n\n### Other Options\n\n1. `BUILD_DOCUMENTATION`=OFF\n2. `ENABLE_TESTS`=OFF\n\n### Prerequisites\n\nTo run all automated tests, or, you're trying to use `yaml-loader` add-on, some dependencies need to prepared at first,\nby youself, maybe.\n\n#### Catch2\n\nIf the tests are enabled, [`Catch2`](https://github.com/catchorg/Catch2) will be downloaded while cmake configuring and\nbuilding automatically. If you have a local cmake-findable Catch2 copy, more attentions would be appreciated.\n\n#### Others\n\nIn our tests, `test-app2-c1` and `yaml-loader` will request [`yaml-cpp`](https://github.com/jbeder/yaml-cpp) is present.\n\n\u003e Optional\n\n##### Linux\n\n```bash\nsudo apt install -y libyaml-cpp-dev\n```\n\n\u003e For CentOS or RedHat: `sudo dnf install yaml-cpp yaml-cpp-devel yaml-cpp-static`\n\n##### macOS\n\n```bash\nbrew install yaml-cpp\n```\n\n##### Windows\n\n```bash\nvcpkg install yaml-cpp\n```\n\n\u003e **NOTE** that [vcpkg](https://github.com/microsoft/vcpkg) want to inject the control file for cmake building, see\n\u003e also [Using vcpkg with CMake](https://github.com/microsoft/vcpkg#using-vcpkg-with-cmake)\n\n### Run the examples\n\nThe example executables can be found in `./bin` after built. For example:\n\n```bash\n# print command tree (with hidden commands)\n./bin/cmdr11-cli -hhh ~~tree\n```\n\n1. ~~You will get them from release page~~.\n2. TODO: we will build a docker release later.\n3. Run me from a online CXX IDE.\n\n### Hooks in cmdr-cxx\n\n1. `auto \u0026 cli = cmdr::get_app()`\n\n2. Register actions:\n\n   `void register_action(opt::Action action, opt::types::on_internal_action const \u0026fn);`\n\n   In your pre_invoke handler, some actions called `internal actions` could by triggered via the returned `Action` code.\n\n   The `Action` codes is extensible, followed by a `on_internal_action` handler user-customized.\n\n3. Hooks\n\n   \u003e `xxx_handlers` or `s`(`_externals`) means you can specify it multiple times.\n\n   1. `set_global_on_arg_added_handlers`, `set_global_on_cmd_added_handlers`\n\n   2. `set_global_on_arg_matched_handlers`, `set_global_on_cmd_matched_handlers`\n\n   3. `set_global_on_loading_externals`\n\n   4. `set_global_on_command_not_hooked`\n\n      cmdr prints some hitting info for a sub-command while no `on_invoke` handler associated with it.\n\n      Or, you can specify one yours via `set_global_on_command_not_hooked`.\n\n   5. `set_global_on_post_run_handlers`\n\n   6. `set_on_handle_exception_ptr`\n\n   7. `set_global_pre_invoke_handler`, `set_global_post_invoke_handler`\n\n   8.\n\n\n\n\n\n## Thanks to JODL\n\nThanks to [JetBrains](https://www.jetbrains.com/?from=cmdr-cxx) for donating product licenses to help develop **cmdr-cxx**  \n[![jetbrains](https://gist.githubusercontent.com/hedzr/447849cb44138885e75fe46f1e35b4a0/raw/bedfe6923510405ade4c034c5c5085487532dee4/jetbrains-variant-4.svg)](https://www.jetbrains.com/?from=hedzr/cmdr-cxx)\n\n\n\n\n\n\n## LICENSE\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhedzr%2Fcmdr-cxx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhedzr%2Fcmdr-cxx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhedzr%2Fcmdr-cxx/lists"}