Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc @ 7228

Last change on this file since 7228 was 7228, checked in by landauf, 14 years ago

re-implemented CommandExecutor and CommandEvaluation. parameter evaluation is currently not implemented, will come soon.

  • Property svn:eol-style set to native
File size: 10.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "CommandEvaluation.h"
30
31#include "util/StringUtils.h"
32#include "CommandExecutor.h"
33#include "ConsoleCommand.h"
34
35namespace orxonox
36{
37    CommandEvaluation::CommandEvaluation()
38    {
39        this->initialize("");
40    }
41
42    void CommandEvaluation::initialize(const std::string& command)
43    {
44        this->execCommand_ = 0;
45        this->hintCommand_ = 0;
46        this->string_ = command;
47        this->execArgumentsOffset_ = 0;
48        this->hintArgumentsOffset_ = 0;
49        this->bPossibleArgumentsRetrieved_ = false;
50        this->possibleArguments_.clear();
51
52        this->tokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
53    }
54
55    unsigned int CommandEvaluation::getNumberOfArguments() const
56    {
57        unsigned int count = this->tokens_.size();
58        if (count > 0 && this->string_[this->string_.size() - 1] != ' ')
59            return count;
60        else
61            return count + 1;
62    }
63
64    const std::string& CommandEvaluation::getLastArgument() const
65    {
66        if (this->tokens_.size() > 0 && this->string_[this->string_.size() - 1] != ' ')
67            return this->tokens_.back();
68        else
69            return BLANKSTRING;
70    }
71
72    const std::string& CommandEvaluation::getToken(unsigned int i) const
73    {
74        if (i < this->tokens_.size())
75            return this->tokens_[i];
76        else
77            return BLANKSTRING;
78    }
79
80    int CommandEvaluation::execute() const
81    {
82        int error;
83        this->query(&error);
84        return error;
85    }
86
87    MultiType CommandEvaluation::query(int* error) const
88    {
89        if (error)
90        {
91            *error = CommandExecutor::Success;
92
93            if (!this->execCommand_)
94                *error = CommandExecutor::Error;
95            else if (!this->execCommand_->isActive())
96                *error = CommandExecutor::Deactivated;
97            else if (!this->execCommand_->hasAccess())
98                *error = CommandExecutor::Denied;
99
100            if (*error != CommandExecutor::Success)
101                return MT_Type::Null;
102        }
103
104        if (this->execCommand_ && this->execCommand_->isActive() && this->execCommand_->hasAccess())
105            return this->execCommand_->getExecutor()->parse(this->tokens_.subSet(this->execArgumentsOffset_).join(), error, " ", false);
106        else
107            return MT_Type::Null;
108    }
109
110    std::string CommandEvaluation::complete() const
111    {
112        if (!this->hintCommand_ || !this->hintCommand_->isActive())
113            return this->string_;
114
115        if (!this->bPossibleArgumentsRetrieved_)
116            this->retrievePossibleArguments();
117
118        if (this->possibleArguments_.empty())
119        {
120            return this->string_;
121        }
122        else
123        {
124            std::string output;
125            for (unsigned int i = 0; i < this->getNumberOfArguments() - 1; ++i)
126                output += this->getToken(i) + ' ';
127
128            output += CommandEvaluation::getCommonBegin(this->possibleArguments_);
129            return output;
130        }
131    }
132
133    std::string CommandEvaluation::hint() const
134    {
135        if (!this->hintCommand_ || !this->hintCommand_->isActive())
136            return "";
137
138        if (!this->bPossibleArgumentsRetrieved_)
139            this->retrievePossibleArguments();
140
141        if (!this->possibleArguments_.empty())
142            return CommandEvaluation::dump(this->possibleArguments_);
143
144        if (this->isValid())
145        {
146            return CommandEvaluation::dump(this->hintCommand_);
147        }
148        else
149        {
150            if (this->getNumberOfArguments() > 2)
151            {
152                return std::string("Error: There is no command with name \"") + this->getToken(0) + " " + this->getToken(1) + "\".";
153            }
154            else
155            {
156                std::string groupLC = getLowercase(this->getToken(0));
157                std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommands().begin();
158                for ( ; it_group != _ConsoleCommand::getCommands().end(); ++it_group)
159                    if (getLowercase(it_group->first) == groupLC)
160                        return std::string("Error: There is no command in group \"") + this->getToken(0) + "\" starting with \"" + this->getToken(1) + "\".";
161
162                return std::string("Error: There is no command starting with \"") + this->getToken(0) + "\".";
163            }
164        }
165    }
166
167    void CommandEvaluation::retrievePossibleArguments() const
168    {
169        this->bPossibleArgumentsRetrieved_ = true;
170        unsigned int argumentID = std::min(this->getNumberOfArguments() - this->hintArgumentsOffset_, this->hintCommand_->getExecutor()->getParamCount());
171        ArgumentCompleter* ac = this->hintCommand_->getArgumentCompleter(argumentID - 1);
172
173COUT(0) << "hint: args: " << this->getNumberOfArguments() << ", aID: " << argumentID << ", offset: " << this->hintArgumentsOffset_ << ", ac: " << ac << std::endl;
174        if (ac)
175        {
176            MultiType param[MAX_FUNCTOR_ARGUMENTS];
177
178            for (size_t i = 0; i < argumentID; ++i)
179            {
180                param[i] = this->getToken(this->getNumberOfArguments() - i - 1);
181COUT(0) << i << ": " << (this->getNumberOfArguments() - i - 1) << " -> " << this->getToken(this->getNumberOfArguments() - i - 1) << " / " << param[i] << std::endl;
182            }
183
184COUT(0) << "hint: 1: " << param[0] << ", 2: " << param[1] << ", 3: " << param[2] << ", 4: " << param[3] << ", 5: " << param[4] << std::endl;
185            this->possibleArguments_ = (*ac)(param[0], param[1], param[2], param[3], param[4]);
186
187            CommandEvaluation::strip(this->possibleArguments_, param[0]);
188        }
189    }
190
191    /* static */ void CommandEvaluation::strip(ArgumentCompletionList& list, const std::string& fragment)
192    {
193        std::string fragmentLC = getLowercase(fragment);
194
195        for (ArgumentCompletionList::iterator it = list.begin(); it != list.end(); )
196        {
197            const std::string& entry = it->getComparable();
198
199            if (entry.size() < fragmentLC.size())
200            {
201                list.erase(it++);
202            }
203            else
204            {
205                bool bErase = false;
206                for (size_t i = 0; i < fragmentLC.size(); ++i)
207                {
208                    if (fragmentLC[i] != entry[i])
209                    {
210                        bErase = true;
211                        break;
212                    }
213                }
214
215                if (bErase)
216                    list.erase(it++);
217                else
218                    ++it;
219            }
220        }
221    }
222
223    /* static */ std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
224    {
225        std::string output;
226        for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
227        {
228            if (it != list.begin())
229                output += ' ';
230
231            output += it->getDisplay();
232        }
233        return output;
234    }
235
236    /* static */ std::string CommandEvaluation::dump(const _ConsoleCommand* command)
237    {
238        std::string output = command->getName();
239        if (command->getExecutor()->getParamCount() > 0)
240            output += ": ";
241
242        for (unsigned int i = 0; i < command->getExecutor()->getParamCount(); i++)
243        {
244            if (i != 0)
245                output += ' ';
246
247            if (command->getExecutor()->defaultValueSet(i))
248                output += '[';
249            else
250                output += '{';
251
252            output += command->getExecutor()->getTypenameParam(i);
253
254            if (command->getExecutor()->defaultValueSet(i))
255                output += '=' + command->getExecutor()->getDefaultValue(i).getString() + ']';
256            else
257                output += '}';
258        }
259        return output;
260    }
261
262    /* static */ std::string CommandEvaluation::getCommonBegin(const ArgumentCompletionList& list)
263    {
264        if (list.size() == 0)
265        {
266            return "";
267        }
268        else if (list.size() == 1)
269        {
270            if (list.begin()->hasDisplay())
271                return (list.begin()->getString());
272            else
273                return (list.begin()->getString() + ' ');
274        }
275        else
276        {
277            std::string output;
278            for (unsigned int i = 0; true; i++)
279            {
280                char tempComparable = 0;
281                char temp = 0;
282                for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
283                {
284                    const std::string& argumentComparable = it->getComparable();
285                    const std::string& argument = it->getString();
286                    if (argument.size() > i)
287                    {
288                        if (it == list.begin())
289                        {
290                            tempComparable = argumentComparable[i];
291                            temp = argument[i];
292                        }
293                        else
294                        {
295                            if (tempComparable != argumentComparable[i])
296                                return output;
297                            else if (temp != argument[i])
298                                temp = tempComparable;
299                        }
300                    }
301                    else
302                    {
303                        return output;
304                    }
305                }
306                output += temp;
307            }
308            return output;
309        }
310    }
311}
Note: See TracBrowser for help on using the repository browser.