summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/context.cxx51
-rw-r--r--cli/context.hxx17
-rw-r--r--cli/html.cxx63
-rw-r--r--cli/man.cxx59
-rw-r--r--cli/options.cli20
-rw-r--r--cli/options.cxx22
-rw-r--r--cli/options.hxx8
-rw-r--r--cli/options.ixx12
-rw-r--r--cli/source.cxx39
9 files changed, 217 insertions, 74 deletions
diff --git a/cli/context.cxx b/cli/context.cxx
index 86de357..b3aebc8 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -1594,6 +1594,57 @@ ns_close (const string& qn, bool last)
} while (true);
}
+class_doc context::
+class_doc (semantics::class_& c)
+{
+ typedef map<string, string> map;
+ const map& m (options.class_doc ());
+
+ string n (c.fq_name ());
+
+ map::const_iterator i (m.find (n));
+
+ if (i == m.end ())
+ {
+ n = string (n, 2, string::npos); // Try without leading '::'.
+ i = m.find (n);
+ }
+
+ if (i == m.end ())
+ return cd_default;
+
+ const string& k (i->second);
+
+ if (k == "exclude")
+ return cd_exclude;
+ else if (k == "short")
+ return cd_short;
+ else if (k == "long")
+ return cd_long;
+ else
+ {
+ cerr << "error: unknown --class-doc kind value '" << k << "'" << endl;
+ throw generation_failed ();
+ }
+}
+
+string context::
+first_sentence (string const& s)
+{
+ size_t p (s.find ('.'));
+
+ // Add some heuristics here: check that there is a space
+ // (or end of text) after the period.
+ //
+ while (p != string::npos &&
+ p + 1 <= s.size () &&
+ s[p + 1] != ' ' &&
+ s[p + 1] != '\n')
+ p = s.find ('.', p + 1);
+
+ return p == string::npos ? s : string (s, 0, p + 1);
+}
+
// namespace
//
diff --git a/cli/context.hxx b/cli/context.hxx
index 460287c..f16f8c2 100644
--- a/cli/context.hxx
+++ b/cli/context.hxx
@@ -30,6 +30,14 @@ enum usage
ut_both
};
+enum class_doc
+{
+ cd_default,
+ cd_exclude,
+ cd_short,
+ cd_long
+};
+
class context
{
public:
@@ -38,6 +46,7 @@ public:
typedef ::options options_type;
typedef ::usage usage_type;
+ typedef ::class_doc class_doc_type;
private:
struct data;
@@ -153,6 +162,14 @@ public:
ns_close (const string& name, bool last = true);
public:
+ class_doc_type
+ class_doc (semantics::class_&);
+
+public:
+ string
+ first_sentence (string const&);
+
+public:
context (std::ostream&, semantics::cli_unit&, options_type const&);
context (context&);
diff --git a/cli/html.cxx b/cli/html.cxx
index 6659bf6..7f68453 100644
--- a/cli/html.cxx
+++ b/cli/html.cxx
@@ -114,7 +114,8 @@ namespace
struct doc: traversal::doc, context
{
- doc (context& c, bool& l): context (c), list_ (l) {}
+ doc (context& c, class_doc_type cd, bool& l)
+ : context (c), cd_ (cd), list_ (l) {}
virtual void
traverse (type& ds)
@@ -124,10 +125,15 @@ namespace
// n = 1 - common doc string
// n = 2 - arg string, common doc string
- // n > 2 - arg string, usage string, man string
+ // n > 2 - arg string, short string, long string
//
size_t n (ds.size ());
- const string& d (n == 1 ? ds[0] : n == 2 ? ds[1] : ds[2]);
+ const string& d (
+ n == 1
+ ? (cd_ == cd_short ? first_sentence (ds[0]) : ds[0])
+ : (n == 2
+ ? (cd_ == cd_short ? first_sentence (ds[1]) : ds[1])
+ : ds[cd_ == cd_short ? 1 : 2]));
std::set<string> arg_set;
if (n > 1)
@@ -151,12 +157,14 @@ namespace
}
private:
+ class_doc_type cd_;
bool& list_; // True if we are currently in <dl>.
};
struct option: traversal::option, context
{
- option (context& c, bool& l): context (c), list_ (l) {}
+ option (context& c, class_doc_type cd, bool& l)
+ : context (c), cd_ (cd), list_ (l) {}
virtual void
traverse (type& o)
@@ -206,23 +214,19 @@ namespace
os << "</dt>" << endl;
string d;
-
- // If we have both the long and the short descriptions, use
- // the long one.
- //
if (type == "bool" && doc.size () < 3)
{
if (doc.size () > 1)
- d = doc[1];
+ d = doc[cd_ == cd_short ? 0 : 1];
else if (doc.size () > 0)
- d = doc[0];
+ d = (cd_ == cd_short ? first_sentence (doc[0]) : doc[0]);
}
else
{
if (doc.size () > 2)
- d = doc[2];
+ d = doc[cd_ == cd_short ? 1 : 2];
else if (doc.size () > 1)
- d = doc[1];
+ d = (cd_ == cd_short ? first_sentence (doc[1]) : doc[1]);
}
// Format the documentation string.
@@ -234,6 +238,7 @@ namespace
}
private:
+ class_doc_type cd_;
bool& list_; // True if we are currently in <dl>.
};
@@ -241,19 +246,36 @@ namespace
//
struct class_: traversal::class_, context
{
- class_ (context& c): context (c) {}
+ class_ (context& c, bool& l): context (c), list_ (l)
+ {
+ *this >> inherits_ >> *this;
+ }
virtual void
traverse (type& c)
{
+ class_doc_type cd (class_doc (c));
+
+ if (cd == cd_exclude)
+ return;
+
if (!options.exclude_base () && !options.include_base_last ())
inherits (c);
- names (c);
+ doc dc (*this, cd, list_);
+ option op (*this, cd, list_);
+ traversal::names n;
+ n >> dc;
+ n >> op;
+ names (c, n);
if (!options.exclude_base () && options.include_base_last ())
inherits (c);
}
+
+ private:
+ bool& list_;
+ traversal::inherits inherits_;
};
}
@@ -265,8 +287,8 @@ generate_html (context& ctx)
traversal::cli_unit unit;
traversal::names unit_names;
traversal::namespace_ ns;
- doc dc (ctx, list);
- class_ cl (ctx);
+ doc dc (ctx, cd_default, list);
+ class_ cl (ctx, list);
unit >> unit_names;
unit_names >> dc;
unit_names >> ns;
@@ -278,15 +300,6 @@ generate_html (context& ctx)
ns_names >> ns;
ns_names >> cl;
- traversal::inherits cl_inherits;
- cl >> cl_inherits >> cl;
-
- option op (ctx, list);
- traversal::names cl_names;
- cl >> cl_names;
- cl_names >> dc;
- cl_names >> op;
-
if (ctx.options.class_ ().empty ())
unit.dispatch (ctx.unit);
else
diff --git a/cli/man.cxx b/cli/man.cxx
index 606fec6..b7bce6f 100644
--- a/cli/man.cxx
+++ b/cli/man.cxx
@@ -70,7 +70,7 @@ namespace
struct doc: traversal::doc, context
{
- doc (context& c): context (c) {}
+ doc (context& c, class_doc_type cd): context (c), cd_ (cd) {}
virtual void
traverse (type& ds)
@@ -80,10 +80,15 @@ namespace
// n = 1 - common doc string
// n = 2 - arg string, common doc string
- // n > 2 - arg string, usage string, man string
+ // n > 2 - arg string, short string, long string
//
size_t n (ds.size ());
- const string& d (n == 1 ? ds[0] : n == 2 ? ds[1] : ds[2]);
+ const string& d (
+ n == 1
+ ? (cd_ == cd_short ? first_sentence (ds[0]) : ds[0])
+ : (n == 2
+ ? (cd_ == cd_short ? first_sentence (ds[1]) : ds[1])
+ : ds[cd_ == cd_short ? 1 : 2]));
std::set<string> arg_set;
if (n > 1)
@@ -97,11 +102,14 @@ namespace
wrap_lines (os, s);
os << endl;
}
+
+ private:
+ class_doc_type cd_;
};
struct option: traversal::option, context
{
- option (context& c) : context (c) {}
+ option (context& c, class_doc_type cd) : context (c), cd_ (cd) {}
virtual void
traverse (type& o)
@@ -143,23 +151,19 @@ namespace
os << "\"" << endl;
string d;
-
- // If we have both the long and the short descriptions, use
- // the long one.
- //
if (type == "bool" && doc.size () < 3)
{
if (doc.size () > 1)
- d = doc[1];
+ d = doc[cd_ == cd_short ? 0 : 1];
else if (doc.size () > 0)
- d = doc[0];
+ d = (cd_ == cd_short ? first_sentence (doc[0]) : doc[0]);
}
else
{
if (doc.size () > 2)
- d = doc[2];
+ d = doc[cd_ == cd_short ? 1 : 2];
else if (doc.size () > 1)
- d = doc[1];
+ d = (cd_ == cd_short ? first_sentence (doc[1]) : doc[1]);
}
// Format the documentation string.
@@ -169,25 +173,41 @@ namespace
wrap_lines (os, d);
os << endl;
}
+
+ private:
+ class_doc_type cd_;
};
//
//
struct class_: traversal::class_, context
{
- class_ (context& c): context (c) {}
+ class_ (context& c): context (c) {*this >> inherits_ >> *this;}
virtual void
traverse (type& c)
{
+ class_doc_type cd (class_doc (c));
+
+ if (cd == cd_exclude)
+ return;
+
if (!options.exclude_base () && !options.include_base_last ())
inherits (c);
- names (c);
+ doc dc (*this, cd);
+ option op (*this, cd);
+ traversal::names n;
+ n >> dc;
+ n >> op;
+ names (c, n);
if (!options.exclude_base () && options.include_base_last ())
inherits (c);
}
+
+ private:
+ traversal::inherits inherits_;
};
}
@@ -197,7 +217,7 @@ generate_man (context& ctx)
traversal::cli_unit unit;
traversal::names unit_names;
traversal::namespace_ ns;
- doc dc (ctx);
+ doc dc (ctx, cd_default);
class_ cl (ctx);
unit >> unit_names;
unit_names >> ns;
@@ -210,15 +230,6 @@ generate_man (context& ctx)
ns_names >> dc;
ns_names >> cl;
- traversal::inherits cl_inherits;
- cl >> cl_inherits >> cl;
-
- option op (ctx);
- traversal::names cl_names;
- cl >> cl_names;
- cl_names >> dc;
- cl_names >> op;
-
if (ctx.options.class_ ().empty ())
unit.dispatch (ctx.unit);
else
diff --git a/cli/options.cli b/cli/options.cli
index 9212024..9554d10 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -182,11 +182,25 @@ class options
By default, base classes are included first."
};
+ std::map<std::string, std::string> --class-doc
+ {
+ "<name>=<kind>",
+ "Specify the documentation <kind> that should be used for the options
+ class <name>. The <name> value should be a fully-qualified class name,
+ for example, \cb{app::options}. The <kind> value can be \cb{short},
+ \cb{long}, or \cb{exclude}. If the value is \cb{exclude}, then the
+ class documentation is excluded from usage and man/HTML output. For
+ usage, the \cb{short} and \cb{long} values determine which usage
+ function will be called when the class is used as base or as part of
+ the page usage (see \cb{--page-usage}). For man/HTML, these values
+ determine which documentation strings are used in the output."
+ };
+
std::vector<std::string> --class
{
- "<fq-name>",
- "Generate the man page or HTML documentation only for the <fq-name> options
- class. The <fq-name> name should be a fully-qualified options class name,
+ "<name>",
+ "Generate the man page or HTML documentation only for the options class
+ <name>. The <name> value should be a fully-qualified options class name,
for example, \cb{app::options}. To generate documentation for multiple
classes, repeat this option and the documentation will be produced in
the order specified. This functionality is useful if you need to assemble
diff --git a/cli/options.cxx b/cli/options.cxx
index 6869a60..95f2a6c 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -592,6 +592,8 @@ options ()
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -699,6 +701,8 @@ options (int& argc,
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -809,6 +813,8 @@ options (int start,
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -919,6 +925,8 @@ options (int& argc,
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -1031,6 +1039,8 @@ options (int start,
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -1139,6 +1149,8 @@ options (::cli::scanner& s,
ansi_color_ (),
exclude_base_ (),
include_base_last_ (),
+ class_doc_ (),
+ class_doc_specified_ (false),
class__ (),
class__specified_ (false),
docvar_ (),
@@ -1286,8 +1298,11 @@ print_usage (::std::ostream& os, ::cli::usage_para p)
os << "--include-base-last Include base class information after derived for" << ::std::endl
<< " usage and documentation." << ::std::endl;
- os << "--class <fq-name> Generate the man page or HTML documentation only" << ::std::endl
- << " for the <fq-name> options class." << ::std::endl;
+ os << "--class-doc <name>=<kind> Specify the documentation <kind> that should be" << ::std::endl
+ << " used for the options class <name>." << ::std::endl;
+
+ os << "--class <name> Generate the man page or HTML documentation only" << ::std::endl
+ << " for the options class <name>." << ::std::endl;
os << "--docvar|-v <name>=<val> Set documentation variable <name> to the value" << ::std::endl
<< " <val>." << ::std::endl;
@@ -1467,6 +1482,9 @@ struct _cli_options_map_init
&::cli::thunk< options, bool, &options::exclude_base_ >;
_cli_options_map_["--include-base-last"] =
&::cli::thunk< options, bool, &options::include_base_last_ >;
+ _cli_options_map_["--class-doc"] =
+ &::cli::thunk< options, std::map<std::string, std::string>, &options::class_doc_,
+ &options::class_doc_specified_ >;
_cli_options_map_["--class"] =
&::cli::thunk< options, std::vector<std::string>, &options::class__,
&options::class__specified_ >;
diff --git a/cli/options.hxx b/cli/options.hxx
index 0612882..268e0fd 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -484,6 +484,12 @@ class options
const bool&
include_base_last () const;
+ const std::map<std::string, std::string>&
+ class_doc () const;
+
+ bool
+ class_doc_specified () const;
+
const std::vector<std::string>&
class_ () const;
@@ -735,6 +741,8 @@ class options
bool ansi_color_;
bool exclude_base_;
bool include_base_last_;
+ std::map<std::string, std::string> class_doc_;
+ bool class_doc_specified_;
std::vector<std::string> class__;
bool class__specified_;
std::map<std::string, std::string> docvar_;
diff --git a/cli/options.ixx b/cli/options.ixx
index 24dc37b..3adfbd0 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -397,6 +397,18 @@ include_base_last () const
return this->include_base_last_;
}
+inline const std::map<std::string, std::string>& options::
+class_doc () const
+{
+ return this->class_doc_;
+}
+
+inline bool options::
+class_doc_specified () const
+{
+ return this->class_doc_specified_;
+}
+
inline const std::vector<std::string>& options::
class_ () const
{
diff --git a/cli/source.cxx b/cli/source.cxx
index 2cb317d..7bf5e8d 100644
--- a/cli/source.cxx
+++ b/cli/source.cxx
@@ -533,24 +533,6 @@ namespace
}
private:
- string
- first_sentence (string const& s)
- {
- size_t p (s.find ('.'));
-
- // Add some heuristics here: check that there is a space
- // (or end of text) after the period.
- //
- while (p != string::npos &&
- p + 1 <= s.size () &&
- s[p + 1] != ' ' &&
- s[p + 1] != '\n')
- p = s.find ('.', p + 1);
-
- return p == string::npos ? s : string (s, 0, p + 1);
- }
-
- private:
size_t length_;
usage_type usage_;
paragraph& para_;
@@ -596,7 +578,15 @@ namespace
virtual void
traverse (type& c)
{
- const char* t (usage != ut_both || usage_ == ut_short ? "" : "long_");
+ class_doc_type cd (class_doc (c));
+
+ if (cd == cd_exclude)
+ return;
+
+ const char* t (
+ (cd == cd_default
+ ? usage != ut_both || usage_ == ut_short
+ : cd == cd_short) ? "" : "long_");
os << "// " << escape (c.name ()) << " base" << endl
<< "//" << endl
@@ -1098,12 +1088,21 @@ namespace
virtual void
traverse (type& c)
{
+ class_doc_type cd (class_doc (c));
+
+ if (cd == cd_exclude)
+ return;
+
+ const char* t (
+ (cd == cd_default
+ ? usage != ut_both || usage_ == ut_short
+ : cd == cd_short) ? "" : "long_");
+
string p (
para_ == para_unknown
? "p"
: cli + "::usage_para::" + (para_ == para_text ? "text" : "option"));
- const char* t (usage != ut_both || usage_ == ut_short ? "" : "long_");
os << "p = " << fq_name (c) << "::print_" << t << "usage (os, " <<
p << ");"
<< endl;