Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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