Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: added new Files shell_completion_plugin for the new Plugin Structure.
Also created the first namespace: OrxShell

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