Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/command/ArgumentCompletionFunctions.cc @ 7401

Last change on this file since 7401 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

  • Property svn:eol-style set to native
File size: 14.8 KB
RevLine 
[1505]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
[7401]29/**
30    @file
31    @brief Implementation of all argument completion functions
32*/
33
[2710]34#include "ArgumentCompletionFunctions.h"
35
[1505]36#include <map>
[2728]37#include <boost/version.hpp>
[2087]38#include <boost/filesystem.hpp>
[1505]39
[3196]40#include "util/Convert.h"
[3280]41#include "util/StringUtils.h"
[7203]42#include "core/Identifier.h"
43#include "core/ConfigFileManager.h"
44#include "core/ConfigValueContainer.h"
[7233]45#include "CommandExecutor.h"
46#include "ConsoleCommand.h"
[1505]47#include "TclThreadManager.h"
48
[2728]49// Boost 1.36 has some issues with deprecated functions that have been omitted
50#if (BOOST_VERSION == 103600)
51#  define BOOST_LEAF_FUNCTION filename
52#else
53#  define BOOST_LEAF_FUNCTION leaf
54#endif
55
[1505]56namespace orxonox
57{
58    namespace autocompletion
59    {
[7401]60        /**
61            @brief Fallback implementation, returns an empty list.
62        */
[1505]63        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
64        {
65            return ArgumentCompletionList();
66        }
67
[7233]68        namespace detail
[7232]69        {
[7401]70            /**
71                @brief Returns true if a group of console commands is visible (i.e. if at least one command in this group is visible).
72            */
[7236]73            bool groupIsVisible(const std::map<std::string, ConsoleCommand*>& group, bool bOnlyShowHidden)
[7233]74            {
[7236]75                for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = group.begin(); it_command != group.end(); ++it_command)
[7233]76                    if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden)
77                        return true;
[7232]78
[7233]79                return false;
80            }
[7232]81
[7401]82            /**
83                @brief Returns a list of all console command groups AND all console command shortcuts.
84                @param fragment The last argument
85                @param bOnlyShowHidden If true, only hidden groups and commands are returned
86            */
[7235]87            ArgumentCompletionList _groupsandcommands(const std::string& fragment, bool bOnlyShowHidden)
[7233]88            {
[7401]89                // note: this function returns only arguments that begin with "fragment", which would't be necessary for the
90                //       auto-completion, but it's necessary to place the line-break "\n" between groups and commands
91                //       only if both groups AND commands are in the list.
92
[7233]93                ArgumentCompletionList groupList;
[7235]94                std::string fragmentLC = getLowercase(fragment);
[7228]95
[7401]96                // get all the groups that are visible (except the shortcut group "")
[7236]97                const std::map<std::string, std::map<std::string, ConsoleCommand*> >& commands = ConsoleCommand::getCommands();
98                for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.begin(); it_group != commands.end(); ++it_group)
[7235]99                    if (groupIsVisible(it_group->second, bOnlyShowHidden) && it_group->first != "" && (fragmentLC == "" || getLowercase(it_group->first).find_first_of(fragmentLC) == 0))
[7233]100                        groupList.push_back(ArgumentCompletionListElement(it_group->first, getLowercase(it_group->first)));
[7228]101
[7401]102                // now add all shortcuts (in group "")
[7236]103                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.find("");
[7233]104                if (it_group != commands.end())
105                {
[7401]106                    // add a line-break if the list isn't empty
[7235]107                    if (!groupList.empty())
108                        groupList.push_back(ArgumentCompletionListElement("", "", "\n"));
[7233]109
[7401]110                    // add the shortcuts
[7236]111                    for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
[7235]112                        if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden && (fragmentLC == "" || getLowercase(it_command->first).find_first_of(fragmentLC) == 0))
[7233]113                            groupList.push_back(ArgumentCompletionListElement(it_command->first, getLowercase(it_command->first)));
114                }
115
[7401]116                // if no shortcut was added, remove the line-break again
[7235]117                if (!groupList.empty() && groupList.back().getDisplay() == "\n")
118                    groupList.pop_back();
119
[7233]120                return groupList;
121            }
122
[7401]123            /**
124                @brief Returns a list of all console commands in a given group.
125                @param fragment The last argument
126                @param group The group's name
127                @param bOnlyShowHidden If true, only hidden console commands are returned
128            */
[7233]129            ArgumentCompletionList _subcommands(const std::string& fragment, const std::string& group, bool bOnlyShowHidden)
[7228]130            {
[7233]131                ArgumentCompletionList commandList;
[7228]132
[7233]133                std::string groupLC = getLowercase(group);
134
[7401]135                // find the iterator of the given group
[7236]136                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
137                for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
[7233]138                    if (getLowercase(it_group->first) == groupLC)
139                        break;
140
[7401]141                // add all commands in the group to the list
[7236]142                if (it_group != ConsoleCommand::getCommands().end())
[7233]143                {
[7236]144                    for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
[7233]145                        if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden)
146                            commandList.push_back(ArgumentCompletionListElement(it_command->first, getLowercase(it_command->first)));
147                }
148
149                return commandList;
[7228]150            }
[7233]151        }
[7228]152
[7401]153        /**
154            @brief Returns a list of all console command groups AND all console command shortcuts.
155        */
[7235]156        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(groupsandcommands)(const std::string& fragment)
[7233]157        {
[7235]158            return detail::_groupsandcommands(fragment, false);
[7228]159        }
160
[7401]161        /**
162            @brief Returns a list of all console commands in a given group.
163        */
[7228]164        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(subcommands)(const std::string& fragment, const std::string& group)
165        {
[7233]166            return detail::_subcommands(fragment, group, false);
167        }
[7228]168
[7401]169        /**
170            @brief Returns a list of commands and groups and also supports auto-completion of the arguments of these commands.
171
172            This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
173        */
[7233]174        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(command)(const std::string& fragment)
175        {
176            CommandEvaluation evaluation = CommandExecutor::evaluate(fragment);
177            const std::string& hint = evaluation.hint();
178
[7235]179            if (evaluation.getPossibleArguments().size() > 0 && evaluation.getPossibleArgumentsSize() > 0)
[7228]180            {
[7233]181                return evaluation.getPossibleArguments();
[7228]182            }
[7233]183            else
184            {
185                ArgumentCompletionList list;
186                list.push_back(ArgumentCompletionListElement("", "", hint));
187                return list;
188            }
[7228]189        }
190
[7401]191        /**
192            @brief Returns a list of hidden commands and groups and also supports auto-completion of the arguments of these commands.
193
194            This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
195
196            This function makes commands visible that would usually be hidden.
197        */
[7234]198        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(hiddencommand)(const std::string& fragment)
199        {
[7276]200            SubString tokens(fragment, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
[7234]201
202            if (tokens.size() == 0)
[7235]203                return detail::_groupsandcommands(fragment, true);
[7234]204
[7236]205            if (ConsoleCommand::getCommandLC(getLowercase(tokens[0])))
[7234]206                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
207
208            if (tokens.size() == 1)
209            {
[7236]210                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().find(tokens[0]);
211                if (it_group != ConsoleCommand::getCommands().end())
[7234]212                    return detail::_subcommands(fragment, tokens[0], true);
213                else
[7235]214                    return detail::_groupsandcommands(fragment, true);
[7234]215            }
216
[7236]217            if (ConsoleCommand::getCommandLC(getLowercase(tokens[0]), getLowercase(tokens[1])))
[7234]218                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
219
220            return ArgumentCompletionList();
221        }
222
[7401]223        /**
224            @brief Returns possible files and directories and also supports files in arbitrary deeply nested subdirectories.
225
226            This function returns files and directories in the given path. This allows to
227            navigate iteratively through the file system. The first argument @a fragment
228            is used to get the current path.
229        */
[1505]230        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
231        {
232            ArgumentCompletionList dirlist;
233            ArgumentCompletionList filelist;
234
235            try
236            {
237                boost::filesystem::path input(fragment);
238                boost::filesystem::path startdirectory(input.branch_path());
239
240                if (!boost::filesystem::exists(startdirectory))
241                {
242                    startdirectory = ".";
243                }
[2710]244#ifdef ORXONOX_PLATFORM_WINDOWS
[1505]245                else
246                {
[6417]247                    const std::string& dir = startdirectory.string();
[1505]248                    if (dir.size() > 0 && dir[dir.size() - 1] == ':')
[2759]249                        startdirectory = dir + '/';
[1505]250                }
251#endif
252
253                boost::filesystem::directory_iterator file(startdirectory);
254                boost::filesystem::directory_iterator end;
255
256                while (file != end)
257                {
258                    if (boost::filesystem::is_directory(*file))
[6417]259                        dirlist.push_back(ArgumentCompletionListElement(file->string() + '/', getLowercase(file->string()) + '/', file->BOOST_LEAF_FUNCTION() + '/'));
[1505]260                    else
[6417]261                        filelist.push_back(ArgumentCompletionListElement(file->string(), getLowercase(file->string()), file->BOOST_LEAF_FUNCTION()));
[1505]262                    ++file;
263                }
264            }
265            catch (...) {}
266
267            filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
268            return filelist;
269        }
270
[7401]271        /**
272            @brief Returns the sections of the config file.
273        */
[6536]274        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
[1505]275        {
[6536]276            ArgumentCompletionList sectionList;
[1505]277
[6536]278            const std::set<std::string>& names = SettingsConfigFile::getInstance().getSectionNames();
279            for (std::set<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)
280                sectionList.push_back(ArgumentCompletionListElement(*it, getLowercase(*it)));
[1505]281
[6536]282            return sectionList;
[1505]283        }
284
[7401]285        /**
286            @brief Returns the entries in a given section of the config file.
287        */
[6536]288        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
[1505]289        {
[6536]290            ArgumentCompletionList entryList;
291            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
292            const std::string& sectionLC = getLowercase(section);
[1505]293
[6536]294            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
295            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
296                entryList.push_back(ArgumentCompletionListElement(it->second.second->getName(), it->second.first));
[1505]297
[6536]298            return entryList;
[1505]299        }
300
[7401]301        /**
302            @brief Returns the current value of a given value in a given section of the config file.
303        */
[6536]304        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
[1505]305        {
[6536]306            ArgumentCompletionList oldValue;
307            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
308            const std::string& sectionLC = getLowercase(section);
309            const std::string& entryLC = getLowercase(entry);
310
311            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
312            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
[1505]313            {
[6536]314                if (it->second.first == entryLC)
[1505]315                {
[6536]316                    const std::string& valuestring = it->second.second->toString();
317                    oldValue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
[1505]318                }
319            }
[6536]320
321            return oldValue;
[1505]322        }
323
[7401]324        /**
325            @brief Returns a list of indexes of the available Tcl threads (see TclThreadManager).
326        */
[1505]327        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
328        {
329            std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
330            ArgumentCompletionList threads;
331
332            for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
[3280]333                threads.push_back(ArgumentCompletionListElement(multi_cast<std::string>(*it)));
[1505]334
335            return threads;
336        }
337    }
338}
Note: See TracBrowser for help on using the repository browser.