Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/orxonox/core/CommandExecutor.cc @ 953

Last change on this file since 953 was 953, checked in by landauf, 16 years ago
  • added some functions to CommandEvaluation
  • added possibility of additional parameters to CommandEvaluator and CommandExecutor
File size: 44.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "CommandExecutor.h"
29#include "ConsoleCommand.h"
30#include "util/String.h"
31#include "Identifier.h"
32#include "Language.h"
33#include "Debug.h"
34#include "Executor.h"
35#include "ConfigValueContainer.h"
36
37#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE "set"
38#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY "tset"
39#define COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND "bind"
40
41namespace orxonox
42{
43    ConsoleCommandShortcutGeneric(keyword1, createExecutor((FunctorStatic*)0, "set", AccessLevel::User));
44    ConsoleCommandShortcutGeneric(keyword2, createExecutor((FunctorStatic*)0, "tset", AccessLevel::User));
45    ConsoleCommandShortcutGeneric(keyword3, createExecutor((FunctorStatic*)0, "bind", AccessLevel::User));
46
47
48    ///////////////////////
49    // CommandEvaluation //
50    ///////////////////////
51    KeybindMode CommandEvaluation::getKeybindMode()
52    {
53        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
54        {
55//            if (this->shortcut_ != 0)
56//                return this->shortcut_->getKeybindMode();
57        }
58        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
59        {
60//            if (this->function_ != 0)
61//                return this->function_->getKeybindMode();
62        }
63        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
64        {
65//            return KeybindMode::onPress;
66        }
67        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
68        {
69//            return KeybindMode::onPress;
70        }
71        else
72        {
73//            return KeybindMode::onPress;
74        }
75    }
76
77    void CommandEvaluation::setAdditionalParameter(const std::string& param)
78    {
79        this->additionalParameter_ = param;
80    }
81
82    bool CommandEvaluation::isValid() const
83    {
84        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
85        {
86            return (this->shortcut_ != 0);
87        }
88        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
89        {
90            return ((this->functionclass_ != 0) && (this->function_ != 0));
91        }
92        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
93        {
94            return ((this->configvalueclass_ != 0) && (this->configvalue_ != 0));
95        }
96        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
97        {
98            return (this->key_ != 0);
99        }
100        else
101        {
102            return false;
103        }
104    }
105
106
107    /////////////////////
108    // CommandExecutor //
109    /////////////////////
110    CommandExecutor& CommandExecutor::getInstance()
111    {
112        static CommandExecutor instance;
113        return instance;
114    }
115
116    CommandEvaluation& CommandExecutor::getEvaluation()
117    {
118        return CommandExecutor::getInstance().evaluation_;
119    }
120
121    bool CommandExecutor::addConsoleCommandShortcut(ExecutorStatic* executor)
122    {
123        CommandExecutor::getInstance().consoleCommandShortcuts_[executor->getName()] = executor;
124        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(executor->getName())] = executor;
125        return true;
126    }
127
128    /**
129        @brief Returns the executor of a console command shortcut with given name.
130        @brief name The name of the requested console command shortcut
131        @return The executor of the requested console command shortcut
132    */
133    ExecutorStatic* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
134    {
135        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
136        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
137            return (*it).second;
138        else
139            return 0;
140    }
141
142    /**
143        @brief Returns the executor of a console command shortcut with given name in lowercase.
144        @brief name The name of the requested console command shortcut in lowercase
145        @return The executor of the requested console command shortcut
146    */
147    ExecutorStatic* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
148    {
149        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
150        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
151            return (*it).second;
152        else
153            return 0;
154    }
155
156    bool CommandExecutor::execute(const std::string& command)
157    {
158        if (CommandExecutor::getEvaluation().processedCommand_ != command)
159            CommandExecutor::parse(command);
160
161        return CommandExecutor::execute(CommandExecutor::getEvaluation());
162    }
163
164
165    bool CommandExecutor::execute(const CommandEvaluation& evaluation)
166    {
167        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
168
169        switch (evaluation.state_)
170        {
171            case CS_Empty:
172                break;
173            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
174                break;
175            case CS_Shortcut_Params:
176                // not enough parameters but lets hope there are some additional parameters
177                if (evaluation.shortcut_ != 0)
178                    return evaluation.shortcut_->parse(tokens.subSet(1).join() + " " + evaluation.additionalParameter_);
179                break;
180            case CS_Shortcut_Finished:
181                // call the shortcut
182                if (evaluation.shortcut_ != 0)
183                    return evaluation.shortcut_->parse(tokens.subSet(1).join() + " " + evaluation.additionalParameter_);
184                break;
185            case CS_Function:
186                break;
187            case CS_Function_Params:
188                // not enough parameters but lets hope there are some additional parameters
189                if (evaluation.function_ != 0)
190                    return evaluation.function_->parse(tokens.subSet(2).join() + " " + evaluation.additionalParameter_);
191                break;
192            case CS_Function_Finished:
193                // call the shortcut
194                if (evaluation.function_ != 0)
195                    return evaluation.function_->parse(tokens.subSet(2).join() + " " + evaluation.additionalParameter_);
196                break;
197            case CS_ConfigValueClass:
198                break;
199            case CS_ConfigValue:
200                break;
201            case CS_ConfigValueType:
202                // not enough parameters but lets hope there are some additional parameters
203                if (evaluation.configvalue_ != 0)
204                    return evaluation.configvalue_->parseString(tokens.subSet(3).join() + " " + evaluation.additionalParameter_);
205                break;
206            case CS_ConfigValueFinished:
207                // set the config value
208                if (evaluation.configvalue_ != 0)
209                    return evaluation.configvalue_->parseString(tokens.subSet(3).join() + " " + evaluation.additionalParameter_);
210                break;
211            case CS_KeybindKey:
212                break;
213            case CS_KeybindCommand:
214                // not enough parameters but lets hope there are some additional parameters
215                break;
216            case CS_KeybindFinished:
217                // set the keybind
218                // ...todo
219                break;
220            case CS_Error:
221                break;
222        }
223
224        return false;
225    }
226
227    std::string CommandExecutor::complete(const std::string& command)
228    {
229        if (CommandExecutor::getEvaluation().processedCommand_ != command)
230            CommandExecutor::parse(command);
231
232        return CommandExecutor::complete(CommandExecutor::getEvaluation());
233    }
234
235    std::string CommandExecutor::complete(const CommandEvaluation& evaluation)
236    {
237        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
238
239        std::list<const std::string*> temp;
240        if (evaluation.state_ == CS_Empty)
241        {
242            temp.insert(temp.end(), evaluation.listOfPossibleShortcuts_.begin(), evaluation.listOfPossibleShortcuts_.end());
243            temp.insert(temp.end(), evaluation.listOfPossibleFunctionClasses_.begin(), evaluation.listOfPossibleFunctionClasses_.end());
244        }
245
246        switch (evaluation.state_)
247        {
248            case CS_Empty:
249                return (tokens.subSet(0, tokens.size() - 1).join() + " " + CommandExecutor::getCommonBegin(temp));
250                break;
251            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
252                break;
253            case CS_Shortcut_Params:
254                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
255                    return (evaluation.processedCommand_ + " ");
256                break;
257            case CS_Shortcut_Finished:
258                break;
259            case CS_Function:
260                return (tokens.subSet(0, tokens.size() - 1).join() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleFunctions_));
261                break;
262            case CS_Function_Params:
263                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
264                    return (evaluation.processedCommand_ + " ");
265                break;
266            case CS_Function_Finished:
267                break;
268            case CS_ConfigValueClass:
269                return (tokens.subSet(0, tokens.size() - 1).join() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValueClasses_));
270                break;
271            case CS_ConfigValue:
272                return (tokens.subSet(0, tokens.size() - 1).join() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValues_));
273                break;
274            case CS_ConfigValueType:
275                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
276                    return (evaluation.processedCommand_ + " ");
277                break;
278            case CS_ConfigValueFinished:
279                break;
280            case CS_KeybindKey:
281                return (tokens.subSet(0, tokens.size() - 1).join() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleKeys_));
282                break;
283            case CS_KeybindCommand:
284                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
285                    return (evaluation.processedCommand_ + " ");
286                break;
287            case CS_KeybindFinished:
288                break;
289            case CS_Error:
290                break;
291        }
292
293        return evaluation.processedCommand_;
294    }
295
296    std::string CommandExecutor::hint(const std::string& command)
297    {
298        if (CommandExecutor::getEvaluation().processedCommand_ != command)
299            CommandExecutor::parse(command);
300
301        return CommandExecutor::hint(CommandExecutor::getEvaluation());
302    }
303
304    std::string CommandExecutor::hint(const CommandEvaluation& evaluation)
305    {
306        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
307
308        switch (evaluation.state_)
309        {
310            case CS_Empty:
311                return (CommandExecutor::dump(evaluation.listOfPossibleShortcuts_) + "\n" + CommandExecutor::dump(evaluation.listOfPossibleFunctionClasses_));
312                break;
313            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
314                break;
315            case CS_Shortcut_Params:
316                if (evaluation.shortcut_ != 0)
317                    return CommandExecutor::dump(evaluation.shortcut_);
318                break;
319            case CS_Shortcut_Finished:
320                if (evaluation.shortcut_ != 0)
321                    return CommandExecutor::dump(evaluation.shortcut_);
322                break;
323            case CS_Function:
324                return CommandExecutor::dump(evaluation.listOfPossibleFunctions_);
325                break;
326            case CS_Function_Params:
327                if (evaluation.function_ != 0)
328                    return CommandExecutor::dump(evaluation.function_);
329                break;
330            case CS_Function_Finished:
331                if (evaluation.function_ != 0)
332                    return CommandExecutor::dump(evaluation.function_);
333                break;
334            case CS_ConfigValueClass:
335                return CommandExecutor::dump(evaluation.listOfPossibleConfigValueClasses_);
336                break;
337            case CS_ConfigValue:
338                return CommandExecutor::dump(evaluation.listOfPossibleConfigValues_);
339                break;
340            case CS_ConfigValueType:
341                if (evaluation.configvalue_ != 0)
342                    return CommandExecutor::dump(evaluation.configvalue_);
343                break;
344            case CS_ConfigValueFinished:
345                if (evaluation.configvalue_ != 0)
346                    return CommandExecutor::dump(evaluation.configvalue_);
347                break;
348            case CS_KeybindKey:
349                return CommandExecutor::dump(evaluation.listOfPossibleKeys_);
350                break;
351            case CS_KeybindCommand:
352                if (evaluation.key_ != 0)
353                    return CommandExecutor::dump(evaluation.key_);
354                break;
355            case CS_KeybindFinished:
356                if (evaluation.key_ != 0)
357                    return CommandExecutor::dump(evaluation.key_);
358                break;
359            case CS_Error:
360                return "Error";
361                break;
362        }
363
364        return "";
365    }
366
367    CommandEvaluation CommandExecutor::evaluate(const std::string& command)
368    {
369        CommandExecutor::parse(command, true);
370        return CommandExecutor::getEvaluation();
371    }
372
373    void CommandExecutor::parse(const std::string& command, bool bInitialize)
374    {
375        CommandExecutor::getEvaluation().tokens_.split((command + COMMAND_EXECUTOR_CURSOR), " ", SubString::WhiteSpaces, false, '\\', '"', '(', ')', '\0');
376        CommandExecutor::getEvaluation().processedCommand_ = command;
377
378        if (bInitialize)
379            CommandExecutor::initialize(command);
380
381        switch (CommandExecutor::getEvaluation().state_)
382        {
383            case CS_Empty:
384                if (CommandExecutor::argumentsGiven() == 0)
385                {
386                    // We want a hint for the first token
387                    // Check if there is already a perfect match
388                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
389                    CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
390
391                    if ((CommandExecutor::getEvaluation().functionclass_ != 0) || (CommandExecutor::getEvaluation().shortcut_ != 0))
392                    {
393                        // Yes, there is a class or a shortcut with the searched name
394                        // Add a whitespace and continue parsing
395                        CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
396                        CommandExecutor::parse(command + " ", false);
397                        return;
398                    }
399
400                    // No perfect match: Create the lists of all possible classes and shortcuts and return
401                    CommandExecutor::createListOfPossibleFunctionClasses(CommandExecutor::getToken(0));
402                    CommandExecutor::createListOfPossibleShortcuts(CommandExecutor::getToken(0));
403                    return;
404                }
405                else
406                {
407                    // There is at least one argument: Check if it's a shortcut, a classname or a special keyword
408                    CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
409                    CommandExecutor::parse(command, false);
410                    return;
411                }
412                break;
413            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
414                if (CommandExecutor::argumentsGiven() >= 1)
415                {
416                    if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
417                    {
418                        // We want to set a config value
419                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueClass;
420                        CommandExecutor::parse(command, false);
421                        return;
422                    }
423                    else if (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND)
424                    {
425                        // We want to set a keybinding
426                        CommandExecutor::getEvaluation().state_ = CS_KeybindKey;
427                        CommandExecutor::parse(command, false);
428                        return;
429                    }
430
431                    if (CommandExecutor::getEvaluation().functionclass_ == 0)
432                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
433                    if (CommandExecutor::getEvaluation().shortcut_ == 0)
434                        CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
435
436                    if ((CommandExecutor::getEvaluation().functionclass_ == 0) && (CommandExecutor::getEvaluation().shortcut_ == 0))
437                    {
438                        // Argument 1 seems to be wrong
439                        AddLanguageEntry("CommandExecutor::NoSuchCommandOrClassName", "No such command or classname");
440                        CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(0) + ": " + GetLocalisation("CommandExecutor::NoSuchCommandOrClassName"));
441                        CommandExecutor::getEvaluation().state_ = CS_Error;
442                        return;
443                    }
444                    else if (CommandExecutor::getEvaluation().shortcut_ != 0)
445                    {
446                        // Argument 1 is a shortcut: Return the needed parameter types
447                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Params;
448                        CommandExecutor::parse(command, false);
449                        return;
450                    }
451                    else
452                    {
453                        // Argument 1 is a classname: Return the possible functions
454                        CommandExecutor::getEvaluation().state_ = CS_Function;
455                        CommandExecutor::parse(command, false);
456                        return;
457                    }
458                }
459                else
460                {
461                    CommandExecutor::getEvaluation().state_ = CS_Error;
462                    return;
463                }
464                break;
465            case CS_Shortcut_Params:
466                if (CommandExecutor::getEvaluation().shortcut_ != 0)
467                {
468                    // Valid command
469                    // Check if there are enough parameters
470                    if (CommandExecutor::enoughParametersGiven(1, CommandExecutor::getEvaluation().shortcut_))
471                    {
472                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Finished;
473                        return;
474                    }
475                }
476                else
477                {
478                    // Something is wrong
479                    CommandExecutor::getEvaluation().state_ = CS_Error;
480                    return;
481                }
482                break;
483            case CS_Function:
484                if (CommandExecutor::getEvaluation().functionclass_ != 0)
485                {
486                    // We have a valid classname
487                    // Check if there is a second argument
488                    if (CommandExecutor::argumentsGiven() >= 2)
489                    {
490                        // There is a second argument: Check if it's a valid functionname
491                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
492                        if (CommandExecutor::getEvaluation().function_ == 0)
493                        {
494                            // Argument 2 seems to be wrong
495                            AddLanguageEntry("CommandExecutor::NoSuchFunctionnameIn", "No such functionname in");
496                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchFunctionnameIn") + " " + CommandExecutor::getEvaluation().functionclass_->getName());
497                            CommandExecutor::getEvaluation().state_ = CS_Error;
498                            return;
499                        }
500                        else
501                        {
502                            // Argument 2 seems to be a valid functionname: Get the parameters
503                            CommandExecutor::getEvaluation().state_ = CS_Function_Params;
504                            CommandExecutor::parse(command, false);
505                            return;
506                        }
507                    }
508                    else
509                    {
510                        // There is no finished second argument
511                        // Check if there's already a perfect match
512                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
513                        {
514                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
515                            if (CommandExecutor::getEvaluation().function_ != 0)
516                            {
517                                // There is a perfect match: Add a whitespace and continue parsing
518                                CommandExecutor::getEvaluation().state_ = CS_Function_Params;
519                                CommandExecutor::parse(command + " ", false);
520                                return;
521                            }
522                        }
523
524                        // No perfect match: Create the list of all possible functions and return
525                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
526                        return;
527                    }
528                }
529                else
530                {
531                    CommandExecutor::getEvaluation().state_ = CS_Error;
532                    return;
533                }
534                break;
535            case CS_Function_Params:
536                if ((CommandExecutor::getEvaluation().functionclass_ != 0) && (CommandExecutor::getEvaluation().function_ != 0))
537                {
538                    // Valid command
539                    // Check if there are enough parameters
540                    if (CommandExecutor::enoughParametersGiven(2, CommandExecutor::getEvaluation().function_))
541                    {
542                        CommandExecutor::getEvaluation().state_ = CS_Function_Finished;
543                        return;
544                    }
545                }
546                else
547                {
548                    // Something is wrong
549                    CommandExecutor::getEvaluation().state_ = CS_Error;
550                    return;
551                }
552                break;
553            case CS_ConfigValueClass:
554                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)))
555                {
556                    // We want to set a config value
557                    // Check if there is a second argument
558                    if (CommandExecutor::argumentsGiven() >= 2)
559                    {
560                        // There is a second argument: Check if it's a valid classname
561                        CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
562                        if (CommandExecutor::getEvaluation().configvalueclass_ == 0)
563                        {
564                            // Argument 2 seems to be wrong
565                            AddLanguageEntry("CommandExecutor::NoSuchClassWithConfigValues", "No such class with config values");
566                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchClassWithConfigValues"));
567                            CommandExecutor::getEvaluation().state_ = CS_Error;
568                            return;
569                        }
570                        else
571                        {
572                            // Argument 2 seems to be a valid classname: Search for possible config values
573                            CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
574                            CommandExecutor::parse(command, false);
575                            return;
576                        }
577                    }
578                    else
579                    {
580                        // There's no finished second argument
581                        // Check if there's already a perfect match
582                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
583                        {
584                            CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
585                            if (CommandExecutor::getEvaluation().configvalueclass_ != 0)
586                            {
587                                // There is a perfect match: Add a whitespace and continue parsing
588                                CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
589                                CommandExecutor::parse(command + " ", false);
590                                return;
591                            }
592                        }
593
594                        // No perfect match: Create the list of all possible classnames and return
595                        CommandExecutor::createListOfPossibleConfigValueClasses(CommandExecutor::getToken(1));
596                        return;
597                    }
598                }
599                else
600                {
601                    // Something is wrong
602                    CommandExecutor::getEvaluation().state_ = CS_Error;
603                    return;
604                }
605                break;
606            case CS_ConfigValue:
607                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && (CommandExecutor::getEvaluation().configvalueclass_ != 0))
608                {
609                    // Check if there is a third argument
610                    if (CommandExecutor::argumentsGiven() >= 3)
611                    {
612                        // There is a third argument: Check if it's a valid config value
613                        CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
614                        if (CommandExecutor::getEvaluation().configvalue_ == 0)
615                        {
616                            // Argument 3 seems to be wrong
617                            AddLanguageEntry("CommandExecutor::NoSuchConfigValueIn", "No such config value in");
618                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(2) + ": " + GetLocalisation("CommandExecutor::NoSuchConfigValueIn") + " " + CommandExecutor::getEvaluation().configvalueclass_->getName());
619                            CommandExecutor::getEvaluation().state_ = CS_Error;
620                            return;
621                        }
622                        else
623                        {
624                            // Argument 3 seems to be a valid config value: Get the type
625                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
626                            CommandExecutor::parse(command, false);
627                            return;
628                        }
629                    }
630                    else
631                    {
632                        // There is no finished third argument
633                        // Check if there's already a perfect match
634                        if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
635                        {
636                            CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
637                            if (CommandExecutor::getEvaluation().configvalueclass_ != 0)
638                            {
639                                // There is a perfect match: Add a whitespace and continue parsing
640                                CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
641                                CommandExecutor::parse(command + " ", false);
642                                return;
643                            }
644                        }
645
646                        // No perfect match: Create the list of all possible config values
647                        CommandExecutor::createListOfPossibleConfigValues(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
648                        return;
649                    }
650                }
651                else
652                {
653                    // Something is wrong
654                    CommandExecutor::getEvaluation().state_ = CS_Error;
655                    return;
656                }
657                break;
658            case CS_ConfigValueType:
659                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && (CommandExecutor::getEvaluation().configvalueclass_ != 0) && (CommandExecutor::getEvaluation().configvalue_ != 0))
660                {
661                    // Valid command
662                    // Check if there are enough parameters
663                    if (CommandExecutor::getEvaluation().tokens_.size() >= 4)
664                    {
665                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueFinished;
666                        return;
667                    }
668                }
669                else
670                {
671                    // Something is wrong
672                    CommandExecutor::getEvaluation().state_ = CS_Error;
673                    return;
674                }
675                break;
676            case CS_KeybindKey:
677                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND))
678                {
679                    // todo
680                }
681                else
682                {
683                    // Something is wrong
684                    CommandExecutor::getEvaluation().state_ = CS_Error;
685                    return;
686                }
687                break;
688            case CS_KeybindCommand:
689                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND) && (false)) // todo
690                {
691                    // Valid command
692                    // Check if there are enough parameters
693                    if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
694                    {
695                        CommandExecutor::getEvaluation().state_ = CS_KeybindFinished;
696                        return;
697                    }
698
699                }
700                else
701                {
702                    // Something is wrong
703                    CommandExecutor::getEvaluation().state_ = CS_Error;
704                    return;
705                }
706                break;
707            case CS_Shortcut_Finished:
708                // Nothing to do
709                break;
710            case CS_Function_Finished:
711                // Nothing to do
712                break;
713            case CS_ConfigValueFinished:
714                // Nothing to do
715                break;
716            case CS_KeybindFinished:
717                // Nothing to do
718                break;
719            case CS_Error:
720                // This is bad
721                break;
722        }
723    }
724
725    void CommandExecutor::initialize(const std::string& command)
726    {
727        CommandExecutor::getEvaluation().processedCommand_ = command;
728        CommandExecutor::getEvaluation().additionalParameter_ = "";
729
730        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.clear();
731        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.clear();
732        CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
733        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.clear();
734        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.clear();
735        CommandExecutor::getEvaluation().listOfPossibleKeys_.clear();
736
737        CommandExecutor::getEvaluation().functionclass_ = 0;
738        CommandExecutor::getEvaluation().configvalueclass_ = 0;
739        CommandExecutor::getEvaluation().shortcut_ = 0;
740        CommandExecutor::getEvaluation().function_ = 0;
741        CommandExecutor::getEvaluation().configvalue_ = 0;
742        CommandExecutor::getEvaluation().key_ = 0;
743
744        CommandExecutor::getEvaluation().errorMessage_ = "";
745        CommandExecutor::getEvaluation().state_ = CS_Empty;
746    }
747
748    bool CommandExecutor::argumentsGiven(unsigned int num)
749    {
750        // Because we added a cursor we have +1 arguments
751        // There are num arguments given if there are at least num arguments + one cursor
752        return (CommandExecutor::getEvaluation().tokens_.size() >= (num + 1));
753    }
754
755    unsigned int CommandExecutor::argumentsGiven()
756    {
757        // Because we added a cursor we have +1 arguments
758        if (CommandExecutor::getEvaluation().tokens_.size() >= 1)
759            return (CommandExecutor::getEvaluation().tokens_.size() - 1);
760        else
761            return 0;
762    }
763
764    std::string CommandExecutor::getToken(unsigned int index)
765    {
766        if ((index >= 0) && (index < (CommandExecutor::getEvaluation().tokens_.size() - 1)))
767            return CommandExecutor::getEvaluation().tokens_[index];
768        else if (index == (CommandExecutor::getEvaluation().tokens_.size() - 1))
769            return CommandExecutor::getEvaluation().tokens_[index].substr(0, CommandExecutor::getEvaluation().tokens_[index].size() - 1);
770        else
771            return "";
772    }
773
774    bool CommandExecutor::enoughParametersGiven(unsigned int head, Executor* executor)
775    {
776        unsigned int neededParams = head + executor->getParamCount();
777        for (unsigned int i = executor->getParamCount() - 1; i >= 0; i--)
778        {
779            if (executor->defaultValueSet(i))
780                neededParams--;
781            else
782                break;
783        }
784        return (CommandExecutor::getEvaluation().tokens_.size() >= neededParams);
785    }
786
787    void CommandExecutor::createListOfPossibleFunctionClasses(const std::string& fragment)
788    {
789        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
790        {
791            if ((*it).second->hasConsoleCommands())
792            {
793                if ((*it).first.find(getLowercase(fragment)) == 0)
794                {
795                    CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.push_back(&(*it).first);
796                }
797            }
798        }
799
800        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.sort(CommandExecutor::compareStringsInList);
801    }
802
803    void CommandExecutor::createListOfPossibleShortcuts(const std::string& fragment)
804    {
805        for (std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
806        {
807            if ((*it).first.find(getLowercase(fragment)) == 0)
808            {
809                CommandExecutor::getEvaluation().listOfPossibleShortcuts_.push_back(&(*it).first);
810            }
811        }
812
813        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.sort(CommandExecutor::compareStringsInList);
814    }
815
816    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
817    {
818        for (std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
819        {
820            if ((*it).first.find(getLowercase(fragment)) == 0)
821            {
822                CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(&(*it).first);
823            }
824        }
825
826        CommandExecutor::getEvaluation().listOfPossibleFunctions_.sort(CommandExecutor::compareStringsInList);
827    }
828
829    void CommandExecutor::createListOfPossibleConfigValueClasses(const std::string& fragment)
830    {
831        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
832        {
833            if ((*it).second->hasConfigValues())
834            {
835                if ((*it).first.find(getLowercase(fragment)) == 0)
836                {
837                    CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.push_back(&(*it).first);
838                }
839            }
840        }
841
842        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.sort(CommandExecutor::compareStringsInList);
843    }
844
845    void CommandExecutor::createListOfPossibleConfigValues(const std::string& fragment, Identifier* identifier)
846    {
847        for (std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMapBegin(); it != identifier->getLowercaseConfigValueMapEnd(); ++it)
848        {
849            if ((*it).first.find(getLowercase(fragment)) == 0)
850            {
851                CommandExecutor::getEvaluation().listOfPossibleConfigValues_.push_back(&(*it).first);
852            }
853        }
854
855        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.sort(CommandExecutor::compareStringsInList);
856    }
857
858    void CommandExecutor::createListOfPossibleKeys(const std::string& fragment)
859    {
860        // todo
861
862        CommandExecutor::getEvaluation().listOfPossibleKeys_.sort(CommandExecutor::compareStringsInList);
863    }
864
865    bool CommandExecutor::compareStringsInList(const std::string* first, const std::string* second)
866    {
867        return ((*first) < (*second));
868    }
869
870    Identifier* CommandExecutor::getIdentifierOfPossibleFunctionClass(const std::string& name)
871    {
872        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
873        if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConsoleCommands())
874            return (*it).second;
875
876        return 0;
877    }
878
879    ExecutorStatic* CommandExecutor::getExecutorOfPossibleShortcut(const std::string& name)
880    {
881        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(getLowercase(name));
882        if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
883            return (*it).second;
884
885        return 0;
886    }
887
888    ExecutorStatic* CommandExecutor::getExecutorOfPossibleFunction(const std::string& name, Identifier* identifier)
889    {
890        std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(getLowercase(name));
891        if (it != identifier->getLowercaseConsoleCommandMapEnd())
892            return (*it).second;
893
894        return 0;
895    }
896
897    Identifier* CommandExecutor::getIdentifierOfPossibleConfigValueClass(const std::string& name)
898    {
899        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
900        if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConfigValues())
901            return (*it).second;
902
903        return 0;
904    }
905
906    ConfigValueContainer* CommandExecutor::getContainerOfPossibleConfigValue(const std::string& name, Identifier* identifier)
907    {
908        std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMap().find(getLowercase(name));
909        if (it != identifier->getLowercaseConfigValueMapEnd())
910            return (*it).second;
911
912        return 0;
913    }
914
915    ConfigValueContainer* CommandExecutor::getContainerOfPossibleKey(const std::string& name)
916    {
917        // todo
918
919        return 0;
920    }
921
922    std::string CommandExecutor::dump(const std::list<const std::string*>& list)
923    {
924        std::string output = "";
925        for (std::list<const std::string*>::const_iterator it = list.begin(); it != list.end(); ++it)
926        {
927            if (it != list.begin())
928                output += " ";
929
930            output += (**it);
931        }
932        return output;
933    }
934
935    std::string CommandExecutor::dump(const ExecutorStatic* executor)
936    {
937        std::string output = "";
938        for (unsigned int i = 0; i < executor->getParamCount(); i++)
939        {
940            if (i != 0)
941                output += " ";
942
943            if (executor->defaultValueSet(i))
944                output += "[";
945            else
946                output += "{";
947
948            output += executor->getTypenameParam(i);
949
950            if (executor->defaultValueSet(i))
951                output += "]";
952            else
953                output += "}";
954        }
955        return output;
956    }
957
958    std::string CommandExecutor::dump(const ConfigValueContainer* container)
959    {
960        return container->getTypename();
961    }
962
963    std::string CommandExecutor::getCommonBegin(const std::list<const std::string*>& list)
964    {
965        if (list.size() == 0)
966        {
967            return "";
968        }
969        else if (list.size() == 1)
970        {
971            return ((**list.begin()) + " ");
972        }
973        else
974        {
975            std::string output = "";
976            for (unsigned int i = 0; true; i++)
977            {
978                char temp = 0;
979                for (std::list<const std::string*>::const_iterator it = list.begin(); it != list.end(); ++it)
980                {
981                    if ((**it).size() > i)
982                    {
983                        if (it == list.begin())
984                        {
985                            temp = (**it)[i];
986                        }
987                        else
988                        {
989                            if (temp != (**it)[i])
990                                return output;
991                        }
992                    }
993                    else
994                    {
995                        return output;
996                    }
997                }
998                output += temp;
999            }
1000            return output;
1001        }
1002    }
1003}
Note: See TracBrowser for help on using the repository browser.