aboutsummaryrefslogtreecommitdiff
path: root/src/zen/zen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/zen.cpp')
-rw-r--r--src/zen/zen.cpp75
1 files changed, 71 insertions, 4 deletions
diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp
index 9a466da2e..86c29344e 100644
--- a/src/zen/zen.cpp
+++ b/src/zen/zen.cpp
@@ -196,6 +196,7 @@ ZenCmdBase::GetSubCommand(cxxopts::Options&,
ZenSubCmdBase::ZenSubCmdBase(std::string_view Name, std::string_view Description)
: m_SubOptions(std::string(Name), std::string(Description))
+, m_Description(Description)
{
m_SubOptions.add_options()("h,help", "Print help");
}
@@ -213,6 +214,35 @@ ZenCmdWithSubCommands::OnParentOptionsParsed(const ZenCliOptions& /*GlobalOption
}
void
+ZenCmdWithSubCommands::PrintHelp()
+{
+ // Show all option groups except the internal "__hidden__" group used to
+ // silently capture positional arguments.
+ std::vector<std::string> Groups = Options().groups();
+ Groups.erase(std::remove(Groups.begin(), Groups.end(), std::string("__hidden__")), Groups.end());
+
+ Options().set_width(TuiConsoleColumns(80));
+ printf("%s\n", Options().help(Groups).c_str());
+
+ // Append subcommand listing.
+ size_t MaxNameLen = 0;
+ for (ZenSubCmdBase* SubCmd : m_SubCommands)
+ {
+ MaxNameLen = std::max(MaxNameLen, SubCmd->SubOptions().program().size());
+ }
+
+ printf("subcommands:\n");
+ for (ZenSubCmdBase* SubCmd : m_SubCommands)
+ {
+ printf(" %-*s %s\n",
+ static_cast<int>(MaxNameLen),
+ SubCmd->SubOptions().program().c_str(),
+ std::string(SubCmd->Description()).c_str());
+ }
+ printf("\nFor global options run: zen --help\n");
+}
+
+void
ZenCmdWithSubCommands::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
std::vector<cxxopts::Options*> SubOptionPtrs;
@@ -226,15 +256,47 @@ ZenCmdWithSubCommands::Run(const ZenCliOptions& GlobalOptions, int argc, char**
std::vector<char*> SubCommandArguments;
int ParentArgc = GetSubCommand(Options(), argc, argv, SubOptionPtrs, MatchedSubOption, SubCommandArguments);
- if (!ParseOptions(Options(), ParentArgc, argv))
+ // Intercept --help/-h in the parent arg range before calling ParseOptions so
+ // we can append subcommand information to the output. When a subcommand was
+ // found argv[ParentArgc-1] is the subcommand name itself, which we exclude.
+ int ParentArgEnd = (MatchedSubOption != nullptr) ? ParentArgc - 1 : ParentArgc;
+ for (int i = 1; i < ParentArgEnd; ++i)
{
- return;
+ std::string_view Arg(argv[i]);
+ if (Arg == "--help" || Arg == "-h")
+ {
+ PrintHelp();
+ return;
+ }
+ }
+
+ // Parse parent options. When a subcommand was matched we strip its name from
+ // the arg list so the parent parser does not see it as an unmatched positional.
+ if (MatchedSubOption != nullptr)
+ {
+ std::vector<char*> ParentArgs;
+ ParentArgs.reserve(static_cast<size_t>(ParentArgc - 1));
+ ParentArgs.push_back(argv[0]);
+ std::copy(argv + 1, argv + ParentArgc - 1, std::back_inserter(ParentArgs));
+ if (!ParseOptions(Options(), static_cast<int>(ParentArgs.size()), ParentArgs.data()))
+ {
+ return;
+ }
+ }
+ else
+ {
+ if (!ParseOptions(Options(), ParentArgc, argv))
+ {
+ return;
+ }
}
if (MatchedSubOption == nullptr)
{
+ PrintHelp();
+
ExtendableStringBuilder<128> VerbList;
- for (bool First = true; ZenSubCmdBase * SubCmd : m_SubCommands)
+ for (bool First = true; ZenSubCmdBase* SubCmd : m_SubCommands)
{
if (!First)
{
@@ -243,7 +305,7 @@ ZenCmdWithSubCommands::Run(const ZenCliOptions& GlobalOptions, int argc, char**
VerbList.Append(SubCmd->SubOptions().program());
First = false;
}
- throw OptionParseException(fmt::format("No subcommand specified. Available subcommands: {}", VerbList.ToView()), Options().help());
+ throw OptionParseException(fmt::format("No subcommand specified. Available subcommands: {}", VerbList.ToView()), {});
}
ZenSubCmdBase* MatchedSubCmd = nullptr;
@@ -621,6 +683,9 @@ main(int argc, char** argv)
Options.add_options()("malloc", "Configure memory allocator subsystem", cxxopts::value(MemoryOptions)->default_value("mimalloc"));
Options.add_options()("help", "Show command line help");
Options.add_options()("c, command", "Sub command", cxxopts::value<std::string>(SubCommand));
+ Options.add_options()("httpclient",
+ "Select HTTP client implementation (e.g. 'curl', 'cpr')",
+ cxxopts::value<std::string>(GlobalOptions.HttpClientBackend)->default_value("cpr"));
int CoreLimit = 0;
@@ -783,6 +848,8 @@ main(int argc, char** argv)
FreeCallstack(Callstack);
});
+ zen::SetDefaultHttpClientBackend(GlobalOptions.HttpClientBackend);
+
zen::MaximizeOpenFileCount();
//////////////////////////////////////////////////////////////////////////