tclap  1.2.2
ZshCompletionOutput.h
Go to the documentation of this file.
1 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
2 
3 /******************************************************************************
4  *
5  * file: ZshCompletionOutput.h
6  *
7  * Copyright (c) 2006, Oliver Kiddle
8  * Copyright (c) 2017 Google Inc.
9  * All rights reserved.
10  *
11  * See the file COPYING in the top directory of this distribution for
12  * more information.
13  *
14  * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  *
22  *****************************************************************************/
23 
24 #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H
25 #define TCLAP_ZSHCOMPLETIONOUTPUT_H
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include <string>
32 #include <vector>
33 #include <list>
34 #include <iostream>
35 #include <map>
36 
37 #include <tclap/CmdLineInterface.h>
38 #include <tclap/CmdLineOutput.h>
39 #include <tclap/XorHandler.h>
40 #include <tclap/Arg.h>
41 #include <tclap/sstream.h>
42 
43 namespace TCLAP {
44 
50 {
51 
52  public:
53 
55 
61  virtual void usage(CmdLineInterface& c);
62 
68  virtual void version(CmdLineInterface& c);
69 
76  virtual void failure(CmdLineInterface& c,
77  ArgException& e );
78 
79  protected:
80 
81  void basename( std::string& s );
82  void quoteSpecialChars( std::string& s );
83 
84  std::string getMutexList( CmdLineInterface& _cmd, Arg* a );
85  void printOption( Arg* it, std::string mutex );
86  void printArg( Arg* it );
87 
88  std::map<std::string, std::string> common;
90 };
91 
93 : common(std::map<std::string, std::string>()),
94  theDelimiter('=')
95 {
96  common["host"] = "_hosts";
97  common["hostname"] = "_hosts";
98  common["file"] = "_files";
99  common["filename"] = "_files";
100  common["user"] = "_users";
101  common["username"] = "_users";
102  common["directory"] = "_directories";
103  common["path"] = "_directories";
104  common["url"] = "_urls";
105 }
106 
108 {
109  std::cout << _cmd.getVersion() << std::endl;
110 }
111 
113 {
114  std::list<Arg*> argList = _cmd.getArgList();
115  std::string progName = _cmd.getProgramName();
116  std::string xversion = _cmd.getVersion();
117  theDelimiter = _cmd.getDelimiter();
118  basename(progName);
119 
120  std::cout << "#compdef " << progName << std::endl << std::endl <<
121  "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl <<
122  "_arguments -s -S";
123 
124  for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
125  {
126  if ( (*it)->shortID().at(0) == '<' )
127  printArg((*it));
128  else if ( (*it)->getFlag() != "-" )
129  printOption((*it), getMutexList(_cmd, *it));
130  }
131 
132  std::cout << std::endl;
133 }
134 
136  ArgException& e )
137 {
138  static_cast<void>(_cmd); // unused
139  std::cout << e.what() << std::endl;
140 }
141 
142 inline void ZshCompletionOutput::quoteSpecialChars( std::string& s )
143 {
144  size_t idx = s.find_last_of(':');
145  while ( idx != std::string::npos )
146  {
147  s.insert(idx, 1, '\\');
148  idx = s.find_last_of(':', idx);
149  }
150  idx = s.find_last_of('\'');
151  while ( idx != std::string::npos )
152  {
153  s.insert(idx, "'\\'");
154  if (idx == 0)
155  idx = std::string::npos;
156  else
157  idx = s.find_last_of('\'', --idx);
158  }
159 }
160 
161 inline void ZshCompletionOutput::basename( std::string& s )
162 {
163  size_t p = s.find_last_of('/');
164  if ( p != std::string::npos )
165  {
166  s.erase(0, p + 1);
167  }
168 }
169 
171 {
172  static int count = 1;
173 
174  std::cout << " \\" << std::endl << " '";
175  if ( a->acceptsMultipleValues() )
176  std::cout << '*';
177  else
178  std::cout << count++;
179  std::cout << ':';
180  if ( !a->isRequired() )
181  std::cout << ':';
182 
183  std::cout << a->getName() << ':';
184  std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
185  if ( compArg != common.end() )
186  {
187  std::cout << compArg->second;
188  }
189  else
190  {
191  std::cout << "_guard \"^-*\" " << a->getName();
192  }
193  std::cout << '\'';
194 }
195 
196 inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
197 {
198  std::string flag = a->flagStartChar() + a->getFlag();
199  std::string name = a->nameStartString() + a->getName();
200  std::string desc = a->getDescription();
201 
202  // remove full stop and capitalization from description as
203  // this is the convention for zsh function
204  if (!desc.compare(0, 12, "(required) "))
205  {
206  desc.erase(0, 12);
207  }
208  if (!desc.compare(0, 15, "(OR required) "))
209  {
210  desc.erase(0, 15);
211  }
212  size_t len = desc.length();
213  if (len && desc.at(--len) == '.')
214  {
215  desc.erase(len);
216  }
217  if (len)
218  {
219  desc.replace(0, 1, 1, tolower(desc.at(0)));
220  }
221 
222  std::cout << " \\" << std::endl << " '" << mutex;
223 
224  if ( a->getFlag().empty() )
225  {
226  std::cout << name;
227  }
228  else
229  {
230  std::cout << "'{" << flag << ',' << name << "}'";
231  }
232  if ( theDelimiter == '=' && a->isValueRequired() )
233  std::cout << "=-";
234  quoteSpecialChars(desc);
235  std::cout << '[' << desc << ']';
236 
237  if ( a->isValueRequired() )
238  {
239  std::string arg = a->shortID();
240  // Example arg: "[-A <integer>] ... "
241  size_t pos = arg.rfind(" ... ");
242  if (pos != std::string::npos) {
243  arg.erase(pos);
244  }
245 
246  arg.erase(0, arg.find_last_of(theDelimiter) + 1);
247  if ( arg.at(arg.length()-1) == ']' )
248  arg.erase(arg.length()-1);
249  if ( arg.at(arg.length()-1) == ']' )
250  {
251  arg.erase(arg.length()-1);
252  }
253  if ( arg.at(0) == '<' )
254  {
255  arg.erase(arg.length()-1);
256  arg.erase(0, 1);
257  }
258  size_t p = arg.find('|');
259  if ( p != std::string::npos )
260  {
261  do
262  {
263  arg.replace(p, 1, 1, ' ');
264  }
265  while ( (p = arg.find_first_of('|', p)) != std::string::npos );
266  quoteSpecialChars(arg);
267  std::cout << ": :(" << arg << ')';
268  }
269  else
270  {
271  std::cout << ':' << arg;
272  std::map<std::string, std::string>::iterator compArg = common.find(arg);
273  if ( compArg != common.end() )
274  {
275  std::cout << ':' << compArg->second;
276  }
277  }
278  }
279 
280  std::cout << '\'';
281 }
282 
284 {
285  XorHandler xorHandler = _cmd.getXorHandler();
286  std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
287 
288  if (a->getName() == "help" || a->getName() == "version")
289  {
290  return "(-)";
291  }
292 
293  ostringstream list;
294  if ( a->acceptsMultipleValues() )
295  {
296  list << '*';
297  }
298 
299  for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
300  {
301  for ( ArgVectorIterator it = xorList[i].begin();
302  it != xorList[i].end();
303  it++)
304  if ( a == (*it) )
305  {
306  list << '(';
307  for ( ArgVectorIterator iu = xorList[i].begin();
308  iu != xorList[i].end();
309  iu++ )
310  {
311  bool notCur = (*iu) != a;
312  bool hasFlag = !(*iu)->getFlag().empty();
313  if ( iu != xorList[i].begin() && (notCur || hasFlag) )
314  list << ' ';
315  if (hasFlag)
316  list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' ';
317  if ( notCur || hasFlag )
318  list << (*iu)->nameStartString() << (*iu)->getName();
319  }
320  list << ')';
321  return list.str();
322  }
323  }
324 
325  // wasn't found in xor list
326  if (!a->getFlag().empty()) {
327  list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
328  a->nameStartString() << a->getName() << ')';
329  }
330 
331  return list.str();
332 }
333 
334 } //namespace TCLAP
335 #endif
std::vector< std::vector< Arg * > > & getXorList()
Definition: XorHandler.h:153
A virtual base class that defines the essential data for all arguments.
Definition: Arg.h:65
const char * what() const
Returns the arg id and error text.
Definition: ArgException.h:80
A simple class that defines and argument exception.
Definition: ArgException.h:36
std::string getDescription() const
Returns the argument description.
Definition: Arg.h:555
virtual std::string & getProgramName()=0
Returns the program name string.
static char flagStartChar()
Definition: Arg.h:227
virtual std::list< Arg * > & getArgList()=0
Returns the argList.
virtual char getDelimiter()=0
Returns the delimiter string.
void quoteSpecialChars(std::string &s)
const std::string & getName() const
Returns the argument name.
Definition: Arg.h:570
bool isValueRequired() const
Indicates whether a value must be specified for argument.
Definition: Arg.h:574
virtual std::string & getVersion()=0
Returns the version string.
virtual void version(CmdLineInterface &c)
Prints the version to stdout.
void printOption(Arg *it, std::string mutex)
void basename(std::string &s)
const std::string & getFlag() const
Returns the argument flag.
Definition: Arg.h:568
virtual XorHandler & getXorHandler()=0
Returns the XorHandler.
static const std::string nameStartString()
Definition: Arg.h:246
virtual void usage(CmdLineInterface &c)
Prints the usage to stdout.
virtual std::string shortID(const std::string &valueId="val") const
Returns a short ID for the usage.
Definition: Arg.h:506
std::list< Arg * >::iterator ArgListIterator
Typedef of an Arg list iterator.
Definition: Arg.h:397
The base class that manages the command line definition and passes along the parsing to the appropria...
virtual bool acceptsMultipleValues()
Use by output classes to determine whether an Arg accepts multiple values.
Definition: Arg.h:675
std::vector< Arg * >::iterator ArgVectorIterator
Typedef of an Arg vector iterator.
Definition: Arg.h:402
std::ostringstream ostringstream
Definition: sstream.h:38
std::map< std::string, std::string > common
Definition: Arg.h:58
std::string getMutexList(CmdLineInterface &_cmd, Arg *a)
This class handles lists of Arg's that are to be XOR'd on the command line.
Definition: XorHandler.h:38
virtual void failure(CmdLineInterface &c, ArgException &e)
Prints (to stderr) an error message, short usage Can be overridden to produce alternative behavior...
The interface that any output object must implement.
Definition: CmdLineOutput.h:41
virtual bool isRequired() const
Indicates whether the argument is required.
Definition: Arg.h:572
A class that generates a Zsh completion function as output from the usage() method for the given CmdL...