summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-11-16 11:43:19 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-11-16 11:43:19 +0200
commit5a2da5767e796bcfdaf5ebf3b80b93c57d31d0aa (patch)
treee3f101a7cae07ce18a485abc261b15467339861b /cli
parent03ee21e34a4829644cc07b4fc6378b2f5e1de937 (diff)
Support specifying documentation variables on command linedoc
Diffstat (limited to 'cli')
-rw-r--r--cli/cli.cxx20
-rw-r--r--cli/options.cli87
-rw-r--r--cli/options.cxx189
-rw-r--r--cli/options.hxx48
-rw-r--r--cli/options.ixx66
-rw-r--r--cli/semantics/unit.hxx1
6 files changed, 227 insertions, 184 deletions
diff --git a/cli/cli.cxx b/cli/cli.cxx
index 41f90aa..ecf3b3b 100644
--- a/cli/cli.cxx
+++ b/cli/cli.cxx
@@ -11,6 +11,8 @@
#include <cutl/compiler/code-stream.hxx>
+#include <semantics/doc.hxx>
+
#include "options.hxx"
#include "parser.hxx"
#include "generator.hxx"
@@ -97,6 +99,24 @@ main (int argc, char* argv[])
parser p (include_paths);
auto_ptr<semantics::cli_unit> unit (p.parse (ifs, path));
+ // Merge documentation variables from the command line.
+ //
+ for (map<string, string>::const_iterator i (ops.docvar ().begin ());
+ i != ops.docvar ().end ();
+ ++i)
+ {
+ using semantics::doc;
+
+ // Values specified in the .cli file override command line.
+ //
+ if (unit->lookup<doc> ("", "var: " + i->first) != 0)
+ continue;
+
+ doc& d (unit->new_node<doc> (semantics::path ("<command line>"), 0, 0));
+ unit->new_edge<semantics::names> (*unit, d, "var: " + i->first);
+ d.push_back (i->second);
+ }
+
generator g;
g.generate (ops, *unit, path);
}
diff --git a/cli/options.cli b/cli/options.cli
index 7f8e2dc..841081d 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -65,6 +65,15 @@ class options
made inline. This option suppresses creation of the inline file."
};
+ std::string --cli-namespace = "::cli"
+ {
+ "<ns>",
+ "Generate the CLI support types in the <ns> namespace (\cb{cli} by
+ default). The namespace can be nested, for example \cb{details::cli}.
+ If the namespace is empty, then the support types are generated in
+ the global namespace."
+ };
+
std::string --ostream-type = "::std::ostream"
{
"<type>",
@@ -72,6 +81,29 @@ class options
should be used to print usage and exception information."
};
+ 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
+ {
+ "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."
+ };
+
bool --suppress-undocumented
{
"Suppress the generation of documentation entries for undocumented
@@ -112,29 +144,27 @@ class options
"Exclude base class information from usage and documentation."
};
- std::string --cli-namespace = "::cli"
- {
- "<ns>",
- "Generate the CLI support types in the <ns> namespace (\cb{cli} by
- default). The namespace can be nested, for example \cb{details::cli}.
- If the namespace is empty, then the support types are generated in
- the global namespace."
- };
-
- 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
+ std::vector<std::string> --class
{
- "Generate documentation in the man page format."
+ "<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}. 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."
};
- bool --generate-html
+ std::map<std::string, std::string> --docvar|-v
{
- "Generate documentation in the HTML format."
+ "<name>=<val>",
+ "Set documentation variable <name> to the value <val>. Documentation
+ variables can be substituted in prologues and epilogues (see
+ \cb{--*-prologue*} and \cb{--*-epilogue*} options) using the
+ \cb{$}<name>\cb{$} expansion syntax (use \cb{$$} to escape expansion).
+ They can also be defined in \cb{.cli} files using the
+ \c{\"\\<name>=<val>\"} syntax."
};
// Prologues.
@@ -273,25 +303,6 @@ class options
"Insert the content of <file> at the end of the generated HTML file."
};
- 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,
- 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
- documentation from multiple classes in a specific order or 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>",
diff --git a/cli/options.cxx b/cli/options.cxx
index dd9d075..c225d49 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -488,52 +488,40 @@ namespace cli
static void
parse (std::map<K, V>& m, scanner& s)
{
- std::string o (s.next ());
+ const char* o (s.next ());
if (s.more ())
{
std::string ov (s.next ());
std::string::size_type p = ov.find ('=');
- if (p == std::string::npos)
- {
- K k = K ();
-
- if (!ov.empty ())
- {
- std::istringstream ks (ov);
+ K k = K ();
+ V v = V ();
+ std::string kstr (ov, 0, p);
+ std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));
- if (!(ks >> k && ks.eof ()))
- throw invalid_value (o, ov);
- }
-
- m[k] = V ();
- }
- else
+ int ac (2);
+ char* av[] =
{
- K k = K ();
- V v = V ();
- std::string kstr (ov, 0, p);
- std::string vstr (ov, p + 1);
+ const_cast<char*> (o), 0
+ };
- if (!kstr.empty ())
- {
- std::istringstream ks (kstr);
-
- if (!(ks >> k && ks.eof ()))
- throw invalid_value (o, ov);
- }
-
- if (!vstr.empty ())
- {
- std::istringstream vs (vstr);
- if (!(vs >> v && vs.eof ()))
- throw invalid_value (o, ov);
- }
+ if (!kstr.empty ())
+ {
+ av[1] = const_cast<char*> (kstr.c_str ());
+ argv_scanner s (0, ac, av);
+ parser<K>::parse (k, s);
+ }
- m[k] = v;
+ if (!vstr.empty ())
+ {
+ av[1] = const_cast<char*> (vstr.c_str ());
+ argv_scanner s (0, ac, av);
+ parser<V>::parse (v, s);
}
+
+ m[k] = v;
}
else
throw missing_value (o);
@@ -566,17 +554,20 @@ options ()
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -597,8 +588,6 @@ options ()
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -630,17 +619,20 @@ options (int& argc,
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -661,8 +653,6 @@ options (int& argc,
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -697,17 +687,20 @@ options (int start,
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -728,8 +721,6 @@ options (int start,
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -764,17 +755,20 @@ options (int& argc,
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -795,8 +789,6 @@ options (int& argc,
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -833,17 +825,20 @@ options (int start,
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -864,8 +859,6 @@ options (int start,
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -898,17 +891,20 @@ options (::cli::scanner& s,
generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
+ cli_namespace_ ("::cli"),
ostream_type_ ("::std::ostream"),
+ generate_cxx_ (),
+ generate_man_ (),
+ generate_html_ (),
+ stdout__ (),
suppress_undocumented_ (),
suppress_usage_ (),
long_usage_ (),
short_usage_ (),
option_length_ (0),
exclude_base_ (),
- cli_namespace_ ("::cli"),
- generate_cxx_ (),
- generate_man_ (),
- generate_html_ (),
+ class__ (),
+ docvar_ (),
hxx_prologue_ (),
ixx_prologue_ (),
cxx_prologue_ (),
@@ -929,8 +925,6 @@ options (::cli::scanner& s,
cxx_epilogue_file_ (),
man_epilogue_file_ (),
html_epilogue_file_ (),
- class__ (),
- stdout__ (),
hxx_suffix_ (".hxx"),
ixx_suffix_ (".ixx"),
cxx_suffix_ (".cxx"),
@@ -976,10 +970,21 @@ print_usage (::std::ostream& os)
os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
+ os << "--cli-namespace <ns> Generate the CLI support types in the <ns>" << ::std::endl
+ << " namespace ('cli' by default)." << ::std::endl;
+
os << "--ostream-type <type> Output stream type instead of the default" << ::std::endl
<< " 'std::ostream' that should be used to print usage" << ::std::endl
<< " and exception information." << ::std::endl;
+ os << "--generate-cxx Generate C++ code." << ::std::endl;
+
+ os << "--generate-man Generate documentation in the man page format." << ::std::endl;
+
+ os << "--generate-html Generate documentation in the HTML format." << ::std::endl;
+
+ os << "--stdout Write output to STDOUT instead of a file." << ::std::endl;
+
os << "--suppress-undocumented Suppress the generation of documentation entries" << ::std::endl
<< " for undocumented options." << ::std::endl;
@@ -998,14 +1003,11 @@ print_usage (::std::ostream& os)
os << "--exclude-base Exclude base class information from usage and" << ::std::endl
<< " documentation." << ::std::endl;
- os << "--cli-namespace <ns> Generate the CLI support types in the <ns>" << ::std::endl
- << " namespace ('cli' by default)." << ::std::endl;
-
- os << "--generate-cxx Generate C++ code." << ::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 << "--generate-man Generate documentation in the man page format." << ::std::endl;
-
- os << "--generate-html Generate documentation in the HTML format." << ::std::endl;
+ os << "--docvar|-v <name>=<val> Set documentation variable <name> to the value" << ::std::endl
+ << " <val>." << ::std::endl;
os << "--hxx-prologue <text> Insert <text> at the beginning of the generated" << ::std::endl
<< " C++ header file." << ::std::endl;
@@ -1067,11 +1069,6 @@ print_usage (::std::ostream& os)
os << "--html-epilogue-file <file> Insert the content of <file> at the end of the" << ::std::endl
<< " generated HTML 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;
@@ -1145,8 +1142,18 @@ struct _cli_options_map_init
&::cli::thunk< options, bool, &options::generate_file_scanner_ >;
_cli_options_map_["--suppress-inline"] =
&::cli::thunk< options, bool, &options::suppress_inline_ >;
+ _cli_options_map_["--cli-namespace"] =
+ &::cli::thunk< options, std::string, &options::cli_namespace_ >;
_cli_options_map_["--ostream-type"] =
&::cli::thunk< options, std::string, &options::ostream_type_ >;
+ _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_["--stdout"] =
+ &::cli::thunk< options, bool, &options::stdout__ >;
_cli_options_map_["--suppress-undocumented"] =
&::cli::thunk< options, bool, &options::suppress_undocumented_ >;
_cli_options_map_["--suppress-usage"] =
@@ -1159,14 +1166,12 @@ struct _cli_options_map_init
&::cli::thunk< options, std::size_t, &options::option_length_ >;
_cli_options_map_["--exclude-base"] =
&::cli::thunk< options, bool, &options::exclude_base_ >;
- _cli_options_map_["--cli-namespace"] =
- &::cli::thunk< options, std::string, &options::cli_namespace_ >;
- _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_["--class"] =
+ &::cli::thunk< options, std::vector<std::string>, &options::class__ >;
+ _cli_options_map_["--docvar"] =
+ &::cli::thunk< options, std::map<std::string, std::string>, &options::docvar_ >;
+ _cli_options_map_["-v"] =
+ &::cli::thunk< options, std::map<std::string, std::string>, &options::docvar_ >;
_cli_options_map_["--hxx-prologue"] =
&::cli::thunk< options, std::vector<std::string>, &options::hxx_prologue_ >;
_cli_options_map_["--ixx-prologue"] =
@@ -1207,10 +1212,6 @@ struct _cli_options_map_init
&::cli::thunk< options, std::string, &options::man_epilogue_file_ >;
_cli_options_map_["--html-epilogue-file"] =
&::cli::thunk< options, std::string, &options::html_epilogue_file_ >;
- _cli_options_map_["--class"] =
- &::cli::thunk< options, std::vector<std::string>, &options::class__ >;
- _cli_options_map_["--stdout"] =
- &::cli::thunk< options, bool, &options::stdout__ >;
_cli_options_map_["--hxx-suffix"] =
&::cli::thunk< options, std::string, &options::hxx_suffix_ >;
_cli_options_map_["--ixx-suffix"] =
diff --git a/cli/options.hxx b/cli/options.hxx
index 0328661..ecafb22 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -393,9 +393,24 @@ class options
suppress_inline () const;
const std::string&
+ cli_namespace () const;
+
+ const std::string&
ostream_type () const;
const bool&
+ generate_cxx () const;
+
+ const bool&
+ generate_man () const;
+
+ const bool&
+ generate_html () const;
+
+ const bool&
+ stdout_ () const;
+
+ const bool&
suppress_undocumented () const;
const bool&
@@ -413,17 +428,11 @@ class options
const bool&
exclude_base () const;
- const std::string&
- cli_namespace () const;
-
- const bool&
- generate_cxx () const;
-
- const bool&
- generate_man () const;
+ const std::vector<std::string>&
+ class_ () const;
- const bool&
- generate_html () const;
+ const std::map<std::string, std::string>&
+ docvar () const;
const std::vector<std::string>&
hxx_prologue () const;
@@ -485,12 +494,6 @@ class options
const std::string&
html_epilogue_file () const;
- const std::vector<std::string>&
- class_ () const;
-
- const bool&
- stdout_ () const;
-
const std::string&
hxx_suffix () const;
@@ -555,17 +558,20 @@ class options
bool generate_description_;
bool generate_file_scanner_;
bool suppress_inline_;
+ std::string cli_namespace_;
std::string ostream_type_;
+ bool generate_cxx_;
+ bool generate_man_;
+ bool generate_html_;
+ bool stdout__;
bool suppress_undocumented_;
bool suppress_usage_;
bool long_usage_;
bool short_usage_;
std::size_t option_length_;
bool exclude_base_;
- std::string cli_namespace_;
- bool generate_cxx_;
- bool generate_man_;
- bool generate_html_;
+ std::vector<std::string> class__;
+ std::map<std::string, std::string> docvar_;
std::vector<std::string> hxx_prologue_;
std::vector<std::string> ixx_prologue_;
std::vector<std::string> cxx_prologue_;
@@ -586,8 +592,6 @@ class options
std::string cxx_epilogue_file_;
std::string man_epilogue_file_;
std::string html_epilogue_file_;
- std::vector<std::string> class__;
- bool stdout__;
std::string hxx_suffix_;
std::string ixx_suffix_;
std::string cxx_suffix_;
diff --git a/cli/options.ixx b/cli/options.ixx
index c2b9a80..b146a60 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -264,12 +264,42 @@ suppress_inline () const
}
inline const std::string& options::
+cli_namespace () const
+{
+ return this->cli_namespace_;
+}
+
+inline const std::string& options::
ostream_type () const
{
return this->ostream_type_;
}
inline const bool& options::
+generate_cxx () const
+{
+ return this->generate_cxx_;
+}
+
+inline const bool& options::
+generate_man () const
+{
+ return this->generate_man_;
+}
+
+inline const bool& options::
+generate_html () const
+{
+ return this->generate_html_;
+}
+
+inline const bool& options::
+stdout_ () const
+{
+ return this->stdout__;
+}
+
+inline const bool& options::
suppress_undocumented () const
{
return this->suppress_undocumented_;
@@ -305,28 +335,16 @@ exclude_base () const
return this->exclude_base_;
}
-inline const std::string& options::
-cli_namespace () const
-{
- return this->cli_namespace_;
-}
-
-inline const bool& options::
-generate_cxx () const
-{
- return this->generate_cxx_;
-}
-
-inline const bool& options::
-generate_man () const
+inline const std::vector<std::string>& options::
+class_ () const
{
- return this->generate_man_;
+ return this->class__;
}
-inline const bool& options::
-generate_html () const
+inline const std::map<std::string, std::string>& options::
+docvar () const
{
- return this->generate_html_;
+ return this->docvar_;
}
inline const std::vector<std::string>& options::
@@ -449,18 +467,6 @@ html_epilogue_file () const
return this->html_epilogue_file_;
}
-inline const std::vector<std::string>& options::
-class_ () const
-{
- return this->class__;
-}
-
-inline const bool& options::
-stdout_ () const
-{
- return this->stdout__;
-}
-
inline const std::string& options::
hxx_suffix () const
{
diff --git a/cli/semantics/unit.hxx b/cli/semantics/unit.hxx
index cd4198b..772d2f7 100644
--- a/cli/semantics/unit.hxx
+++ b/cli/semantics/unit.hxx
@@ -293,6 +293,7 @@ namespace semantics
{
}
+ using namespace_::add_edge_left;
using namespace_::add_edge_right;
private: