Changeset 6105 for code/trunk/src/libraries/core/Shell.cc
- Timestamp:
- Nov 20, 2009, 4:55:40 PM (14 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/console (added) merged: 5941,5945,5968-5975,5983,5985-5986,5991-5992,5994-5996,5998,6000,6004-6007,6010-6017,6034,6037,6041,6043-6044,6089,6103-6104
- Property svn:mergeinfo changed
-
code/trunk/src/libraries/core/Shell.cc
r5929 r6105 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, bool bPrependOutputLevel) 48 : OutputListener(consoleName) 49 , inputBuffer_(new InputBuffer()) 50 , consoleName_(consoleName) 51 , bPrependOutputLevel_(bPrependOutputLevel) 52 , bScrollable_(bScrollable) 53 { 60 54 RegisterRootObject(Shell); 61 55 … … 64 58 this->historyPosition_ = 0; 65 59 this->historyOffset_ = 0; 66 this->finishedLastLine_ = true; 67 this->bAddOutputLevel_ = false; 68 69 this->clearLines(); 70 71 this->inputBuffer_ = new InputBuffer(); 60 this->bFinishedLastLine_ = true; 61 62 this->clearOutput(); 72 63 this->configureInputBuffer(); 73 74 this->outputBuffer_.registerListener(this);75 OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);76 64 77 65 // Get a config file for the command history … … 79 67 ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini"); 80 68 69 // Use a stringstream object to buffer the output and get it line by line in update() 70 this->outputStream_ = &this->outputBuffer_; 71 81 72 this->setConfigValues(); 82 73 83 Core::setSoftDebugLevel(OutputHandler::LD_Shell, level); 74 // Get the previous output and add it to the Shell 75 for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin(); 76 it != OutputHandler::getInstance().getOutputVectorEnd(); ++it) 77 { 78 if (it->first <= this->getSoftDebugLevel()) 79 { 80 this->outputBuffer_ << it->second; 81 this->outputChanged(it->first); 82 } 83 } 84 85 // Register the shell as output listener 86 OutputHandler::getInstance().registerOutputListener(this); 84 87 } 85 88 86 89 Shell::~Shell() 87 90 { 88 OutputHandler::getOutStream().setOutputBuffer(0); 89 if (this->inputBuffer_) 90 this->inputBuffer_->destroy(); 91 OutputHandler::getInstance().unregisterOutputListener(this); 92 this->inputBuffer_->destroy(); 91 93 } 92 94 93 95 void Shell::setConfigValues() 94 96 { 95 SetConfigValue Generic(commandHistoryConfigFileType_,maxHistoryLength_, 100)97 SetConfigValue(maxHistoryLength_, 100) 96 98 .callback(this, &Shell::commandHistoryLengthChanged); 97 SetConfigValue Generic(commandHistoryConfigFileType_,historyOffset_, 0)99 SetConfigValue(historyOffset_, 0) 98 100 .callback(this, &Shell::commandHistoryOffsetChanged); 99 101 SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>()); 102 103 #ifdef ORXONOX_RELEASE 104 const unsigned int defaultLevel = 1; 105 #else 106 const unsigned int defaultLevel = 3; 107 #endif 108 SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevel_, "softDebugLevel" + this->consoleName_, "OutputHandler", defaultLevel) 109 .description("The maximal level of debug output shown in the Shell"); 110 this->setSoftDebugLevel(this->softDebugLevel_); 100 111 } 101 112 … … 121 132 { 122 133 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 134 this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false); 135 this->inputBuffer_->registerListener(this, &Shell::execute, '\n', false); 136 this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t', true); 137 this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true); 138 this->inputBuffer_->registerListener(this, &Shell::backspace, '\177', true); 139 this->inputBuffer_->registerListener(this, &Shell::exit, '\033', true); // escape 140 this->inputBuffer_->registerListener(this, &Shell::deleteChar, KeyCode::Delete); 141 this->inputBuffer_->registerListener(this, &Shell::cursorRight, KeyCode::Right); 142 this->inputBuffer_->registerListener(this, &Shell::cursorLeft, KeyCode::Left); 143 this->inputBuffer_->registerListener(this, &Shell::cursorEnd, KeyCode::End); 144 this->inputBuffer_->registerListener(this, &Shell::cursorHome, KeyCode::Home); 145 this->inputBuffer_->registerListener(this, &Shell::historyUp, KeyCode::Up); 146 this->inputBuffer_->registerListener(this, &Shell::historyDown, KeyCode::Down); 147 if (this->bScrollable_) 148 { 149 this->inputBuffer_->registerListener(this, &Shell::scrollUp, KeyCode::PageUp); 150 this->inputBuffer_->registerListener(this, &Shell::scrollDown, KeyCode::PageDown); 151 } 152 else 153 { 154 this->inputBuffer_->registerListener(this, &Shell::historySearchUp, KeyCode::PageUp); 155 this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown); 156 } 157 } 158 159 /* 143 160 void Shell::history() 144 161 { … … 146 163 147 164 for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i) 148 instance.add Line(instance.commandHistory_[i], -1);165 instance.addOutputLine(instance.commandHistory_[i], -1); 149 166 for (unsigned int i = 0; i < instance.historyOffset_; ++i) 150 instance.addLine(instance.commandHistory_[i], -1); 151 } 167 instance.addOutputLine(instance.commandHistory_[i], -1); 168 } 169 */ 152 170 153 171 void Shell::registerListener(ShellListener* listener) 154 172 { 155 this->listeners_. insert(this->listeners_.end(),listener);173 this->listeners_.push_back(listener); 156 174 } 157 175 … … 161 179 { 162 180 if ((*it) == listener) 163 this->listeners_.erase(it++);181 it = this->listeners_.erase(it); 164 182 else 165 183 ++it; … … 170 188 { 171 189 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(); 190 this->updateListeners<&ShellListener::cursorChanged>(); 191 } 192 193 void Shell::addOutputLine(const std::string& line, int level) 194 { 195 // Make sure we really only have one line per line (no new lines!) 196 SubString lines(line, '\n'); 197 for (unsigned i = 0; i < lines.size(); ++i) 198 { 199 if (level <= this->softDebugLevel_) 200 this->outputLines_.push_front(lines[i]); 201 this->updateListeners<&ShellListener::lineAdded>(); 202 } 203 } 204 205 void Shell::clearOutput() 206 { 207 this->outputLines_.clear(); 208 this->scrollIterator_ = this->outputLines_.begin(); 197 209 198 210 this->scrollPosition_ = 0; 199 this-> finishedLastLine_ = true;200 201 SHELL_UPDATE_LISTENERS(linesChanged);211 this->bFinishedLastLine_ = true; 212 213 this->updateListeners<&ShellListener::linesChanged>(); 202 214 } 203 215 … … 207 219 return this->scrollIterator_; 208 220 else 209 return this-> lines_.begin();221 return this->outputLines_.begin(); 210 222 } 211 223 212 224 std::list<std::string>::const_iterator Shell::getEndIterator() const 213 225 { 214 return this-> lines_.end();226 return this->outputLines_.end(); 215 227 } 216 228 … … 231 243 } 232 244 233 void Shell::outputChanged() 234 { 235 std::string output; 236 bool newline; 245 void Shell::outputChanged(int level) 246 { 247 bool newline = false; 237 248 do 238 249 { 239 newline = this->outputBuffer_.getLine(&output); 250 std::string output; 251 std::getline(this->outputBuffer_, output); 252 253 bool eof = this->outputBuffer_.eof(); 254 bool fail = this->outputBuffer_.fail(); 255 if (eof) 256 this->outputBuffer_.flush(); 257 if (eof || fail) 258 this->outputBuffer_.clear(); 259 newline = (!eof && !fail); 240 260 241 261 if (!newline && output == "") 242 262 break; 243 263 244 if (this-> finishedLastLine_)264 if (this->bFinishedLastLine_) 245 265 { 246 if (this->b AddOutputLevel_)247 output.insert(0, 1, static_cast<char>( OutputHandler::getOutStream().getOutputLevel()));248 249 this-> lines_.insert(this->lines_.begin(),output);266 if (this->bPrependOutputLevel_) 267 output.insert(0, 1, static_cast<char>(level)); 268 269 this->outputLines_.push_front(output); 250 270 251 271 if (this->scrollPosition_) 252 272 this->scrollPosition_++; 253 273 else 254 this->scrollIterator_ = this-> lines_.begin();255 256 this-> finishedLastLine_ = newline;274 this->scrollIterator_ = this->outputLines_.begin(); 275 276 this->bFinishedLastLine_ = newline; 257 277 258 278 if (!this->scrollPosition_) 259 279 { 260 SHELL_UPDATE_LISTENERS(lineAdded);280 this->updateListeners<&ShellListener::lineAdded>(); 261 281 } 262 282 } 263 283 else 264 284 { 265 (*this-> lines_.begin()) += output;266 this-> finishedLastLine_ = newline;267 SHELL_UPDATE_LISTENERS(onlyLastLineChanged);285 (*this->outputLines_.begin()) += output; 286 this->bFinishedLastLine_ = newline; 287 this->updateListeners<&ShellListener::onlyLastLineChanged>(); 268 288 } 269 289 … … 271 291 } 272 292 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() 293 void Shell::clearInput() 312 294 { 313 295 this->inputBuffer_->clear(); 314 296 this->historyPosition_ = 0; 315 SHELL_UPDATE_LISTENERS(inputChanged); 316 SHELL_UPDATE_LISTENERS(cursorChanged); 317 } 318 319 void Shell::cursor_right() 297 this->updateListeners<&ShellListener::inputChanged>(); 298 this->updateListeners<&ShellListener::cursorChanged>(); 299 } 300 301 void Shell::setPromptPrefix(const std::string& str) 302 { 303 } 304 305 306 // ########################################## 307 // ### InputBuffer callback functions ### 308 // ########################################## 309 310 void Shell::inputChanged() 311 { 312 this->updateListeners<&ShellListener::inputChanged>(); 313 this->updateListeners<&ShellListener::cursorChanged>(); 314 } 315 316 void Shell::execute() 317 { 318 this->addToHistory(this->inputBuffer_->get()); 319 this->updateListeners<&ShellListener::executed>(); 320 321 if (!CommandExecutor::execute(this->inputBuffer_->get())) 322 this->addOutputLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1); 323 324 this->clearInput(); 325 } 326 327 void Shell::hintAndComplete() 328 { 329 this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get())); 330 this->addOutputLine(CommandExecutor::hint(this->inputBuffer_->get()), -1); 331 332 this->inputChanged(); 333 } 334 335 void Shell::backspace() 336 { 337 this->inputBuffer_->removeBehindCursor(); 338 this->updateListeners<&ShellListener::inputChanged>(); 339 this->updateListeners<&ShellListener::cursorChanged>(); 340 } 341 342 void Shell::exit() 343 { 344 if (this->inputBuffer_->getSize() > 0) 345 { 346 this->clearInput(); 347 return; 348 } 349 350 this->clearInput(); 351 this->scrollPosition_ = 0; 352 this->scrollIterator_ = this->outputLines_.begin(); 353 354 this->updateListeners<&ShellListener::exit>(); 355 } 356 357 void Shell::deleteChar() 358 { 359 this->inputBuffer_->removeAtCursor(); 360 this->updateListeners<&ShellListener::inputChanged>(); 361 } 362 363 void Shell::cursorRight() 320 364 { 321 365 this->inputBuffer_->increaseCursor(); 322 SHELL_UPDATE_LISTENERS(cursorChanged);323 } 324 325 void Shell::cursor _left()366 this->updateListeners<&ShellListener::cursorChanged>(); 367 } 368 369 void Shell::cursorLeft() 326 370 { 327 371 this->inputBuffer_->decreaseCursor(); 328 SHELL_UPDATE_LISTENERS(cursorChanged);329 } 330 331 void Shell::cursor _end()372 this->updateListeners<&ShellListener::cursorChanged>(); 373 } 374 375 void Shell::cursorEnd() 332 376 { 333 377 this->inputBuffer_->setCursorToEnd(); 334 SHELL_UPDATE_LISTENERS(cursorChanged);335 } 336 337 void Shell::cursor _home()378 this->updateListeners<&ShellListener::cursorChanged>(); 379 } 380 381 void Shell::cursorHome() 338 382 { 339 383 this->inputBuffer_->setCursorToBegin(); 340 SHELL_UPDATE_LISTENERS(cursorChanged);341 } 342 343 void Shell::history _up()384 this->updateListeners<&ShellListener::cursorChanged>(); 385 } 386 387 void Shell::historyUp() 344 388 { 345 389 if (this->historyPosition_ < this->commandHistory_.size()) … … 350 394 } 351 395 352 void Shell::history _down()396 void Shell::historyDown() 353 397 { 354 398 if (this->historyPosition_ > 0) … … 359 403 } 360 404 361 void Shell::scroll_up() 362 { 363 if (this->scrollIterator_ != this->lines_.end()) 405 void Shell::historySearchUp() 406 { 407 if (this->historyPosition_ == this->historyOffset_) 408 return; 409 unsigned int cursorPosition = this->getCursorPosition(); 410 std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position 411 for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++) 412 { 413 if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive 414 { 415 this->historyPosition_ = newPos; 416 this->inputBuffer_->set(this->getFromHistory()); 417 this->setCursorPosition(cursorPosition); 418 return; 419 } 420 } 421 } 422 423 void Shell::historySearchDown() 424 { 425 if (this->historyPosition_ == 0) 426 return; 427 unsigned int cursorPosition = this->getCursorPosition(); 428 std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning 429 for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--) 430 { 431 if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$ 432 { 433 this->historyPosition_ = newPos; 434 this->inputBuffer_->set(this->getFromHistory()); 435 this->setCursorPosition(cursorPosition); 436 return; 437 } 438 } 439 } 440 441 void Shell::scrollUp() 442 { 443 if (this->scrollIterator_ != this->outputLines_.end()) 364 444 { 365 445 ++this->scrollIterator_; 366 446 ++this->scrollPosition_; 367 447 368 SHELL_UPDATE_LISTENERS(linesChanged);369 } 370 } 371 372 void Shell::scroll _down()373 { 374 if (this->scrollIterator_ != this-> lines_.begin())448 this->updateListeners<&ShellListener::linesChanged>(); 449 } 450 } 451 452 void Shell::scrollDown() 453 { 454 if (this->scrollIterator_ != this->outputLines_.begin()) 375 455 { 376 456 --this->scrollIterator_; 377 457 --this->scrollPosition_; 378 458 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); 459 this->updateListeners<&ShellListener::linesChanged>(); 460 } 396 461 } 397 462 }
Note: See TracChangeset
for help on using the changeset viewer.