Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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