$search
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