diff options
Diffstat (limited to 'src/zen/zen.cpp')
| -rw-r--r-- | src/zen/zen.cpp | 75 |
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(); ////////////////////////////////////////////////////////////////////////// |