summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-11-17 13:59:39 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-11-17 13:59:39 +0200
commit0e56fe29a9afeee00e02e722496678df89d37d50 (patch)
treeada5f6ea6978344f2e75e6194d65a1191cc6e649 /cli
parent577a38358b295379511ea8bb130ef1dcb7157c0f (diff)
Complete the implementation of the option documentation
Add the man page generator. Port CLI usage, HTML documentation and the man page to the auto-generated version. Update examples and documentation.
Diffstat (limited to 'cli')
-rw-r--r--cli/context.cxx79
-rw-r--r--cli/context.hxx9
-rw-r--r--cli/generator.cxx129
-rw-r--r--cli/html.cxx12
-rw-r--r--cli/makefile1
-rw-r--r--cli/man.cxx163
-rw-r--r--cli/man.hxx14
-rw-r--r--cli/options.cli114
-rw-r--r--cli/options.cxx107
-rw-r--r--cli/options.hxx36
-rw-r--r--cli/options.ixx54
-rw-r--r--cli/source.cxx8
12 files changed, 650 insertions, 76 deletions
diff --git a/cli/context.cxx b/cli/context.cxx
index ccd3c8b..05e15cc 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -309,7 +309,19 @@ format (string const& s, output_type ot)
{
case '\\':
{
- r += '\\';
+ switch (ot)
+ {
+ case ot_man:
+ {
+ r += "\\e";
+ break;
+ }
+ default:
+ {
+ r += '\\';
+ break;
+ }
+ }
break;
}
case '"':
@@ -461,6 +473,12 @@ format (string const& s, output_type ot)
switch (ot)
{
+ case ot_plain:
+ {
+ if (b & 1)
+ r += "'";
+ break;
+ }
case ot_html:
{
if (b & 1)
@@ -474,6 +492,17 @@ format (string const& s, output_type ot)
break;
}
+ case ot_man:
+ {
+ if ((b & 6) == 6)
+ r += "\\f(BI";
+ else if (b & 2)
+ r += "\\fI";
+ else if (b & 4)
+ r += "\\fB";
+
+ break;
+ }
default:
break;
}
@@ -490,6 +519,7 @@ format (string const& s, output_type ot)
switch (ot)
{
case ot_plain:
+ case ot_man:
{
r += '\n';
break;
@@ -506,25 +536,43 @@ format (string const& s, output_type ot)
}
}
}
+ else if (s[i] == '.')
+ {
+ if (ot == ot_man)
+ r += "\\.";
+ else
+ r += '.';
+ }
else if (!blocks.empty () && s[i] == '}')
{
unsigned char b (blocks.top ());
switch (ot)
{
- case ot_html:
+ case ot_plain:
{
if (b & 1)
- r += "</code>";
+ r += "'";
+ break;
+ }
+ case ot_html:
+ {
+ if (b & 4)
+ r += "</b>";
if (b & 2)
r += "</i>";
- if (b & 4)
- r += "</b>";
+ if (b & 1)
+ r += "</code>";
break;
}
+ case ot_man:
+ {
+ if (b & 6)
+ r += "\\fP";
+ }
default:
break;
}
@@ -541,6 +589,27 @@ format (string const& s, output_type ot)
return r;
}
+string context::
+fq_name (semantics::nameable& n, bool cxx_name)
+{
+ using namespace semantics;
+
+ string r;
+
+ if (dynamic_cast<cli_unit*> (&n))
+ {
+ return ""; // Map to global namespace.
+ }
+ else
+ {
+ r = fq_name (n.scope ());
+ r += "::";
+ r += cxx_name ? escape (n.name ()) : n.name ();
+ }
+
+ return r;
+}
+
// namespace
//
diff --git a/cli/context.hxx b/cli/context.hxx
index f6d53c3..30539af 100644
--- a/cli/context.hxx
+++ b/cli/context.hxx
@@ -70,7 +70,8 @@ public:
enum output_type
{
ot_plain,
- ot_html
+ ot_html,
+ ot_man
};
static string
@@ -96,6 +97,12 @@ public:
}
public:
+ // Return fully-qualified C++ or CLI name.
+ //
+ string
+ fq_name (semantics::nameable& n, bool cxx_name = true);
+
+public:
context (std::ostream&, semantics::cli_unit&, options_type const&);
context (context&);
diff --git a/cli/generator.cxx b/cli/generator.cxx
index 6043825..7531ffe 100644
--- a/cli/generator.cxx
+++ b/cli/generator.cxx
@@ -21,6 +21,7 @@
#include "runtime-inline.hxx"
#include "runtime-source.hxx"
+#include "man.hxx"
#include "html.hxx"
#include "context.hxx"
@@ -35,10 +36,23 @@ using semantics::path;
namespace
{
- static char const header[] =
- "// This code was generated by CLI, a command line interface\n"
- "// compiler for C++.\n"
- "//\n\n";
+ static char const cxx_header[] =
+ "// This code was generated by CLI, a command line interface\n"
+ "// compiler for C++.\n"
+ "//\n\n";
+
+ static char const man_header[] =
+ ".\\\"\n"
+ ".\\\" The following documentation was generated by CLI, a command\n"
+ ".\\\" line interface compiler for C++.\n"
+ ".\\\"\n";
+
+ static char const html_header[] =
+ "\n"
+ "<!-- \n"
+ " The following documentation was generated by CLI, a command\n"
+ " line interface compiler for C++.\n"
+ "-->\n\n";
string
make_guard (string const& file, context& ctx)
@@ -63,6 +77,18 @@ namespace
return ctx.escape (r);
}
+
+ void
+ open (ifstream& ifs, string const& path)
+ {
+ ifs.open (path.c_str (), ios_base::in | ios_base::binary);
+
+ if (!ifs.is_open ())
+ {
+ cerr << path << ": error: unable to open in read mode" << endl;
+ throw generator::failed ();
+ }
+ }
}
generator::
@@ -103,6 +129,8 @@ generate (options const& ops, semantics::cli_unit& unit, path const& p)
fs::auto_removes auto_rm;
+ // C++ output.
+ //
if (gen_cxx)
{
bool inl (!ops.suppress_inline ());
@@ -177,10 +205,10 @@ generate (options const& ops, semantics::cli_unit& unit, path const& p)
// Print headers.
//
- hxx << header;
+ hxx << cxx_header;
if (inl)
- ixx << header;
- cxx << header;
+ ixx << cxx_header;
+ cxx << cxx_header;
typedef
compiler::ostream_filter<compiler::cxx_indenter, char>
@@ -255,8 +283,83 @@ generate (options const& ops, semantics::cli_unit& unit, path const& p)
}
}
+ // man output
+ //
+ if (gen_man)
+ {
+ // Prologue & epilogue.
+ //
+ ifstream prologue, epilogue;
+ {
+ string file (ops.man_prologue ());
+
+ if (!file.empty ())
+ open (prologue, file);
+ }
+
+ {
+ string file (ops.man_epilogue ());
+
+ if (!file.empty ())
+ open (epilogue, file);
+ }
+
+ ofstream man;
+
+ if (!ops.stdout ())
+ {
+ path man_path (base + ops.man_suffix ());
+
+ if (!ops.output_dir ().empty ())
+ man_path = path (ops.output_dir ()) / man_path;
+
+ man.open (man_path.string ().c_str ());
+
+ if (!man.is_open ())
+ {
+ cerr << "error: unable to open '" << man_path << "' in write mode"
+ << endl;
+ throw failed ();
+ }
+
+ auto_rm.add (man_path);
+ }
+
+ ostream& os (ops.stdout () ? cout : man);
+
+ if (prologue.is_open ())
+ os << prologue.rdbuf ();
+
+ os << man_header;
+
+ context ctx (os, unit, ops);
+ generate_man (ctx);
+
+ if (epilogue.is_open ())
+ os << epilogue.rdbuf ();
+ }
+
+ // HTML output
+ //
if (gen_html)
{
+ // Prologue & epilogue.
+ //
+ ifstream prologue, epilogue;
+ {
+ string file (ops.html_prologue ());
+
+ if (!file.empty ())
+ open (prologue, file);
+ }
+
+ {
+ string file (ops.html_epilogue ());
+
+ if (!file.empty ())
+ open (epilogue, file);
+ }
+
ofstream html;
if (!ops.stdout ())
@@ -278,8 +381,18 @@ generate (options const& ops, semantics::cli_unit& unit, path const& p)
auto_rm.add (html_path);
}
- context ctx (ops.stdout () ? cout : html, unit, ops);
+ ostream& os (ops.stdout () ? cout : html);
+
+ if (prologue.is_open ())
+ os << prologue.rdbuf ();
+
+ os << html_header;
+
+ context ctx (os, unit, ops);
generate_html (ctx);
+
+ if (epilogue.is_open ())
+ os << epilogue.rdbuf ();
}
auto_rm.cancel ();
diff --git a/cli/html.cxx b/cli/html.cxx
index b147703..be675c7 100644
--- a/cli/html.cxx
+++ b/cli/html.cxx
@@ -162,6 +162,17 @@ namespace
virtual void
traverse (type& c)
{
+ string const& n (options.class_ ());
+
+ if (!n.empty ())
+ {
+ string fqn (fq_name (c, false));
+ fqn = string (fqn, 2, fqn.size () - 2); // Get rid of leading ::.
+
+ if (n != fqn)
+ return;
+ }
+
os << "<dl class=\"options\">" << endl;
names (c, names_option_);
@@ -170,6 +181,7 @@ namespace
}
private:
+ bool generated_;
option option_;
traversal::names names_option_;
};
diff --git a/cli/makefile b/cli/makefile
index 7edd27e..0ebba36 100644
--- a/cli/makefile
+++ b/cli/makefile
@@ -16,6 +16,7 @@ source.cxx \
runtime-header.cxx \
runtime-inline.cxx \
runtime-source.cxx \
+man.cxx \
html.cxx \
generator.cxx \
name-processor.cxx
diff --git a/cli/man.cxx b/cli/man.cxx
new file mode 100644
index 0000000..cb7822c
--- /dev/null
+++ b/cli/man.cxx
@@ -0,0 +1,163 @@
+// file : cli/man.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include "man.hxx"
+
+namespace
+{
+ struct option: traversal::option, context
+ {
+ option (context& c) : context (c) {}
+
+ virtual void
+ traverse (type& o)
+ {
+ using semantics::names;
+
+ names& n (o.named ());
+
+ os << ".IP \"\\fB";
+
+ for (names::name_iterator i (n.name_begin ()); i != n.name_end (); ++i)
+ {
+ if (i != n.name_begin ())
+ os << "\\fP|\\fB";
+
+ os << *i;
+ }
+
+ os << "\\fP";
+
+ type::doc_list const& doc (o.doc ());
+ string type (o.type ().name ());
+
+ std::set<string> arg_set;
+
+ if (type != "bool")
+ {
+ string s (
+ translate_arg (
+ doc.size () > 0 ? doc[0] : string ("<arg>"), arg_set));
+
+ os << ' ' << format (s, ot_man);
+ }
+
+ os << "\"" << endl;
+
+ string d;
+
+ // If we have both the long and the short descriptions, use
+ // the long one.
+ //
+ if (type == "bool")
+ {
+ if (doc.size () > 1)
+ d = doc[1];
+ else if (doc.size () > 0)
+ d = doc[0];
+ }
+ else
+ {
+ if (doc.size () > 2)
+ d = doc[2];
+ else if (doc.size () > 1)
+ d = doc[1];
+ }
+
+ // Format the documentation string.
+ //
+ d = format (translate (d, arg_set), ot_man);
+
+ if (!d.empty ())
+ {
+ size_t b (0), e (0), i (0);
+
+ for (size_t n (d.size ()); i < n; ++i)
+ {
+ if (d[i] == ' ' || d[i] == '\n')
+ e = i;
+
+ if (d[i] == '\n' || (i - b >= 76 && e != b))
+ {
+ if (b != 0)
+ os << endl;
+
+ os << string (d, b, e - b);
+
+ if (d[i] == '\n')
+ os << endl;
+
+ b = e = e + 1;
+ }
+ }
+
+ // Flush the last line.
+ //
+ if (b != i)
+ {
+ if (b != 0)
+ os << endl;
+
+ os << string (d, b, i - b);
+ }
+ }
+
+ os << endl
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct class_: traversal::class_, context
+ {
+ class_ (context& c)
+ : context (c), option_ (c)
+ {
+ names_option_ >> option_;
+ }
+
+ virtual void
+ traverse (type& c)
+ {
+ string const& n (options.class_ ());
+
+ if (!n.empty ())
+ {
+ string fqn (fq_name (c, false));
+ fqn = string (fqn, 2, fqn.size () - 2); // Get rid of leading ::.
+
+ if (n != fqn)
+ return;
+ }
+
+ names (c, names_option_);
+ }
+
+ private:
+ bool generated_;
+ option option_;
+ traversal::names names_option_;
+ };
+}
+
+void
+generate_man (context& ctx)
+{
+ traversal::cli_unit unit;
+ traversal::names unit_names;
+ traversal::namespace_ ns;
+ class_ cl (ctx);
+
+ unit >> unit_names >> ns;
+ unit_names >> cl;
+
+ traversal::names ns_names;
+
+ ns >> ns_names >> ns;
+ ns_names >> cl;
+
+ unit.dispatch (ctx.unit);
+}
diff --git a/cli/man.hxx b/cli/man.hxx
new file mode 100644
index 0000000..7a4100a
--- /dev/null
+++ b/cli/man.hxx
@@ -0,0 +1,14 @@
+// file : cli/man.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CLI_MAN_HXX
+#define CLI_MAN_HXX
+
+#include "context.hxx"
+
+void
+generate_man (context&);
+
+#endif // CLI_MAN_HXX
diff --git a/cli/options.cli b/cli/options.cli
index 1127553..085a26a 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -20,110 +20,170 @@ class options
std::string --output-dir | -o
{
"<dir>",
- "Write generated files to <dir>."
+ "Write the generated files to <dir> instead of the current directory."
};
bool --suppress-inline
{
- "Generate all functions non-inline."
+ "Generate all functions non-inline. By default simple functions are
+ made inline. This option suppresses creation of the inline file."
};
bool --suppress-usage
{
- "Suppress generation of usage printing code."
+ "Suppress the generation of the usage printing code."
+ };
+
+ bool --long-usage
+ {
+ "If no short documentation string is provided, use the complete
+ long documentation string in usage. By default, in this situation
+ only the first sentence from the long string is used."
+ };
+
+ std::size_t --option-length = 0
+ {
+ "<len>",
+ "Indent option descriptions <len> characters when printing usage. This is
+ useful when you have multiple options classes, potentially in separate
+ files, and would like their usage to have the same indentation level."
};
bool --generate-cxx
{
- ""
+ "Generate C++ code. If neither \cb{--generate-man} nor \cb{--generate-html}
+ is specified, this mode is assumed by default."
};
bool --generate-man
{
- ""
+ "Generate documentation in the man page format."
};
bool --generate-html
{
- ""
+ "Generate documentation in the HTML format."
};
- bool --stdout
+ std::string --man-prologue
{
- ""
+ "<file>",
+ "Insert the content of <file> at the beginning of the man page file."
};
- std::size_t --option-length = 0
+ std::string --man-epilogue
{
- "<len>",
- "Indent option description <len> characters when printing usage."
+ "<file>",
+ "Insert the content of <file> at the end of the man page file."
+ };
+
+ std::string --html-prologue
+ {
+ "<file>",
+ "Insert the content of <file> at the beginning of the HTML file."
+ };
+
+ std::string --html-epilogue
+ {
+ "<file>",
+ "Insert the content of <file> at the end of the HTML file."
+ };
+
+ 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,
+ for example, \cb{app::options}. This functionality is useful if you need
+ to insert custom documentation between options belonging to different
+ classes."
+ };
+
+ bool --stdout
+ {
+ "Write output to STDOUT instead of a file. This option is not valid
+ when generating C++ code and is normally used to combine generated
+ documentation for several option classes in a single file."
};
std::string --hxx-suffix = ".hxx"
{
"<suffix>",
- "Use <suffix> instead of the default '.hxx' to construct the name of
+ "Use <suffix> instead of the default \cb{.hxx} to construct the name of
the generated header file."
};
std::string --ixx-suffix = ".ixx"
{
"<suffix>",
- "Use <suffix> instead of the default '.ixx' to construct the name of
+ "Use <suffix> instead of the default \cb{.ixx} to construct the name of
the generated inline file."
};
std::string --cxx-suffix = ".cxx"
{
"<suffix>",
- "Use <suffix> instead of the default '.cxx' to construct the name of
+ "Use <suffix> instead of the default \cb{.cxx} to construct the name of
the generated source file."
};
+ std::string --man-suffix = ".1"
+ {
+ "<suffix>",
+ "Use <suffix> instead of the default \cb{.1} to construct the name of
+ the generated man page file."
+ };
+
std::string --html-suffix = ".html"
{
"<suffix>",
- "Use <suffix> instead of the default '.html' to construct the name of
- the generated HTML file."
+ "Use <suffix> instead of the default \cb{.html} to construct the name
+ of the generated HTML file."
};
std::string --option-prefix = "-"
{
"<prefix>",
- "Use <prefix> instead of the default '-' as an option prefix."
+ "Use <prefix> instead of the default \cb{-} as an option prefix. Unknown
+ command line arguments that start with this prefix are treated as unknown
+ options. If you set the option prefix to the empty value, then all the
+ unknown command line arguments will be treated as program arguments."
};
std::string --option-separator = "--"
{
"<sep>",
- "Use <sep> instead of the default '--' as an optional separator between
- options and arguments."
+ "Use <sep> instead of the default \cb{--} as an optional separator between
+ options and arguments. All the command line arguments that are parsed
+ after this separator are treated as program arguments. Set the option
+ separator to the empty value if you don't want this functionality."
};
bool --include-with-brackets
{
- "Use angle brackets (<>) instead of quotes (\"\") in generated #include
- directives."
+ "Use angle brackets (<>) instead of quotes (\"\") in the generated
+ \cb{#include} directives."
};
std::string --include-prefix
{
"<prefix>",
- "Add <prefix> to generated #include directive paths."
+ "Add <prefix> to the generated \cb{#include} directive paths."
};
std::string --guard-prefix
{
"<prefix>",
- "Add <prefix> to generated header inclusion guards."
+ "Add <prefix> to the generated header inclusion guards. The prefix is
+ transformed to upper case and characters that are illegal in a
+ preprocessor macro name are replaced with underscores."
};
std::map<std::string, std::string> --reserved-name
{
"<name>=<rep>",
- "Add <name> to the list of names that should not be used as identifiers.
- The name can optionally be followed by '=' and the <rep> replacement
- name that should be used instead.",
- ""
+ "Add <name> with an optional <rep> replacement to the list of names
+ that should not be used as identifiers. If provided, the replacement
+ name is used instead. All C++ keywords are already in this list."
};
};
diff --git a/cli/options.cxx b/cli/options.cxx
index 1f495b9..38ed14d 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -243,14 +243,21 @@ options (int argc,
output_dir_ (),
suppress_inline_ (),
suppress_usage_ (),
+ long_usage_ (),
+ option_length_ (0),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
+ man_prologue_ (),
+ man_epilogue_ (),
+ html_prologue_ (),
+ html_epilogue_ (),
+ class__ (),
stdout_ (),
- option_length_ (0),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
+ man_suffix_ (".1"),
html_suffix_ (".html"),
option_prefix_ ("-"),
option_separator_ ("--"),
@@ -273,14 +280,21 @@ options (int start,
output_dir_ (),
suppress_inline_ (),
suppress_usage_ (),
+ long_usage_ (),
+ option_length_ (0),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
+ man_prologue_ (),
+ man_epilogue_ (),
+ html_prologue_ (),
+ html_epilogue_ (),
+ class__ (),
stdout_ (),
- option_length_ (0),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
+ man_suffix_ (".1"),
html_suffix_ (".html"),
option_prefix_ ("-"),
option_separator_ ("--"),
@@ -303,14 +317,21 @@ options (int argc,
output_dir_ (),
suppress_inline_ (),
suppress_usage_ (),
+ long_usage_ (),
+ option_length_ (0),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
+ man_prologue_ (),
+ man_epilogue_ (),
+ html_prologue_ (),
+ html_epilogue_ (),
+ class__ (),
stdout_ (),
- option_length_ (0),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
+ man_suffix_ (".1"),
html_suffix_ (".html"),
option_prefix_ ("-"),
option_separator_ ("--"),
@@ -334,14 +355,21 @@ options (int start,
output_dir_ (),
suppress_inline_ (),
suppress_usage_ (),
+ long_usage_ (),
+ option_length_ (0),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
+ man_prologue_ (),
+ man_epilogue_ (),
+ html_prologue_ (),
+ html_epilogue_ (),
+ class__ (),
stdout_ (),
- option_length_ (0),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
+ man_suffix_ (".1"),
html_suffix_ (".html"),
option_prefix_ ("-"),
option_separator_ ("--"),
@@ -360,22 +388,41 @@ print_usage (::std::ostream& os)
os << "--version Print version and exit." << ::std::endl;
- os << "--output-dir|-o <dir> Write generated files to <dir>." << ::std::endl;
+ os << "--output-dir|-o <dir> Write the generated files to <dir> instead of the" << ::std::endl
+ << " current directory." << ::std::endl;
os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
- os << "--suppress-usage Suppress generation of usage printing code." << ::std::endl;
+ os << "--suppress-usage Suppress the generation of the usage printing code." << ::std::endl;
- os << "--generate-cxx" << std::endl;
+ os << "--long-usage If no short documentation string is provided, use" << ::std::endl
+ << " the complete long documentation string in usage." << ::std::endl;
- os << "--generate-man" << std::endl;
+ os << "--option-length <len> Indent option descriptions <len> characters when" << ::std::endl
+ << " printing usage." << ::std::endl;
- os << "--generate-html" << std::endl;
+ os << "--generate-cxx Generate C++ code." << ::std::endl;
- os << "--stdout" << std::endl;
+ os << "--generate-man Generate documentation in the man page format." << ::std::endl;
- os << "--option-length <len> Indent option description <len> characters when" << ::std::endl
- << " printing usage." << ::std::endl;
+ os << "--generate-html Generate documentation in the HTML format." << ::std::endl;
+
+ os << "--man-prologue <file> Insert the content of <file> at the beginning of" << ::std::endl
+ << " the man page file." << ::std::endl;
+
+ os << "--man-epilogue <file> Insert the content of <file> at the end of the man" << ::std::endl
+ << " page file." << ::std::endl;
+
+ os << "--html-prologue <file> Insert the content of <file> at the beginning of" << ::std::endl
+ << " the HTML file." << ::std::endl;
+
+ os << "--html-epilogue <file> Insert the content of <file> at the end of the HTML" << ::std::endl
+ << " file." << ::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 << "--stdout Write output to STDOUT instead of a file." << ::std::endl;
os << "--hxx-suffix <suffix> Use <suffix> instead of the default '.hxx' to" << ::std::endl
<< " construct the name of the generated header file." << ::std::endl;
@@ -386,6 +433,9 @@ print_usage (::std::ostream& os)
os << "--cxx-suffix <suffix> Use <suffix> instead of the default '.cxx' to" << ::std::endl
<< " construct the name of the generated source file." << ::std::endl;
+ os << "--man-suffix <suffix> Use <suffix> instead of the default '.1' to" << ::std::endl
+ << " construct the name of the generated man page file." << ::std::endl;
+
os << "--html-suffix <suffix> Use <suffix> instead of the default '.html' to" << ::std::endl
<< " construct the name of the generated HTML file." << ::std::endl;
@@ -396,16 +446,17 @@ print_usage (::std::ostream& os)
<< " optional separator between options and arguments." << ::std::endl;
os << "--include-with-brackets Use angle brackets (<>) instead of quotes (\"\") in" << ::std::endl
- << " generated #include directives." << ::std::endl;
+ << " the generated '#include' directives." << ::std::endl;
- os << "--include-prefix <prefix> Add <prefix> to generated #include directive paths." << ::std::endl;
+ os << "--include-prefix <prefix> Add <prefix> to the generated '#include' directive" << ::std::endl
+ << " paths." << ::std::endl;
- os << "--guard-prefix <prefix> Add <prefix> to generated header inclusion guards." << ::std::endl;
+ os << "--guard-prefix <prefix> Add <prefix> to the generated header inclusion" << ::std::endl
+ << " guards." << ::std::endl;
- os << "--reserved-name <name>=<rep> Add <name> to the list of names that should not be" << ::std::endl
- << " used as identifiers. The name can optionally be" << ::std::endl
- << " followed by '=' and the <rep> replacement name that" << ::std::endl
- << " should be used instead." << ::std::endl;
+ os << "--reserved-name <name>=<rep> Add <name> with an optional <rep> replacement to" << ::std::endl
+ << " the list of names that should not be used as" << ::std::endl
+ << " identifiers." << ::std::endl;
}
typedef
@@ -430,22 +481,36 @@ struct _cli_options_map_init
&::cli::thunk< options, bool, &options::suppress_inline_ >;
_cli_options_map_["--suppress-usage"] =
&::cli::thunk< options, bool, &options::suppress_usage_ >;
+ _cli_options_map_["--long-usage"] =
+ &::cli::thunk< options, bool, &options::long_usage_ >;
+ _cli_options_map_["--option-length"] =
+ &::cli::thunk< options, std::size_t, &options::option_length_ >;
_cli_options_map_["--generate-cxx"] =
&::cli::thunk< options, bool, &options::generate_cxx_ >;
_cli_options_map_["--generate-man"] =
&::cli::thunk< options, bool, &options::generate_man_ >;
_cli_options_map_["--generate-html"] =
&::cli::thunk< options, bool, &options::generate_html_ >;
+ _cli_options_map_["--man-prologue"] =
+ &::cli::thunk< options, std::string, &options::man_prologue_ >;
+ _cli_options_map_["--man-epilogue"] =
+ &::cli::thunk< options, std::string, &options::man_epilogue_ >;
+ _cli_options_map_["--html-prologue"] =
+ &::cli::thunk< options, std::string, &options::html_prologue_ >;
+ _cli_options_map_["--html-epilogue"] =
+ &::cli::thunk< options, std::string, &options::html_epilogue_ >;
+ _cli_options_map_["--class"] =
+ &::cli::thunk< options, std::string, &options::class__ >;
_cli_options_map_["--stdout"] =
&::cli::thunk< options, bool, &options::stdout_ >;
- _cli_options_map_["--option-length"] =
- &::cli::thunk< options, std::size_t, &options::option_length_ >;
_cli_options_map_["--hxx-suffix"] =
&::cli::thunk< options, std::string, &options::hxx_suffix_ >;
_cli_options_map_["--ixx-suffix"] =
&::cli::thunk< options, std::string, &options::ixx_suffix_ >;
_cli_options_map_["--cxx-suffix"] =
&::cli::thunk< options, std::string, &options::cxx_suffix_ >;
+ _cli_options_map_["--man-suffix"] =
+ &::cli::thunk< options, std::string, &options::man_suffix_ >;
_cli_options_map_["--html-suffix"] =
&::cli::thunk< options, std::string, &options::html_suffix_ >;
_cli_options_map_["--option-prefix"] =
diff --git a/cli/options.hxx b/cli/options.hxx
index 96f50e6..fdf7627 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -190,6 +190,12 @@ class options
suppress_usage () const;
const bool&
+ long_usage () const;
+
+ const std::size_t&
+ option_length () const;
+
+ const bool&
generate_cxx () const;
const bool&
@@ -198,12 +204,24 @@ class options
const bool&
generate_html () const;
+ const std::string&
+ man_prologue () const;
+
+ const std::string&
+ man_epilogue () const;
+
+ const std::string&
+ html_prologue () const;
+
+ const std::string&
+ html_epilogue () const;
+
+ const std::string&
+ class_ () const;
+
const bool&
stdout () const;
- const std::size_t&
- option_length () const;
-
const std::string&
hxx_suffix () const;
@@ -214,6 +232,9 @@ class options
cxx_suffix () const;
const std::string&
+ man_suffix () const;
+
+ const std::string&
html_suffix () const;
const std::string&
@@ -253,14 +274,21 @@ class options
std::string output_dir_;
bool suppress_inline_;
bool suppress_usage_;
+ bool long_usage_;
+ std::size_t option_length_;
bool generate_cxx_;
bool generate_man_;
bool generate_html_;
+ std::string man_prologue_;
+ std::string man_epilogue_;
+ std::string html_prologue_;
+ std::string html_epilogue_;
+ std::string class__;
bool stdout_;
- std::size_t option_length_;
std::string hxx_suffix_;
std::string ixx_suffix_;
std::string cxx_suffix_;
+ std::string man_suffix_;
std::string html_suffix_;
std::string option_prefix_;
std::string option_separator_;
diff --git a/cli/options.ixx b/cli/options.ixx
index 6cf5899..1745d4a 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -119,6 +119,18 @@ suppress_usage () const
}
inline const bool& options::
+long_usage () const
+{
+ return long_usage_;
+}
+
+inline const std::size_t& options::
+option_length () const
+{
+ return option_length_;
+}
+
+inline const bool& options::
generate_cxx () const
{
return generate_cxx_;
@@ -136,16 +148,40 @@ generate_html () const
return generate_html_;
}
-inline const bool& options::
-stdout () const
+inline const std::string& options::
+man_prologue () const
{
- return stdout_;
+ return man_prologue_;
}
-inline const std::size_t& options::
-option_length () const
+inline const std::string& options::
+man_epilogue () const
{
- return option_length_;
+ return man_epilogue_;
+}
+
+inline const std::string& options::
+html_prologue () const
+{
+ return html_prologue_;
+}
+
+inline const std::string& options::
+html_epilogue () const
+{
+ return html_epilogue_;
+}
+
+inline const std::string& options::
+class_ () const
+{
+ return class__;
+}
+
+inline const bool& options::
+stdout () const
+{
+ return stdout_;
}
inline const std::string& options::
@@ -167,6 +203,12 @@ cxx_suffix () const
}
inline const std::string& options::
+man_suffix () const
+{
+ return man_suffix_;
+}
+
+inline const std::string& options::
html_suffix () const
{
return html_suffix_;
diff --git a/cli/source.cxx b/cli/source.cxx
index 4cfd425..f473665 100644
--- a/cli/source.cxx
+++ b/cli/source.cxx
@@ -188,7 +188,7 @@ namespace
// If we have both the long and the short descriptions, use
// the short one. Otherwise, use the first sentence from the
- // long one.
+ // long one ubless --long-usage was specified.
//
string d;
@@ -197,14 +197,14 @@ namespace
if (doc.size () > 1)
d = doc[0];
else if (doc.size () > 0)
- d = frist_sentence (doc[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 = frist_sentence (doc[1]);
+ d = options.long_usage () ? doc[1] : first_sentence (doc[1]);
}
// Format the documentation string.
@@ -281,7 +281,7 @@ namespace
}
string
- frist_sentence (string const& s)
+ first_sentence (string const& s)
{
size_t p (s.find ('.'));