Changeset 6412 for code/branches/pickup2/src/libraries/core/Shell.cc
- Timestamp:
- Dec 25, 2009, 1:18:03 PM (15 years ago)
- Location:
- code/branches/pickup2
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/pickup2
- Property svn:mergeinfo changed
-
code/branches/pickup2/src/libraries/core/Shell.cc
r5929 r6412 23 23 * Fabian 'x3n' Landau 24 24 * Co-authors: 25 * ...25 * Reto Grieder 26 26 * 27 27 */ … … 30 30 31 31 #include "util/OutputHandler.h" 32 #include "util/StringUtils.h" 33 #include "util/SubString.h" 32 34 #include "CommandExecutor.h" 33 35 #include "CoreIncludes.h" 34 36 #include "ConfigValueIncludes.h" 35 #include "Core.h"36 37 #include "ConsoleCommand.h" 37 38 #define SHELL_UPDATE_LISTENERS(function) \39 for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ) \40 (*(it++))->function()41 38 42 39 namespace orxonox 43 40 { 44 SetConsoleCommand(Shell, clearShell, true);45 SetConsoleCommand(Shell, history, true);46 47 41 SetConsoleCommandShortcut(OutputHandler, log); 48 42 SetConsoleCommandShortcut(OutputHandler, error); … … 51 45 SetConsoleCommandShortcut(OutputHandler, debug); 52 46 53 Shell* Shell::singletonPtr_s = 0; 54 55 Shell::Shell() 56 { 57 int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell); 58 Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1); 59 47 Shell::Shell(const std::string& consoleName, bool bScrollable) 48 : OutputListener(consoleName) 49 , inputBuffer_(new InputBuffer()) 50 , consoleName_(consoleName) 51 , bScrollable_(bScrollable) 52 { 60 53 RegisterRootObject(Shell); 61 54 … … 64 57 this->historyPosition_ = 0; 65 58 this->historyOffset_ = 0; 66 this->finishedLastLine_ = true; 67 this->bAddOutputLevel_ = false; 68 69 this->clearLines(); 70 71 this->inputBuffer_ = new InputBuffer(); 59 this->bFinishedLastLine_ = true; 60 61 this->clearOutput(); 72 62 this->configureInputBuffer(); 73 63 74 this->outputBuffer_.registerListener(this); 75 OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_); 76 77 // Get a config file for the command history 78 this->commandHistoryConfigFileType_ = ConfigFileManager::getInstance().getNewConfigFileType(); 79 ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini"); 64 // Specify file for the command history 65 ConfigFileManager::getInstance().setFilename(ConfigFileType::CommandHistory, "commandHistory.ini"); 66 67 // Use a stringstream object to buffer the output 68 this->outputStream_ = &this->outputBuffer_; 80 69 81 70 this->setConfigValues(); 82 71 83 Core::setSoftDebugLevel(OutputHandler::LD_Shell, level); 72 // Get the previous output and add it to the Shell 73 for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin(); 74 it != OutputHandler::getInstance().getOutputVectorEnd(); ++it) 75 { 76 if (it->first <= this->getSoftDebugLevel()) 77 { 78 this->outputBuffer_ << it->second; 79 this->outputChanged(it->first); 80 } 81 } 82 83 // Register the shell as output listener 84 OutputHandler::getInstance().registerOutputListener(this); 84 85 } 85 86 86 87 Shell::~Shell() 87 88 { 88 OutputHandler::getOutStream().setOutputBuffer(0); 89 if (this->inputBuffer_) 90 this->inputBuffer_->destroy(); 89 OutputHandler::getInstance().unregisterOutputListener(this); 90 this->inputBuffer_->destroy(); 91 91 } 92 92 93 93 void Shell::setConfigValues() 94 94 { 95 SetConfigValue Generic(commandHistoryConfigFileType_,maxHistoryLength_, 100)95 SetConfigValue(maxHistoryLength_, 100) 96 96 .callback(this, &Shell::commandHistoryLengthChanged); 97 SetConfigValue Generic(commandHistoryConfigFileType_,historyOffset_, 0)97 SetConfigValue(historyOffset_, 0) 98 98 .callback(this, &Shell::commandHistoryOffsetChanged); 99 SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>()); 99 setConfigValueGeneric(this, &commandHistory_, ConfigFileType::CommandHistory, "Shell", "commandHistory_", std::vector<std::string>()); 100 101 #ifdef ORXONOX_RELEASE 102 const unsigned int defaultLevel = 1; 103 #else 104 const unsigned int defaultLevel = 3; 105 #endif 106 setConfigValueGeneric(this, &softDebugLevel_, ConfigFileType::Settings, "OutputHandler", "softDebugLevel" + this->consoleName_, defaultLevel) 107 .description("The maximal level of debug output shown in the Shell"); 108 this->setSoftDebugLevel(this->softDebugLevel_); 100 109 } 101 110 … … 121 130 { 122 131 this->inputBuffer_->registerListener(this, &Shell::inputChanged, true); 123 this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false); 124 this->inputBuffer_->registerListener(this, &Shell::hintandcomplete, '\t', true); 125 this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true); 126 this->inputBuffer_->registerListener(this, &Shell::deletechar, KeyCode::Delete); 127 this->inputBuffer_->registerListener(this, &Shell::exit, static_cast<char>(27), true); 128 this->inputBuffer_->registerListener(this, &Shell::cursor_right, KeyCode::Right); 129 this->inputBuffer_->registerListener(this, &Shell::cursor_left, KeyCode::Left); 130 this->inputBuffer_->registerListener(this, &Shell::cursor_end, KeyCode::End); 131 this->inputBuffer_->registerListener(this, &Shell::cursor_home, KeyCode::Home); 132 this->inputBuffer_->registerListener(this, &Shell::history_up, KeyCode::Up); 133 this->inputBuffer_->registerListener(this, &Shell::history_down, KeyCode::Down); 134 this->inputBuffer_->registerListener(this, &Shell::scroll_up, KeyCode::PageUp); 135 this->inputBuffer_->registerListener(this, &Shell::scroll_down, KeyCode::PageDown); 136 } 137 138 void Shell::clearShell() 139 { 140 Shell::getInstance().clearLines(); 141 } 142 132 this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false); 133 this->inputBuffer_->registerListener(this, &Shell::execute, '\n', false); 134 this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t', true); 135 this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true); 136 this->inputBuffer_->registerListener(this, &Shell::backspace, '\177', true); 137 this->inputBuffer_->registerListener(this, &Shell::exit, '\033', true); // escape 138 this->inputBuffer_->registerListener(this, &Shell::deleteChar, KeyCode::Delete); 139 this->inputBuffer_->registerListener(this, &Shell::cursorRight, KeyCode::Right); 140 this->inputBuffer_->registerListener(this, &Shell::cursorLeft, KeyCode::Left); 141 this->inputBuffer_->registerListener(this, &Shell::cursorEnd, KeyCode::End); 142 this->inputBuffer_->registerListener(this, &Shell::cursorHome, KeyCode::Home); 143 this->inputBuffer_->registerListener(this, &Shell::historyUp, KeyCode::Up); 144 this->inputBuffer_->registerListener(this, &Shell::historyDown, KeyCode::Down); 145 if (this->bScrollable_) 146 { 147 this->inputBuffer_->registerListener(this, &Shell::scrollUp, KeyCode::PageUp); 148 this->inputBuffer_->registerListener(this, &Shell::scrollDown, KeyCode::PageDown); 149 } 150 else 151 { 152 this->inputBuffer_->registerListener(this, &Shell::historySearchUp, KeyCode::PageUp); 153 this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown); 154 } 155 } 156 157 /* 143 158 void Shell::history() 144 159 { … … 146 161 147 162 for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i) 148 instance.add Line(instance.commandHistory_[i], -1);163 instance.addOutput(instance.commandHistory_[i] + '\n', -1); 149 164 for (unsigned int i = 0; i < instance.historyOffset_; ++i) 150 instance.addLine(instance.commandHistory_[i], -1); 151 } 165 instance.addOutput(instance.commandHistory_[i] + '\n', -1); 166 } 167 */ 152 168 153 169 void Shell::registerListener(ShellListener* listener) 154 170 { 155 this->listeners_. insert(this->listeners_.end(),listener);171 this->listeners_.push_back(listener); 156 172 } 157 173 … … 161 177 { 162 178 if ((*it) == listener) 163 this->listeners_.erase(it++);179 it = this->listeners_.erase(it); 164 180 else 165 181 ++it; … … 170 186 { 171 187 this->inputBuffer_->setCursorPosition(cursor); 172 SHELL_UPDATE_LISTENERS(cursorChanged); 173 } 174 175 void Shell::setInput(const std::string& input) 176 { 177 this->inputBuffer_->set(input); 178 this->inputChanged(); 179 } 180 181 void Shell::addLine(const std::string& line, int level) 182 { 183 int original_level = OutputHandler::getOutStream().getOutputLevel(); 184 OutputHandler::getOutStream().setOutputLevel(level); 185 186 if (!this->finishedLastLine_) 187 this->outputBuffer_ << std::endl; 188 189 this->outputBuffer_ << line << std::endl; 190 OutputHandler::getOutStream().setOutputLevel(original_level); 191 } 192 193 void Shell::clearLines() 194 { 195 this->lines_.clear(); 196 this->scrollIterator_ = this->lines_.begin(); 188 this->updateListeners<&ShellListener::cursorChanged>(); 189 } 190 191 void Shell::addOutput(const std::string& text, LineType type) 192 { 193 this->outputBuffer_ << text; 194 this->outputChanged(type); 195 } 196 197 void Shell::clearOutput() 198 { 199 this->outputLines_.clear(); 200 this->scrollIterator_ = this->outputLines_.begin(); 197 201 198 202 this->scrollPosition_ = 0; 199 this-> finishedLastLine_ = true;200 201 SHELL_UPDATE_LISTENERS(linesChanged);202 } 203 204 std::list<std::string>::const_iterator Shell::getNewestLineIterator() const203 this->bFinishedLastLine_ = true; 204 205 this->updateListeners<&ShellListener::linesChanged>(); 206 } 207 208 Shell::LineList::const_iterator Shell::getNewestLineIterator() const 205 209 { 206 210 if (this->scrollPosition_) 207 211 return this->scrollIterator_; 208 212 else 209 return this-> lines_.begin();210 } 211 212 std::list<std::string>::const_iterator Shell::getEndIterator() const213 { 214 return this-> lines_.end();213 return this->outputLines_.begin(); 214 } 215 216 Shell::LineList::const_iterator Shell::getEndIterator() const 217 { 218 return this->outputLines_.end(); 215 219 } 216 220 … … 222 226 } 223 227 224 std::stringShell::getFromHistory() const228 const std::string& Shell::getFromHistory() const 225 229 { 226 230 unsigned int index = mod(static_cast<int>(this->historyOffset_) - static_cast<int>(this->historyPosition_), this->maxHistoryLength_); … … 228 232 return this->commandHistory_[index]; 229 233 else 230 return ""; 231 } 232 233 void Shell::outputChanged() 234 { 235 std::string output; 236 bool newline; 234 return BLANKSTRING; 235 } 236 237 void Shell::outputChanged(int lineType) 238 { 239 bool newline = false; 237 240 do 238 241 { 239 newline = this->outputBuffer_.getLine(&output); 240 241 if (!newline && output == "") 242 std::string output; 243 std::getline(this->outputBuffer_, output); 244 245 bool eof = this->outputBuffer_.eof(); 246 bool fail = this->outputBuffer_.fail(); 247 if (eof) 248 this->outputBuffer_.flush(); 249 if (eof || fail) 250 this->outputBuffer_.clear(); 251 newline = (!eof && !fail); 252 253 if (!newline && output.empty()) 242 254 break; 243 255 244 if (this-> finishedLastLine_)256 if (this->bFinishedLastLine_) 245 257 { 246 if (this->bAddOutputLevel_) 247 output.insert(0, 1, static_cast<char>(OutputHandler::getOutStream().getOutputLevel())); 248 249 this->lines_.insert(this->lines_.begin(), output); 258 this->outputLines_.push_front(std::make_pair(output, static_cast<LineType>(lineType))); 250 259 251 260 if (this->scrollPosition_) 252 261 this->scrollPosition_++; 253 262 else 254 this->scrollIterator_ = this-> lines_.begin();255 256 this-> finishedLastLine_ = newline;263 this->scrollIterator_ = this->outputLines_.begin(); 264 265 this->bFinishedLastLine_ = newline; 257 266 258 267 if (!this->scrollPosition_) 259 { 260 SHELL_UPDATE_LISTENERS(lineAdded); 261 } 268 this->updateListeners<&ShellListener::lineAdded>(); 262 269 } 263 270 else 264 271 { 265 (*this->lines_.begin())+= output;266 this-> finishedLastLine_ = newline;267 SHELL_UPDATE_LISTENERS(onlyLastLineChanged);272 this->outputLines_.front().first += output; 273 this->bFinishedLastLine_ = newline; 274 this->updateListeners<&ShellListener::onlyLastLineChanged>(); 268 275 } 276 this->bFinishedLastLine_ = newline; 269 277 270 278 } while (newline); 271 279 } 272 280 273 void Shell::inputChanged() 274 { 275 SHELL_UPDATE_LISTENERS(inputChanged); 276 SHELL_UPDATE_LISTENERS(cursorChanged); 277 } 278 279 void Shell::execute() 280 { 281 this->addToHistory(this->inputBuffer_->get()); 282 this->addLine(this->inputBuffer_->get(), 0); 283 284 if (!CommandExecutor::execute(this->inputBuffer_->get())) 285 this->addLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1); 286 287 this->clear(); 288 } 289 290 void Shell::hintandcomplete() 291 { 292 this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get())); 293 this->addLine(CommandExecutor::hint(this->inputBuffer_->get()), -1); 294 295 this->inputChanged(); 296 } 297 298 void Shell::backspace() 299 { 300 this->inputBuffer_->removeBehindCursor(); 301 SHELL_UPDATE_LISTENERS(inputChanged); 302 SHELL_UPDATE_LISTENERS(cursorChanged); 303 } 304 305 void Shell::deletechar() 306 { 307 this->inputBuffer_->removeAtCursor(); 308 SHELL_UPDATE_LISTENERS(inputChanged); 309 } 310 311 void Shell::clear() 281 void Shell::clearInput() 312 282 { 313 283 this->inputBuffer_->clear(); 314 284 this->historyPosition_ = 0; 315 SHELL_UPDATE_LISTENERS(inputChanged); 316 SHELL_UPDATE_LISTENERS(cursorChanged); 317 } 318 319 void Shell::cursor_right() 285 this->updateListeners<&ShellListener::inputChanged>(); 286 this->updateListeners<&ShellListener::cursorChanged>(); 287 } 288 289 void Shell::setPromptPrefix(const std::string& str) 290 { 291 } 292 293 294 // ########################################## 295 // ### InputBuffer callback functions ### 296 // ########################################## 297 298 void Shell::inputChanged() 299 { 300 this->updateListeners<&ShellListener::inputChanged>(); 301 this->updateListeners<&ShellListener::cursorChanged>(); 302 } 303 304 void Shell::execute() 305 { 306 this->addToHistory(this->inputBuffer_->get()); 307 this->updateListeners<&ShellListener::executed>(); 308 309 if (!CommandExecutor::execute(this->inputBuffer_->get())) 310 { 311 this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\"." << std::endl; 312 this->outputChanged(Error); 313 } 314 315 this->clearInput(); 316 } 317 318 void Shell::hintAndComplete() 319 { 320 this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get())); 321 this->outputBuffer_ << CommandExecutor::hint(this->inputBuffer_->get()) << std::endl; 322 this->outputChanged(Hint); 323 324 this->inputChanged(); 325 } 326 327 void Shell::backspace() 328 { 329 this->inputBuffer_->removeBehindCursor(); 330 this->updateListeners<&ShellListener::inputChanged>(); 331 this->updateListeners<&ShellListener::cursorChanged>(); 332 } 333 334 void Shell::exit() 335 { 336 if (this->inputBuffer_->getSize() > 0) 337 { 338 this->clearInput(); 339 return; 340 } 341 342 this->clearInput(); 343 this->scrollPosition_ = 0; 344 this->scrollIterator_ = this->outputLines_.begin(); 345 346 this->updateListeners<&ShellListener::exit>(); 347 } 348 349 void Shell::deleteChar() 350 { 351 this->inputBuffer_->removeAtCursor(); 352 this->updateListeners<&ShellListener::inputChanged>(); 353 } 354 355 void Shell::cursorRight() 320 356 { 321 357 this->inputBuffer_->increaseCursor(); 322 SHELL_UPDATE_LISTENERS(cursorChanged);323 } 324 325 void Shell::cursor _left()358 this->updateListeners<&ShellListener::cursorChanged>(); 359 } 360 361 void Shell::cursorLeft() 326 362 { 327 363 this->inputBuffer_->decreaseCursor(); 328 SHELL_UPDATE_LISTENERS(cursorChanged);329 } 330 331 void Shell::cursor _end()364 this->updateListeners<&ShellListener::cursorChanged>(); 365 } 366 367 void Shell::cursorEnd() 332 368 { 333 369 this->inputBuffer_->setCursorToEnd(); 334 SHELL_UPDATE_LISTENERS(cursorChanged);335 } 336 337 void Shell::cursor _home()370 this->updateListeners<&ShellListener::cursorChanged>(); 371 } 372 373 void Shell::cursorHome() 338 374 { 339 375 this->inputBuffer_->setCursorToBegin(); 340 SHELL_UPDATE_LISTENERS(cursorChanged);341 } 342 343 void Shell::history _up()376 this->updateListeners<&ShellListener::cursorChanged>(); 377 } 378 379 void Shell::historyUp() 344 380 { 345 381 if (this->historyPosition_ < this->commandHistory_.size()) … … 350 386 } 351 387 352 void Shell::history _down()388 void Shell::historyDown() 353 389 { 354 390 if (this->historyPosition_ > 0) … … 359 395 } 360 396 361 void Shell::scroll_up() 362 { 363 if (this->scrollIterator_ != this->lines_.end()) 397 void Shell::historySearchUp() 398 { 399 if (this->historyPosition_ == this->historyOffset_) 400 return; 401 unsigned int cursorPosition = this->getCursorPosition(); 402 const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position 403 for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++) 404 { 405 if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive 406 { 407 this->historyPosition_ = newPos; 408 this->inputBuffer_->set(this->getFromHistory()); 409 this->setCursorPosition(cursorPosition); 410 return; 411 } 412 } 413 } 414 415 void Shell::historySearchDown() 416 { 417 if (this->historyPosition_ == 0) 418 return; 419 unsigned int cursorPosition = this->getCursorPosition(); 420 const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning 421 for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--) 422 { 423 if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$ 424 { 425 this->historyPosition_ = newPos; 426 this->inputBuffer_->set(this->getFromHistory()); 427 this->setCursorPosition(cursorPosition); 428 return; 429 } 430 } 431 } 432 433 void Shell::scrollUp() 434 { 435 if (this->scrollIterator_ != this->outputLines_.end()) 364 436 { 365 437 ++this->scrollIterator_; 366 438 ++this->scrollPosition_; 367 439 368 SHELL_UPDATE_LISTENERS(linesChanged);369 } 370 } 371 372 void Shell::scroll _down()373 { 374 if (this->scrollIterator_ != this-> lines_.begin())440 this->updateListeners<&ShellListener::linesChanged>(); 441 } 442 } 443 444 void Shell::scrollDown() 445 { 446 if (this->scrollIterator_ != this->outputLines_.begin()) 375 447 { 376 448 --this->scrollIterator_; 377 449 --this->scrollPosition_; 378 450 379 SHELL_UPDATE_LISTENERS(linesChanged); 380 } 381 } 382 383 void Shell::exit() 384 { 385 if (this->inputBuffer_->getSize() > 0) 386 { 387 this->clear(); 388 return; 389 } 390 391 this->clear(); 392 this->scrollPosition_ = 0; 393 this->scrollIterator_ = this->lines_.begin(); 394 395 SHELL_UPDATE_LISTENERS(exit); 451 this->updateListeners<&ShellListener::linesChanged>(); 452 } 396 453 } 397 454 }
Note: See TracChangeset
for help on using the changeset viewer.