299 lines
8.3 KiB
C++
299 lines
8.3 KiB
C++
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
|
|
|
/******************************************************************************
|
|
*
|
|
* file: StdOutput.h
|
|
*
|
|
* Copyright (c) 2004, Michael E. Smoot
|
|
* All rights reverved.
|
|
*
|
|
* See the file COPYING in the top directory of this distribution for
|
|
* more information.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifndef TCLAP_STDCMDLINEOUTPUT_H
|
|
#define TCLAP_STDCMDLINEOUTPUT_H
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <list>
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
|
|
#include <tclap/CmdLineInterface.h>
|
|
#include <tclap/CmdLineOutput.h>
|
|
#include <tclap/XorHandler.h>
|
|
#include <tclap/Arg.h>
|
|
|
|
namespace TCLAP {
|
|
|
|
/**
|
|
* A class that isolates any output from the CmdLine object so that it
|
|
* may be easily modified.
|
|
*/
|
|
class StdOutput : public CmdLineOutput
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
* Prints the usage to stdout. Can be overridden to
|
|
* produce alternative behavior.
|
|
* \param c - The CmdLine object the output is generated for.
|
|
*/
|
|
virtual void usage(CmdLineInterface& c);
|
|
|
|
/**
|
|
* Prints the version to stdout. Can be overridden
|
|
* to produce alternative behavior.
|
|
* \param c - The CmdLine object the output is generated for.
|
|
*/
|
|
virtual void version(CmdLineInterface& c);
|
|
|
|
/**
|
|
* Prints (to stderr) an error message, short usage
|
|
* Can be overridden to produce alternative behavior.
|
|
* \param c - The CmdLine object the output is generated for.
|
|
* \param e - The ArgException that caused the failure.
|
|
*/
|
|
virtual void failure(CmdLineInterface& c,
|
|
ArgException& e );
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Writes a brief usage message with short args.
|
|
* \param c - The CmdLine object the output is generated for.
|
|
* \param os - The stream to write the message to.
|
|
*/
|
|
void _shortUsage( CmdLineInterface& c, std::ostream& os ) const;
|
|
|
|
/**
|
|
* Writes a longer usage message with long and short args,
|
|
* provides descriptions and prints message.
|
|
* \param c - The CmdLine object the output is generated for.
|
|
* \param os - The stream to write the message to.
|
|
*/
|
|
void _longUsage( CmdLineInterface& c, std::ostream& os ) const;
|
|
|
|
/**
|
|
* This function inserts line breaks and indents long strings
|
|
* according the params input. It will only break lines at spaces,
|
|
* commas and pipes.
|
|
* \param os - The stream to be printed to.
|
|
* \param s - The string to be printed.
|
|
* \param maxWidth - The maxWidth allowed for the output line.
|
|
* \param indentSpaces - The number of spaces to indent the first line.
|
|
* \param secondLineOffset - The number of spaces to indent the second
|
|
* and all subsequent lines in addition to indentSpaces.
|
|
*/
|
|
void spacePrint( std::ostream& os,
|
|
const std::string& s,
|
|
int maxWidth,
|
|
int indentSpaces,
|
|
int secondLineOffset ) const;
|
|
|
|
};
|
|
|
|
|
|
inline void StdOutput::version(CmdLineInterface& _cmd)
|
|
{
|
|
std::string progName = _cmd.getProgramName();
|
|
std::string xversion = _cmd.getVersion();
|
|
|
|
std::cout << std::endl << progName << " version: "
|
|
<< xversion << std::endl << std::endl;
|
|
}
|
|
|
|
inline void StdOutput::usage(CmdLineInterface& _cmd )
|
|
{
|
|
std::cout << std::endl << "USAGE: " << std::endl << std::endl;
|
|
|
|
_shortUsage( _cmd, std::cout );
|
|
|
|
std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
|
|
|
|
_longUsage( _cmd, std::cout );
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
inline void StdOutput::failure( CmdLineInterface& _cmd,
|
|
ArgException& e )
|
|
{
|
|
std::string progName = _cmd.getProgramName();
|
|
|
|
std::cerr << "PARSE ERROR: " << e.argId() << std::endl
|
|
<< " " << e.error() << std::endl << std::endl;
|
|
|
|
if ( _cmd.hasHelpAndVersion() )
|
|
{
|
|
std::cerr << "Brief USAGE: " << std::endl;
|
|
|
|
_shortUsage( _cmd, std::cerr );
|
|
|
|
std::cerr << std::endl << "For complete USAGE and HELP type: "
|
|
<< std::endl << " " << progName << " --help"
|
|
<< std::endl << std::endl;
|
|
}
|
|
else
|
|
usage(_cmd);
|
|
|
|
throw ExitException(1);
|
|
}
|
|
|
|
inline void
|
|
StdOutput::_shortUsage( CmdLineInterface& _cmd,
|
|
std::ostream& os ) const
|
|
{
|
|
std::list<Arg*> argList = _cmd.getArgList();
|
|
std::string progName = _cmd.getProgramName();
|
|
XorHandler xorHandler = _cmd.getXorHandler();
|
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
|
|
|
std::string s = progName + " ";
|
|
|
|
// first the xor
|
|
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
|
{
|
|
s += " {";
|
|
for ( ArgVectorIterator it = xorList[i].begin();
|
|
it != xorList[i].end(); it++ )
|
|
s += (*it)->shortID() + "|";
|
|
|
|
s[s.length()-1] = '}';
|
|
}
|
|
|
|
// then the rest
|
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
|
if ( !xorHandler.contains( (*it) ) )
|
|
s += " " + (*it)->shortID();
|
|
|
|
// if the program name is too long, then adjust the second line offset
|
|
int secondLineOffset = static_cast<int>(progName.length()) + 2;
|
|
if ( secondLineOffset > 75/2 )
|
|
secondLineOffset = static_cast<int>(75/2);
|
|
|
|
spacePrint( os, s, 75, 3, secondLineOffset );
|
|
}
|
|
|
|
inline void
|
|
StdOutput::_longUsage( CmdLineInterface& _cmd,
|
|
std::ostream& os ) const
|
|
{
|
|
std::list<Arg*> argList = _cmd.getArgList();
|
|
std::string message = _cmd.getMessage();
|
|
XorHandler xorHandler = _cmd.getXorHandler();
|
|
std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
|
|
|
|
// first the xor
|
|
for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
|
|
{
|
|
for ( ArgVectorIterator it = xorList[i].begin();
|
|
it != xorList[i].end();
|
|
it++ )
|
|
{
|
|
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
|
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
|
|
|
if ( it+1 != xorList[i].end() )
|
|
spacePrint(os, "-- OR --", 75, 9, 0);
|
|
}
|
|
os << std::endl << std::endl;
|
|
}
|
|
|
|
// then the rest
|
|
for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
|
|
if ( !xorHandler.contains( (*it) ) )
|
|
{
|
|
spacePrint( os, (*it)->longID(), 75, 3, 3 );
|
|
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
|
|
os << std::endl;
|
|
}
|
|
|
|
os << std::endl;
|
|
|
|
spacePrint( os, message, 75, 3, 0 );
|
|
}
|
|
|
|
inline void StdOutput::spacePrint( std::ostream& os,
|
|
const std::string& s,
|
|
int maxWidth,
|
|
int indentSpaces,
|
|
int secondLineOffset ) const
|
|
{
|
|
int len = static_cast<int>(s.length());
|
|
|
|
if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
|
|
{
|
|
int allowedLen = maxWidth - indentSpaces;
|
|
int start = 0;
|
|
while ( start < len )
|
|
{
|
|
// find the substring length
|
|
// int stringLen = std::min<int>( len - start, allowedLen );
|
|
// doing it this way to support a VisualC++ 2005 bug
|
|
using namespace std;
|
|
int stringLen = min<int>( len - start, allowedLen );
|
|
|
|
// trim the length so it doesn't end in middle of a word
|
|
if ( stringLen == allowedLen )
|
|
while ( stringLen >= 0 &&
|
|
s[stringLen+start] != ' ' &&
|
|
s[stringLen+start] != ',' &&
|
|
s[stringLen+start] != '|' )
|
|
stringLen--;
|
|
|
|
// ok, the word is longer than the line, so just split
|
|
// wherever the line ends
|
|
if ( stringLen <= 0 )
|
|
stringLen = allowedLen;
|
|
|
|
// check for newlines
|
|
for ( int i = 0; i < stringLen; i++ )
|
|
if ( s[start+i] == '\n' )
|
|
stringLen = i+1;
|
|
|
|
// print the indent
|
|
for ( int i = 0; i < indentSpaces; i++ )
|
|
os << " ";
|
|
|
|
if ( start == 0 )
|
|
{
|
|
// handle second line offsets
|
|
indentSpaces += secondLineOffset;
|
|
|
|
// adjust allowed len
|
|
allowedLen -= secondLineOffset;
|
|
}
|
|
|
|
os << s.substr(start,stringLen) << std::endl;
|
|
|
|
// so we don't start a line with a space
|
|
while ( s[stringLen+start] == ' ' && start < len )
|
|
start++;
|
|
|
|
start += stringLen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int i = 0; i < indentSpaces; i++ )
|
|
os << " ";
|
|
os << s << std::endl;
|
|
}
|
|
}
|
|
|
|
} //namespace TCLAP
|
|
#endif
|