BASIS  version 1.2.3 (revision 2104)
DocBookOutput.h
00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
00002 
00003 /****************************************************************************** 
00004  * 
00005  *  file:  DocBookOutput.h
00006  * 
00007  *  Copyright (c) 2004, Michael E. Smoot
00008  *  All rights reverved.
00009  * 
00010  *  See the file COPYING in the top directory of this distribution for
00011  *  more information.
00012  *  
00013  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 
00014  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
00015  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
00016  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
00017  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
00018  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00019  *  DEALINGS IN THE SOFTWARE.  
00020  *  
00021  *****************************************************************************/ 
00022 
00023 #ifndef TCLAP_DOCBOOKOUTPUT_H
00024 #define TCLAP_DOCBOOKOUTPUT_H
00025 
00026 #include <string>
00027 #include <vector>
00028 #include <list>
00029 #include <iostream>
00030 #include <algorithm>
00031 
00032 #include <sbia/tclap/CmdLineInterface.h>
00033 #include <sbia/tclap/CmdLineOutput.h>
00034 #include <sbia/tclap/XorHandler.h>
00035 #include <sbia/tclap/Arg.h>
00036 
00037 namespace TCLAP {
00038 
00039 /**
00040  * A class that generates DocBook output for usage() method for the 
00041  * given CmdLine and its Args.
00042  */
00043 class DocBookOutput : public CmdLineOutput
00044 {
00045 
00046     public:
00047 
00048         /**
00049          * Prints the usage to stdout.  Can be overridden to 
00050          * produce alternative behavior.
00051          * \param c - The CmdLine object the output is generated for. 
00052          */
00053         virtual void usage(CmdLineInterface& c);
00054 
00055         /**
00056          * Prints the version to stdout. Can be overridden 
00057          * to produce alternative behavior.
00058          * \param c - The CmdLine object the output is generated for. 
00059          */
00060         virtual void version(CmdLineInterface& c);
00061 
00062         /**
00063          * Prints (to stderr) an error message, short usage 
00064          * Can be overridden to produce alternative behavior.
00065          * \param c - The CmdLine object the output is generated for. 
00066          * \param e - The ArgException that caused the failure. 
00067          */
00068         virtual void failure(CmdLineInterface& c, 
00069                              ArgException& e );
00070 
00071     protected:
00072 
00073         /**
00074          * Substitutes the char r for string x in string s.
00075          * \param s - The string to operate on. 
00076          * \param r - The char to replace. 
00077          * \param x - What to replace r with. 
00078          */
00079         void substituteSpecialChars( std::string& s, char r, std::string& x );
00080         void removeChar( std::string& s, char r);
00081         void basename( std::string& s );
00082 
00083         void printShortArg(Arg* it);
00084         void printLongArg(Arg* it);
00085 
00086         char theDelimiter;
00087 };
00088 
00089 
00090 inline void DocBookOutput::version(CmdLineInterface& _cmd) 
00091 { 
00092     std::cout << _cmd.getVersion() << std::endl;
00093 }
00094 
00095 inline void DocBookOutput::usage(CmdLineInterface& _cmd ) 
00096 {
00097     std::list<Arg*> argList = _cmd.getArgList();
00098     std::string progName = _cmd.getProgramName();
00099     std::string xversion = _cmd.getVersion();
00100     theDelimiter = _cmd.getDelimiter();
00101     XorHandler xorHandler = _cmd.getXorHandler();
00102     std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
00103     basename(progName);
00104 
00105     std::cout << "<?xml version='1.0'?>" << std::endl;
00106     std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl;
00107     std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl;
00108 
00109     std::cout << "<refentry>" << std::endl;
00110 
00111     std::cout << "<refmeta>" << std::endl;
00112     std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl;
00113     std::cout << "<manvolnum>1</manvolnum>" << std::endl;
00114     std::cout << "</refmeta>" << std::endl;
00115 
00116     std::cout << "<refnamediv>" << std::endl;
00117     std::cout << "<refname>" << progName << "</refname>" << std::endl;
00118     std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl;
00119     std::cout << "</refnamediv>" << std::endl;
00120 
00121     std::cout << "<refsynopsisdiv>" << std::endl;
00122     std::cout << "<cmdsynopsis>" << std::endl;
00123 
00124     std::cout << "<command>" << progName << "</command>" << std::endl;
00125 
00126     // xor
00127     for ( int i = 0; (unsigned int)i < xorList.size(); i++ )
00128     {
00129         std::cout << "<group choice='req'>" << std::endl;
00130         for ( ArgVectorIterator it = xorList[i].begin(); 
00131                         it != xorList[i].end(); it++ )
00132             printShortArg((*it));
00133 
00134         std::cout << "</group>" << std::endl;
00135     }
00136     
00137     // rest of args
00138     for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
00139         if ( !xorHandler.contains( (*it) ) )
00140             printShortArg((*it));
00141 
00142     std::cout << "</cmdsynopsis>" << std::endl;
00143     std::cout << "</refsynopsisdiv>" << std::endl;
00144 
00145     std::cout << "<refsect1>" << std::endl;
00146     std::cout << "<title>Description</title>" << std::endl;
00147     std::cout << "<para>" << std::endl;
00148     std::cout << _cmd.getMessage() << std::endl; 
00149     std::cout << "</para>" << std::endl;
00150     std::cout << "</refsect1>" << std::endl;
00151 
00152     std::cout << "<refsect1>" << std::endl;
00153     std::cout << "<title>Options</title>" << std::endl;
00154 
00155     std::cout << "<variablelist>" << std::endl;
00156     
00157     for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
00158         printLongArg((*it));
00159 
00160     std::cout << "</variablelist>" << std::endl;
00161     std::cout << "</refsect1>" << std::endl;
00162 
00163     std::cout << "<refsect1>" << std::endl;
00164     std::cout << "<title>Version</title>" << std::endl;
00165     std::cout << "<para>" << std::endl;
00166     std::cout << xversion << std::endl; 
00167     std::cout << "</para>" << std::endl;
00168     std::cout << "</refsect1>" << std::endl;
00169     
00170     std::cout << "</refentry>" << std::endl;
00171 
00172 }
00173 
00174 inline void DocBookOutput::failure( CmdLineInterface& _cmd,
00175                     ArgException& e ) 
00176 { 
00177     static_cast<void>(_cmd); // unused
00178     std::cout << e.what() << std::endl;
00179     throw ExitException(1);
00180 }
00181 
00182 inline void DocBookOutput::substituteSpecialChars( std::string& s,
00183                                                    char r,
00184                                                    std::string& x )
00185 {
00186     size_t p;
00187     while ( (p = s.find_first_of(r)) != std::string::npos )
00188     {
00189         s.erase(p,1);
00190         s.insert(p,x);
00191     }
00192 }
00193 
00194 inline void DocBookOutput::removeChar( std::string& s, char r)
00195 {
00196     size_t p;
00197     while ( (p = s.find_first_of(r)) != std::string::npos )
00198     {
00199         s.erase(p,1);
00200     }
00201 }
00202 
00203 inline void DocBookOutput::basename( std::string& s )
00204 {
00205     size_t p = s.find_last_of('/');
00206     if ( p != std::string::npos )
00207     {
00208         s.erase(0, p + 1);
00209     }
00210 }
00211 
00212 inline void DocBookOutput::printShortArg(Arg* a)
00213 {
00214     std::string lt = "&lt;"; 
00215     std::string gt = "&gt;"; 
00216 
00217     std::string id = a->shortID();
00218     substituteSpecialChars(id,'<',lt);
00219     substituteSpecialChars(id,'>',gt);
00220     removeChar(id,'[');
00221     removeChar(id,']');
00222     
00223     std::string choice = "opt";
00224     if ( a->isRequired() )
00225         choice = "plain";
00226 
00227     std::cout << "<arg choice='" << choice << '\'';
00228     if ( a->acceptsMultipleValues() )
00229         std::cout << " rep='repeat'";
00230 
00231 
00232     std::cout << '>';
00233     if ( !a->getFlag().empty() )
00234         std::cout << a->flagStartChar() << a->getFlag();
00235     else
00236         std::cout << a->nameStartString() << a->getName();
00237     if ( a->isValueRequired() )
00238     {
00239         std::string arg = a->shortID();
00240         removeChar(arg,'[');
00241         removeChar(arg,']');
00242         removeChar(arg,'<');
00243         removeChar(arg,'>');
00244         arg.erase(0, arg.find_last_of(theDelimiter) + 1);
00245         std::cout << theDelimiter;
00246         std::cout << "<replaceable>" << arg << "</replaceable>";
00247     }
00248     std::cout << "</arg>" << std::endl;
00249 
00250 }
00251 
00252 inline void DocBookOutput::printLongArg(Arg* a)
00253 {
00254     std::string lt = "&lt;"; 
00255     std::string gt = "&gt;"; 
00256 
00257     std::string desc = a->getDescription();
00258     substituteSpecialChars(desc,'<',lt);
00259     substituteSpecialChars(desc,'>',gt);
00260 
00261     std::cout << "<varlistentry>" << std::endl;
00262 
00263     if ( !a->getFlag().empty() )
00264     {
00265         std::cout << "<term>" << std::endl;
00266         std::cout << "<option>";
00267         std::cout << a->flagStartChar() << a->getFlag();
00268         std::cout << "</option>" << std::endl;
00269         std::cout << "</term>" << std::endl;
00270     }
00271 
00272     std::cout << "<term>" << std::endl;
00273     std::cout << "<option>";
00274     std::cout << a->nameStartString() << a->getName();
00275     if ( a->isValueRequired() )
00276     {
00277         std::string arg = a->shortID();
00278         removeChar(arg,'[');
00279         removeChar(arg,']');
00280         removeChar(arg,'<');
00281         removeChar(arg,'>');
00282         arg.erase(0, arg.find_last_of(theDelimiter) + 1);
00283         std::cout << theDelimiter;
00284         std::cout << "<replaceable>" << arg << "</replaceable>";
00285     }
00286     std::cout << "</option>" << std::endl;
00287     std::cout << "</term>" << std::endl;
00288 
00289     std::cout << "<listitem>" << std::endl;
00290     std::cout << "<para>" << std::endl;
00291     std::cout << desc << std::endl;
00292     std::cout << "</para>" << std::endl;
00293     std::cout << "</listitem>" << std::endl;
00294 
00295     std::cout << "</varlistentry>" << std::endl;
00296 }
00297 
00298 } //namespace TCLAP
00299 #endif