From a22e3dc68dd88eb047bfd9716e5cb780c95a3cea Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 1 Feb 2016 12:08:06 +0200 Subject: Add support for link transformation (--link-regex) --- cli/context.cxx | 152 ++++++++++++++++++++++++++++++++++++++++++++++---------- cli/context.hxx | 17 +++++++ cli/options.cli | 22 ++++++++ cli/options.cxx | 30 +++++++++++ cli/options.hxx | 12 +++++ cli/options.ixx | 18 +++++++ 6 files changed, 226 insertions(+), 25 deletions(-) diff --git a/cli/context.cxx b/cli/context.cxx index 506c8fa..1aa7833 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -111,7 +111,8 @@ context (ostream& os_, opt_sep (options.option_separator ()), cli (data_->cli_), reserved_name_map (options.reserved_name ()), - keyword_set (data_->keyword_set_) + keyword_set (data_->keyword_set_), + link_regex (data_->link_regex_) { if (options.suppress_usage ()) usage = ut_none; @@ -133,6 +134,22 @@ context (ostream& os_, for (size_t i (0); i < sizeof (keywords) / sizeof (char*); ++i) data_->keyword_set_.insert (keywords[i]); + + // Link regex. + // + for (vector::const_iterator i (ops.link_regex ().begin ()); + i != ops.link_regex ().end (); ++i) + { + try + { + data_->link_regex_.push_back (regexsub (*i)); + } + catch (const regex_format& e) + { + cerr << "error: invalid regex '" << *i << "': " << e.what () << endl; + throw generation_failed (); + } + } } context:: @@ -149,7 +166,8 @@ context (context& c) opt_sep (c.opt_sep), cli (c.cli), reserved_name_map (c.reserved_name_map), - keyword_set (c.keyword_set) + keyword_set (c.keyword_set), + link_regex (c.link_regex) { } @@ -224,6 +242,43 @@ escape (string const& name) const } string context:: +process_link_target (const string& tg) +{ + bool t (options.link_regex_trace ()); + + if (t) + cerr << "link: '" << tg << "'" << endl; + + string r; + bool found (false); + + for (regex_mapping::const_iterator i (link_regex.begin ()); + i != link_regex.end (); ++i) + { + if (t) + cerr << "try: '" << i->regex () << "' : "; + + if (i->match (tg)) + { + r = i->replace (tg); + found = true; + + if (t) + cerr << "'" << r << "' : "; + } + + if (t) + cerr << (found ? '+' : '-') << endl; + + if (found) + break; + } + + return found ? r : tg; +} + + +string context:: translate_arg (string const& s, std::set& set) { string r; @@ -713,11 +768,22 @@ format_line (output_type ot, string& r, const char* s, size_t n) { r += ""; } else @@ -789,24 +855,42 @@ format_line (output_type ot, string& r, const char* s, size_t n) { if (b & link) { - if (!link_empty) - r += " ("; + string t (link_section.empty () + ? link_target + : link_target + "(" + link_section + ")"); - if (link_section.empty ()) - r += link_target; + string pt (process_link_target (t)); + + if (pt.empty ()) + { + if (link_empty) + { + cerr << "error: link target '" << t << "' became empty " + << "and link text is also empty" << endl; + throw generation_failed (); + } + } else { - if (color) - r += "\033[1m"; + if (!link_empty) + r += " ("; - r += link_target + "(" + link_section + ")"; + if (link_section.empty ()) + r += pt; + else + { + if (color) + r += "\033[1m"; - if (color) - r += "\033[0m"; - } + r += pt; + + if (color) + r += "\033[0m"; + } - if (!link_empty) - r += ")"; + if (!link_empty) + r += ")"; + } } else { @@ -864,16 +948,34 @@ format_line (output_type ot, string& r, const char* s, size_t n) { if (b & link) { - if (!link_empty) - r += " ("; + string t (link_section.empty () + ? link_target + : link_target + "(" + link_section + ")"); - if (link_section.empty ()) - r += link_target; + string pt (process_link_target (t)); + + if (pt.empty ()) + { + if (link_empty) + { + cerr << "error: link target '" << t << "' became empty " + << "and link text is also empty" << endl; + throw generation_failed (); + } + } else - r += "\\fB" + link_target + "(" + link_section + ")\\fP"; + { + if (!link_empty) + r += " ("; - if (!link_empty) - r += ")"; + if (link_section.empty ()) + r += pt; + else + r += "\\fB" + pt + "\\fP"; + + if (!link_empty) + r += ")"; + } } else { diff --git a/cli/context.hxx b/cli/context.hxx index cdc0aa5..b33bfef 100644 --- a/cli/context.hxx +++ b/cli/context.hxx @@ -9,9 +9,11 @@ #include #include #include +#include #include #include // std::size_t +#include #include #include @@ -52,6 +54,14 @@ public: typedef ::usage usage_type; typedef ::class_doc class_doc_type; + // Regex. + // + typedef cutl::re::regex regex; + typedef cutl::re::regexsub regexsub; + typedef cutl::re::format regex_format; + + typedef std::vector regex_mapping; + private: struct data; cutl::shared_ptr data_; @@ -76,12 +86,16 @@ public: typedef std::set keyword_set_type; keyword_set_type const& keyword_set; + regex_mapping const& link_regex; + private: struct data { string inl_; string cli_; keyword_set_type keyword_set_; + + regex_mapping link_regex_; }; public: @@ -90,6 +104,9 @@ public: string escape (string const&) const; + string + process_link_target (const string&); + // Translate and format the documentation string. Translate converts // the -style constructs to \i{arg}. Format converts the string // to the output format. diff --git a/cli/options.cli b/cli/options.cli index 26bf834..8a4a3e0 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -234,6 +234,28 @@ class options \c{\"\\=\"} syntax." }; + std::vector --link-regex + { + "", + "Add to the list of regular expressions used to transform link + targets in the generated documentation. The argument to this option + is a Perl-like regular expression in the form + \c{\b{/}\i{pattern}\b{/}\i{replacement}\b{/}}. Any character can be + used as a delimiter instead of '\cb{/}' and the delimiter can be escaped + inside \ci{pattern} and \ci{replacement} with a backslash (\cb{\\}). + You can specify multiple regular expressions by repeating this option. + All the regular expressions are tried in the order specified and the + first expression that matches is used. Use the \cb{--link-regex-trace} + option to debug link transformation." + }; + + bool --link-regex-trace + { + "Trace the process of applying regular expressions specified with the + \cb{--link-regex} option. Use this option to find out why your regular + expressions don't do what you expected them to do." + }; + // Prologues. // std::vector --hxx-prologue diff --git a/cli/options.cxx b/cli/options.cxx index 562a789..cdc2d41 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -601,6 +601,9 @@ options () class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -727,6 +730,9 @@ options (int& argc, class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -856,6 +862,9 @@ options (int start, class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -985,6 +994,9 @@ options (int& argc, class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -1116,6 +1128,9 @@ options (int start, class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -1243,6 +1258,9 @@ options (::cli::scanner& s, class__specified_ (false), docvar_ (), docvar_specified_ (false), + link_regex_ (), + link_regex_specified_ (false), + link_regex_trace_ (), hxx_prologue_ (), hxx_prologue_specified_ (false), ixx_prologue_ (), @@ -1415,6 +1433,13 @@ print_usage (::std::ostream& os, ::cli::usage_para p) os << "--docvar|-v = Set documentation variable to the value" << ::std::endl << " ." << ::std::endl; + os << "--link-regex Add to the list of regular expressions" << ::std::endl + << " used to transform link targets in the generated" << ::std::endl + << " documentation." << ::std::endl; + + os << "--link-regex-trace Trace the process of applying regular expressions" << ::std::endl + << " specified with the --link-regex option." << ::std::endl; + os << "--hxx-prologue Insert at the beginning of the generated" << ::std::endl << " C++ header file." << ::std::endl; @@ -1628,6 +1653,11 @@ struct _cli_options_map_init _cli_options_map_["-v"] = &::cli::thunk< options, std::map, &options::docvar_, &options::docvar_specified_ >; + _cli_options_map_["--link-regex"] = + &::cli::thunk< options, std::vector, &options::link_regex_, + &options::link_regex_specified_ >; + _cli_options_map_["--link-regex-trace"] = + &::cli::thunk< options, bool, &options::link_regex_trace_ >; _cli_options_map_["--hxx-prologue"] = &::cli::thunk< options, std::vector, &options::hxx_prologue_, &options::hxx_prologue_specified_ >; diff --git a/cli/options.hxx b/cli/options.hxx index 1793343..5edd480 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -514,6 +514,15 @@ class options docvar_specified () const; const std::vector& + link_regex () const; + + bool + link_regex_specified () const; + + const bool& + link_regex_trace () const; + + const std::vector& hxx_prologue () const; bool @@ -803,6 +812,9 @@ class options bool class__specified_; std::map docvar_; bool docvar_specified_; + std::vector link_regex_; + bool link_regex_specified_; + bool link_regex_trace_; std::vector hxx_prologue_; bool hxx_prologue_specified_; std::vector ixx_prologue_; diff --git a/cli/options.ixx b/cli/options.ixx index 618d15f..95c1038 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -452,6 +452,24 @@ docvar_specified () const } inline const std::vector& options:: +link_regex () const +{ + return this->link_regex_; +} + +inline bool options:: +link_regex_specified () const +{ + return this->link_regex_specified_; +} + +inline const bool& options:: +link_regex_trace () const +{ + return this->link_regex_trace_; +} + +inline const std::vector& options:: hxx_prologue () const { return this->hxx_prologue_; -- cgit v1.1