[Debtags-commits] [svn] r1632 - in tagcoll/trunk: tagcoll tools
Enrico Zini
enrico at costa.debian.org
Sat Mar 4 14:32:18 UTC 2006
Author: enrico
Date: Sat Mar 4 14:32:17 2006
New Revision: 1632
Added:
tagcoll/trunk/tools/TagcollOptions.h
tagcoll/trunk/tools/manpage.cc
Modified:
tagcoll/trunk/tagcoll/Commandline.cc
tagcoll/trunk/tagcoll/Commandline.h
tagcoll/trunk/tools/Makefile.am
tagcoll/trunk/tools/tagcoll.cc
Log:
Implemented manpage generation
Modified: tagcoll/trunk/tagcoll/Commandline.cc
==============================================================================
--- tagcoll/trunk/tagcoll/Commandline.cc (original)
+++ tagcoll/trunk/tagcoll/Commandline.cc Sat Mar 4 14:32:17 2006
@@ -1,4 +1,8 @@
#include <tagcoll/Commandline.h>
+#include <config.h>
+#include <locale.h>
+#include <ctype.h>
+#include <set>
using namespace std;
@@ -43,6 +47,22 @@
return string("--") + c + "=" + usage;
}
+static string manfmtshort(char c, const std::string& usage)
+{
+ if (usage.empty())
+ return string("\\-") + c;
+ else
+ return string("\\-") + c + " \\fI" + usage + "\\fP";
+}
+
+static string manfmtlong(const std::string& c, const std::string& usage)
+{
+ if (usage.empty())
+ return string("\\-\\-") + c;
+ else
+ return string("\\-\\-") + c + "=\\fI" + usage + "\\fP";
+}
+
const std::string& Option::fullUsage() const
{
if (m_fullUsage.empty())
@@ -66,6 +86,27 @@
return m_fullUsage;
}
+std::string Option::fullUsageForMan() const
+{
+ string res;
+
+ for (vector<char>::const_iterator i = shortNames.begin();
+ i != shortNames.end(); i++)
+ {
+ if (!res.empty()) res += ", ";
+ res += manfmtshort(*i, usage);
+ }
+
+ for (vector<string>::const_iterator i = longNames.begin();
+ i != longNames.end(); i++)
+ {
+ if (!res.empty()) res += ", ";
+ res += manfmtlong(*i, usage);
+ }
+
+ return res;
+}
+
bool StringOption::parse(const char* str)
{
@@ -520,6 +561,191 @@
out << endl;
}
+static string toupper(const std::string& str)
+{
+ string res;
+ for (size_t i = 0; i < str.size(); i++)
+ res += ::toupper(str[i]);
+ return res;
+}
+
+static string man_date()
+{
+ time_t tnow = time(0);
+ struct tm* now = gmtime(&tnow);
+ char buf[20];
+ const char* oldlocale = setlocale(LC_TIME, "C");
+ string res(buf, strftime(buf, 20, "%B %d, %Y", now));
+ setlocale(LC_TIME, oldlocale);
+ return res;
+}
+
+void Help::outputManOption(std::ostream& out, const Option* o)
+{
+ out << ".TP" << endl;
+ out << ".B " << o->fullUsageForMan() << endl;
+ out << o->description << "." << endl;
+}
+
+void Help::outputMan(std::ostream& out, const CommandParser& cp, int section)
+{
+ std::map<std::string, OptionParser*> m_info;
+
+ // Dig informations from cp
+ for(map<string, OptionParser*>::const_iterator i = cp.m_aliases.begin();
+ i != cp.m_aliases.end(); i++)
+ {
+ if (i->first == string())
+ continue;
+ map<string, OptionParser*>::iterator j = m_info.find(i->second->name());
+ if (j == m_info.end())
+ m_info[i->second->name()] = i->second;
+ }
+
+
+ // Manpage header
+ out << ".TH " << toupper(m_app) << " " << section << " \"" << man_date() << "\" \"" << m_ver << "\"" << endl;
+
+ out << ".SH NAME" << endl;
+ out << cp.name() << " \\- " << cp.description << endl;
+
+ out << ".SH SYNOPSIS" << endl;
+ out << m_app << " [options] " << cp.usage << endl;
+
+ out << ".SH DESCRIPTION" << endl;
+
+ out << ".SH COMMANDS" << endl;
+ out << "\\fB" << cp.name() << "\\fP always requires a non-switch argument, that indicates what is the operation that should be performed:" << endl;
+ for (map<string, OptionParser*>::const_iterator i = m_info.begin();
+ i != m_info.end(); i++)
+ {
+ out << ".TP" << endl;
+ out << "\\fB" << i->second->primaryAlias << "\\fP";
+
+ const vector<string>& v = i->second->aliases;
+ for (vector<string>::const_iterator j = v.begin(); j != v.end(); j++)
+ out << " or \\fB" << *j << "\\fP";
+
+ out << " " << i->second->usage << endl;
+ out << ".br" << endl;
+ out << i->second->description << endl;
+ }
+
+ out << ".SH OPTIONS" << endl;
+
+ out << "This program follows the usual GNU command line syntax, with long options starting with two dashes (`\\-')." << endl << endl;
+ out << "Every one of the commands listed above has its own set of options. To keep this manpage readable, all the options are presented together. Please refer to \"\\fB" << cp.name() << "\\fP help \\fIcommand\\fP\" to see which options are accepted by a given command." << endl;
+
+ // Harvest merged option informations
+ set<OptionGroup*> groups;
+ vector<Option*> options;
+ for(map<string, OptionParser*>::const_iterator i = cp.m_aliases.begin();
+ i != cp.m_aliases.end(); i++)
+ {
+ if (i->first == string())
+ continue;
+ OptionParser& o = *i->second;
+
+ for (vector<OptionGroup*>::const_iterator i = o.m_groups.begin();
+ i != o.m_groups.end(); i++)
+ groups.insert(*i);
+ for (vector<Option*>::const_iterator j = o.m_options.begin();
+ j != o.m_options.end(); j++)
+ options.push_back(*j);
+ }
+
+ for (set<OptionGroup*>::const_iterator i = groups.begin();
+ i != groups.end(); i++)
+ {
+ if (!(*i)->description.empty())
+ out << endl << (*i)->description << ":" << endl;
+ for (vector<Option*>::const_iterator j = (*i)->options.begin();
+ j != (*i)->options.end(); ++j)
+ outputManOption(out, *j);
+ out << ".PP" << endl;
+ }
+
+ if (!options.empty())
+ {
+ out << endl;
+ out << "Other options:" << endl;
+ for (vector<Option*>::const_iterator j = options.begin();
+ j != options.end(); ++j)
+ outputManOption(out, *j);
+ }
+
+ out << ".SH AUTHOR" << endl;
+ out << "\\fB" << cp.name() << "\\fP is maintained by " << PACKAGE_BUGREPORT << "." << endl << endl;
+ out << "This manpage has been automatically generated by the " << m_app << " program." << endl;
+}
+
+#if 0
+void Help::outputMan(std::ostream& out, const OptionParser& o, int section)
+{
+ HelpWriter writer(out);
+
+ out << "Usage: " << m_app << " [options] " << o.primaryAlias << " [options] " << o.usage << endl;
+ out << endl;
+ if (!o.aliases.empty())
+ {
+ out << "Command aliases: ";
+ for (vector<string>::const_iterator i = o.aliases.begin();
+ i != o.aliases.end(); i++)
+ if (i == o.aliases.begin())
+ out << *i;
+ else
+ out << ", " << *i;
+ out << "." << endl;
+ out << endl;
+ }
+ writer.outstring("Description: " + o.description);
+
+ // Compute size of option display
+ size_t maxLeftCol = 0;
+ for (vector<OptionGroup*>::const_iterator i = o.m_groups.begin();
+ i != o.m_groups.end(); i++)
+ for (vector<Option*>::const_iterator j = (*i)->options.begin();
+ j != (*i)->options.end(); j++)
+ {
+ size_t w = (*j)->fullUsage().size();
+ if (w > maxLeftCol)
+ maxLeftCol = w;
+ }
+ for (vector<Option*>::const_iterator j = o.m_options.begin();
+ j != o.m_options.end(); j++)
+ {
+ size_t w = (*j)->fullUsage().size();
+ if (w > maxLeftCol)
+ maxLeftCol = w;
+ }
+
+ if (maxLeftCol)
+ {
+ // Output the options
+ out << endl;
+ out << "Options are:" << endl;
+ for (vector<OptionGroup*>::const_iterator i = o.m_groups.begin();
+ i != o.m_groups.end(); i++)
+ {
+ if (!(*i)->description.empty())
+ writer.outstring((*i)->description + ":");
+ for (vector<Option*>::const_iterator j = (*i)->options.begin();
+ j != (*i)->options.end(); j++)
+ writer.outlist(" " + (*j)->fullUsage(), maxLeftCol + 3, (*j)->description);
+ }
+ if (!o.m_options.empty())
+ {
+ out << endl;
+ writer.outstring("Other options:");
+ for (vector<Option*>::const_iterator j = o.m_options.begin();
+ j != o.m_options.end(); j++)
+ writer.outlist(" " + (*j)->fullUsage(), maxLeftCol + 3, (*j)->description);
+ }
+ }
+ out << endl;
+}
+#endif
+
}
}
Modified: tagcoll/trunk/tagcoll/Commandline.h
==============================================================================
--- tagcoll/trunk/tagcoll/Commandline.h (original)
+++ tagcoll/trunk/tagcoll/Commandline.h Sat Mar 4 14:32:17 2006
@@ -93,6 +93,7 @@
/// Return a full usage message including all the aliases for this option
const std::string& fullUsage() const;
+ std::string fullUsageForMan() const;
std::vector<char> shortNames;
std::vector<std::string> longNames;
@@ -278,6 +279,10 @@
void outputVersion(std::ostream& out);
void outputHelp(std::ostream& out, const CommandParser& cp);
void outputHelp(std::ostream& out, const OptionParser& cp);
+
+ void outputManOption(std::ostream& out, const Option* o);
+ void outputMan(std::ostream& out, const CommandParser& cp, int section);
+ //void outputMan(std::ostream& out, const OptionParser& cp, int section);
};
}
Modified: tagcoll/trunk/tools/Makefile.am
==============================================================================
--- tagcoll/trunk/tools/Makefile.am (original)
+++ tagcoll/trunk/tools/Makefile.am Sat Mar 4 14:32:17 2006
@@ -1,8 +1,9 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = tagcoll taggrep tagidx
+noinst_PROGRAMS = manpage
-tagcoll_SOURCES = tagcoll.cc CommandlineParser.cc
+tagcoll_SOURCES = tagcoll.cc
tagcoll_LDADD = ../tagcoll/libtagcoll.la ../tagcoll/tagexpr/libtagexpr.la
taggrep_SOURCES = taggrep.cc CommandlineParser.cc
@@ -11,6 +12,9 @@
tagidx_SOURCES = tagidx.cc CommandlineParser.cc
tagidx_LDADD = ../tagcoll/libtagcoll.la ../tagcoll/tagexpr/libtagexpr.la
+manpage_SOURCES = manpage.cc
+manpage_LDADD = ../tagcoll/libtagcoll.la ../tagcoll/tagexpr/libtagexpr.la
+
INCLUDES = -I$(top_srcdir)
-EXTRA_DIST = CommandlineParser.h Index.h
+EXTRA_DIST = CommandlineParser.h
Modified: tagcoll/trunk/tools/tagcoll.cc
==============================================================================
--- tagcoll/trunk/tools/tagcoll.cc (original)
+++ tagcoll/trunk/tools/tagcoll.cc Sat Mar 4 14:32:17 2006
@@ -62,296 +62,11 @@
#include <algorithm>
#include <iostream>
+#include "TagcollOptions.h"
+
using namespace std;
using namespace Tagcoll;
-namespace Tagcoll {
-namespace commandline {
-
-struct CommandlineParser : public CommandParser
-{
- struct HelpGroup : public OptionGroup
- {
- BoolOption* help;
- BoolOption* version;
-
- HelpGroup()
- {
- add(help = new BoolOption("help", 'h', "help"));
- add(version = new BoolOption("version", 'V', "version"));
- help->shortNames.push_back('?');
- help->description = "show commandline help";
- version->description = "show program version";
- }
- ~HelpGroup()
- {
- delete help;
- }
- } helpGroup;
-
- struct InputGroup : public OptionGroup
- {
- ExistingFileOption* derived;
- ExistingFileOption* extimpl;
- ExistingFileOption* rename;
- ExistingFileOption* patch;
- StringOption* rmunfaceted;
- StringOption* rmtags;
-
- InputGroup()
- {
- add(derived = new ExistingFileOption("derived-tags-from", 'e', "derived"));
- add(extimpl = new ExistingFileOption("extimpl", 'i', "implications-from"));
- add(rename = new ExistingFileOption("rename", 'r', "rename-from"));
- add(patch = new ExistingFileOption("patch", 'p', "patch-with"));
- add(rmunfaceted = new StringOption("rmunfaceted", 0, "remove-unfaceted"));
- add(rmtags = new StringOption("rmtags", 0, "remove-tags"));
-
- derived->description = "expand derived tags using the given list";
- extimpl->description = "use an external list of implications";
- rename->description = "rename tags using the given mapping list";
- patch->description = "apply patches from the given tag patch file";
- patch->longNames.push_back("patch");
- rmunfaceted->description = "while parsing, remove all tags with no facet part";
- rmtags->usage = "<expression>";
- rmtags->description = "while parsing, remove all tags matching the given tag expression";
- }
- ~InputGroup()
- {
- delete derived; delete extimpl; delete rename; delete patch;
- delete rmunfaceted; delete rmtags;
- }
- } inputGroup;
-
- struct OutputGroup : public OptionGroup
- {
- BoolOption* group;
- BoolOption* redundant;
-
- OutputGroup()
- {
- add(group = new BoolOption("group", 'g', "group"));
- add(redundant = new BoolOption("redundant", 0, "redundant"));
- group->description = "group items with the same tagset in the output collection";
- group->longNames.push_back("group-items");
- redundant->description = "when implications are provided, expand them explicitly in the output";
- }
- ~OutputGroup()
- {
- delete group;
- delete redundant;
- }
- } outputGroup;
-
- struct HierarchyGroup : public OptionGroup
- {
- IntOption* flatten;
- IntOption* filter;
-
- HierarchyGroup()
- {
- add(flatten = new IntOption("flatten", 0, "flatten-threshold"));
- add(filter = new IntOption("filter", 'f', "filter"));
-
- flatten->description = "set the number of total items below which a branch is flattened when using the \"hierarchy\" command (defaults to 0, meaning \"don't flatten\")";
- filter->description = "filter out the tags with cardinality less than the given value (defaults to not filter; currently only works when building hierarchies)";
- }
-
- ~HierarchyGroup()
- {
- delete flatten;
- delete filter;
- }
- } hierarchyGroup;
-
- struct Generic : public OptionParser
- {
- Generic(CommandlineParser* cp) : OptionParser("")
- {
- add(&cp->helpGroup);
- }
- } generic;
- struct Help : public OptionParser
- {
- Help(CommandlineParser* cp) : OptionParser("help")
- {
- usage = "[command]";
- description = "print help informations";
- }
- } help;
- struct Copy : public OptionParser
- {
- Copy(CommandlineParser* cp) : OptionParser("copy")
- {
- usage = "[files...]";
- description = "output the collection";
- add(&cp->inputGroup);
- add(&cp->outputGroup);
- add(&cp->helpGroup);
- aliases.push_back("cat");
- }
- } copy;
- struct Reverse : public OptionParser
- {
- StringOption* untaggedTag;
-
- Reverse(CommandlineParser* cp) : OptionParser("reverse")
- {
- add(untaggedTag = new StringOption("untagged-tag", 0, "untagged-tag"));
- untaggedTag->usage = "<tag>";
- untaggedTag->description = "set item name to use for associating untagged items when using the \"reverse\" command. If not specified, untagged items are not included in the output";
-
- usage = "[files...]";
- description = "\"reverse\" the collection, outputting one with items associated to tags";
- add(&cp->helpGroup);
- }
- ~Reverse()
- {
- delete untaggedTag;
- }
- } reverse;
- struct Diff : public OptionParser
- {
- Diff(CommandlineParser* cp) : OptionParser("diff")
- {
- usage = "<file1> <file2>";
- description = "output a tag patch file with the differences between two files";
- add(&cp->helpGroup);
- }
- } diff;
- struct Related : public OptionParser
- {
- IntOption* distance;
-
- Related(CommandlineParser* cp) : OptionParser("related")
- {
- add(distance = new IntOption("distance", 'd', "distance"));
- distance->description = "set the maximum distance to use for the \"related\" command (defaults to 0)";
-
- usage = "<item> [files...]";
- description = "print a list of items related to the given one";
- add(&cp->helpGroup);
- }
- ~Related()
- {
- delete distance;
- }
- } related;
- struct Implications : public OptionParser
- {
- Implications(CommandlineParser* cp) : OptionParser("implications")
- {
- usage = "[files...]";
- description = "compute a list of tag implications";
- add(&cp->helpGroup);
- }
- } implications;
- struct Hierarchy : public OptionParser
- {
- Hierarchy(CommandlineParser* cp) : OptionParser("hierarchy")
- {
- usage = "[files...]";
- description = "build a smart hierarchy with the collection data";
- add(&cp->hierarchyGroup);
- add(&cp->helpGroup);
- }
- } hierarchy;
- struct CleanHierarchy : public OptionParser
- {
- CleanHierarchy(CommandlineParser* cp) : OptionParser("cleanhierarchy")
- {
- usage = "[files...]";
- description = "build a cleaned smart hierarchy with the collection data";
- add(&cp->hierarchyGroup);
- add(&cp->helpGroup);
- }
- } cleanhierarchy;
- struct FindSpecials : public OptionParser
- {
- FindSpecials(CommandlineParser* cp) : OptionParser("findspecials")
- {
- usage = "[files...]";
- description =
- "generate a smart hierarchy and print, for each toplevel tag, "
- "what are the items that make it toplevel instead of going below "
- "another tag";
- add(&cp->hierarchyGroup);
- add(&cp->helpGroup);
- }
- } findspecials;
- struct Grep : public OptionParser
- {
- Grep(CommandlineParser* cp) : OptionParser("grep")
- {
- usage = "<expression> [files...]";
- description = "output the collection of tags that match the given tag expression";
- add(&cp->helpGroup);
- }
- } grep;
- struct Items : public OptionParser
- {
- Items(CommandlineParser* cp) : OptionParser("items")
- {
- usage = "[files...]";
- description = "output only the items of the input collection";
- add(&cp->helpGroup);
- }
- } items;
-
- arglist args;
-
- CommandlineParser(int argc, const char* argv[]) : CommandParser("main"),
- generic(this),
- help(this), copy(this), reverse(this), diff(this), related(this), implications(this),
- hierarchy(this), cleanhierarchy(this), findspecials(this), grep(this), items(this)
- {
- add(generic);
- add(help);
- add(copy);
- add(reverse);
- add(diff);
- add(related);
- add(implications);
- add(hierarchy);
- add(cleanhierarchy);
- add(findspecials);
- add(grep);
- add(items);
-
- usage = "<command> [options and arguments]";
- description = "Perform various operations on a tagged collection";
-
- for (int i = 1; i < argc; i++)
- args.push_back(argv[i]);
- }
-
- arglist parse()
- {
- parseList(args);
- if (!lastCommand())
- throw commandline::BadOption("could not understand the command to execute");
- return args;
- }
-
- bool hasNext() const { return !args.empty(); }
- string next()
- {
- if (args.empty())
- return string();
- string res(*args.begin());
- args.erase(args.begin());
- return res;
- }
-
-#if 0
- //opts.add("verbose", 'v', "verbose", "enable verbose output");
- //opts.add("debug", 0, "debug", "enable debugging output (including verbose output)");
-#endif
-};
-
-}
-}
-
bool isdir(const std::string& file)
{
@@ -583,7 +298,7 @@
FilterTagsByExpression<string, string> filterByExpression;
public:
- Reader(commandline::CommandlineParser& opts)
+ Reader(commandline::TagcollOptions& opts)
: addImplied(implications), removeImplied(implications),
addDerived(derivedTags), removeDerived(derivedTags),
unfacetedRemover("::"), filterByExpression("")
@@ -654,7 +369,7 @@
filters.setConsumer(cons);
readCollection(file, filters);
}
- void output(commandline::CommandlineParser& opts, Consumer<string, string>& cons)
+ void output(commandline::TagcollOptions& opts, Consumer<string, string>& cons)
{
if (opts.hasNext())
while (opts.hasNext())
@@ -714,7 +429,7 @@
}
public:
- Writer(commandline::CommandlineParser& opts)
+ Writer(commandline::TagcollOptions& opts)
: output(conv, conv, stdout), grouper(0)
{
if (opts.outputGroup.group->boolValue())
@@ -733,10 +448,10 @@
int main(int argc, const char* argv[])
{
- commandline::CommandlineParser opts(argc, argv);
+ commandline::TagcollOptions opts;
try {
- opts.parse();
+ opts.parse(argc, argv);
Reader reader(opts);
More information about the Debtags-commits
mailing list