tclap: ZshCompletionOutput.h Source File

Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

# ZshCompletionOutput.h

Go to the documentation of this file.

    00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
    00002
    00003 /******************************************************************************
    00004  *
    00005  *  file:  ZshCompletionOutput.h
    00006  *
    00007  *  Copyright (c) 2006, Oliver Kiddle
    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_ZSHCOMPLETIONOUTPUT_H
    00024 #define TCLAP_ZSHCOMPLETIONOUTPUT_H
    00025
    00026 #include <string>
    00027 #include <vector>
    00028 #include <list>
    00029 #include <iostream>
    00030 #include <map>
    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 ZshCompletionOutput : public CmdLineOutput
    00044 {
    00045
    00046     public:
    00047
    00048         ZshCompletionOutput();
    00049
    00055         virtual void usage(CmdLineInterface& c);
    00056
    00062         virtual void version(CmdLineInterface& c);
    00063
    00070         virtual void failure(CmdLineInterface& c,
    00071                              ArgException& e );
    00072
    00073     protected:
    00074
    00075         void basename( std::string& s );
    00076         void quoteSpecialChars( std::string& s );
    00077
    00078         std::string getMutexList( CmdLineInterface& _cmd, Arg* a );
    00079         void printOption( Arg* it, std::string mutex );
    00080         void printArg( Arg* it );
    00081
    00082         std::map<std::string, std::string> common;
    00083         char theDelimiter;
    00084 };
    00085
    00086 ZshCompletionOutput::ZshCompletionOutput()
    00087 {
    00088     common["host"] = "_hosts";
    00089     common["hostname"] = "_hosts";
    00090     common["file"] = "_files";
    00091     common["filename"] = "_files";
    00092     common["user"] = "_users";
    00093     common["username"] = "_users";
    00094     common["directory"] = "_directories";
    00095     common["path"] = "_directories";
    00096     common["url"] = "_urls";
    00097 }
    00098
    00099 inline void ZshCompletionOutput::version(CmdLineInterface& _cmd)
    00100 {
    00101     std::cout << _cmd.getVersion() << std::endl;
    00102 }
    00103
    00104 inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd )
    00105 {
    00106     std::list<Arg*> argList = _cmd.getArgList();
    00107     std::string progName = _cmd.getProgramName();
    00108     std::string version = _cmd.getVersion();
    00109     theDelimiter = _cmd.getDelimiter();
    00110     basename(progName);
    00111
    00112     std::cout << "#compdef " << progName << std::endl << std::endl <<
    00113         "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl <<
    00114         "_arguments -s -S";
    00115
    00116     for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
    00117     {
    00118         if ( (*it)->shortID().at(0) == '<' )
    00119             printArg((*it));
    00120         else if ( (*it)->getFlag() != "-" )
    00121             printOption((*it), getMutexList(_cmd, *it));
    00122     }
    00123
    00124     std::cout << std::endl;
    00125 }
    00126
    00127 inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd,
    00128                                 ArgException& e )
    00129 {
    00130     static_cast<void>(_cmd); // unused
    00131     std::cout << e.what() << std::endl;
    00132 }
    00133
    00134 inline void ZshCompletionOutput::quoteSpecialChars( std::string& s )
    00135 {
    00136     size_t idx = s.find_last_of(':');
    00137     while ( idx != std::string::npos )
    00138     {
    00139         s.insert(idx, 1, '\\');
    00140         idx = s.find_last_of(':', idx);
    00141     }
    00142     idx = s.find_last_of('\'');
    00143     while ( idx != std::string::npos )
    00144     {
    00145         s.insert(idx, "'\\'");
    00146         if (idx == 0)
    00147             idx = std::string::npos;
    00148         else
    00149             idx = s.find_last_of('\'', --idx);
    00150     }
    00151 }
    00152
    00153 inline void ZshCompletionOutput::basename( std::string& s )
    00154 {
    00155     size_t p = s.find_last_of('/');
    00156     if ( p != std::string::npos )
    00157     {
    00158         s.erase(0, p + 1);
    00159     }
    00160 }
    00161
    00162 inline void ZshCompletionOutput::printArg(Arg* a)
    00163 {
    00164     static int count = 1;
    00165
    00166     std::cout << " \\" << std::endl << "  '";
    00167     if ( a->acceptsMultipleValues() )
    00168         std::cout << '*';
    00169     else
    00170         std::cout << count++;
    00171     std::cout << ':';
    00172     if ( !a->isRequired() )
    00173         std::cout << ':';
    00174
    00175     std::cout << a->getName() << ':';
    00176     std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
    00177     if ( compArg != common.end() )
    00178     {
    00179         std::cout << compArg->second;
    00180     }
    00181     else
    00182     {
    00183         std::cout << "_guard \"^-*\" " << a->getName();
    00184     }
    00185     std::cout << '\'';
    00186 }
    00187
    00188 inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
    00189 {
    00190     std::string flag = a->flagStartChar() + a->getFlag();
    00191     std::string name = a->nameStartString() + a->getName();
    00192     std::string desc = a->getDescription();
    00193
    00194     // remove full stop and capitalisation from description as
    00195     // this is the convention for zsh function
    00196     if (!desc.compare(0, 12, "(required)  "))
    00197     {
    00198         desc.erase(0, 12);
    00199     }
    00200     if (!desc.compare(0, 15, "(OR required)  "))
    00201     {
    00202         desc.erase(0, 15);
    00203     }
    00204     size_t len = desc.length();
    00205     if (len && desc.at(--len) == '.')
    00206     {
    00207         desc.erase(len);
    00208     }
    00209     if (len)
    00210     {
    00211         desc.replace(0, 1, 1, tolower(desc.at(0)));
    00212     }
    00213
    00214     std::cout << " \\" << std::endl << "  '" << mutex;
    00215
    00216     if ( a->getFlag().empty() )
    00217     {
    00218         std::cout << name;
    00219     }
    00220     else
    00221     {
    00222         std::cout << "'{" << flag << ',' << name << "}'";
    00223     }
    00224     if ( theDelimiter == '=' && a->isValueRequired() )
    00225         std::cout << "=-";
    00226     quoteSpecialChars(desc);
    00227     std::cout << '[' << desc << ']';
    00228
    00229     if ( a->isValueRequired() )
    00230     {
    00231         std::string arg = a->shortID();
    00232         arg.erase(0, arg.find_last_of(theDelimiter) + 1);
    00233         if ( arg.at(arg.length()-1) == ']' )
    00234             arg.erase(arg.length()-1);
    00235         if ( arg.at(arg.length()-1) == ']' )
    00236         {
    00237             arg.erase(arg.length()-1);
    00238         }
    00239         if ( arg.at(0) == '<' )
    00240         {
    00241             arg.erase(arg.length()-1);
    00242             arg.erase(0, 1);
    00243         }
    00244         size_t p = arg.find('|');
    00245         if ( p != std::string::npos )
    00246         {
    00247             do
    00248             {
    00249                 arg.replace(p, 1, 1, ' ');
    00250             }
    00251             while ( (p = arg.find_first_of('|', p)) != std::string::npos );
    00252             quoteSpecialChars(arg);
    00253             std::cout << ": :(" << arg << ')';
    00254         }
    00255         else
    00256         {
    00257             std::cout << ':' << arg;
    00258             std::map<std::string, std::string>::iterator compArg = common.find(arg);
    00259             if ( compArg != common.end() )
    00260             {
    00261                 std::cout << ':' << compArg->second;
    00262             }
    00263         }
    00264     }
    00265
    00266     std::cout << '\'';
    00267 }
    00268
    00269 inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a)
    00270 {
    00271     XorHandler xorHandler = _cmd.getXorHandler();
    00272     std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
    00273
    00274     if (a->getName() == "help" || a->getName() == "version")
    00275     {
    00276         return "(-)";
    00277     }
    00278
    00279     std::ostringstream list;
    00280     if ( a->acceptsMultipleValues() )
    00281     {
    00282         list << '*';
    00283     }
    00284
    00285     for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
    00286     {
    00287         for ( ArgVectorIterator it = xorList[i].begin();
    00288             it != xorList[i].end();
    00289             it++)
    00290         if ( a == (*it) )
    00291         {
    00292             list << '(';
    00293             for ( ArgVectorIterator iu = xorList[i].begin();
    00294                 iu != xorList[i].end();
    00295                 iu++ )
    00296             {
    00297                 bool notCur = (*iu) != a;
    00298                 bool hasFlag = !(*iu)->getFlag().empty();
    00299                 if ( iu != xorList[i].begin() && (notCur || hasFlag) )
    00300                     list << ' ';
    00301                 if (hasFlag)
    00302                     list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' ';
    00303                 if ( notCur || hasFlag )
    00304                     list << (*iu)->nameStartString() << (*iu)->getName();
    00305             }
    00306             list << ')';
    00307             return list.str();
    00308         }
    00309     }
    00310
    00311     // wasn't found in xor list
    00312     if (!a->getFlag().empty()) {
    00313         list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
    00314             a->nameStartString() << a->getName() << ')';
    00315     }
    00316
    00317     return list.str();
    00318 }
    00319
    00320 } //namespace TCLAP
    00321 #endif