switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / OverloadedCommand.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief OverloadedCommand non-inline non-template implementation */
30
31 #include "OverloadedCommand.hh"
32 //#include "OverloadedCommand.ih"
33
34 // Custom includes
35
36 //#include "OverloadedCommand.mpp"
37 #define prefix_
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41 // senf::console::OverloadedCommandNode
42
43 prefix_ senf::console::OverloadedCommandNode &
44 senf::console::OverloadedCommandNode::insertOverload(DirectoryNode & dir,
45                                                      std::string const & name,
46                                                      CommandOverload::ptr overload)
47 {
48     OverloadedCommandNode & node (
49         dir.hasChild(name)
50         ? dynamic_cast<OverloadedCommandNode &>(dir(name))
51         : dir.add(name, OverloadedCommandNode::create()));
52     node.add(overload);
53     return node;
54 }
55
56 //-/////////////////////////////////////////////////////////////////////////////////////////////////
57 // So soll die doku aussehen:
58 //
59 // Usage:
60 //      1- foo arg1:int arg2:double
61 //      2- foo arg3:string
62 //      3- foo
63 //
64 // With:
65 //      arg1 -   arg1-doc
66 //      arg2 -   arg2-doc
67 //          default: 1.23
68 //      arg3 -   arg3-doc
69 //
70 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
71 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
72 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
73 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
74 // Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
75 // sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
76 //
77 // Variant 1:
78 // Variant 1 doc la;ksjf lkj sdlkfj lkjekj sdflkj ekljsdlkfj wlej
79 // slkj dkj sldkfj lwekljsdf skldjf lskjdf l jsd
80 //
81 // Variant 2:
82 // Variant 2 doc lskdfj lwkej lksjdflksjf
83 //
84 // Variatn 3:
85 // Variant 3 doc slkjflw ekj lskdfj lskdjf laksdj flksj elkj aldskjf lwkejlksdj
86 // ldkfaj wlekj slkdfj lskdjf lwkejlkasdjf
87
88 prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
89     const
90 {
91     typedef std::vector<ArgumentDoc> ArgumentDocs;
92     ArgumentDocs argumentDocs;
93     bool haveDocumentedArg (false);
94
95     os << "Usage:\n";
96     {
97         Overloads::const_iterator i (overloads_.begin());
98         Overloads::const_iterator const i_end (overloads_.end());
99         unsigned index (1);
100         for (; i != i_end; ++i, ++index) {
101             os << "    ";
102             if (overloads_.size() > 1) os << index << "- ";
103             os << name();
104             for (unsigned j (0); j < (*i)->numArguments(); ++j) {
105                 ArgumentDoc arg;
106                 (*i)->argumentDoc(j, arg);
107
108                 os << ' ';
109                 if (! arg.defaultValue.empty())
110                     os << '[';
111                 if (! arg.name.empty()) os << arg.name;
112                 if (! arg.type.empty()) os << ':' << arg.type;
113                 if (arg.name.empty() && arg.type.empty()) os << "...";
114                 if (! arg.defaultValue.empty())
115                     os << ']';
116
117                 if (! arg.name.empty() || ! arg.defaultValue.empty()) {
118                     ArgumentDocs::iterator k (argumentDocs.begin());
119                     ArgumentDocs::iterator const k_end (argumentDocs.end());
120                     for (; k != k_end; ++k)
121                         if (k->name == arg.name && k->defaultValue == arg.defaultValue) {
122                             if (! arg.doc.empty() && k->doc.empty()) {
123                                 k->doc == arg.doc;
124                                 haveDocumentedArg = true;
125                             }
126                             break;
127                         }
128                     if (k == k_end) {
129                         argumentDocs.push_back(arg);
130                         if (! arg.doc.empty())
131                             haveDocumentedArg = true;
132                     }
133                 }
134             }
135             os << '\n';
136         }
137     }
138
139     if (haveDocumentedArg) {
140         os << "\n" "With:\n";
141         ArgumentDocs::const_iterator i (argumentDocs.begin());
142         ArgumentDocs::const_iterator const i_end (argumentDocs.end());
143         for (; i != i_end; ++i) {
144             if (! i->doc.empty() || ! i->defaultValue.empty()) {
145                 os << "    "
146                    << i->name
147                    << std::string(i->name.length()<8 ? 8-i->name.length() : 0, ' ')
148                    << "  "
149                    << i->doc
150                    << '\n';
151                 if (! i->defaultValue.empty())
152                     os << "        default: " << i->defaultValue << '\n';
153             }
154         }
155     }
156
157     if (! doc_.empty())
158         os << "\n" << doc_ << "\n";
159
160     {
161         Overloads::const_iterator i (overloads_.begin());
162         Overloads::const_iterator const i_end (overloads_.end());
163         unsigned index (1);
164         for (; i != i_end; ++i, ++index) {
165             std::string overloadDoc ((*i)->doc());
166             if (! overloadDoc.empty()) {
167                 os << "\n";
168                 if (overloads_.size() > 1)
169                     os << "Variant " << index << ":\n";
170                 os << overloadDoc << "\n";
171             }
172         }
173     }
174 }
175
176 prefix_ std::string senf::console::OverloadedCommandNode::v_shorthelp()
177     const
178 {
179     if (!shortdoc_.empty())
180         return shortdoc_;
181     if (!doc_.empty())
182         return doc_.substr(0,doc_.find('\n'));
183     Overloads::const_iterator i (overloads_.begin());
184     Overloads::const_iterator const i_end (overloads_.end());
185     for (; i != i_end; ++i) {
186         std::string overloadDoc ((*i)->doc());
187         if (! overloadDoc.empty())
188             return overloadDoc.substr(0,overloadDoc.find('\n'));
189     }
190     return "";
191 }
192
193 prefix_ void senf::console::OverloadedCommandNode::v_execute(boost::any & rv,
194                                                              std::ostream & os,
195                                                              ParseCommandInfo const & command)
196     const
197 {
198     Overloads::const_iterator i (overloads_.begin());
199     Overloads::const_iterator const i_end (overloads_.end());
200     SyntaxErrorException err;
201     for (; i != i_end; ++i) {
202         try {
203             (**i)(rv, os, command);
204             return;
205         }
206         catch (SyntaxErrorException & ex) {
207             err = ex;
208         };
209     }
210     throw err;
211 }
212
213 //-/////////////////////////////////////////////////////////////////////////////////////////////////
214 // senf::console::SimpleCommandOverload
215
216 prefix_ unsigned senf::console::SimpleCommandOverload::v_numArguments()
217     const
218 {
219     return 1;
220 }
221
222 prefix_ void senf::console::SimpleCommandOverload::v_argumentDoc(unsigned index, ArgumentDoc & doc)
223     const
224 {}
225
226 prefix_ std::string senf::console::SimpleCommandOverload::v_doc()
227     const
228 {
229     return doc_;
230 }
231
232 prefix_ void senf::console::SimpleCommandOverload::v_execute(boost::any & rv,
233                                                              std::ostream & os,
234                                                              ParseCommandInfo const & command)
235     const
236 {
237     fn_(os, command);
238 }
239
240 //-/////////////////////////////////////////////////////////////////////////////////////////////////
241 #undef prefix_
242 //#include "OverloadedCommand.mpp"
243
244 \f
245 // Local Variables:
246 // mode: c++
247 // fill-column: 100
248 // comment-column: 40
249 // c-file-style: "senf"
250 // indent-tabs-mode: nil
251 // ispell-local-dictionary: "american"
252 // compile-command: "scons -u test"
253 // End: