Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

even smarter autocompletion

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