UniversalIndentGUI 1.2.0
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines