- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# StdOutput.h

Go to the documentation of this file.

    00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
    00002
    00003 /******************************************************************************
    00004  *
    00005  *  file:  StdOutput.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_STDCMDLINEOUTPUT_H
    00024 #define TCLAP_STDCMDLINEOUTPUT_H
    00025
    00026 #include <string>
    00027 #include <vector>
    00028 #include <list>
    00029 #include <iostream>
    00030 #include <algorithm>
    00031
    00032 #include <tclap/CmdLineInterface.h>
    00033 #include <tclap/CmdLineOutput.h>
    00034 #include <tclap/XorHandler.h>
    00035 #include <tclap/Arg.h>
    00036
    00037 namespace TCLAP {
    00038
    00043 class StdOutput : public CmdLineOutput
    00044 {
    00045
    00046     public:
    00047
    00053         virtual void usage(CmdLineInterface& c);
    00054
    00060         virtual void version(CmdLineInterface& c);
    00061
    00068         virtual void failure(CmdLineInterface& c,
    00069                      ArgException& e );
    00070
    00071     protected:
    00072
    00078         void _shortUsage( CmdLineInterface& c, std::ostream& os ) const;
    00079
    00086         void _longUsage( CmdLineInterface& c, std::ostream& os ) const;
    00087
    00099         void spacePrint( std::ostream& os,
    00100                          const std::string& s,
    00101                          int maxWidth,
    00102                          int indentSpaces,
    00103                          int secondLineOffset ) const;
    00104
    00105 };
    00106
    00107
    00108 inline void StdOutput::version(CmdLineInterface& _cmd)
    00109 {
    00110     std::string progName = _cmd.getProgramName();
    00111     std::string xversion = _cmd.getVersion();
    00112
    00113     std::cout << std::endl << progName << "  version: "
    00114               << xversion << std::endl << std::endl;
    00115 }
    00116
    00117 inline void StdOutput::usage(CmdLineInterface& _cmd )
    00118 {
    00119     std::cout << std::endl << "USAGE: " << std::endl << std::endl;
    00120
    00121     _shortUsage( _cmd, std::cout );
    00122
    00123     std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
    00124
    00125     _longUsage( _cmd, std::cout );
    00126
    00127     std::cout << std::endl;
    00128
    00129 }
    00130
    00131 inline void StdOutput::failure( CmdLineInterface& _cmd,
    00132                                 ArgException& e )
    00133 {
    00134     std::string progName = _cmd.getProgramName();
    00135
    00136     std::cerr << "PARSE ERROR: " << e.argId() << std::endl
    00137               << "             " << e.error() << std::endl << std::endl;
    00138
    00139     if ( _cmd.hasHelpAndVersion() )
    00140         {
    00141             std::cerr << "Brief USAGE: " << std::endl;
    00142
    00143             _shortUsage( _cmd, std::cerr );
    00144
    00145             std::cerr << std::endl << "For complete USAGE and HELP type: "
    00146                       << std::endl << "   " << progName << " --help"
    00147                       << std::endl << std::endl;
    00148         }
    00149     else
    00150         usage(_cmd);
    00151
    00152     throw ExitException(1);
    00153 }
    00154
    00155 inline void
    00156 StdOutput::_shortUsage( CmdLineInterface& _cmd,
    00157                         std::ostream& os ) const
    00158 {
    00159     std::list<Arg*> argList = _cmd.getArgList();
    00160     std::string progName = _cmd.getProgramName();
    00161     XorHandler xorHandler = _cmd.getXorHandler();
    00162     std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
    00163
    00164     std::string s = progName + " ";
    00165
    00166     // first the xor
    00167     for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
    00168         {
    00169             s += " {";
    00170             for ( ArgVectorIterator it = xorList[i].begin();
    00171                   it != xorList[i].end(); it++ )
    00172                 s += (*it)->shortID() + "|";
    00173
    00174             s[s.length()-1] = '}';
    00175         }
    00176
    00177     // then the rest
    00178     for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
    00179         if ( !xorHandler.contains( (*it) ) )
    00180             s += " " + (*it)->shortID();
    00181
    00182     // if the program name is too long, then adjust the second line offset
    00183     int secondLineOffset = static_cast<int>(progName.length()) + 2;
    00184     if ( secondLineOffset > 75/2 )
    00185         secondLineOffset = static_cast<int>(75/2);
    00186
    00187     spacePrint( os, s, 75, 3, secondLineOffset );
    00188 }
    00189
    00190 inline void
    00191 StdOutput::_longUsage( CmdLineInterface& _cmd,
    00192                        std::ostream& os ) const
    00193 {
    00194     std::list<Arg*> argList = _cmd.getArgList();
    00195     std::string message = _cmd.getMessage();
    00196     XorHandler xorHandler = _cmd.getXorHandler();
    00197     std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
    00198
    00199     // first the xor
    00200     for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
    00201         {
    00202             for ( ArgVectorIterator it = xorList[i].begin();
    00203                   it != xorList[i].end();
    00204                   it++ )
    00205                 {
    00206                     spacePrint( os, (*it)->longID(), 75, 3, 3 );
    00207                     spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
    00208
    00209                     if ( it+1 != xorList[i].end() )
    00210                         spacePrint(os, "-- OR --", 75, 9, 0);
    00211                 }
    00212             os << std::endl << std::endl;
    00213         }
    00214
    00215     // then the rest
    00216     for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
    00217         if ( !xorHandler.contains( (*it) ) )
    00218             {
    00219                 spacePrint( os, (*it)->longID(), 75, 3, 3 );
    00220                 spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
    00221                 os << std::endl;
    00222             }
    00223
    00224     os << std::endl;
    00225
    00226     spacePrint( os, message, 75, 3, 0 );
    00227 }
    00228
    00229 inline void StdOutput::spacePrint( std::ostream& os,
    00230                                    const std::string& s,
    00231                                    int maxWidth,
    00232                                    int indentSpaces,
    00233                                    int secondLineOffset ) const
    00234 {
    00235     int len = static_cast<int>(s.length());
    00236
    00237     if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
    00238         {
    00239             int allowedLen = maxWidth - indentSpaces;
    00240             int start = 0;
    00241             while ( start < len )
    00242                 {
    00243                     // find the substring length
    00244                     // int stringLen = std::min<int>( len - start, allowedLen );
    00245                     // doing it this way to support a VisualC++ 2005 bug
    00246                     using namespace std;
    00247                     int stringLen = min<int>( len - start, allowedLen );
    00248
    00249                     // trim the length so it doesn't end in middle of a word
    00250                     if ( stringLen == allowedLen )
    00251                         while ( stringLen >= 0 &&
    00252                                 s[stringLen+start] != ' ' &&
    00253                                 s[stringLen+start] != ',' &&
    00254                                 s[stringLen+start] != '|' )
    00255                             stringLen--;
    00256
    00257                     // ok, the word is longer than the line, so just split
    00258                     // wherever the line ends
    00259                     if ( stringLen <= 0 )
    00260                         stringLen = allowedLen;
    00261
    00262                     // check for newlines
    00263                     for ( int i = 0; i < stringLen; i++ )
    00264                         if ( s[start+i] == '\n' )
    00265                             stringLen = i+1;
    00266
    00267                     // print the indent
    00268                     for ( int i = 0; i < indentSpaces; i++ )
    00269                         os << " ";
    00270
    00271                     if ( start == 0 )
    00272                         {
    00273                             // handle second line offsets
    00274                             indentSpaces += secondLineOffset;
    00275
    00276                             // adjust allowed len
    00277                             allowedLen -= secondLineOffset;
    00278                         }
    00279
    00280                     os << s.substr(start,stringLen) << std::endl;
    00281
    00282                     // so we don't start a line with a space
    00283                     while ( s[stringLen+start] == ' ' && start < len )
    00284                         start++;
    00285
    00286                     start += stringLen;
    00287                 }
    00288         }
    00289     else
    00290         {
    00291             for ( int i = 0; i < indentSpaces; i++ )
    00292                 os << " ";
    00293             os << s << std::endl;
    00294         }
    00295 }
    00296
    00297 } //namespace TCLAP
    00298 #endif