diff options
author | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 13:16:53 +0200 |
---|---|---|
committer | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 17:57:26 +0200 |
commit | c63274342f1aaa3d1087c0df5ffdaccfd0afcd56 (patch) | |
tree | b04628f6c8c6768e2d5771737f3f13687cd0ed29 /3rdparty/python-console/Console.cpp | |
parent | 66670831b89d934ef00c47c0527137f6ec38a0b0 (diff) | |
download | nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.tar.gz nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.tar.bz2 nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.zip |
initial import of python-console
Diffstat (limited to '3rdparty/python-console/Console.cpp')
-rw-r--r-- | 3rdparty/python-console/Console.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/3rdparty/python-console/Console.cpp b/3rdparty/python-console/Console.cpp new file mode 100644 index 00000000..f9413542 --- /dev/null +++ b/3rdparty/python-console/Console.cpp @@ -0,0 +1,297 @@ +#include "Console.h" +#include "Interpreter.h" +#include "ColumnFormatter.h" + +#include <iostream> +#include <QKeyEvent> +#include <QFont> + +#include "Utils.h" + +const QString Console::PROMPT = ">>> "; +const QString Console::MULTILINE_PROMPT = "... "; +const QColor Console::NORMAL_COLOR = QColor::fromRgbF( 0, 0, 0 ); +const QColor Console::ERROR_COLOR = QColor::fromRgbF( 1.0, 0, 0 ); +const QColor Console::OUTPUT_COLOR = QColor::fromRgbF( 0, 0, 1.0 ); + +Console::Console( QWidget* parent ): + QTextEdit( parent ), + m_interpreter( new Interpreter ) +{ + QFont font; + font.setFamily("Courier New"); + setFont(font); + m_parseHelper.subscribe( this ); + displayPrompt( ); +} + +Console::~Console( ) +{ + delete m_interpreter; +} + +void Console::keyPressEvent( QKeyEvent* e ) +{ + switch ( e->key() ) + { + case Qt::Key_Return: + handleReturnKeyPress( ); + return; + + case Qt::Key_Tab: + autocomplete( ); + return; + + case Qt::Key_Backspace: + if ( ! canBackspace( ) ) + return; + break; + + case Qt::Key_Up: + previousHistory( ); + return; + + case Qt::Key_Down: + nextHistory( ); + return; + + case Qt::Key_Left: + if ( ! canGoLeft( ) ) + return; + } + + QTextEdit::keyPressEvent( e ); +} + +void Console::handleReturnKeyPress( ) +{ + if ( ! cursorIsOnInputLine( ) ) + { + return; + } + + QString line = getLine( ); + +#ifndef NDEBUG + std::cout << line.toStdString( ) << "\n"; +#endif + + m_parseHelper.process( line.toStdString( ) ); + if ( m_parseHelper.buffered( ) ) + { + append(""); + displayPrompt( ); + } + if ( line.size( ) ) + { + m_historyBuffer.push_back( line.toStdString( ) ); + m_historyIt = m_historyBuffer.end(); + } + moveCursorToEnd( ); +} + +void Console::parseEvent( const ParseMessage& message ) +{ + // handle invalid user input + if ( message.errorCode ) + { + setTextColor( ERROR_COLOR ); + append(message.message.c_str()); + + setTextColor( NORMAL_COLOR ); + append(""); + displayPrompt( ); + return; + } + + // interpret valid user input + int errorCode; + std::string res; + if ( message.message.size() ) + res = m_interpreter->interpret( message.message, &errorCode ); + if ( errorCode ) + { + setTextColor( ERROR_COLOR ); + } + else + { + setTextColor( OUTPUT_COLOR ); + } + + if ( res.size( ) ) + { + append(res.c_str()); + } + + setTextColor( NORMAL_COLOR ); + + // set up the next line on the console + append(""); + displayPrompt( ); +} + +QString Console::getLine( ) +{ + QTextCursor cursor = textCursor(); + cursor.movePosition( QTextCursor::StartOfLine ); + cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) ); + cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor ); + QString line = cursor.selectedText( ); + cursor.clearSelection( ); + return line; +} + +bool Console::cursorIsOnInputLine( ) +{ + int cursorBlock = textCursor( ).blockNumber( ); + QTextCursor bottomCursor = textCursor( ); + bottomCursor.movePosition( QTextCursor::End ); + int bottomBlock = bottomCursor.blockNumber( ); + return ( cursorBlock == bottomBlock ); +} + +bool Console::inputLineIsEmpty( ) +{ + QTextCursor bottomCursor = textCursor( ); + bottomCursor.movePosition( QTextCursor::End ); + int col = bottomCursor.columnNumber( ); + return ( col == Console::PROMPT.size( ) ); +} + +bool Console::canBackspace( ) +{ + if ( ! cursorIsOnInputLine( ) ) + { + return false; + } + + if ( inputLineIsEmpty( ) ) + { + return false; + } + + return true; +} + +bool Console::canGoLeft( ) +{ + if ( cursorIsOnInputLine( ) ) + { + QTextCursor bottomCursor = textCursor( ); + int col = bottomCursor.columnNumber( ); + return (col > Console::PROMPT.size( )); + } + return true; +} + +void Console::displayPrompt( ) +{ + QTextCursor cursor = textCursor(); + cursor.movePosition( QTextCursor::End ); + if ( m_parseHelper.buffered( ) ) + { + cursor.insertText( Console::MULTILINE_PROMPT ); + } + else + { + cursor.insertText( Console::PROMPT ); + } + cursor.movePosition( QTextCursor::EndOfLine ); +} + +void Console::autocomplete( ) +{ + if ( ! cursorIsOnInputLine( ) ) + return; + + QString line = getLine( ); + const std::list<std::string>& suggestions = + m_interpreter->suggest( line.toStdString( ) ); + if (suggestions.size() == 1) + { + line = suggestions.back().c_str(); + } + else + { + // try to complete to longest common prefix + std::string prefix = + LongestCommonPrefix(suggestions.begin(), suggestions.end()); + if (prefix.size() > line.size()) + { + line = prefix.c_str(); + } + else + { + ColumnFormatter fmt; + fmt.setItems(suggestions.begin(), suggestions.end()); + fmt.format(width() / 10); + setTextColor( OUTPUT_COLOR ); + const std::list<std::string>& formatted = fmt.formattedOutput(); + for (std::list<std::string>::const_iterator it = formatted.begin(); + it != formatted.end(); ++it) + { + append(it->c_str()); + } + std::cout << width() << "\n"; + setTextColor( NORMAL_COLOR ); + } + } + + // set up the next line on the console + append(""); + displayPrompt( ); + moveCursorToEnd( ); + cursor.insertText( line ); + moveCursorToEnd( ); +} + +void Console::previousHistory( ) +{ + if ( ! cursorIsOnInputLine( ) ) + return; + + if ( ! m_historyBuffer.size( ) ) + return; + + QTextCursor cursor = textCursor(); + cursor.movePosition( QTextCursor::StartOfLine ); + cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) ); + cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor ); + cursor.removeSelectedText( ); + if ( m_historyIt != m_historyBuffer.begin( ) ) + { + --m_historyIt; + } + cursor.insertText( m_historyIt->c_str() ); +} + +void Console::nextHistory( ) +{ + if ( ! cursorIsOnInputLine( ) ) + return; + + if ( ! m_historyBuffer.size( ) ) + return; + if ( m_historyIt == m_historyBuffer.end( ) ) + { + return; + } + QTextCursor cursor = textCursor(); + cursor.movePosition( QTextCursor::StartOfLine ); + cursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, Console::PROMPT.size( ) ); + cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor ); + cursor.removeSelectedText( ); + ++m_historyIt; + if ( m_historyIt == m_historyBuffer.end( ) ) + { + return; + } + cursor.insertText( m_historyIt->c_str() ); +} + +void Console::moveCursorToEnd( ) +{ + QTextCursor cursor = textCursor(); + cursor.movePosition( QTextCursor::End ); + setTextCursor( cursor ); +} |