Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10240 was 9869, checked in by bensch, 18 years ago

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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