Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: ClassList better, and some shell-commands

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