Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: c_str() removed

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