summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--doc/cli.118
-rw-r--r--doc/cli.xhtml31
11 files changed, 253 insertions, 87 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;
diff --git a/doc/cli.1 b/doc/cli.1
index 1a89aed..57fd6c2 100644
--- a/doc/cli.1
+++ b/doc/cli.1
@@ -149,10 +149,20 @@ Exclude base class information from usage and documentation\.
.IP "\fB--include-base-last\fR"
Include base class information after derived for usage and documentation\. By
default, base classes are included first\.
-.IP "\fB--class\fR \fIfq-name\fR"
-Generate the man page or HTML documentation only for the \fIfq-name\fR options
-class\. The \fIfq-name\fR name should be a fully-qualified options class name,
-for example, \fBapp::options\fR\. To generate documentation for multiple
+.IP "\fB--class-doc\fR \fIname\fR=\fIkind\fR"
+Specify the documentation \fIkind\fR that should be used for the options class
+\fIname\fR\. The \fIname\fR value should be a fully-qualified class name, for
+example, \fBapp::options\fR\. The \fIkind\fR value can be \fBshort\fR,
+\fBlong\fR, or \fBexclude\fR\. If the value is \fBexclude\fR, then the class
+documentation is excluded from usage and man/HTML output\. For usage, the
+\fBshort\fR and \fBlong\fR values determine which usage function will be
+called when the class is used as base or as part of the page usage (see
+\fB--page-usage\fR)\. For man/HTML, these values determine which documentation
+strings are used in the output\.
+.IP "\fB--class\fR \fIname\fR"
+Generate the man page or HTML documentation only for the options class
+\fIname\fR\. The \fIname\fR value should be a fully-qualified options class
+name, for example, \fBapp::options\fR\. 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
documentation from multiple classes in a specific order or to insert custom
diff --git a/doc/cli.xhtml b/doc/cli.xhtml
index 4d80b83..962d53b 100644
--- a/doc/cli.xhtml
+++ b/doc/cli.xhtml
@@ -197,15 +197,28 @@
<dd>Include base class information after derived for usage and
documentation. By default, base classes are included first.</dd>
- <dt><code><b>--class</b></code> <i>fq-name</i></dt>
- <dd>Generate the man page or HTML documentation only for the
- <i>fq-name</i> options class. The <i>fq-name</i> name should be a
- fully-qualified options class name, for example,
- <code><b>app::options</b></code>. 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
- documentation from multiple classes in a specific order or to insert
- custom documentation between options belonging to different classes.</dd>
+ <dt><code><b>--class-doc</b></code> <i>name</i>=<i>kind</i></dt>
+ <dd>Specify the documentation <i>kind</i> that should be used for the
+ options class <i>name</i>. The <i>name</i> value should be a
+ fully-qualified class name, for example, <code><b>app::options</b></code>.
+ The <i>kind</i> value can be <code><b>short</b></code>,
+ <code><b>long</b></code>, or <code><b>exclude</b></code>. If the value is
+ <code><b>exclude</b></code>, then the class documentation is excluded from
+ usage and man/HTML output. For usage, the <code><b>short</b></code> and
+ <code><b>long</b></code> values determine which usage function will be
+ called when the class is used as base or as part of the page usage (see
+ <code><b>--page-usage</b></code>). For man/HTML, these values determine
+ which documentation strings are used in the output.</dd>
+
+ <dt><code><b>--class</b></code> <i>name</i></dt>
+ <dd>Generate the man page or HTML documentation only for the options class
+ <i>name</i>. The <i>name</i> value should be a fully-qualified options
+ class name, for example, <code><b>app::options</b></code>. 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 documentation from multiple classes in a
+ specific order or to insert custom documentation between options belonging
+ to different classes.</dd>
<dt><code><b>--docvar</b></code>|<code><b>-v</b></code> <i>name</i>=<i>val</i></dt>
<dd>Set documentation variable <i>name</i> to the value <i>val</i>.