aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.cli/dispatch_command.cc
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-01 21:12:11 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-01 21:12:11 +0100
commit85baf16dd366fb501dc522a0957ec680dc9478f0 (patch)
tree64b9a9463c6b886e9784b1fce9ff5c80dc7e0a23 /nihil.cli/dispatch_command.cc
parente461c17c24115132601362a96b6a85c0dd12f471 (diff)
downloadnihil-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.cc31
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);