Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 25, 2009, 1:18:03 PM (15 years ago)
Author:
dafrick
Message:

Merged presentation2 branch into pickup2 branch.

Location:
code/branches/pickup2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/pickup2

  • code/branches/pickup2/src/libraries/core/Shell.cc

    r5929 r6412  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
     
    3030
    3131#include "util/OutputHandler.h"
     32#include "util/StringUtils.h"
     33#include "util/SubString.h"
    3234#include "CommandExecutor.h"
    3335#include "CoreIncludes.h"
    3436#include "ConfigValueIncludes.h"
    35 #include "Core.h"
    3637#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()
    4138
    4239namespace orxonox
    4340{
    44     SetConsoleCommand(Shell, clearShell, true);
    45     SetConsoleCommand(Shell, history, true);
    46 
    4741    SetConsoleCommandShortcut(OutputHandler, log);
    4842    SetConsoleCommandShortcut(OutputHandler, error);
     
    5145    SetConsoleCommandShortcut(OutputHandler, debug);
    5246
    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    {
    6053        RegisterRootObject(Shell);
    6154
     
    6457        this->historyPosition_ = 0;
    6558        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();
    7262        this->configureInputBuffer();
    7363
    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_;
    8069
    8170        this->setConfigValues();
    8271
    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);
    8485    }
    8586
    8687    Shell::~Shell()
    8788    {
    88         OutputHandler::getOutStream().setOutputBuffer(0);
    89         if (this->inputBuffer_)
    90             this->inputBuffer_->destroy();
     89        OutputHandler::getInstance().unregisterOutputListener(this);
     90        this->inputBuffer_->destroy();
    9191    }
    9292
    9393    void Shell::setConfigValues()
    9494    {
    95         SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
     95        SetConfigValue(maxHistoryLength_, 100)
    9696            .callback(this, &Shell::commandHistoryLengthChanged);
    97         SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
     97        SetConfigValue(historyOffset_, 0)
    9898            .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_);
    100109    }
    101110
     
    121130    {
    122131        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    /*
    143158    void Shell::history()
    144159    {
     
    146161
    147162        for (unsigned int i = instance.historyOffset_; i < instance.commandHistory_.size(); ++i)
    148             instance.addLine(instance.commandHistory_[i], -1);
     163            instance.addOutput(instance.commandHistory_[i] + '\n', -1);
    149164        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    */
    152168
    153169    void Shell::registerListener(ShellListener* listener)
    154170    {
    155         this->listeners_.insert(this->listeners_.end(), listener);
     171        this->listeners_.push_back(listener);
    156172    }
    157173
     
    161177        {
    162178            if ((*it) == listener)
    163                 this->listeners_.erase(it++);
     179                it = this->listeners_.erase(it);
    164180            else
    165181                ++it;
     
    170186    {
    171187        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();
    197201
    198202        this->scrollPosition_ = 0;
    199         this->finishedLastLine_ = true;
    200 
    201         SHELL_UPDATE_LISTENERS(linesChanged);
    202     }
    203 
    204     std::list<std::string>::const_iterator Shell::getNewestLineIterator() const
     203        this->bFinishedLastLine_ = true;
     204
     205        this->updateListeners<&ShellListener::linesChanged>();
     206    }
     207
     208    Shell::LineList::const_iterator Shell::getNewestLineIterator() const
    205209    {
    206210        if (this->scrollPosition_)
    207211            return this->scrollIterator_;
    208212        else
    209             return this->lines_.begin();
    210     }
    211 
    212     std::list<std::string>::const_iterator Shell::getEndIterator() const
    213     {
    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();
    215219    }
    216220
     
    222226    }
    223227
    224     std::string Shell::getFromHistory() const
     228    const std::string& Shell::getFromHistory() const
    225229    {
    226230        unsigned int index = mod(static_cast<int>(this->historyOffset_) - static_cast<int>(this->historyPosition_), this->maxHistoryLength_);
     
    228232            return this->commandHistory_[index];
    229233        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;
    237240        do
    238241        {
    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())
    242254                break;
    243255
    244             if (this->finishedLastLine_)
     256            if (this->bFinishedLastLine_)
    245257            {
    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)));
    250259
    251260                if (this->scrollPosition_)
    252261                    this->scrollPosition_++;
    253262                else
    254                     this->scrollIterator_ = this->lines_.begin();
    255 
    256                 this->finishedLastLine_ = newline;
     263                    this->scrollIterator_ = this->outputLines_.begin();
     264
     265                this->bFinishedLastLine_ = newline;
    257266
    258267                if (!this->scrollPosition_)
    259                 {
    260                     SHELL_UPDATE_LISTENERS(lineAdded);
    261                 }
     268                    this->updateListeners<&ShellListener::lineAdded>();
    262269            }
    263270            else
    264271            {
    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>();
    268275            }
     276            this->bFinishedLastLine_ = newline;
    269277
    270278        } while (newline);
    271279    }
    272280
    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()
    312282    {
    313283        this->inputBuffer_->clear();
    314284        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()
    320356    {
    321357        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()
    326362    {
    327363        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()
    332368    {
    333369        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()
    338374    {
    339375        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()
    344380    {
    345381        if (this->historyPosition_ < this->commandHistory_.size())
     
    350386    }
    351387
    352     void Shell::history_down()
     388    void Shell::historyDown()
    353389    {
    354390        if (this->historyPosition_ > 0)
     
    359395    }
    360396
    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())
    364436        {
    365437            ++this->scrollIterator_;
    366438            ++this->scrollPosition_;
    367439
    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())
    375447        {
    376448            --this->scrollIterator_;
    377449            --this->scrollPosition_;
    378450
    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        }
    396453    }
    397454}
Note: See TracChangeset for help on using the changeset viewer.