Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: alias-completion works too now :)

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