12 #include <ui_PythonREPL.h>
35 if (
event->type() == QEvent::KeyPress)
37 auto *keyEvent =
static_cast<QKeyEvent *
>(
event);
38 if (keyEvent->modifiers() & Qt::ShiftModifier &&
39 (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return))
44 QTextCursor cursor = m_repl->
codeEdit()->textCursor();
46 switch (keyEvent->key())
59 const int lastCharPos = m_repl->
codeEdit()->document()->characterCount() - 2;
60 if (m_repl->
codeEdit()->document()->characterAt(lastCharPos) == QLatin1Char(
':'))
66 QString pythonCode = m_repl->
codeEdit()->toPlainText();
70 m_repl->m_history.
add(std::move(pythonCode));
74 case Qt::Key_Backspace:
79 return QObject::eventFilter(obj,
event);
88 return QObject::eventFilter(obj,
event);
92 if (cursor.blockNumber() < m_repl->
codeEdit()->blockCount() - 1)
94 return QObject::eventFilter(obj,
event);
96 else if (!m_repl->m_history.
empty())
99 m_repl->
codeEdit()->insertPlainText(m_repl->m_history.
newer());
103 if (cursor.blockNumber() > 0)
105 return QObject::eventFilter(obj,
event);
107 else if (!m_repl->m_history.
empty())
110 m_repl->
codeEdit()->insertPlainText(m_repl->m_history.
older());
114 m_repl->
codeEdit()->moveCursor(QTextCursor::StartOfLine);
115 m_repl->
codeEdit()->moveCursor(QTextCursor::NextWord);
119 int posDiff =
replArrows.size() - cursor.columnNumber();
122 cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, posDiff);
123 m_repl->
codeEdit()->setTextCursor(cursor);
125 return QObject::eventFilter(obj,
event);
131 return QObject::eventFilter(obj,
event);
138 : m_interpreter(interpreter), QMainWindow(parent), m_ui(new Ui_PythonREPL), m_state()
153 return m_ui->codeEdit;
158 return m_ui->outputDisplay;
166 const auto codeEditorHeight =
static_cast<int>(
height() * 0.25);
167 m_ui->splitter->setSizes({
height() - codeEditorHeight, codeEditorHeight});
170 codeEdit()->installEventFilter(keyPressEater);
175 QFont font(
"Monospace");
176 font.setStyleHint(QFont::TypeWriter);
180 connect(m_ui->toolBar->actions().at(0), &QAction::triggered,
this, &
PythonRepl::reset);
186 m_ui->outputDisplay->clear();
202 auto iter = pythonCode.begin() +
replArrows.size();
203 while (iter < pythonCode.end())
207 const char c = iter->toLatin1();
229 m_commands.push_back(cmd);
230 m_current = m_commands.rbegin();
235 if (m_current == m_commands.rend())
237 m_current = m_commands.rbegin();
239 const QString ¤t = *m_current;
246 if (m_current == m_commands.rend())
251 const QString ¤t = *m_current;
252 if (m_current == m_commands.rbegin())
254 m_current = m_commands.rend();
265 return m_commands.empty();
270 return m_commands.size();
static const QString continuationDots(QStringLiteral("... "))
static const QString replArrows(QStringLiteral(">>> "))
void qtCompatSetTabStopWidth(QPlainTextEdit *edit, int width)
#define QTCOMPAT_FONTMETRICS_WIDTH(fm, text)
Class used by the REPL to handle key presses.
KeyPressEater(PythonRepl *repl, QObject *parent=nullptr)
bool eventFilter(QObject *obj, QEvent *event) override
void executeStatementWithState(const std::string &code, QListWidget *output, PythonInterpreter::State &state)
Homemade REPL (Read Print Eval Loop)
PythonRepl(PythonInterpreter *interpreter, QMainWindow *parent=nullptr)
void importNeededPackages()
QListWidget * outputDisplay()
QPlainTextEdit * codeEdit()
~PythonRepl() noexcept override
void executeCode(const QString &pythonCode)