Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 952 was 952, checked in by landauf, 16 years ago

added CommandEvaluation to store the results of a command evaluation in CommandExecutor

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