UniversalIndentGUI 1.2.0
|
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