diff --git a/libraries/cli11/include/cli11/CLI11.hpp b/libraries/cli11/include/cli11/CLI11.hpp index 66af6ce62a..fb540451f3 100644 --- a/libraries/cli11/include/cli11/CLI11.hpp +++ b/libraries/cli11/include/cli11/CLI11.hpp @@ -3,7 +3,7 @@ // https://github.com/CLIUtils/CLI11 // // This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts -// from: 1d3b0a7 +// from: b19d133 // // CLI11 2.2.0 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry // Schreiner under NSF AWARD 1414736. All rights reserved. @@ -34,28 +34,28 @@ #pragma once // Standard combined includes: -#include -#include -#include -#include +#include +#include #include -#include -#include +#include +#include #include -#include -#include +#include +#include #include +#include +#include +#include +#include +#include #include +#include #include -#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include +#include #define CLI11_VERSION_MAJOR 2 @@ -9420,4 +9420,134 @@ inline std::string Formatter::make_option_usage(const Option *opt) const { + +class LeapFormatter : public Formatter { + // pseudographics - to draw subcommand tree + const char* tree_line = u8"\u2502"; + const char* tree_angle = u8"\u2514"; + const char* tree_fork = u8"\u251C"; + +public: + LeapFormatter() : Formatter() { + // this gives better, more compact display + column_width(25); + } + LeapFormatter(const LeapFormatter&) = default; + LeapFormatter(LeapFormatter&&) = default; + + /// This prints out all the subcommands + virtual std::string make_subcommands(const App* app, AppFormatMode mode) const { + std::stringstream out; + + std::vector subcommands = app->get_subcommands({}); + + // Make a list in definition order of the groups seen + std::vector subcmd_groups_seen; + for(const App* com: subcommands) { + if(com->get_name().empty()) { + if(!com->get_group().empty()) { + out << make_expanded(com); + } + continue; + } + std::string group_key = com->get_group(); + if(!group_key.empty() && + std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) { + return detail::to_lower(a) == detail::to_lower(group_key); + }) == subcmd_groups_seen.end()) + subcmd_groups_seen.push_back(group_key); + } + + // For each group, filter out and print subcommands + for(const std::string& group: subcmd_groups_seen) { + if(mode != AppFormatMode::SubCompact) {// do not show "Subcommands" header for nested tems in compact mode + out << "\n" + << group << ":\n"; + } + std::vector subcommands_group = app->get_subcommands([&group](const App* sub_app) { + return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); + }); + for(const App* new_com: subcommands_group) { + if(new_com->get_name().empty()) + continue; + + std::string tree_symbol = (subcommands_group.back() == new_com ? tree_angle : tree_fork); + std::string line_symbol = (subcommands_group.back() == new_com ? "" : tree_line); + std::string subc_symbol = ""; + + const App* parent = app->get_parent(); + if(parent != nullptr) { + std::vector sc_group = parent->get_subcommands([&group](const App* sub_app) { + return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); + }); + if(sc_group.back() != app) { + subc_symbol = tree_line; + } + } + + switch(mode) { + case AppFormatMode::All: + out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::Sub); + out << "\n"; + break; + case AppFormatMode::AllCompact: + + out << tree_symbol << new_com->help(new_com->get_name(), AppFormatMode::SubCompact); + out << line_symbol; + out << "\n"; + break; + case AppFormatMode::Normal: + case AppFormatMode::Sub: + out << make_subcommand(new_com); + break; + case AppFormatMode::SubCompact: + out << tree_symbol << make_expanded(new_com, mode); + break; + default: + throw HorribleError("Internal error: unknown help type requested"); + } + } + } + + return out.str(); + } + + /// This prints out a subcommand in help-all + virtual std::string make_expanded(const App* sub, AppFormatMode mode = AppFormatMode::Sub) const { + std::stringstream out; + std::string tmp; + std::string subc_symbol = " "; + if(mode == AppFormatMode::SubCompact) { + detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_); + out << make_subcommands(sub, mode); + } else { + out << sub->get_display_name(true) << "\n"; + out << make_description(sub); + if(sub->get_name().empty() && !sub->get_aliases().empty()) { + detail::format_aliases(out, sub->get_aliases(), column_width_ + 2); + } + out << make_positionals(sub); + out << make_groups(sub, mode); + out << make_subcommands(sub, mode); + } + + // Drop blank spaces + tmp = detail::find_and_replace(out.str(), "\n\n", "\n"); + tmp = tmp.substr(0, tmp.size() - 1);// Remove the final '\n' + + // + auto group = sub->get_parent()->get_group(); + std::vector sc_group = sub->get_parent()->get_subcommands( + [&group](const App* sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); }); + + if(sc_group.back() != sub) { + subc_symbol = tree_line; + } + + // Indent all but the first line (the name) + return detail::find_and_replace(tmp, "\n", "\n" + subc_symbol + " ") + "\n"; + } +}; + + } // namespace CLI diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index a398859fc4..ea5d4346d7 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -2759,9 +2759,16 @@ int main( int argc, char** argv ) { wallet_url = default_wallet_url; CLI::App app{"Command Line Interface to EOSIO Client"}; + + // custom leap formatter + auto fmt = std::make_shared(); + app.formatter(fmt); + + // enable help-all, display help on error app.set_help_all_flag("--help-all", "Show all help"); app.failure_message(CLI::FailureMessage::help); app.require_subcommand(); + // Hide obsolete options by putting them into a group with an empty name. app.add_option( "-H,--host", obsoleted_option_host_port, localized("The host where ${n} is running", ("n", node_executable_name)) )->group(""); app.add_option( "-p,--port", obsoleted_option_host_port, localized("The port where ${n} is running", ("n", node_executable_name)) )->group(""); diff --git a/programs/leap-util/actions/chain.cpp b/programs/leap-util/actions/chain.cpp index e5c2229de9..14ed97c72c 100644 --- a/programs/leap-util/actions/chain.cpp +++ b/programs/leap-util/actions/chain.cpp @@ -37,8 +37,8 @@ void chain_actions::setup(CLI::App& app) { sub->require_subcommand(1); auto* build = sub->add_subcommand("build-info", "extract build environment information as JSON"); - auto opt1 = build->add_option("--output-file,-o", opt->build_output_file, "write into specified file")->capture_default_str(); - auto opt2 = build->add_flag("--print,-p", opt->build_just_print, "print to console"); + build->add_option("--output-file,-o", opt->build_output_file, "write into specified file")->capture_default_str(); + build->add_flag("--print,-p", opt->build_just_print, "print to console"); build->require_option(1); build->callback([&]() { diff --git a/programs/leap-util/leap_formatter.hpp b/programs/leap-util/leap_formatter.hpp deleted file mode 100644 index 10ccecf095..0000000000 --- a/programs/leap-util/leap_formatter.hpp +++ /dev/null @@ -1,12 +0,0 @@ - -#include -#include -#include - -class leap_formatter : public CLI::Formatter { - public: - leap_formatter() : Formatter() { - // 30 is default for CLI11, but seems like overkill - column_width(25); - } -}; \ No newline at end of file diff --git a/programs/leap-util/main.cpp b/programs/leap-util/main.cpp index 249950becf..3886cc712c 100644 --- a/programs/leap-util/main.cpp +++ b/programs/leap-util/main.cpp @@ -12,15 +12,13 @@ #include -#include "leap_formatter.hpp" - int main(int argc, char** argv) { fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); CLI::App app{"Leap Command Line Utility"}; // custom leap formatter - auto fmt = std::make_shared(); + auto fmt = std::make_shared(); app.formatter(fmt); app.set_help_all_flag("--help-all", "Show all help");