Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: construct for ShellCommandAlias… have to work some more on this :/

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