Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5193 was 5193, checked in by bensch, 19 years ago

orxonox/trunk: better algorithms

File size: 8.9 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: ...
13   co-programmer: ...
14*/
15
16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "shell_completion.h"
19
20#include "shell_input.h"
21
22#include "substring.h"
23#include "base_object.h"
24#include "class_list.h"
25#include "list.h"
26#include "debug.h"
27
28#include "stdlibincl.h"
29
30using namespace std;
31
32/**
33 * standard constructor
34 * @todo this constructor is not jet implemented - do it
35*/
36ShellCompletion::ShellCompletion(ShellInput* input)
37{
38  this->completionList = NULL;
39  this->input = input;
40}
41
42
43/**
44 * standard deconstructor
45*/
46ShellCompletion::~ShellCompletion ()
47{
48  // delete what has to be deleted here
49  if (this->completionList)
50  {
51    this->emptyCompletionList();
52    delete this->completionList;
53  }
54}
55
56
57
58/**
59 * autocompletes the Shell's inputLine
60 * @returns true, if a result was found, false otherwise
61 *
62 * @todo implement it!!
63 */
64bool ShellCompletion::autoComplete(ShellInput* input)
65{
66  const char* completionLine;
67
68  long classID;                    //< the classID retrieved from the Class.
69  tList<BaseObject>* objectList;   //< the list of Objects stored in classID
70  bool emptyComplete = false;      //< if the completion input is empty string. e.g ""
71  SHELLC_TYPE firstType = SHELLC_NONE;
72  SHELLC_TYPE secondType = SHELLC_NONE;
73  long completeType = SHELLC_NONE;
74  const char* completeString;
75
76
77  PRINTF(5)("AutoComplete on input\n");
78  this->emptyCompletionList();
79
80  if (input != NULL)
81    this->input = input;
82  if (this->input == NULL)
83  {
84    PRINTF(2)("No ShellInput supplied\n");
85    return false;
86  }
87
88  // Check if we are in a input. eg. the supplied string "class " and now we complete either function or object
89  if (this->input->getInput() != NULL &&
90      strrchr(this->input->getInput(), ' ') >= this->input->getInput() + strlen(this->input->getInput())-1)
91  {
92    emptyComplete = true;
93  }
94
95  // CREATE INPUTS
96  if (this->input->getInput() == NULL)
97    completionLine = "";
98  else
99    completionLine = this->input->getInput() + strspn(this->input->getInput(), " \t\n");
100  SubString inputSplits(completionLine, true);
101
102  // What String will be completed
103  if (emptyComplete == true)
104    completeString = "";
105  else
106    completeString = inputSplits.getString(inputSplits.getCount()-1);
107
108  // CLASS COMPLETION
109  if (inputSplits.getCount() == 0)
110  {
111    PRINTF(5)("Listing all Classes\n");
112    completeType |= SHELLC_CLASS;
113  }
114  else if (inputSplits.getCount() == 1 && emptyComplete == false)
115  {
116    printf("trying to complete a Class with '%s'\n", inputSplits.getString(0));
117    completeType |= SHELLC_CLASS;
118  }
119
120  // OBJECT/FUNCTION COMPLETIONS
121  else if ((inputSplits.getCount() == 1 && emptyComplete == true) ||
122            (inputSplits.getCount() == 2 && emptyComplete == false))
123  {
124    classID = ClassList::StringToID(inputSplits.getString(0));
125    if (classID == CL_NULL)
126    {
127      return false;
128    }
129    else
130    {
131      completeType |= SHELLC_OBJECT;
132    }
133  }
134
135  if (completeType & SHELLC_CLASS)
136    this->objectComplete(completeString, CL_SHELL_COMMAND_CLASS);
137  if (completeType & SHELLC_OBJECT)
138    this->objectComplete(completeString, classID);
139
140  if (emptyComplete == false)
141    this->generalComplete(inputSplits.getString(inputSplits.getCount()-1));
142  else
143    this->generalComplete("");
144}
145
146/**
147 * autocompletes a className
148 * @param classBegin the Beginning of a String to autoComplete
149 * @return true on success, false otherwise
150 */
151bool ShellCompletion::classComplete(const char* classBegin)
152{
153  if (unlikely(classBegin == NULL))
154    return false;
155  const tList<const char>* clList = ClassList::getClassList();
156  if (clList != NULL)
157  {
158    if (!this->addToCompleteList(clList, classBegin))
159      return false;
160  }
161  else
162    return false;
163  return true;
164}
165
166/**
167 * autocompletes an ObjectName
168 * @param objectBegin the beginning string of a Object
169 * @param classID the ID of the Class to search for.
170 * @return true on success, false otherwise
171 */
172bool ShellCompletion::objectComplete(const char* objectBegin, long classID)
173{
174  if (unlikely(objectBegin == NULL))
175    return false;
176  const tList<BaseObject>* boList = ClassList::getList(classID);
177  if (boList != NULL)
178  {
179    //printf("%s\n", boList->firstElement()->getName());
180    if (!this->addToCompleteList(boList, objectBegin))
181      return false;
182  }
183  else
184    return false;
185  return true;
186}
187
188/**
189 * completes a Function
190 * @param functionBegin the beginning of the function String
191 */
192bool ShellCompletion::functionComplete(const char* functionBegin)
193{
194}
195
196/**
197 * completes the inputline on grounds of an inputList
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(const char* begin, const char* displayAs, const char* addBack, const char* addFront)
205{
206  if (completionList == NULL || this->input == NULL )
207    return false;
208  if (completionList->getSize() == 0)
209    return false;
210
211  ShellC_Element* addElem = completionList->firstElement();
212  const char* addString = addElem->name;
213  unsigned int addLength = 0;
214  unsigned int inputLenght = strlen(begin);
215
216  // Determin the longest Match
217  if (addString != NULL)
218    addLength = strlen(addString);
219  tIterator<ShellC_Element>* charIterator = completionList->getIterator();
220  ShellC_Element* charElem = charIterator->firstElement();
221  while (charElem != NULL)
222  {
223    PRINTF(0)(displayAs, charElem->name);
224    for (unsigned int i = inputLenght; i < addLength; i++)
225      if (addString[i] != charElem->name[i])
226      {
227       addLength = i;
228       break;
229      }
230    charElem = charIterator->nextElement();
231  }
232  delete charIterator;
233
234  if (addLength >= inputLenght)
235  {
236    char* adder = new char[addLength+1];
237    strncpy(adder, addString, addLength);
238    adder[addLength] = '\0';
239
240    if (this->input)
241    {
242     this->input->removeCharacters(inputLenght);
243     this->input->addCharacters(adder);
244
245      if (completionList->getSize() == 1)
246      {
247        if ( addBack != NULL )
248         this->input->addCharacters(addBack);
249        this->input->addCharacter(' ');
250      }
251     delete[] adder;
252    }
253  }
254  return true;
255}
256
257/**
258 * searches for classes, which beginn with completionBegin
259 * @param inputList the List to parse through
260 * @param completionBegin the beginning string
261 * !! The strings MUST NOT be deleted !!
262 */
263bool ShellCompletion::addToCompleteList(const tList<const char>* inputList, const char* completionBegin)
264{
265  if (inputList == NULL || completionBegin == NULL)
266    return false;
267  unsigned int searchLength = strlen(completionBegin);
268
269  tIterator<const char>* iterator = inputList->getIterator();
270  const char* enumString = iterator->firstElement();
271  while (enumString != NULL)
272  {
273    if (strlen(enumString) >= searchLength &&
274        !strncasecmp(enumString, completionBegin, searchLength))
275    {
276      printf("%s\n", enumString);
277      ShellC_Element* newElem = new ShellC_Element;
278      newElem->name = enumString;
279      this->completionList->add(newElem);
280    }
281    enumString = iterator->nextElement();
282  }
283  delete iterator;
284
285  return true;
286}
287
288/**
289 * searches for classes, which beginn with completionBegin
290 * @param inputList the List to parse through
291 * @param completionBegin the beginning string
292 * !! The strings MUST NOT be deleted !!
293 */
294bool ShellCompletion::addToCompleteList(const tList<BaseObject>* inputList, const char* completionBegin)
295{
296  if (inputList == NULL || completionBegin == NULL)
297    return false;
298  unsigned int searchLength = strlen(completionBegin);
299
300  tIterator<BaseObject>* iterator = inputList->getIterator();
301  BaseObject* enumBO = iterator->firstElement();
302  while (enumBO != NULL)
303  {
304    if (enumBO->getName() != NULL &&
305        strlen(enumBO->getName()) >= searchLength &&
306        !strncasecmp(enumBO->getName(), completionBegin, searchLength))
307    {
308      ShellC_Element* newElem = new ShellC_Element;
309      newElem->name = enumBO->getName();
310      this->completionList->add(newElem);
311      printf("%s\n",enumBO->getName());
312    }
313    enumBO = iterator->nextElement();
314  }
315  delete iterator;
316
317  return true;
318}
319
320
321void ShellCompletion::emptyCompletionList()
322{
323  if (this->completionList != NULL)
324  {
325    tIterator<ShellC_Element>* elemIT = this->completionList->getIterator();
326    ShellC_Element* elem = elemIT->firstElement();
327    while (elem != NULL)
328    {
329      delete elem;
330      elem = elemIT->nextElement();
331    }
332    delete this->completionList;
333  }
334  this->completionList = new tList<ShellC_Element>;
335}
Note: See TracBrowser for help on using the repository browser.