Commit afb5d04b authored by Nikita Sirgienko's avatar Nikita Sirgienko

[T9024] Improve tabulation handling in Command Entries. Now the tabulation...

[T9024] Improve tabulation handling in Command Entries. Now the tabulation works like tabulation in code editors.
- Tabulation in the begin of line works propper
- Added backward tabulation
- Added multiline tabulation
Bug: 418358
parent 17f9a1f2
Pipeline #25226 failed with stage
in 1 minute and 54 seconds
......@@ -372,7 +372,7 @@ CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantLi
QAction* showCompletion = new QAction(i18n("Show Completion"), collection);
collection->addAction(QLatin1String("show_completion"), showCompletion);
QList<QKeySequence> showCompletionShortcuts;
showCompletionShortcuts << Qt::Key_Tab << Qt::CTRL + Qt::Key_Space;
showCompletionShortcuts << Qt::CTRL + Qt::Key_Space; // No Tab, because the tab handeled by entries itself
collection->setDefaultShortcuts(showCompletion, showCompletionShortcuts);
connect(showCompletion, SIGNAL(triggered()), m_worksheet, SLOT(showCompletion()));
m_editActions.push_back(showCompletion);
......
......@@ -42,6 +42,7 @@
#include <QPropertyAnimation>
#include <QJsonArray>
#include <QJsonObject>
#include <QTextDocumentFragment>
#include <KLocalizedString>
#include <KColorScheme>
......@@ -91,8 +92,8 @@ CommandEntry::CommandEntry(Worksheet* worksheet) : WorksheetEntry(worksheet),
connect(&m_controlElement, &WorksheetControlItem::doubleClick, this, &CommandEntry::changeResultCollapsingAction);
connect(m_commandItem, &WorksheetTextItem::tabPressed, this, &CommandEntry::showCompletion);
connect(m_commandItem, &WorksheetTextItem::backtabPressed, this, &CommandEntry::selectPreviousCompletion);
connect(m_commandItem, &WorksheetTextItem::tabPressed, this, &CommandEntry::handleTabPress);
connect(m_commandItem, &WorksheetTextItem::backtabPressed, this, &CommandEntry::handleBacktabPress);
connect(m_commandItem, &WorksheetTextItem::applyCompletion, this, &CommandEntry::applySelectedCompletion);
connect(m_commandItem, &WorksheetTextItem::execute, this, [=]() { evaluate();} );
connect(m_commandItem, &WorksheetTextItem::moveToPrevious, this, &CommandEntry::moveToPreviousItem);
......@@ -610,42 +611,133 @@ QJsonValue CommandEntry::toJupyterJson()
return entry;
}
void CommandEntry::showCompletion()
void CommandEntry::handleTabPress()
{
const QString line = currentLine();
const QString& line = currentLine();
if(!worksheet()->completionEnabled() || line.trimmed().isEmpty())
// When the auto completion is disabled, we insert 'Tab' and exit immediately
// When the auto completion is enabled, the logic is more complicated
if(!worksheet()->completionEnabled())
{
if (m_commandItem->hasFocus())
m_commandItem->insertTab();
return;
} else if (isShowingCompletionPopup()) {
QString comp = m_completionObject->completion();
qDebug() << "command" << m_completionObject->command();
qDebug() << "completion" << comp;
if (comp != m_completionObject->command()
|| !m_completionObject->hasMultipleMatches()) {
if (m_completionObject->hasMultipleMatches()) {
completeCommandTo(comp, PreliminaryCompletion);
} else {
completeCommandTo(comp, FinalCompletion);
m_completionBox->hide();
}
if (isShowingCompletionPopup())
handleExistedCompletionBox();
else
{
QTextCursor cursor = m_commandItem->textCursor();
int p = m_commandItem->textCursor().positionInBlock();
if (cursor.hasSelection())
{
int count = 1 + cursor.selectedText().count(QChar(0x2029));
cursor.setPosition(cursor.selectionEnd());
cursor.beginEditBlock();
for (int i = 0; i < count; i++)
{
cursor.movePosition(QTextCursor::StartOfLine);
cursor.insertText(QLatin1String(" "));
cursor.movePosition(QTextCursor::StartOfLine);
cursor.movePosition(QTextCursor::PreviousCharacter);
}
} else {
m_completionBox->down();
cursor.endEditBlock();
}
} else {
else if(line.left(p).trimmed().isEmpty())
{
if (m_commandItem->hasFocus())
m_commandItem->insertTab();
}
else
makeCompletion(line, p);
}
}
void CommandEntry::showCompletion()
{
if(!worksheet()->completionEnabled())
return;
if (isShowingCompletionPopup())
handleExistedCompletionBox();
else
{
int p = m_commandItem->textCursor().positionInBlock();
Cantor::CompletionObject* tco=worksheet()->session()->completionFor(line, p);
if(tco)
setCompletion(tco);
makeCompletion(currentLine(), p);
}
}
void CommandEntry::handleExistedCompletionBox()
{
QString comp = m_completionObject->completion();
if (comp != m_completionObject->command() || !m_completionObject->hasMultipleMatches())
{
if (m_completionObject->hasMultipleMatches())
completeCommandTo(comp, PreliminaryCompletion);
else
{
completeCommandTo(comp, FinalCompletion);
m_completionBox->hide();
}
}
else
{
m_completionBox->down();
}
}
void CommandEntry::selectPreviousCompletion()
void CommandEntry::makeCompletion(const QString& line, int position)
{
Cantor::CompletionObject* tco=worksheet()->session()->completionFor(line, position);
if(tco)
setCompletion(tco);
}
void CommandEntry::handleBacktabPress()
{
QTextCursor cursor = m_commandItem->textCursor();
if (isShowingCompletionPopup())
m_completionBox->up();
else if (cursor.hasSelection())
{
int count = 1 + cursor.selectedText().count(QChar(0x2029));
cursor.setPosition(cursor.selectionEnd());
cursor.beginEditBlock();
for (int i = 0; i < count; i++)
{
const QString& line = cursor.block().text();
cursor.movePosition(QTextCursor::StartOfLine);
int counter = 0;
// 4 spaces is Cantor tabulation size, so we remove also 4 characters or less
while (cursor.positionInBlock() < line.length() && line[cursor.positionInBlock()] == QLatin1Char(' ') && counter < 4)
{
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
counter++;
}
cursor.removeSelectedText();
cursor.movePosition(QTextCursor::PreviousCharacter);
}
cursor.endEditBlock();
}
else
{
const QString& line = currentLine();
if (line.length() >= 4)
{
cursor.movePosition(QTextCursor::StartOfLine);
int counter = 0;
// 4 spaces is Cantor tabulation size, so we remove also 4 characters or less
while (cursor.positionInBlock() < line.length() && line[cursor.positionInBlock()] == QLatin1Char(' ') && counter < 4)
{
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
counter++;
}
cursor.removeSelectedText();
}
}
}
QString CommandEntry::toPlain(const QString& commandSep, const QString& commentStartingSeq, const QString& commentEndingSeq)
......
......@@ -105,7 +105,8 @@ class CommandEntry : public WorksheetEntry
void addToExecution();
void showCompletion() override;
void selectPreviousCompletion();
void handleTabPress();
void handleBacktabPress();
void updateEntry() override;
void updatePrompt(const QString& postfix = CommandEntry::Prompt);
void expressionChangedStatus(Cantor::Expression::Status status);
......@@ -133,6 +134,8 @@ class CommandEntry : public WorksheetEntry
QPoint getPopupPosition();
QPoint toGlobalPosition(QPointF localPos);
void initMenus();
void handleExistedCompletionBox();
void makeCompletion(const QString& line, int position);
private:
enum CompletionMode {
......
......@@ -88,14 +88,14 @@ void CompletionObject::setLine(const QString& line, int index)
d->parenCompletion = false;
d->line = line;
if (index < 0)
index = line.length();
index = line.length();
if (index > 1 && line[index-1] == QLatin1Char('(')) {
--index; // move before the parenthesis
d->parenCompletion = true; // but remember it was there
--index; // move before the parenthesis
d->parenCompletion = true; // but remember it was there
}
int cmd_index = locateIdentifier(line, index-1);
if (cmd_index < 0)
cmd_index = index;
cmd_index = index;
d->position=cmd_index;
d->command=line.mid(cmd_index, index-cmd_index);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment