Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_completion.cc @ 7413

Last change on this file since 7413 was 7413, checked in by bensch, 18 years ago

orxonox/trunk: Shell Completes some Parameters nicely now

File size: 10.4 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
17
18#include "shell_completion.h"
19#include "shell_command_class.h"
20#include "shell_completion_plugin.h"
21
22#include "shell_command.h"
23
24#include "substring.h"
25#include "class_list.h"
26#include "debug.h"
27
28namespace OrxShell
29{
30
31  /**
32   * @brief standard constructor
33   */
34  ShellCompletion::ShellCompletion()
35  { }
36
37
38  /**
39   * @brief standard deconstructor
40   */
41  ShellCompletion::~ShellCompletion ()
42  { }
43
44
45
46  /**
47   * @brief autocompletes the Shell's inputLine
48   * @param input the input to complete, will most possibly be changed.
49   * @returns true, if a result was found, false otherwise
50   */
51  bool ShellCompletion::autoComplete(std::string& input)
52  {
53    long classID = CL_NULL;                          //< the classID retrieved from the Class.
54    const std::list<BaseObject*>* objectList = NULL; //< the list of Objects stored in classID's ClassList
55    bool emptyComplete = false;                      //< if the completion input is empty string. e.g ""
56    long completeType = NullCompletion;              //< the Type we'd like to complete.
57    std::string completeString = "";                 //< the string to complete.
58    unsigned int parameterBegin = 0;                 //< The SubString-entry, the Parameters begin.
59    const ShellCommand* command = NULL;              //< The Command.
60
61
62    PRINTF(5)("AutoComplete on input\n");
63    this->clearCompletionList();
64
65    // Check if we are in a input. eg. the supplied string "class " and now we complete either function or object
66    if (input.empty() || input[input.size()-1] == ' ')
67      emptyComplete = true;
68
69    // CREATE INPUTS
70    SubString inputSplits(input, SubString::WhiteSpacesWithComma);
71
72    // What String will be completed
73    if (!emptyComplete && inputSplits.size() >= 1)
74      completeString = inputSplits.getString(inputSplits.size()-1);
75
76    // CLASS/ALIAS COMPLETION (on first argument)
77    if (inputSplits.size() == 0 || (!emptyComplete && inputSplits.size() == 1))
78    {
79      completeType |= ClassCompletion;
80      completeType |= AliasCompletion;
81    }
82
83    // OBJECT/FUNCTION COMPLETIONS
84    else if ((emptyComplete && inputSplits.size() == 1) ||
85             (!emptyComplete && inputSplits.size() == 2))
86    {
87      classID = ClassList::StringToID(inputSplits.getString(0));
88      objectList = ClassList::getList((ClassID)classID);
89      if (classID != CL_NULL)
90        completeType |= ObjectCompletion;
91      completeType |= FunctionCompletion;
92    }
93    // Complete the last Function
94    else if ((emptyComplete && inputSplits.size() == 2 ) ||
95             (!emptyComplete && inputSplits.size() == 3))
96    {
97      if (ClassList::exists(inputSplits[0], inputSplits[1]))
98        completeType |= FunctionCompletion;
99    }
100
101    // Looking for ParameterCompletions.
102    if (completeType == NullCompletion)
103    {
104      if ((command = ShellCommand::getCommandFromInput(input)) != NULL)
105        completeType |= ParamCompletion;
106    }
107
108    if (completeType & ClassCompletion)
109      this->objectComplete(completeString, CL_SHELL_COMMAND_CLASS);
110    if (completeType & ObjectCompletion)
111      this->objectComplete(completeString, classID);
112    if (completeType & FunctionCompletion)
113      this->commandComplete(completeString, inputSplits[0]);
114    if (completeType & AliasCompletion)
115      this->aliasComplete(completeString);
116    if (completeType & ParamCompletion)
117      this->paramComplete(completeString, command);
118
119
120
121    this->generalComplete(input, completeString);
122    return true;
123  }
124
125  /**
126   * @brief autocompletes an ObjectName
127   * @param objectBegin the beginning string of a Object
128   * @param classID the ID of the Class to search for.
129   * @return true on success, false otherwise
130   */
131  bool ShellCompletion::objectComplete(const std::string& objectBegin, long classID)
132  {
133    const std::list<BaseObject*>* boList = ClassList::getList((ClassID)classID);
134    if (boList != NULL)
135    {
136      CompletionType type = ObjectCompletion;
137      if (classID == CL_SHELL_COMMAND_CLASS)
138        type = ClassCompletion;
139      if (!this->addToCompleteList(*boList, objectBegin, type))
140        return false;
141    }
142    else
143      return false;
144    return true;
145  }
146
147  /**
148   * @brief completes a Command
149   * @param commandBegin the beginning of the function String
150   * @param classID the class' ID to complete the function of
151   */
152  bool ShellCompletion::commandComplete(const std::string& commandBegin, const std::string& className)
153  {
154    std::list<std::string> fktList;
155    ShellCommandClass::getCommandListOfClass(className, fktList);
156    if (!this->addToCompleteList(fktList, commandBegin, FunctionCompletion))
157      return false;
158    return true;
159  }
160
161  /**
162   * @brief completes an Alias
163   * @param aliasBegin the beginning of the Alias-String to complete
164   * @returns true on succes, false if something went wrong
165   */
166  bool ShellCompletion::aliasComplete(const std::string& aliasBegin)
167  {
168    std::list<std::string> aliasList;
169    ShellCommandAlias::getCommandListOfAlias(aliasList);
170    if (!this->addToCompleteList(aliasList, aliasBegin, AliasCompletion))
171      return false;
172    return true;
173  }
174
175  /**
176   * @brief completes Parameters.
177   * @param paramBegin: Begin of the Parameters.
178   * @returns true on succes, false if something went wrong
179   */
180  bool ShellCompletion::paramComplete(const std::string& paramBegin, const ShellCommand* command)
181  {
182    std::vector<std::string> completed;
183    command->getCompletorPlugin(0)->addToCompleteList(completed, paramBegin);
184      for (unsigned int i = 0; i < completed.size(); i++)
185        this->completionList.push_back(CompletionElement(completed[i], ParamCompletion));
186  }
187
188
189  /**
190   * @brief completes the inputline on grounds of an inputList
191   * @param input the Input to complete.
192   * @param begin the String to search in the inputList, and to extend with it.
193   * @param displayAs how to display the found value to the user, printf-style, !!with only one %s!! ex.: "::%s::"
194   * @param addBack what should be added at the end of the completion
195   * @param addFront what should be added to the front of one finished completion
196   * @return true if ok, false otherwise
197   */
198  bool ShellCompletion::generalComplete(std::string& input,
199                                        const std::string& begin, const std::string& displayAs,
200                                        const std::string& addBack, const std::string& addFront)
201  {
202    if (completionList.size() == 0)
203      return false;
204
205    CompletionElement addElem = completionList.front();
206    const std::string& addString = addElem.name;
207    unsigned int addLength = addString.size();
208    unsigned int inputLenght = begin.size();
209
210    // Determin the longest Match (starting with the first candidate in full length).
211    CompletionType changeType = NullCompletion;
212    std::vector<CompletionElement>::iterator charIT;
213    for (charIT = completionList.begin(); charIT != completionList.end(); charIT++)
214    {
215      printf("== %s\n", (*charIT).name.c_str());
216      if ((*charIT).type != changeType)
217      {
218        if (changeType != NullCompletion)
219          PRINT(0)("\n");
220        PRINT(0)("%s: ", ShellCompletion::typeToString((*charIT).type).c_str());
221        changeType = (*charIT).type;
222      }
223      PRINTF(0)("%s ", (*charIT).name.c_str());
224      for (unsigned int i = inputLenght; i < addLength; i++)
225        if (addString[i] != (*charIT).name[i])
226          addLength = i;
227    }
228    PRINT(0)("\n");
229
230    if (addLength >= inputLenght)
231    {
232      std::string adder = addString;
233      adder.resize(addLength);
234
235      input.resize(input.size()-inputLenght);
236      input += adder;
237
238      if (completionList.size() == 1)
239      {
240        if ( addBack != "")
241          input += addBack;
242        input += ' ';
243      }
244    }
245    return true;
246  }
247
248  /**
249   * @brief searches for classes, which beginn with completionBegin
250   * @param inputList the List to parse through
251   * @param completionBegin the beginning string
252   * !! The strings MUST NOT be deleted !!
253   */
254  bool ShellCompletion::addToCompleteList(const std::list<std::string>& inputList, const std::string& completionBegin, CompletionType type)
255  {
256    unsigned int searchLength = completionBegin.size();
257
258    std::list<std::string>::const_iterator string;
259    for (string = inputList.begin(); string != inputList.end(); string++)
260    {
261      if ((*string).size() >= searchLength &&
262          !nocaseCmp(*string, completionBegin, searchLength))
263      {
264        this->completionList.push_back(CompletionElement (*string, type));
265      }
266    }
267    return true;
268  }
269
270  /**
271   * @brief searches for classes, which beginn with completionBegin
272   * @param inputList the List to parse through
273   * @param completionBegin the beginning string
274   * !! The strings MUST NOT be deleted !!
275   */
276  bool ShellCompletion::addToCompleteList(const std::list<BaseObject*>& inputList, const std::string& completionBegin, CompletionType type)
277  {
278    unsigned int searchLength = completionBegin.size();
279
280    std::list<BaseObject*>::const_iterator bo;
281    for(bo = inputList.begin(); bo != inputList.end(); bo++)
282    {
283      if ((*bo)->getName() != NULL &&
284          strlen((*bo)->getName()) >= searchLength &&
285          !nocaseCmp((*bo)->getName(), completionBegin, searchLength))
286      {
287        this->completionList.push_back(CompletionElement((*bo)->getName(), type));
288      }
289    }
290
291    return true;
292  }
293
294  /**
295   * @brief deletes the Completion List.
296   *
297   * This is done at the beginning of each completion-run
298   */
299  void ShellCompletion::clearCompletionList()
300  {
301    this->completionList.clear();
302  }
303
304  const std::string& ShellCompletion::typeToString(CompletionType type)
305  {
306    switch (type)
307    {
308      default:// SHELLC_NONE
309        return typeNames[0];
310      case  ClassCompletion:
311        return typeNames[1];
312      case ObjectCompletion:
313        return typeNames[2];
314      case FunctionCompletion:
315        return typeNames[3];
316      case AliasCompletion:
317        return typeNames[4];
318      case ParamCompletion:
319        return typeNames[5];
320    }
321  }
322
323
324  const std::string ShellCompletion::typeNames[] =
325    {
326      "error",
327      "class",
328      "object",
329      "function",
330      "alias",
331      "parameter",
332    };
333
334}
Note: See TracBrowser for help on using the repository browser.