Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/resources/src/lib/shell/shell_completion.cc @ 7913

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

orxonox/trunk: more std::string

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