diff options
| author | Stefan Boberg <[email protected]> | 2026-03-30 17:57:56 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2026-03-30 17:57:56 +0200 |
| commit | 6058329192d2fa41e662c4e954995a53ef3edb19 (patch) | |
| tree | fdf1c98585a32e0098f445ee13f3f8f25d12a728 /src | |
| parent | Add interactive help command to zen CLI (diff) | |
| download | zen-6058329192d2fa41e662c4e954995a53ef3edb19.tar.xz zen-6058329192d2fa41e662c4e954995a53ef3edb19.zip | |
Show global options and subcommands in help command pages
- Include global zen options (debug, verbose, logging, tracing, sentry)
below each command's own help text
- For commands with subcommands (e.g. hub, exec), show a summary listing
of all subcommands followed by detailed per-subcommand options
- Add SubCommands() accessor to ZenCmdWithSubCommands
- Pass global cxxopts::Options to HelpCommand via SetGlobalOptions()
Diffstat (limited to 'src')
| -rw-r--r-- | src/zen/cmds/help_cmd.cpp | 71 | ||||
| -rw-r--r-- | src/zen/cmds/help_cmd.h | 4 | ||||
| -rw-r--r-- | src/zen/zen.cpp | 2 | ||||
| -rw-r--r-- | src/zen/zen.h | 2 |
4 files changed, 77 insertions, 2 deletions
diff --git a/src/zen/cmds/help_cmd.cpp b/src/zen/cmds/help_cmd.cpp index 82c260a0e..98961abcc 100644 --- a/src/zen/cmds/help_cmd.cpp +++ b/src/zen/cmds/help_cmd.cpp @@ -79,6 +79,73 @@ PrintCommandList(std::span<const CommandInfo> Commands) } } +// Build the global options help text, filtering out hidden groups +static std::string +GlobalOptionsHelpText(cxxopts::Options* GlobalOptions) +{ + if (GlobalOptions == nullptr) + { + return {}; + } + + std::vector<std::string> Groups = GlobalOptions->groups(); + Groups.erase(std::remove(Groups.begin(), Groups.end(), std::string("__hidden__")), Groups.end()); + GlobalOptions->set_width(TuiConsoleColumns(80)); + return GlobalOptions->help(Groups); +} + +// Build the full help text for a command, including subcommands and global options +std::string +HelpCommand::BuildFullHelpText(const CommandInfo& Cmd) const +{ + std::string Text = Cmd.Cmd->HelpText(); + + // If this command has subcommands, append their listing and individual options + ZenCmdWithSubCommands* CmdWithSubs = dynamic_cast<ZenCmdWithSubCommands*>(Cmd.Cmd); + if (CmdWithSubs != nullptr) + { + auto SubCmds = CmdWithSubs->SubCommands(); + if (!SubCmds.empty()) + { + // Subcommand summary listing + size_t MaxNameLen = 0; + for (ZenSubCmdBase* Sub : SubCmds) + { + MaxNameLen = std::max(MaxNameLen, Sub->SubOptions().program().size()); + } + + Text += "\nSubcommands:\n"; + for (ZenSubCmdBase* Sub : SubCmds) + { + Text += fmt::format(" {:<{}} {}\n", Sub->SubOptions().program(), MaxNameLen, Sub->Description()); + } + + // Detailed options for each subcommand + for (ZenSubCmdBase* Sub : SubCmds) + { + std::vector<std::string> Groups = Sub->SubOptions().groups(); + Groups.erase(std::remove(Groups.begin(), Groups.end(), std::string("__hidden__")), Groups.end()); + Sub->SubOptions().set_width(TuiConsoleColumns(80)); + std::string SubHelp = Sub->SubOptions().help(Groups); + if (!SubHelp.empty()) + { + Text += "\n"; + Text += SubHelp; + } + } + } + } + + std::string GlobalHelp = GlobalOptionsHelpText(m_GlobalOptions); + if (!GlobalHelp.empty()) + { + Text += "\n\nGlobal Options:\n"; + Text += GlobalHelp; + } + + return Text; +} + void HelpCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { @@ -103,7 +170,7 @@ HelpCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { if (StrCaseCompare(m_CommandName.c_str(), Cmd.CmdName) == 0) { - std::string HelpText = Cmd.Cmd->HelpText(); + std::string HelpText = BuildFullHelpText(Cmd); if (IsTuiAvailable()) { @@ -175,7 +242,7 @@ HelpCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) continue; // Category header selected, ignore } - std::string HelpText = SelectedCmd->Cmd->HelpText(); + std::string HelpText = BuildFullHelpText(*SelectedCmd); std::vector<std::string> Lines = SplitLines(HelpText); std::string Title = fmt::format("zen {} -- {}", SelectedCmd->CmdName, SelectedCmd->CmdSummary); TuiPager(Title, Lines); diff --git a/src/zen/cmds/help_cmd.h b/src/zen/cmds/help_cmd.h index 2bccd9db1..29018e803 100644 --- a/src/zen/cmds/help_cmd.h +++ b/src/zen/cmds/help_cmd.h @@ -18,14 +18,18 @@ public: ~HelpCommand(); void SetCommands(std::span<const CommandInfo> Commands) { m_Commands = Commands; } + void SetGlobalOptions(cxxopts::Options* GlobalOptions) { m_GlobalOptions = GlobalOptions; } virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: + std::string BuildFullHelpText(const CommandInfo& Cmd) const; + cxxopts::Options m_Options{Name, Description}; std::span<const CommandInfo> m_Commands; + cxxopts::Options* m_GlobalOptions = nullptr; std::string m_CommandName; bool m_List = false; }; diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index 67c2e6c77..87d83cc77 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -855,6 +855,8 @@ main(int argc, char** argv) Options.parse_positional({"command"}); + HelpCmd.SetGlobalOptions(&Options); + const bool IsNullInvoke = (argc == 1); // If no arguments are passed we want to print usage information try diff --git a/src/zen/zen.h b/src/zen/zen.h index b24b61369..80178910a 100644 --- a/src/zen/zen.h +++ b/src/zen/zen.h @@ -120,6 +120,8 @@ class ZenCmdWithSubCommands : public ZenCmdBase public: void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) final; + std::span<ZenSubCmdBase* const> SubCommands() const { return m_SubCommands; } + protected: void AddSubCommand(ZenSubCmdBase& SubCmd); virtual bool OnParentOptionsParsed(const ZenCliOptions& GlobalOptions); |