Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/shell/shell_completion.cc @ 9697

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

adapted shell

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