Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

replaced the temporary names of all ConsoleCommand related classes and functions by their real names

  • Property svn:eol-style set to native
File size: 13.9 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        this->bEvaluatedParams_ = false;
52        this->bTriedToEvaluatedParams_ = false;
53        this->numberOfEvaluatedParams_ = 0;
54
55        this->tokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '(', ')', true, '\0');
56    }
57
58    unsigned int CommandEvaluation::getNumberOfArguments() const
59    {
60        unsigned int count = this->tokens_.size();
61        if (count > 0 && this->string_[this->string_.size() - 1] != ' ')
62            return count;
63        else
64            return count + 1;
65    }
66
67    const std::string& CommandEvaluation::getLastArgument() const
68    {
69        if (this->tokens_.size() > 0 && this->string_[this->string_.size() - 1] != ' ')
70            return this->tokens_.back();
71        else
72            return BLANKSTRING;
73    }
74
75    const std::string& CommandEvaluation::getToken(unsigned int i) const
76    {
77        if (i < this->tokens_.size())
78            return this->tokens_[i];
79        else
80            return BLANKSTRING;
81    }
82
83    int CommandEvaluation::execute()
84    {
85        int error;
86        this->query(&error);
87        return error;
88    }
89
90    MultiType CommandEvaluation::query(int* error)
91    {
92        if (error)
93        {
94            *error = CommandExecutor::Success;
95
96            if (!this->execCommand_)
97                *error = CommandExecutor::Error;
98            else if (!this->execCommand_->isActive())
99                *error = CommandExecutor::Deactivated;
100            else if (!this->execCommand_->hasAccess())
101                *error = CommandExecutor::Denied;
102
103            if (*error != CommandExecutor::Success)
104                return MT_Type::Null;
105        }
106
107        if (this->execCommand_ && this->execCommand_->isActive() && this->execCommand_->hasAccess())
108        {
109            if (!this->bTriedToEvaluatedParams_)
110                this->evaluateParams(false);
111
112            if (this->bEvaluatedParams_)
113            {
114                COUT(6) << "CE_execute (evaluation): " << this->execCommand_->getName() << " with " << this->numberOfEvaluatedParams_ << " params: " << this->param_[0] << ' ' << this->param_[1] << ' ' << this->param_[2] << ' ' << this->param_[3] << ' ' << this->param_[4] << std::endl;
115                switch (this->numberOfEvaluatedParams_)
116                {
117                    case 0:  return (*this->execCommand_->getExecutor())();
118                    case 1:  return (*this->execCommand_->getExecutor())(this->param_[0]);
119                    case 2:  return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1]);
120                    case 3:  return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2]);
121                    case 4:  return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2], this->param_[3]);
122                    case 5:
123                    default: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
124                }
125            }
126            else
127            {
128                COUT(5) << "CE_execute: " << this->string_ << "\n";
129                return this->execCommand_->getExecutor()->parse(this->tokens_.subSet(this->execArgumentsOffset_), error, " ");
130            }
131        }
132        else
133            return MT_Type::Null;
134    }
135
136    int CommandEvaluation::evaluateParams(bool bPrintError)
137    {
138        this->bTriedToEvaluatedParams_ = true;
139
140        if (!this->execCommand_)
141        {
142            if (bPrintError)
143                COUT(1) << "Error: Can't evaluate params, no console command assigned." << std::endl;
144            return CommandExecutor::Error;
145        }
146
147        int error;
148        this->numberOfEvaluatedParams_ = this->execCommand_->getExecutor()->evaluateParams(this->tokens_.subSet(this->execArgumentsOffset_), this->param_, &error, " ");
149        if (!error)
150            this->bEvaluatedParams_ = true;
151        else if (bPrintError)
152            COUT(1) << "Error: Can't evaluate params, not enough arguments given." << std::endl;
153
154        return error;
155    }
156
157    void CommandEvaluation::setEvaluatedParameter(unsigned int index, const MultiType& param)
158    {
159        if (index < MAX_FUNCTOR_ARGUMENTS)
160            this->param_[index] = param;
161    }
162
163    MultiType CommandEvaluation::getEvaluatedParameter(unsigned int index) const
164    {
165        if (index < MAX_FUNCTOR_ARGUMENTS)
166            return this->param_[index];
167
168        return MT_Type::Null;
169    }
170
171    std::string CommandEvaluation::complete()
172    {
173        if (!this->hintCommand_ || !this->hintCommand_->isActive())
174            return this->string_;
175
176        if (!this->bPossibleArgumentsRetrieved_)
177            this->retrievePossibleArguments();
178
179        if (CommandEvaluation::getSize(this->possibleArguments_) == 0)
180        {
181            return this->string_;
182        }
183        else
184        {
185            std::string output = this->string_.substr(0, this->string_.find_last_of(' ') + 1);
186            output += CommandEvaluation::getCommonBegin(this->possibleArguments_);
187            return output;
188        }
189    }
190
191    std::string CommandEvaluation::hint()
192    {
193        if (!this->hintCommand_ || !this->hintCommand_->isActive())
194            return "";
195
196        if (!this->bPossibleArgumentsRetrieved_)
197            this->retrievePossibleArguments();
198
199        if (CommandEvaluation::getSize(this->possibleArguments_) > 0 || (!this->possibleArguments_.empty() && this->isValid()))
200            return CommandEvaluation::dump(this->possibleArguments_);
201
202        if (this->isValid())
203        {
204            return CommandEvaluation::dump(this->hintCommand_);
205        }
206        else
207        {
208            if (this->getNumberOfArguments() > 2)
209            {
210                return std::string("Error: There is no command with name \"") + this->getToken(0) + " " + this->getToken(1) + "\".";
211            }
212            else
213            {
214                std::string groupLC = getLowercase(this->getToken(0));
215                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
216                for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
217                    if (getLowercase(it_group->first) == groupLC)
218                        return std::string("Error: There is no command in group \"") + this->getToken(0) + "\" starting with \"" + this->getToken(1) + "\".";
219
220                return std::string("Error: There is no command starting with \"") + this->getToken(0) + "\".";
221            }
222        }
223    }
224
225    void CommandEvaluation::retrievePossibleArguments()
226    {
227        this->bPossibleArgumentsRetrieved_ = true;
228        unsigned int argumentID = std::min(this->getNumberOfArguments() - this->hintArgumentsOffset_, this->hintCommand_->getExecutor()->getParamCount());
229        ArgumentCompleter* ac = this->hintCommand_->getArgumentCompleter(argumentID - 1);
230
231        if (ac)
232        {
233            MultiType param[MAX_FUNCTOR_ARGUMENTS];
234
235            size_t max = this->hintArgumentsOffset_ + this->hintCommand_->getExecutor()->getParamCount();
236
237            for (size_t i = 0; i < argumentID; ++i)
238                param[i] = this->getToken(std::min(this->getNumberOfArguments(), max) - i - 1);
239
240            if (this->getNumberOfArguments() > max)
241            {
242                if (ac->useMultipleWords())
243                {
244                    std::string surplusArguments = this->tokens_.subSet(max - 1).join();
245                    if (this->string_[this->string_.size() - 1] == ' ')
246                        surplusArguments += ' ';
247
248                    this->possibleArguments_ = (*ac)(surplusArguments, param[1], param[2], param[3], param[4]);
249                    CommandEvaluation::strip(this->possibleArguments_, this->getToken(this->getNumberOfArguments() - 1));
250                }
251            }
252            else
253            {
254                this->possibleArguments_ = (*ac)(param[0], param[1], param[2], param[3], param[4]);
255                CommandEvaluation::strip(this->possibleArguments_, param[0]);
256            }
257        }
258    }
259
260    /* static */ size_t CommandEvaluation::getSize(const ArgumentCompletionList& list)
261    {
262        size_t count = 0;
263        for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
264            if (it->getComparable() != "")
265                ++count;
266        return count;
267    }
268
269    /* static */ void CommandEvaluation::strip(ArgumentCompletionList& list, const std::string& fragment)
270    {
271        std::string fragmentLC = getLowercase(fragment);
272
273        for (ArgumentCompletionList::iterator it = list.begin(); it != list.end(); )
274        {
275            const std::string& entry = it->getComparable();
276
277            if (entry == "")
278            {
279                ++it;
280                continue;
281            }
282
283            if (entry.size() < fragmentLC.size())
284            {
285                list.erase(it++);
286            }
287            else
288            {
289                bool bErase = false;
290                for (size_t i = 0; i < fragmentLC.size(); ++i)
291                {
292                    if (fragmentLC[i] != entry[i])
293                    {
294                        bErase = true;
295                        break;
296                    }
297                }
298
299                if (bErase)
300                    list.erase(it++);
301                else
302                    ++it;
303            }
304        }
305    }
306
307    /* static */ std::string CommandEvaluation::getCommonBegin(const ArgumentCompletionList& list)
308    {
309        if (CommandEvaluation::getSize(list) == 0)
310        {
311            return "";
312        }
313        else if (CommandEvaluation::getSize(list) == 1)
314        {
315            for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
316            {
317                if (it->getComparable() != "")
318                {
319                    if (it->hasDisplay())
320                        return (it->getString());
321                    else
322                        return (it->getString() + ' ');
323                }
324            }
325
326            return "";
327        }
328        else
329        {
330            std::string output;
331            for (unsigned int i = 0; true; i++)
332            {
333                char tempComparable = 0;
334                char temp = 0;
335                for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
336                {
337                    const std::string& argumentComparable = it->getComparable();
338                    const std::string& argument = it->getString();
339
340                    if (argumentComparable == "")
341                        continue;
342
343                    if (argument.size() > i)
344                    {
345                        if (tempComparable == 0)
346                        {
347                            tempComparable = argumentComparable[i];
348                            temp = argument[i];
349                        }
350                        else
351                        {
352                            if (tempComparable != argumentComparable[i])
353                                return output;
354                            else if (temp != argument[i])
355                                temp = tempComparable;
356                        }
357                    }
358                    else
359                    {
360                        return output;
361                    }
362                }
363                output += temp;
364            }
365            return output;
366        }
367    }
368
369    /* static */ std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
370    {
371        std::string output;
372        for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
373        {
374            output += it->getDisplay();
375
376            if (it->getComparable() != "")
377                output += ' ';
378        }
379        return output;
380    }
381
382    /* static */ std::string CommandEvaluation::dump(const ConsoleCommand* command)
383    {
384        std::string output = command->getName();
385        if (command->getExecutor()->getParamCount() > 0)
386            output += ": ";
387
388        for (unsigned int i = 0; i < command->getExecutor()->getParamCount(); i++)
389        {
390            if (i != 0)
391                output += ' ';
392
393            if (command->getExecutor()->defaultValueSet(i))
394                output += '[';
395            else
396                output += '{';
397
398            output += command->getExecutor()->getTypenameParam(i);
399
400            if (command->getExecutor()->defaultValueSet(i))
401                output += '=' + command->getExecutor()->getDefaultValue(i).getString() + ']';
402            else
403                output += '}';
404        }
405        return output;
406    }
407}
Note: See TracBrowser for help on using the repository browser.