Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: list to vector

File size: 9.7 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_
17
18#include "shell_completion.h"
19#include "shell_command_class.h"
20
21#include "shell_input.h"
22#include "shell_command.h"
23
24#include "substring.h"
25#include "class_list.h"
26#include "debug.h"
27
28using namespace std;
29
30/**
31 * @brief standard constructor
32 */
33ShellCompletion::ShellCompletion()
34{ }
35
36
37/**
38 * @brief standard deconstructor
39 */
40ShellCompletion::~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 */
50bool 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 */
129bool 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 */
148bool 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 */
169bool 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 */
184bool 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 */
204bool 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 */
264bool 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 */
290bool 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 */
316void ShellCompletion::clearCompletionList()
317{
318  this->completionList.clear();
319}
320
321const 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
339const std::string ShellCompletion::typeNames[] =
340{
341  "error",
342  "class",
343  "object",
344  "function",
345  "alias"
346};
Note: See TracBrowser for help on using the repository browser.