Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

oroxnox/trunk: way better algorithm for the completion… more with logic and stuff

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: ...
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
72
73  PRINTF(5)("AutoComplete on input\n");
74  this->emptyCompletionList();
75
76  if (input != NULL)
77    this->input = input;
78  if (this->input == NULL)
79  {
80    PRINTF(2)("No ShellInput supplied\n");
81    return false;
82  }
83
84  // Check if we are in a input. eg. the supplied string "class " and now we complete either function or object
85  if (this->input->getInput() != NULL &&
86      strrchr(this->input->getInput(), ' ') >= this->input->getInput() + strlen(this->input->getInput())-1)
87  {
88    emptyComplete = true;
89  }
90
91  if (this->input->getInput() == NULL)
92    completionLine = "";
93  else
94    completionLine = this->input->getInput() + strspn(this->input->getInput(), " \t\n");
95
96  SubString inputSplits(completionLine, true);
97
98  // CLASS COMPLETION
99  if (inputSplits.getCount() == 0)
100  {
101    PRINTF(5)("Listing all Classes\n");
102    this->objectComplete("", CL_SHELL_COMMAND_CLASS);
103    return false;
104  }
105  else if (inputSplits.getCount() == 1 && emptyComplete == false)
106  {
107    printf("trying to complete a Class with '%s'\n", inputSplits.getString(0));
108    this->objectComplete(inputSplits.getString(0), CL_SHELL_COMMAND_CLASS);
109  }
110
111  // OBJECT/FUNCTION COMPLETIONS
112  else if ( (inputSplits.getCount() == 1 && emptyComplete == true ) ||
113             (inputSplits.getCount() == 2 && emptyComplete == false))
114  {
115    classID = ClassList::StringToID(inputSplits.getString(0));
116    if (classID == CL_NULL)
117      return false;
118    if (inputSplits.getCount()==2)
119    {
120      if  (completionLine[strlen(completionLine)-1] != ' ')
121       this->objectComplete(inputSplits.getString(1), classID);
122    }
123    else
124      this->objectComplete("", classID);
125  }
126//  else if (inputSplits.getCount() <= 3 )
127
128/*  completionLine = new char[strlen(this->input->getText())+1];
129  strcpy(completionLine, this->input->getText());
130
131  char* commandBegin = strrchr(completionLine, ' ');
132  if (commandBegin == NULL)
133    commandBegin = completionLine;
134  else
135  {
136    if(commandBegin >= completionLine + strlen(completionLine))
137      commandBegin = completionLine + strlen(completionLine);
138    else
139      commandBegin++;
140  }
141
142  char* objectStart;
143  if (objectStart = strstr(commandBegin, "::"))
144  {
145    char* classIdentity = new char[objectStart - commandBegin +1];
146    strncpy(classIdentity, commandBegin, objectStart - commandBegin);
147    classIdentity[objectStart - commandBegin] = '\0';
148    this->objectComplete(objectStart+2, ClassList::StringToID(classIdentity));
149    delete[] classIdentity;
150  }
151  else
152    this->classComplete(commandBegin);
153
154  delete[] completionLine;*/
155}
156
157/**
158 * autocompletes a className
159 * @param classBegin the Beginning of a String to autoComplete
160 * @return true on success, false otherwise
161 */
162bool ShellCompletion::classComplete(const char* classBegin)
163{
164  if (unlikely(classBegin == NULL))
165    return false;
166  const tList<const char>* clList = ClassList::getClassList();
167  if (clList != NULL)
168  {
169    const tList<ShellC_Element>* classList = this->addToCompleteList(clList, classBegin);
170    if (classList != NULL)
171      this->generalComplete(classList, classBegin, "CL: %s ");
172    else
173      return false;
174    delete classList;
175  }
176  else
177    return false;
178  return true;
179}
180
181/**
182 * autocompletes an ObjectName
183 * @param objectBegin the beginning string of a Object
184 * @param classID the ID of the Class to search for.
185 * @return true on success, false otherwise
186 */
187bool ShellCompletion::objectComplete(const char* objectBegin, long classID)
188{
189  if (unlikely(objectBegin == NULL))
190    return false;
191  tList<BaseObject>* boList = ClassList::getList(classID);
192  if (boList != NULL)
193  {
194    //printf("%s\n", boList->firstElement()->getName());
195    const tList<ShellC_Element>* objectList = this->addToCompleteList(boList, objectBegin);
196    if (objectList != NULL)
197      this->generalComplete(objectList, objectBegin, "%s ");
198    else
199      return false;
200  }
201  else
202    return false;
203  return true;
204}
205
206/**
207 * completes a Function
208 * @param functionBegin the beginning of the function String
209 */
210bool ShellCompletion::functionComplete(const char* functionBegin)
211{
212}
213
214/**
215 * completes the inputline on grounds of an inputList
216 * @param stringList the List to parse through
217 * @param begin the String to search in the inputList, and to extend with it.
218 * @param displayAs how to display the found value to the user, printf-style, !!with only one %s!! ex.: "::%s::"
219 * @param addBack what should be added at the end of the completion
220 * @param addFront what should be added to the front of one finished completion
221 * @return true if ok, false otherwise
222 */
223bool ShellCompletion::generalComplete(const tList<ShellC_Element>* stringList, const char* begin, const char* displayAs, const char* addBack, const char* addFront)
224{
225  if (stringList == NULL || this->input == NULL )
226    return false;
227  if (stringList->getSize() == 0)
228    return false;
229
230  ShellC_Element* addElem = stringList->firstElement();
231  const char* addString = addElem->name;
232  unsigned int addLength = 0;
233  unsigned int inputLenght = strlen(begin);
234
235  // Determin the longest Match
236  if (addString != NULL)
237    addLength = strlen(addString);
238  tIterator<ShellC_Element>* charIterator = stringList->getIterator();
239  ShellC_Element* charElem = charIterator->firstElement();
240  while (charElem != NULL)
241  {
242    PRINTF(0)(displayAs, charElem->name);
243    for (unsigned int i = inputLenght; i < addLength; i++)
244      if (addString[i] != charElem->name[i])
245      {
246       addLength = i;
247       break;
248      }
249    charElem = charIterator->nextElement();
250  }
251  delete charIterator;
252
253  if (addLength >= inputLenght)
254  {
255    char* adder = new char[addLength+1];
256    strncpy(adder, addString, addLength);
257    adder[addLength] = '\0';
258
259    if (this->input)
260    {
261     this->input->removeCharacters(inputLenght);
262     this->input->addCharacters(adder);
263
264      if (stringList->getSize() == 1)
265      {
266        if ( addBack != NULL )
267         this->input->addCharacters(addBack);
268        this->input->addCharacter(' ');
269      }
270     delete[] adder;
271    }
272  }
273  return true;
274}
275
276/**
277 * searches for classes, which beginn with completionBegin
278 * @param inputList the List to parse through
279 * @param completionBegin the beginning string
280 * !! The strings MUST NOT be deleted !!
281 */
282const tList<ShellC_Element>* ShellCompletion::addToCompleteList(const tList<const char>* inputList, const char* completionBegin)
283{
284  if (inputList == NULL || completionBegin == NULL)
285    return NULL;
286  unsigned int searchLength = strlen(completionBegin);
287
288  tIterator<const char>* iterator = inputList->getIterator();
289  const char* enumString = iterator->firstElement();
290  while (enumString != NULL)
291  {
292    if (strlen(enumString) >= searchLength &&
293        !strncasecmp(enumString, completionBegin, searchLength))
294    {
295      printf("%s\n", enumString);
296      ShellC_Element* newElem = new ShellC_Element;
297      newElem->name = enumString;
298      this->completionList->add(newElem);
299    }
300    enumString = iterator->nextElement();
301  }
302  delete iterator;
303
304  return this->completionList;
305}
306
307/**
308 * searches for classes, which beginn with completionBegin
309 * @param inputList the List to parse through
310 * @param completionBegin the beginning string
311 * !! The strings MUST NOT be deleted !!
312 */
313const tList<ShellC_Element>* ShellCompletion::addToCompleteList(const tList<BaseObject>* inputList, const char* completionBegin)
314{
315  if (inputList == NULL || completionBegin == NULL)
316    return NULL;
317  unsigned int searchLength = strlen(completionBegin);
318
319  tIterator<BaseObject>* iterator = inputList->getIterator();
320  BaseObject* enumBO = iterator->firstElement();
321  while (enumBO != NULL)
322  {
323    if (enumBO->getName() != NULL &&
324        strlen(enumBO->getName()) >= searchLength &&
325        !strncasecmp(enumBO->getName(), completionBegin, searchLength))
326    {
327      ShellC_Element* newElem = new ShellC_Element;
328      newElem->name = enumBO->getName();
329      this->completionList->add(newElem);
330      printf("%s\n",enumBO->getName());
331    }
332    enumBO = iterator->nextElement();
333  }
334  delete iterator;
335
336  return this->completionList;
337}
338
339
340void ShellCompletion::emptyCompletionList()
341{
342  if (this->completionList != NULL)
343  {
344    tIterator<ShellC_Element>* elemIT = this->completionList->getIterator();
345    ShellC_Element* elem = elemIT->firstElement();
346    while (elem != NULL)
347    {
348      delete elem;
349      elem = elemIT->nextElement();
350    }
351    delete this->completionList;
352  }
353  this->completionList = new tList<ShellC_Element>;
354}
Note: See TracBrowser for help on using the repository browser.