Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged consolecommands3 branch back to trunk.

note: the console command interface has changed completely, but the documentation is not yet up to date. just copy an existing command and change it to your needs, it's pretty self-explanatory. also the include files related to console commands are now located in core/command/. in the game it should work exactly like before, except for some changes in the auto-completion.

  • Property svn:eol-style set to native
File size: 11.6 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 "ArgumentCompletionFunctions.h"
30
31#include <map>
32#include <boost/version.hpp>
33#include <boost/filesystem.hpp>
34
35#include "util/Convert.h"
36#include "util/StringUtils.h"
37#include "core/Identifier.h"
38#include "core/ConfigFileManager.h"
39#include "core/ConfigValueContainer.h"
40#include "CommandExecutor.h"
41#include "ConsoleCommand.h"
42#include "TclThreadManager.h"
43
44// Boost 1.36 has some issues with deprecated functions that have been omitted
45#if (BOOST_VERSION == 103600)
46#  define BOOST_LEAF_FUNCTION filename
47#else
48#  define BOOST_LEAF_FUNCTION leaf
49#endif
50
51namespace orxonox
52{
53    namespace autocompletion
54    {
55        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
56        {
57            return ArgumentCompletionList();
58        }
59
60        namespace detail
61        {
62            bool groupIsVisible(const std::map<std::string, ConsoleCommand*>& group, bool bOnlyShowHidden)
63            {
64                for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = group.begin(); it_command != group.end(); ++it_command)
65                    if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden)
66                        return true;
67
68                return false;
69            }
70
71            ArgumentCompletionList _groupsandcommands(const std::string& fragment, bool bOnlyShowHidden)
72            {
73                ArgumentCompletionList groupList;
74                std::string fragmentLC = getLowercase(fragment);
75
76                const std::map<std::string, std::map<std::string, ConsoleCommand*> >& commands = ConsoleCommand::getCommands();
77                for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.begin(); it_group != commands.end(); ++it_group)
78                    if (groupIsVisible(it_group->second, bOnlyShowHidden) && it_group->first != "" && (fragmentLC == "" || getLowercase(it_group->first).find_first_of(fragmentLC) == 0))
79                        groupList.push_back(ArgumentCompletionListElement(it_group->first, getLowercase(it_group->first)));
80
81                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.find("");
82                if (it_group != commands.end())
83                {
84                    if (!groupList.empty())
85                        groupList.push_back(ArgumentCompletionListElement("", "", "\n"));
86
87                    for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
88                        if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden && (fragmentLC == "" || getLowercase(it_command->first).find_first_of(fragmentLC) == 0))
89                            groupList.push_back(ArgumentCompletionListElement(it_command->first, getLowercase(it_command->first)));
90                }
91
92                if (!groupList.empty() && groupList.back().getDisplay() == "\n")
93                    groupList.pop_back();
94
95                return groupList;
96            }
97
98            ArgumentCompletionList _subcommands(const std::string& fragment, const std::string& group, bool bOnlyShowHidden)
99            {
100                ArgumentCompletionList commandList;
101
102                std::string groupLC = getLowercase(group);
103
104                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
105                for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
106                    if (getLowercase(it_group->first) == groupLC)
107                        break;
108
109                if (it_group != ConsoleCommand::getCommands().end())
110                {
111                    for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
112                        if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden)
113                            commandList.push_back(ArgumentCompletionListElement(it_command->first, getLowercase(it_command->first)));
114                }
115
116                return commandList;
117            }
118        }
119
120        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(groupsandcommands)(const std::string& fragment)
121        {
122            return detail::_groupsandcommands(fragment, false);
123        }
124
125        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(subcommands)(const std::string& fragment, const std::string& group)
126        {
127            return detail::_subcommands(fragment, group, false);
128        }
129
130        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(command)(const std::string& fragment)
131        {
132            CommandEvaluation evaluation = CommandExecutor::evaluate(fragment);
133            const std::string& hint = evaluation.hint();
134
135            if (evaluation.getPossibleArguments().size() > 0 && evaluation.getPossibleArgumentsSize() > 0)
136            {
137                return evaluation.getPossibleArguments();
138            }
139            else
140            {
141                ArgumentCompletionList list;
142                list.push_back(ArgumentCompletionListElement("", "", hint));
143                return list;
144            }
145        }
146
147        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(hiddencommand)(const std::string& fragment)
148        {
149            SubString tokens(fragment, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
150
151            if (tokens.size() == 0)
152                return detail::_groupsandcommands(fragment, true);
153
154            if (ConsoleCommand::getCommandLC(getLowercase(tokens[0])))
155                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
156
157            if (tokens.size() == 1)
158            {
159                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().find(tokens[0]);
160                if (it_group != ConsoleCommand::getCommands().end())
161                    return detail::_subcommands(fragment, tokens[0], true);
162                else
163                    return detail::_groupsandcommands(fragment, true);
164            }
165
166            if (ConsoleCommand::getCommandLC(getLowercase(tokens[0]), getLowercase(tokens[1])))
167                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
168
169            return ArgumentCompletionList();
170        }
171
172        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
173        {
174            ArgumentCompletionList dirlist;
175            ArgumentCompletionList filelist;
176
177            try
178            {
179                boost::filesystem::path input(fragment);
180                boost::filesystem::path startdirectory(input.branch_path());
181
182                if (!boost::filesystem::exists(startdirectory))
183                {
184                    startdirectory = ".";
185                }
186#ifdef ORXONOX_PLATFORM_WINDOWS
187                else
188                {
189                    const std::string& dir = startdirectory.string();
190                    if (dir.size() > 0 && dir[dir.size() - 1] == ':')
191                        startdirectory = dir + '/';
192                }
193#endif
194
195                boost::filesystem::directory_iterator file(startdirectory);
196                boost::filesystem::directory_iterator end;
197
198                while (file != end)
199                {
200                    if (boost::filesystem::is_directory(*file))
201                        dirlist.push_back(ArgumentCompletionListElement(file->string() + '/', getLowercase(file->string()) + '/', file->BOOST_LEAF_FUNCTION() + '/'));
202                    else
203                        filelist.push_back(ArgumentCompletionListElement(file->string(), getLowercase(file->string()), file->BOOST_LEAF_FUNCTION()));
204                    ++file;
205                }
206            }
207            catch (...) {}
208
209            filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
210            return filelist;
211        }
212
213        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
214        {
215            ArgumentCompletionList sectionList;
216
217            const std::set<std::string>& names = SettingsConfigFile::getInstance().getSectionNames();
218            for (std::set<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)
219                sectionList.push_back(ArgumentCompletionListElement(*it, getLowercase(*it)));
220
221            return sectionList;
222        }
223
224        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
225        {
226            ArgumentCompletionList entryList;
227            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
228            const std::string& sectionLC = getLowercase(section);
229
230            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
231            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
232                entryList.push_back(ArgumentCompletionListElement(it->second.second->getName(), it->second.first));
233
234            return entryList;
235        }
236
237        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
238        {
239            ArgumentCompletionList oldValue;
240            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
241            const std::string& sectionLC = getLowercase(section);
242            const std::string& entryLC = getLowercase(entry);
243
244            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
245            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
246            {
247                if (it->second.first == entryLC)
248                {
249                    const std::string& valuestring = it->second.second->toString();
250                    oldValue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
251                }
252            }
253
254            return oldValue;
255        }
256
257        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
258        {
259            std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
260            ArgumentCompletionList threads;
261
262            for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
263                threads.push_back(ArgumentCompletionListElement(multi_cast<std::string>(*it)));
264
265            return threads;
266        }
267    }
268}
Note: See TracBrowser for help on using the repository browser.