diff options
| author | Lexi Winter <lexi@le-fay.org> | 2025-07-01 21:12:11 +0100 |
|---|---|---|
| committer | Lexi Winter <lexi@le-fay.org> | 2025-07-01 21:12:11 +0100 |
| commit | 85baf16dd366fb501dc522a0957ec680dc9478f0 (patch) | |
| tree | 64b9a9463c6b886e9784b1fce9ff5c80dc7e0a23 /nihil.cli/dispatch_command.cc | |
| parent | e461c17c24115132601362a96b6a85c0dd12f471 (diff) | |
| download | nihil-85baf16dd366fb501dc522a0957ec680dc9478f0.tar.gz nihil-85baf16dd366fb501dc522a0957ec680dc9478f0.tar.bz2 | |
cli: clean up
Diffstat (limited to 'nihil.cli/dispatch_command.cc')
| -rw-r--r-- | nihil.cli/dispatch_command.cc | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/nihil.cli/dispatch_command.cc b/nihil.cli/dispatch_command.cc index 6cf7f05..6e3a757 100644 --- a/nihil.cli/dispatch_command.cc +++ b/nihil.cli/dispatch_command.cc @@ -1,9 +1,9 @@ // This source code is released into the public domain. module; -#include <stdlib.h> // getprogname, NOLINT +#include <stdlib.h> // getprogname, NOLINT #include <sysexits.h> // EX_USAGE -#include <unistd.h> // getopt +#include <unistd.h> // getopt module nihil.cli; @@ -19,39 +19,36 @@ auto print_commands(command_tree_node const &node) -> void for (auto &&child : node.children()) std::print(std::cerr, " {}\n", child.command().path()); } -} +} // namespace auto dispatch_command(int argc, char **argv) -> int { - auto tree = build_command_tree(); - - // The caller should have stripped argv[0] already. find() will - // strip all the remaining elements except the last, which means - // argv[0] will be set to something reasonable for the next call - // to getopt(). - - // find() never returns nullptr; at worst it will return the root node. - auto const *node = tree.find(argc, argv); - auto const &command = node->command(); - // Reset getopt(3) for the command, in case main() used it already. optreset = 1; optind = 1; + // Node that tree.find() never fails, at worst it will return the root node. + auto tree = build_command_tree(); + auto [node, rest] = tree.find(std::span(argv, argc)); + auto const &command = node->command(); + // Set the program name to the existing progname plus the full path to the command being // invoked; this makes error messages nicer. Save the old progname so we can restore it // after invoking the command. auto const *old_progname = ::getprogname(); { - auto cprogname = std::format("{} {}", ::getprogname(), - command.path()); + auto cprogname = std::format("{} {}", ::getprogname(), command.path()); ::setprogname(cprogname.c_str()); } // Invoke the command see what it returns. If it's an exit code, just return it. // Otherwise, handle the error. - auto ret = command.invoke(argc, argv); + auto nrest = static_cast<int>(std::ranges::distance(rest)); + // Keep the first argument, because getopt() wants it + if (nrest < argc) + ++nrest; + auto ret = command.invoke(nrest, argv + (argc - nrest)); // Restore the old progname. ::setprogname(old_progname); |
