Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/bugger/src/core/CommandExecutor.cc @ 2559

Last change on this file since 2559 was 2344, checked in by rgrieder, 16 years ago

Completed destruction of static elements like XMLPort, Identifier, etc.
Of initially about 250 memory leaks (not in the actual meaning but the memory was never freed anyway) only 1 remains in TinyCpp.

  • Core class is now a normal Singleton that gets created and destroyed in main.
  • The same goes for Language, LuaBind, SignalHandler and PlayerManager.
  • Added a new std::set to the CommandExecutor so that the external ConsoleCommands can get destroyed too.
  • Code for destroying CommandLineArguments
  • Added destruction code for ConstructionCallbacks in Identifier
  • Moved internal identifier map (the one with the typeid(.) names) in a static function in Identifier. This was necessary in order to destroy ALL Identifiers with the static destruction function. Before it was possible to create an Identifier with having a class instance (that would call RegisterObject) for instance by simply accessing it via getIdentifier.
  • Removed a big memory leak in Button (forgot to destroy the ConfigValueContainers)
  • Added destruction code for InputBufferListenerTuples in InputBuffer destructor.
  • Added destruction code for load and save executors in both XMLPortParam and XMLPortObject
  • Added destruction code for ConsoleCommands in GSRoot, GSGraphics and GSLevel (temporary solution anyway)
  • Deleting the CEGUILua script module seems to work properly now, one memory leak less (GUIManager.cc)
  • Added global destruction calls in Main.cc
  • Property svn:eol-style set to native
File size: 30.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "CommandExecutor.h"
30#include "ConsoleCommand.h"
31#include "util/String.h"
32#include "util/Debug.h"
33#include "Identifier.h"
34#include "Language.h"
35#include "TclBind.h"
36
37namespace orxonox
38{
39    CommandExecutor& CommandExecutor::getInstance()
40    {
41        static CommandExecutor instance;
42        return instance;
43    }
44
45    CommandEvaluation& CommandExecutor::getEvaluation()
46    {
47        return CommandExecutor::getInstance().evaluation_;
48    }
49
50    const CommandEvaluation& CommandExecutor::getLastEvaluation()
51    {
52        return CommandExecutor::getInstance().evaluation_;
53    }
54
55    ConsoleCommand& CommandExecutor::addConsoleCommandShortcut(ConsoleCommand* command, bool bDeleteAtExit)
56    {
57        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(command->getName());
58        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
59        {
60            COUT(2) << "Warning: Overwriting console-command shortcut with name " << command->getName() << "." << std::endl;
61        }
62
63        // Make sure we can also delete the external ConsoleCommands that don't belong to an Identifier
64        if (command && bDeleteAtExit)
65        {
66            CommandExecutor::getInstance().consoleCommandExternals_.insert(command);
67        }
68
69        CommandExecutor::getInstance().consoleCommandShortcuts_[command->getName()] = command;
70        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(command->getName())] = command;
71        return (*command);
72    }
73
74    /**
75        @brief Returns the executor of a console command shortcut with given name.
76        @brief name The name of the requested console command shortcut
77        @return The executor of the requested console command shortcut
78    */
79    ConsoleCommand* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
80    {
81        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
82        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
83            return (*it).second;
84        else
85            return 0;
86    }
87
88    /**
89        @brief Returns the executor of a console command shortcut with given name in lowercase.
90        @brief name The name of the requested console command shortcut in lowercase
91        @return The executor of the requested console command shortcut
92    */
93    ConsoleCommand* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
94    {
95        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
96        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
97            return (*it).second;
98        else
99            return 0;
100    }
101
102    bool CommandExecutor::execute(const std::string& command, bool useTcl)
103    {
104        if (useTcl)
105            return TclBind::eval(command);
106
107        CommandExecutor::parseIfNeeded(command);
108        return CommandExecutor::getEvaluation().execute();
109    }
110
111    std::string CommandExecutor::complete(const std::string& command)
112    {
113        CommandExecutor::parseIfNeeded(command);
114        return CommandExecutor::getEvaluation().complete();
115    }
116
117    std::string CommandExecutor::hint(const std::string& command)
118    {
119        CommandExecutor::parseIfNeeded(command);
120        return CommandExecutor::getEvaluation().hint();
121    }
122
123    CommandEvaluation CommandExecutor::evaluate(const std::string& command)
124    {
125        CommandExecutor::parse(command);
126        CommandExecutor::getEvaluation().evaluateParams();
127        return CommandExecutor::getEvaluation();
128    }
129
130    void CommandExecutor::parseIfNeeded(const std::string& command)
131    {
132        if (CommandExecutor::getEvaluation().state_ == CS_Uninitialized)
133        {
134            CommandExecutor::parse(command);
135        }
136        else if (CommandExecutor::getEvaluation().originalCommand_ != command)
137        {
138            if (CommandExecutor::getEvaluation().command_ == command)
139            {
140                CommandExecutor::parse(command);
141                CommandExecutor::getEvaluation().bNewCommand_ = false;
142            }
143            else
144            {
145                CommandExecutor::parse(command);
146            }
147        }
148    }
149
150    void CommandExecutor::parse(const std::string& command, bool bInitialize)
151    {
152        if (bInitialize)
153            CommandExecutor::getEvaluation().initialize(command);
154
155        CommandExecutor::getEvaluation().commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
156        CommandExecutor::getEvaluation().command_ = command;
157
158        switch (CommandExecutor::getEvaluation().state_)
159        {
160            case CS_Uninitialized:
161            {
162                // Impossible
163                break;
164            }
165            case CS_Empty:
166            {
167                if (CommandExecutor::argumentsGiven() == 0)
168                {
169                    CommandExecutor::createListOfPossibleFunctions("");
170                    CommandExecutor::createListOfPossibleIdentifiers("");
171                    break;
172                }
173                else
174                {
175                    CommandExecutor::getEvaluation().state_ = CS_ShortcutOrIdentifier;
176                    // Move on to next case
177                }
178            }
179            case CS_ShortcutOrIdentifier:
180            {
181                if (CommandExecutor::argumentsGiven() > 1)
182                {
183                    // There's a finished first argument - check if it's a shortcut or a classname
184                    CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
185                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
186
187                    if (CommandExecutor::getEvaluation().function_)
188                    {
189                        // It's a shortcut
190                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
191                        CommandExecutor::getEvaluation().functionclass_ = 0;
192                        // Move on to next case
193                    }
194                    else if (CommandExecutor::getEvaluation().functionclass_)
195                    {
196                        // It's a functionname
197                        CommandExecutor::getEvaluation().state_ = CS_Function;
198                        CommandExecutor::getEvaluation().function_ = 0;
199                        // Move on to next case
200                    }
201                    else
202                    {
203                        // The first argument is bad
204                        CommandExecutor::getEvaluation().state_ = CS_Error;
205                        AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
206                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + " " + GetLocalisation("commandexecutorunknownfirstargument") + ".";
207                        return;
208                    }
209                }
210                else
211                {
212                    // There's no finished first argument - search possible shortcuts or classnames
213                    CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
214                    CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
215
216                    unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
217                    unsigned int num_identifiers = CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.size();
218
219                    if (num_functions == 1 && num_identifiers == 0)
220                    {
221                        // It's a shortcut
222                        std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
223                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname);
224                        if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(0)))
225                        {
226                            // Unfinished shortcut
227                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
228                        }
229                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
230                        CommandExecutor::getEvaluation().functionclass_ = 0;
231                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
232                        if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
233                        {
234                            CommandExecutor::getEvaluation().command_ += " ";
235                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
236                        }
237                        // Move on to next case
238                    }
239                    else if (num_identifiers == 1 && num_functions == 0)
240                    {
241                        // It's a classname
242                        std::string classname = *(*CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin()).first;
243                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(classname);
244                        if (getLowercase(classname) != getLowercase(CommandExecutor::getArgument(0)))
245                        {
246                            // Unfinished classname
247                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
248                        }
249                        CommandExecutor::getEvaluation().state_ = CS_Function;
250                        CommandExecutor::getEvaluation().function_ = 0;
251                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " ";
252                        // Move on to next case
253                    }
254                    else if (num_identifiers == 0 && num_functions == 0)
255                    {
256                        // No possibilities
257                        CommandExecutor::getEvaluation().state_ = CS_Error;
258                        AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
259                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + " " + CommandExecutor::getArgument(0) + ".";
260                        return;
261                    }
262                    else
263                    {
264                        // There are several possiblilities
265                        std::list<std::pair<const std::string*, const std::string*> > temp;
266                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.end());
267                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.end());
268                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getCommonBegin(temp);
269                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
270                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
271                        CommandExecutor::getEvaluation().bCommandChanged_ = true;
272                        return;
273                    }
274                }
275            }
276            case CS_Function:
277            {
278                if (CommandExecutor::getEvaluation().functionclass_)
279                {
280                    // There is a classname - search for the commandname
281                    if (CommandExecutor::argumentsGiven() > 2)
282                    {
283                        // There is a finished second argument - check if it's a commandname
284                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
285
286                        if (CommandExecutor::getEvaluation().function_)
287                        {
288                            // It's a function
289                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
290                            // Move on to next case
291                        }
292                        else
293                        {
294                            // The second argument is bad
295                            CommandExecutor::getEvaluation().state_ = CS_Error;
296                            AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
297                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
298                            return;
299                        }
300                    }
301                    else
302                    {
303                        // There is no finished second argument - search for possibilities
304                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
305                        unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
306
307                        if (num_functions == 1)
308                        {
309                            // It's a function
310                            std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
311                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname, CommandExecutor::getEvaluation().functionclass_);
312                            if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(1)))
313                            {
314                                // Unfinished function
315                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
316                            }
317                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
318                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getEvaluation().function_->getName();
319                            if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
320                            {
321                                CommandExecutor::getEvaluation().command_ += " ";
322                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
323                            }
324                            // Move on to next case
325                        }
326                        else if (num_functions == 0)
327                        {
328                            // No possibilities
329                            CommandExecutor::getEvaluation().state_ = CS_Error;
330                            AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
331                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + " " + GetLocalisation("commandexecutorunknownsecondargumentstart") + " " + CommandExecutor::getArgument(1) + ".";
332                            return;
333                        }
334                        else
335                        {
336                            // There are several possibilities
337                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleFunctions_);
338                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
339                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
340                            return;
341                        }
342                    }
343                }
344                else
345                {
346                    // There is no classname - move on to CS_ParamPreparation
347                }
348            }
349            case CS_ParamPreparation:
350            {
351                if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
352                {
353                    CommandExecutor::getEvaluation().state_ = CS_Finished;
354                    return;
355                }
356                else
357                {
358                    unsigned int argumentNumber = CommandExecutor::argumentsGiven() - 2;
359                    if (CommandExecutor::getEvaluation().functionclass_)
360                        argumentNumber -= 1;
361
362                    CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
363                    CommandExecutor::getEvaluation().state_ = CS_Params;
364
365                    if (CommandExecutor::getEvaluation().bCommandChanged_)
366                    {
367                        // Don't do more than one change
368                        return;
369                    }
370                }
371            }
372            case CS_Params:
373            {
374                if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
375                {
376                    // There is exactly one possible argument
377                    CommandExecutor::getEvaluation().argument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
378                    CommandExecutor::getEvaluation().possibleArgument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
379                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
380                    return;
381                }
382                else if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 0)
383                {
384                    // The user tries something new - we let him do
385                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
386                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
387                    return;
388                }
389                else
390                {
391                    // There are several possibilities
392                    unsigned int argumentNumber = CommandExecutor::argumentsGiven();
393                    if (argumentNumber > 0)
394                        --argumentNumber;
395                    if (CommandExecutor::getEvaluation().functionclass_ && argumentNumber > 0)
396                        --argumentNumber;
397
398                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
399                    CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
400                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
401                    return;
402                }
403            }
404            case CS_Finished:
405            {
406                // Nothing more to do
407                break;
408            }
409            case CS_Error:
410            {
411                // Bad, very bad
412                break;
413            }
414        }
415    }
416
417    unsigned int CommandExecutor::argumentsFinished()
418    {
419        unsigned int argumentsGiven = CommandExecutor::argumentsGiven();
420        if (argumentsGiven > 0)
421            return argumentsGiven - 1;
422        else
423            return 0;
424    }
425
426    unsigned int CommandExecutor::argumentsGiven()
427    {
428        if (CommandExecutor::getEvaluation().command_.size() > 0 && CommandExecutor::getEvaluation().command_[CommandExecutor::getEvaluation().command_.size() - 1] == ' ')
429            return CommandExecutor::getEvaluation().commandTokens_.size() + 1;
430        else
431            return CommandExecutor::getEvaluation().commandTokens_.size();
432    }
433
434    bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
435    {
436        if (CommandExecutor::getEvaluation().functionclass_)
437            return (CommandExecutor::argumentsGiven() > (2 + command->getParamCount()));
438        else
439            return (CommandExecutor::argumentsGiven() > (1 + command->getParamCount()));
440    }
441
442    std::string CommandExecutor::getArgument(unsigned int index)
443    {
444        if (index < (CommandExecutor::getEvaluation().commandTokens_.size()))
445            return CommandExecutor::getEvaluation().commandTokens_[index];
446        else
447            return "";
448    }
449
450    std::string CommandExecutor::getLastArgument()
451    {
452        return CommandExecutor::getArgument(CommandExecutor::argumentsGiven() - 1);
453    }
454
455    void CommandExecutor::createListOfPossibleIdentifiers(const std::string& fragment)
456    {
457        CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.clear();
458        std::string lowercase = getLowercase(fragment);
459        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
460            if ((*it).second->hasConsoleCommands())
461                if ((*it).first.find(lowercase) == 0 || fragment == "")
462                    CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
463    }
464
465    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
466    {
467        CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
468        std::string lowercase = getLowercase(fragment);
469        if (!identifier)
470        {
471            for (std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
472                if ((*it).first.find(lowercase) == 0 || fragment == "")
473                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
474        }
475        else
476        {
477            for (std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
478                if ((*it).first.find(lowercase) == 0 || fragment == "")
479                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
480        }
481    }
482
483    void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
484    {
485        CommandExecutor::createArgumentCompletionList(command, param);
486
487        CommandExecutor::getEvaluation().listOfPossibleArguments_.clear();
488        std::string lowercase = getLowercase(fragment);
489        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
490        {
491            if ((*it).lowercaseComparison())
492            {
493                if ((*it).getComparable().find(lowercase) == 0 || fragment == "")
494                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
495            }
496            else
497            {
498                if ((*it).getComparable().find(fragment) == 0 || fragment == "")
499                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
500            }
501        }
502    }
503
504    Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
505    {
506        std::string lowercase = getLowercase(name);
507        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(lowercase);
508        if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConsoleCommands())
509            return (*it).second;
510
511        return 0;
512    }
513
514    ConsoleCommand* CommandExecutor::getPossibleCommand(const std::string& name, Identifier* identifier)
515    {
516        std::string lowercase = getLowercase(name);
517        if (!identifier)
518        {
519            std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(lowercase);
520            if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
521                return (*it).second;
522        }
523        else
524        {
525            std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(lowercase);
526            if (it != identifier->getLowercaseConsoleCommandMapEnd())
527                return (*it).second;
528        }
529        return 0;
530    }
531
532    std::string CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
533    {
534        CommandExecutor::createArgumentCompletionList(command, param);
535
536        std::string lowercase = getLowercase(name);
537        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
538        {
539            if ((*it).lowercaseComparison())
540            {
541                if ((*it).getComparable() == lowercase)
542                    return (*it).getString();
543            }
544            else
545            {
546                if ((*it).getComparable() == name)
547                    return (*it).getString();
548            }
549        }
550
551        return "";
552    }
553
554    void CommandExecutor::createArgumentCompletionList(ConsoleCommand* command, unsigned int param)
555    {
556        std::string params[5];
557
558        unsigned int index = 0;
559        unsigned int lowestIndex = 1 + (CommandExecutor::getEvaluation().functionclass_ != 0);
560
561        for (unsigned int i = CommandExecutor::argumentsGiven() - 1; i >= lowestIndex; --i)
562        {
563            params[index] = CommandExecutor::getArgument(i);
564            ++index;
565            if (index >= 5)
566                break;
567        }
568
569        command->createArgumentCompletionList(param, params[0], params[1], params[2], params[3], params[4]);
570    }
571
572    std::string CommandExecutor::getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list)
573    {
574        if (list.size() == 0)
575        {
576            return "";
577        }
578        else if (list.size() == 1)
579        {
580            return ((*(*list.begin()).first) + " ");
581        }
582        else
583        {
584            std::string output = "";
585            for (unsigned int i = 0; true; i++)
586            {
587                char temp = 0;
588                for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
589                {
590                    if ((*(*it).first).size() > i)
591                    {
592                        if (it == list.begin())
593                        {
594                            temp = (*(*it).first)[i];
595                        }
596                        else
597                        {
598                            if (temp != (*(*it).first)[i])
599                                return output;
600                        }
601                    }
602                    else
603                    {
604                        return output;
605                    }
606                }
607                output += temp;
608            }
609            return output;
610        }
611    }
612
613    std::string CommandExecutor::getCommonBegin(const ArgumentCompletionList& list)
614    {
615        if (list.size() == 0)
616        {
617            return "";
618        }
619        else if (list.size() == 1)
620        {
621            return ((*list.begin()).getComparable() + " ");
622        }
623        else
624        {
625            std::string output = "";
626            for (unsigned int i = 0; true; i++)
627            {
628                char temp = 0;
629                for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
630                {
631                    std::string argument = (*it).getComparable();
632                    if (argument.size() > i)
633                    {
634                        if (it == list.begin())
635                        {
636                            temp = argument[i];
637                        }
638                        else
639                        {
640                            if (temp != argument[i])
641                                return output;
642                        }
643                    }
644                    else
645                    {
646                        return output;
647                    }
648                }
649                output += temp;
650            }
651            return output;
652        }
653    }
654
655    void CommandExecutor::destroyExternalCommands()
656    {
657        for (std::set<ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandExternals_.begin();
658            it != CommandExecutor::getInstance().consoleCommandExternals_.end(); ++it)
659            delete *it;
660    }
661}
Note: See TracBrowser for help on using the repository browser.