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