summaryrefslogtreecommitdiff
path: root/cli/man.cxx
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/man.cxx
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/man.cxx')
-rw-r--r--cli/man.cxx163
1 files changed, 163 insertions, 0 deletions
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);
+}