OverloadedCommand.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
17 #include "OverloadedCommand.hh"
18 //#include "OverloadedCommand.ih"
19 
20 // Custom includes
21 
22 //#include "OverloadedCommand.mpp"
23 #define prefix_
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
25 
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 // senf::console::CommandOverload
28 
30 {}
31 
32 prefix_ void senf::console::CommandOverload::operator()(boost::any & rv, std::ostream & os,
33  ParseCommandInfo const & command)
34 {
35  execute(rv, os, command);
36 }
37 
38 prefix_ void senf::console::CommandOverload::execute(boost::any & rv, std::ostream & os,
39  ParseCommandInfo const & command)
40 {
41  v_execute(rv, os, command);
42 }
43 
45  const
46 {
47  return v_numArguments();
48 }
49 
51  const
52 {
53  return v_argumentDoc(index,doc);
54 }
55 
57  const
58 {
59  return v_doc();
60 }
61 
63  const
64 {
65  SENF_ASSERT( node_, "Overload not added to any node yet" );
66  return *node_;
67 }
68 
70  const
71 {
72  return node().overloadIndex(*this);
73 }
74 
76  : node_(0)
77 {}
78 
79 
80 //-/////////////////////////////////////////////////////////////////////////////////////////////////
81 // senf::console::OverloadedCommandNode
82 
85  std::string const & name,
86  CommandOverload::ptr overload)
87 {
89  dir.hasChild(name)
90  ? dynamic_cast<OverloadedCommandNode &>(dir(name))
91  : dir.add(name, OverloadedCommandNode::create()));
92  node.add(overload);
93  return node;
94 }
95 
96 //-/////////////////////////////////////////////////////////////////////////////////////////////////
97 // So soll die doku aussehen:
98 //
99 // Usage:
100 // 1- foo arg1:int arg2:double
101 // 2- foo arg3:string
102 // 3- foo
103 //
104 // With:
105 // arg1 - arg1-doc
106 // arg2 - arg2-doc
107 // default: 1.23
108 // arg3 - arg3-doc
109 //
110 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
111 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
112 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
113 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
114 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
115 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
116 //
117 // Variant 1:
118 // Variant 1 doc la;ksjf lkj sdlkfj lkjekj sdflkj ekljsdlkfj wlej
119 // slkj dkj sldkfj lwekljsdf skldjf lskjdf l jsd
120 //
121 // Variant 2:
122 // Variant 2 doc lskdfj lwkej lksjdflksjf
123 //
124 // Variatn 3:
125 // Variant 3 doc slkjflw ekj lskdfj lskdjf laksdj flksj elkj aldskjf lwkejlksdj
126 // ldkfaj wlekj slkdfj lskdjf lwkejlkasdjf
127 
128 prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
129  const
130 {
131  typedef std::vector<ArgumentDoc> ArgumentDocs;
132  ArgumentDocs argumentDocs;
133  bool haveDocumentedArg (false);
134 
135  os << "Usage:\n";
136  {
137  Overloads::const_iterator i (overloads_.begin());
138  Overloads::const_iterator const i_end (overloads_.end());
139  unsigned index (1);
140  for (; i != i_end; ++i, ++index) {
141  os << " ";
142  if (overloads_.size() > 1) os << index << "- ";
143  os << name();
144  for (unsigned j (0); j < (*i)->numArguments(); ++j) {
145  ArgumentDoc arg;
146  (*i)->argumentDoc(j, arg);
147 
148  os << ' ';
149  if (! arg.defaultValue.empty())
150  os << '[';
151  if (! arg.name.empty()) os << arg.name;
152  if (! arg.type.empty()) os << ':' << arg.type;
153  if (arg.name.empty() && arg.type.empty()) os << "...";
154  if (! arg.defaultValue.empty())
155  os << ']';
156 
157  if (! arg.name.empty() || ! arg.defaultValue.empty()) {
158  ArgumentDocs::iterator k (argumentDocs.begin());
159  ArgumentDocs::iterator const k_end (argumentDocs.end());
160  for (; k != k_end; ++k)
161  if (k->name == arg.name && k->defaultValue == arg.defaultValue) {
162  if (! arg.doc.empty() && k->doc.empty()) {
163  k->doc = arg.doc;
164  haveDocumentedArg = true;
165  }
166  break;
167  }
168  if (k == k_end) {
169  argumentDocs.push_back(arg);
170  if (! arg.doc.empty())
171  haveDocumentedArg = true;
172  }
173  }
174  }
175  os << '\n';
176  }
177  }
178 
179  if (haveDocumentedArg) {
180  os << "\n" "With:\n";
181  ArgumentDocs::const_iterator i (argumentDocs.begin());
182  ArgumentDocs::const_iterator const i_end (argumentDocs.end());
183  for (; i != i_end; ++i) {
184  if (! i->doc.empty() || ! i->defaultValue.empty()) {
185  os << " "
186  << i->name
187  << std::string(i->name.length()<8 ? 8-i->name.length() : 0, ' ')
188  << " "
189  << i->doc
190  << '\n';
191  if (! i->defaultValue.empty())
192  os << " default: " << i->defaultValue << '\n';
193  }
194  }
195  }
196 
197  if (! doc_.empty())
198  os << "\n" << doc_ << "\n";
199 
200  {
201  Overloads::const_iterator i (overloads_.begin());
202  Overloads::const_iterator const i_end (overloads_.end());
203  unsigned index (1);
204  for (; i != i_end; ++i, ++index) {
205  std::string overloadDoc ((*i)->doc());
206  if (! overloadDoc.empty()) {
207  os << "\n";
208  if (overloads_.size() > 1)
209  os << "Variant " << index << ":\n";
210  os << overloadDoc << "\n";
211  }
212  }
213  }
214 }
215 
216 prefix_ std::string senf::console::OverloadedCommandNode::v_shorthelp()
217  const
218 {
219  if (!shortdoc_.empty())
220  return shortdoc_;
221  if (!doc_.empty())
222  return doc_.substr(0,doc_.find('\n'));
223  for (auto const & i : overloads_) {
224  std::string overloadDoc (i->doc());
225  if (! overloadDoc.empty())
226  return overloadDoc.substr(0,overloadDoc.find('\n'));
227  }
228  return "";
229 }
230 
231 prefix_ void senf::console::OverloadedCommandNode::v_execute(boost::any & rv,
232  std::ostream & os,
233  ParseCommandInfo const & command)
234  const
235 {
237  for (auto const & i : overloads_) {
238  try {
239  (*i)(rv, os, command);
240  return;
241  }
242  catch (SyntaxErrorException & ex) {
243  err = ex;
244  };
245  }
246  throw err;
247 }
248 
249 //-/////////////////////////////////////////////////////////////////////////////////////////////////
250 // senf::console::SimpleCommandOverload
251 
252 prefix_ unsigned senf::console::SimpleCommandOverload::v_numArguments()
253  const
254 {
255  return 1;
256 }
257 
258 prefix_ void senf::console::SimpleCommandOverload::v_argumentDoc(unsigned index, ArgumentDoc & doc)
259  const
260 {}
261 
262 prefix_ std::string senf::console::SimpleCommandOverload::v_doc()
263  const
264 {
265  return doc_;
266 }
267 
268 prefix_ void senf::console::SimpleCommandOverload::v_execute(boost::any & rv,
269  std::ostream & os,
270  ParseCommandInfo const & command)
271  const
272 {
273  fn_(os, command);
274 }
275 
276 //-/////////////////////////////////////////////////////////////////////////////////////////////////
277 #undef prefix_
278 //#include "OverloadedCommand.mpp"
279 
280 
281 // Local Variables:
282 // mode: c++
283 // fill-column: 100
284 // comment-column: 40
285 // c-file-style: "senf"
286 // indent-tabs-mode: nil
287 // ispell-local-dictionary: "american"
288 // compile-command: "scons -u test"
289 // End:
std::string type
Argument type (string representation)
void argumentDoc(unsigned index, ArgumentDoc &doc) const
Get information on argument index.
OverloadedCommandNode & node() const
Access owning node.
std::string doc
Documentation for this argument.
boost::intrusive_ptr< CommandOverload > ptr
Command & add(boost::intrusive_ptr< Command > overload)
Add an additional overload.
virtual void v_argumentDoc(unsigned index, ArgumentDoc &doc) const =0
Return argument documentation.
Config/console tree directory node.
Definition: Node.hh:406
#define prefix_
unsigned overloadIndex(CommandOverload const &overload)
Return the overload index for overload.
bool hasChild(std::string const &name) const
true, if there is a child with name name
Syntax error parsing command arguments exception.
Definition: Parse.hh:472
Command node which allows multiple registered callbacks.
virtual unsigned v_numArguments() const =0
Return the number of arguments.
void operator()(boost::any &rv, std::ostream &os, ParseCommandInfo const &command)
Call the overload.
Single parsed console command.
Definition: Parse.hh:363
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
Add node to tree.
std::string defaultValue
Default value (string representation) or empty string.
void execute(boost::any &rv, std::ostream &os, ParseCommandInfo const &command)
Call the overload.
OverloadedCommand public header.
#define SENF_ASSERT(x, comment)
unsigned overloadIndex() const
Get index of overload in it&#39;s OverloadedCommandNode.
std::string doc() const
Get overload documentation.
std::string name
Argument name.
unspecified_keyword_type name
Argument name.
static OverloadedCommandNode & insertOverload(DirectoryNode &dir, std::string const &name, CommandOverload::ptr overload)
virtual std::string v_doc() const =0
Return overload documentation.
Documentation for a single argument.
unsigned numArguments() const
Number of arguments this overload takes.
virtual void v_execute(boost::any &rv, std::ostream &os, ParseCommandInfo const &command) const =0
Execute the overload.