Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: Super-good completion :), and extremely tired bensch

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