From 2eb28736a05c7083f2b30b501954a789bbd85f88 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 2 Sep 2015 15:18:11 +0200 Subject: Add --short-usage option When combined with --long-usage, it makes CLI generate both short and long usage printing code. --- cli/context.cxx | 11 ++++++- cli/context.hxx | 11 ++++++- cli/header.cxx | 19 +++++++++--- cli/options.cli | 9 ++++++ cli/options.cxx | 25 ++++++++++++++- cli/options.hxx | 22 +++++++++++-- cli/options.ixx | 19 +++++++++++- cli/source.cxx | 96 ++++++++++++++++++++++++++++++++++++++++----------------- 8 files changed, 171 insertions(+), 41 deletions(-) diff --git a/cli/context.cxx b/cli/context.cxx index af6b58f..1324b0c 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -101,7 +101,6 @@ context (ostream& os_, options (ops), modifier (options.generate_modifier ()), specifier (options.generate_specifier ()), - usage (!options.suppress_usage ()), inl (data_->inl_), opt_prefix (options.option_prefix ()), opt_sep (options.option_separator ()), @@ -109,6 +108,16 @@ context (ostream& os_, reserved_name_map (options.reserved_name ()), keyword_set (data_->keyword_set_) { + if (options.suppress_usage ()) + usage = ut_none; + else + { + if (options.long_usage ()) + usage = options.short_usage () ? ut_both : ut_long; + else + usage = ut_short; + } + if (!options.suppress_inline ()) data_->inl_ = "inline "; diff --git a/cli/context.hxx b/cli/context.hxx index afaf577..b6ce420 100644 --- a/cli/context.hxx +++ b/cli/context.hxx @@ -29,6 +29,15 @@ public: typedef std::string string; typedef ::options options_type; +public: + enum usage_type + { + ut_none, + ut_short, + ut_long, + ut_both + }; + private: struct data; cutl::shared_ptr data_; @@ -40,7 +49,7 @@ public: bool modifier; bool specifier; - bool usage; + usage_type usage; string const& inl; string const& opt_prefix; diff --git a/cli/header.cxx b/cli/header.cxx index 26c23b8..ddf0895 100644 --- a/cli/header.cxx +++ b/cli/header.cxx @@ -179,13 +179,22 @@ namespace // Usage. // - if (usage) + if (usage != ut_none) { os << "// Print usage information." << endl - << "//" << endl - << "static void" << endl - << "print_usage (" << options.ostream_type () << "&);" - << endl; + << "//" << endl; + + if (usage != ut_both) + os << "static void" << endl + << "print_usage (" << options.ostream_type () << "&);" + << endl; + else + os << "static void" << endl + << "print_short_usage (" << options.ostream_type () << "&);" + << endl + << "static void" << endl + << "print_long_usage (" << options.ostream_type () << "&);" + << endl; } // Description. diff --git a/cli/options.cli b/cli/options.cli index ab7be1c..28a4ee4 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -83,6 +83,15 @@ class options only the first sentence from the long string is used." }; + bool --short-usage + { + "If specified together with \cb{--long-usage}, generate both short + and long usage versions. In this mode, the usage printing functions + are called \cb{print_short_usage()} and \cb{print_long_usage()} and + for the long usage the long documentation string is always used, + even if the short version is provided." + }; + std::size_t --option-length = 0 { "", diff --git a/cli/options.cxx b/cli/options.cxx index 1e94e17..dcb408a 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -1,7 +1,14 @@ -// This code was generated by CLI, a command line interface +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface // compiler for C++. // +// Begin prologue. +// +// +// End prologue. + #include "options.hxx" #include @@ -562,6 +569,7 @@ options () suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -624,6 +632,7 @@ options (int& argc, suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -689,6 +698,7 @@ options (int start, suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -754,6 +764,7 @@ options (int& argc, suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -821,6 +832,7 @@ options (int start, suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -884,6 +896,7 @@ options (::cli::scanner& s, suppress_undocumented_ (), suppress_usage_ (), long_usage_ (), + short_usage_ (), option_length_ (0), exclude_base_ (), cli_namespace_ ("::cli"), @@ -967,6 +980,9 @@ print_usage (::std::ostream& os) os << "--long-usage If no short documentation string is provided, use" << ::std::endl << " the complete long documentation string in usage." << ::std::endl; + os << "--short-usage If specified together with '--long-usage'," << ::std::endl + << " generate both short and long usage versions." << ::std::endl; + os << "--option-length Indent option descriptions characters when" << ::std::endl << " printing usage." << ::std::endl; @@ -1126,6 +1142,8 @@ struct _cli_options_map_init &::cli::thunk< options, bool, &options::suppress_usage_ >; _cli_options_map_["--long-usage"] = &::cli::thunk< options, bool, &options::long_usage_ >; + _cli_options_map_["--short-usage"] = + &::cli::thunk< options, bool, &options::short_usage_ >; _cli_options_map_["--option-length"] = &::cli::thunk< options, std::size_t, &options::option_length_ >; _cli_options_map_["--exclude-base"] = @@ -1289,3 +1307,8 @@ _parse (::cli::scanner& s, } } +// Begin epilogue. +// +// +// End epilogue. + diff --git a/cli/options.hxx b/cli/options.hxx index d3a9c5c..22495e4 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -1,10 +1,17 @@ -// This code was generated by CLI, a command line interface +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface // compiler for C++. // #ifndef CLI_OPTIONS_HXX #define CLI_OPTIONS_HXX +// Begin prologue. +// +// +// End prologue. + #include #include #include @@ -351,6 +358,8 @@ class options ::cli::unknown_mode option = ::cli::unknown_mode::fail, ::cli::unknown_mode argument = ::cli::unknown_mode::stop); + options (); + // Option accessors. // const bool& @@ -392,6 +401,9 @@ class options const bool& long_usage () const; + const bool& + short_usage () const; + const std::size_t& option_length () const; @@ -520,8 +532,6 @@ class options // Implementation details. // protected: - options (); - bool _parse (const char*, ::cli::scanner&); @@ -545,6 +555,7 @@ class options bool suppress_undocumented_; bool suppress_usage_; bool long_usage_; + bool short_usage_; std::size_t option_length_; bool exclude_base_; std::string cli_namespace_; @@ -589,4 +600,9 @@ class options #include "options.ixx" +// Begin epilogue. +// +// +// End epilogue. + #endif // CLI_OPTIONS_HXX diff --git a/cli/options.ixx b/cli/options.ixx index a361898..a66312d 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -1,7 +1,14 @@ -// This code was generated by CLI, a command line interface +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface // compiler for C++. // +// Begin prologue. +// +// +// End prologue. + namespace cli { // unknown_mode @@ -274,6 +281,12 @@ long_usage () const return this->long_usage_; } +inline const bool& options:: +short_usage () const +{ + return this->short_usage_; +} + inline const std::size_t& options:: option_length () const { @@ -514,3 +527,7 @@ options_file () const return this->options_file_; } +// Begin epilogue. +// +// +// End epilogue. diff --git a/cli/source.cxx b/cli/source.cxx index 2bf1c0f..6a8ea76 100644 --- a/cli/source.cxx +++ b/cli/source.cxx @@ -229,7 +229,8 @@ namespace // struct option_usage: traversal::option, context { - option_usage (context& c, size_t l) : context (c), length_ (l) {} + option_usage (context& c, size_t l, usage_type u) + : context (c), length_ (l), usage_ (u) {} virtual void traverse (type& o) @@ -278,25 +279,29 @@ namespace } } - // If we have both the long and the short descriptions, use - // the short one. Otherwise, use the first sentence from the - // long one unless --long-usage was specified. + // Figure out which documentation string we should use. // string d; - - if (type == "bool" && doc.size () < 3) - { - if (doc.size () > 1) - d = doc[0]; - else if (doc.size () > 0) - d = options.long_usage () ? doc[0] : first_sentence (doc[0]); - } - else { - if (doc.size () > 2) - d = doc[1]; - else if (doc.size () > 1) - d = options.long_usage () ? doc[1] : first_sentence (doc[1]); + size_t i (type == "bool" && doc.size () < 3 ? 0 : 1); + + if (doc.size () > i) // Have at least one. + { + if (usage == ut_both && usage_ == ut_long) + { + d = doc.size () > i + 1 // Have both short and long? + ? doc[i + 1] // Then use long. + : doc[i]; + } + else // Short or long. + { + d = doc.size () > i + 1 // Have both short and long? + ? doc[i] // Then use short, + : (usage == ut_long // Otherwise, if asked for long, + ? doc[i] // Then use long, + : first_sentence (doc[i])); // Else first sentence of long. + } + } } // Format the documentation string. @@ -426,6 +431,7 @@ namespace private: size_t length_; + usage_type usage_; }; // @@ -463,16 +469,24 @@ namespace struct base_usage: traversal::class_, context { - base_usage (context& c): context (c) {} + base_usage (context& c, usage_type u): context (c), usage_ (u) {} virtual void traverse (type& c) { + const char* t ( + usage != ut_both + ? "" + : usage_ == ut_short ? "short_" : "long_"); + os << "// " << escape (c.name ()) << " base" << endl << "//" << endl - << fq_name (c) << "::print_usage (os);" + << fq_name (c) << "::print_" << t << "usage (os);" << endl; } + + private: + usage_type usage_; }; // @@ -483,13 +497,11 @@ namespace : context (c), base_parse_ (c), base_desc_ (c), - base_usage_ (c), option_map_ (c), option_desc_ (c) { inherits_base_parse_ >> base_parse_; inherits_base_desc_ >> base_desc_; - inherits_base_usage_ >> base_usage_; names_option_map_ >> option_map_; names_option_desc_ >> option_desc_; } @@ -609,7 +621,7 @@ namespace // Usage. // - if (usage) + if (usage != ut_none) { bool b (hb && !options.exclude_base ()); @@ -690,24 +702,53 @@ namespace // If len is 0 then it means we have no options to print. // os << "void " << name << "::" << endl - << "print_usage (" << options.ostream_type () << "&" << - (len != 0 || b ? " os)" : ")") + << "print_" << (usage == ut_both ? "short_" : "") << "usage (" << + options.ostream_type () << "&" << (len != 0 || b ? " os)" : ")") << "{"; // Call our bases. // if (b) - inherits (c, inherits_base_usage_); + { + base_usage t (*this, usage == ut_both ? ut_short : usage); + traversal::inherits i (t); + inherits (c, i); + } // Print option usage. // { - option_usage t (*this, len); + option_usage t (*this, len, usage == ut_both ? ut_short : usage); traversal::names n (t); names (c, n); } os << "}"; + + // Long version. + // + if (usage == ut_both) + { + os << "void " << name << "::" << endl + << "print_long_usage (" << + options.ostream_type () << "&" << (len != 0 || b ? " os)" : ")") + << "{"; + + if (b) + { + base_usage t (*this, ut_long); + traversal::inherits i (t); + inherits (c, i); + } + + { + option_usage t (*this, len, ut_long); + traversal::names n (t); + names (c, n); + } + + os << "}"; + } } // Description. @@ -891,9 +932,6 @@ namespace base_desc base_desc_; traversal::inherits inherits_base_desc_; - base_usage base_usage_; - traversal::inherits inherits_base_usage_; - option_map option_map_; traversal::names names_option_map_; -- cgit v1.1