FakeVim: handle keyboard selection in command buffer

Change-Id: I6a1f605fc77b9af596ee60c5f98e1b3252333284
Reviewed-by: Lukas Holecek <hluk@email.cz>
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2012-10-20 18:48:37 +02:00
parent 033f211a10
commit a570e7327f
3 changed files with 75 additions and 42 deletions

View File

@@ -1093,25 +1093,26 @@ const QString &History::move(const QStringRef &prefix, int skip)
class CommandBuffer class CommandBuffer
{ {
public: public:
CommandBuffer() : m_pos(0), m_userPos(0), m_historyAutoSave(true) {} CommandBuffer() : m_pos(0), m_anchor(0), m_userPos(0), m_historyAutoSave(true) {}
void setPrompt(const QChar &prompt) { m_prompt = prompt; } void setPrompt(const QChar &prompt) { m_prompt = prompt; }
void setContents(const QString &s) { m_buffer = s; m_pos = s.size(); } void setContents(const QString &s) { m_buffer = s; m_anchor = m_pos = s.size(); }
void setContents(const QString &s, int pos) { m_buffer = s; m_pos = m_userPos = pos; } void setContents(const QString &s, int pos) { m_buffer = s; m_anchor = m_pos = m_userPos = pos; }
QStringRef userContents() const { return m_buffer.leftRef(m_userPos); } QStringRef userContents() const { return m_buffer.leftRef(m_userPos); }
const QChar &prompt() const { return m_prompt; } const QChar &prompt() const { return m_prompt; }
const QString &contents() const { return m_buffer; } const QString &contents() const { return m_buffer; }
bool isEmpty() const { return m_buffer.isEmpty(); } bool isEmpty() const { return m_buffer.isEmpty(); }
int cursorPos() const { return m_pos; } int cursorPos() const { return m_pos; }
int anchorPos() const { return m_anchor; }
void insertChar(QChar c) { m_buffer.insert(m_pos++, c); m_userPos = m_pos; } void insertChar(QChar c) { m_buffer.insert(m_pos++, c); m_anchor = m_userPos = m_pos; }
void insertText(const QString &s) void insertText(const QString &s)
{ {
m_buffer.insert(m_pos, s); m_userPos = m_pos = m_pos + s.size(); m_buffer.insert(m_pos, s); m_anchor = m_userPos = m_pos = m_pos + s.size();
} }
void deleteChar() { if (m_pos) m_buffer.remove(--m_pos, 1); m_userPos = m_pos; } void deleteChar() { if (m_pos) m_buffer.remove(--m_pos, 1); m_anchor = m_userPos = m_pos; }
void moveLeft() { if (m_pos) m_userPos = --m_pos; } void moveLeft() { if (m_pos) m_userPos = --m_pos; }
void moveRight() { if (m_pos < m_buffer.size()) m_userPos = ++m_pos; } void moveRight() { if (m_pos < m_buffer.size()) m_userPos = ++m_pos; }
@@ -1132,7 +1133,7 @@ public:
if (m_historyAutoSave) if (m_historyAutoSave)
historyPush(); historyPush();
m_buffer.clear(); m_buffer.clear();
m_userPos = m_pos = 0; m_anchor = m_userPos = m_pos = 0;
} }
QString display() const QString display() const
@@ -1150,22 +1151,55 @@ public:
return msg; return msg;
} }
void deleteSelected()
{
if (m_pos < m_anchor) {
m_buffer.remove(m_pos, m_anchor - m_pos);
m_anchor = m_pos;
} else {
m_buffer.remove(m_anchor, m_pos - m_anchor);
m_pos = m_anchor;
}
}
bool handleInput(const Input &input) bool handleInput(const Input &input)
{ {
if (input.isKey(Key_Left)) { if (input.isShift(Key_Left)) {
moveLeft(); moveLeft();
} else if (input.isShift(Key_Right)) {
moveRight();
} else if (input.isShift(Key_Home)) {
moveStart();
} else if (input.isShift(Key_End)) {
moveEnd();
} else if (input.isKey(Key_Left)) {
moveLeft();
m_anchor = m_pos;
} else if (input.isKey(Key_Right)) { } else if (input.isKey(Key_Right)) {
moveRight(); moveRight();
m_anchor = m_pos;
} else if (input.isKey(Key_Home)) { } else if (input.isKey(Key_Home)) {
moveStart(); moveStart();
m_anchor = m_pos;
} else if (input.isKey(Key_End)) { } else if (input.isKey(Key_End)) {
moveEnd(); moveEnd();
m_anchor = m_pos;
} else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
historyUp();
} else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) {
historyDown();
} else if (input.isKey(Key_Delete)) { } else if (input.isKey(Key_Delete)) {
if (m_pos < m_buffer.size()) if (m_anchor == m_pos) {
m_buffer.remove(m_pos, 1); if (m_pos < m_buffer.size())
else m_buffer.remove(m_pos, 1);
deleteChar(); else
deleteChar();
} else {
deleteSelected();
}
} else if (!input.text().isEmpty()) { } else if (!input.text().isEmpty()) {
if (m_anchor != m_pos)
deleteSelected();
insertText(input.text()); insertText(input.text());
} else { } else {
return false; return false;
@@ -1178,6 +1212,7 @@ private:
QChar m_prompt; QChar m_prompt;
History m_history; History m_history;
int m_pos; int m_pos;
int m_anchor;
int m_userPos; // last position of inserted text (for retrieving history items) int m_userPos; // last position of inserted text (for retrieving history items)
bool m_historyAutoSave; // store items to history on clear()? bool m_historyAutoSave; // store items to history on clear()?
}; };
@@ -2812,6 +2847,7 @@ void FakeVimHandler::Private::updateMiniBuffer()
QString msg; QString msg;
int cursorPos = -1; int cursorPos = -1;
int anchorPos = -1;
MessageLevel messageLevel = MessageMode; MessageLevel messageLevel = MessageMode;
if (g.mapStates.last().silent && g.currentMessageLevel < MessageInfo) if (g.mapStates.last().silent && g.currentMessageLevel < MessageInfo)
@@ -2821,12 +2857,16 @@ void FakeVimHandler::Private::updateMiniBuffer()
msg = _("PASSING"); msg = _("PASSING");
} else if (m_subsubmode == SearchSubSubMode) { } else if (m_subsubmode == SearchSubSubMode) {
msg = g.searchBuffer.display(); msg = g.searchBuffer.display();
if (g.mapStates.size() == 1) if (g.mapStates.size() == 1) {
cursorPos = g.searchBuffer.cursorPos() + 1; cursorPos = g.searchBuffer.cursorPos() + 1;
anchorPos = g.searchBuffer.anchorPos() + 1;
}
} else if (m_mode == ExMode) { } else if (m_mode == ExMode) {
msg = g.commandBuffer.display(); msg = g.commandBuffer.display();
if (g.mapStates.size() == 1) if (g.mapStates.size() == 1) {
cursorPos = g.commandBuffer.cursorPos() + 1; cursorPos = g.commandBuffer.cursorPos() + 1;
anchorPos = g.commandBuffer.anchorPos() + 1;
}
} else if (!g.currentMessage.isEmpty()) { } else if (!g.currentMessage.isEmpty()) {
msg = g.currentMessage; msg = g.currentMessage;
g.currentMessage.clear(); g.currentMessage.clear();
@@ -2859,7 +2899,7 @@ void FakeVimHandler::Private::updateMiniBuffer()
msg = _("(replace)"); msg = _("(replace)");
} }
emit q->commandBufferChanged(msg, cursorPos, messageLevel, q); emit q->commandBufferChanged(msg, cursorPos, anchorPos, messageLevel, q);
int linesInDoc = linesInDocument(); int linesInDoc = linesInDocument();
int l = cursorLine(); int l = cursorLine();
@@ -4334,18 +4374,12 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
} else if (input.isKey(Key_Tab)) { } else if (input.isKey(Key_Tab)) {
// FIXME: Complete actual commands. // FIXME: Complete actual commands.
g.commandBuffer.historyUp(); g.commandBuffer.historyUp();
} else if (input.isKey(Key_Left)) {
g.commandBuffer.moveLeft();
} else if (input.isReturn()) { } else if (input.isReturn()) {
showMessage(MessageCommand, g.commandBuffer.display()); showMessage(MessageCommand, g.commandBuffer.display());
handleExCommand(g.commandBuffer.contents()); handleExCommand(g.commandBuffer.contents());
g.commandBuffer.clear(); g.commandBuffer.clear();
if (m_textedit || m_plaintextedit) if (m_textedit || m_plaintextedit)
leaveVisualMode(); leaveVisualMode();
} else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
g.commandBuffer.historyUp();
} else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) {
g.commandBuffer.historyDown();
} else if (!g.commandBuffer.handleInput(input)) { } else if (!g.commandBuffer.handleInput(input)) {
qDebug() << "IGNORED IN EX-MODE: " << input.key() << input.text(); qDebug() << "IGNORED IN EX-MODE: " << input.key() << input.text();
return EventUnhandled; return EventUnhandled;
@@ -4371,10 +4405,6 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
} else { } else {
g.searchBuffer.deleteChar(); g.searchBuffer.deleteChar();
} }
} else if (input.isKey(Key_Left)) {
g.searchBuffer.moveLeft();
} else if (input.isKey(Key_Right)) {
g.searchBuffer.moveRight();
} else if (input.isReturn()) { } else if (input.isReturn()) {
const QString &needle = g.searchBuffer.contents(); const QString &needle = g.searchBuffer.contents();
if (!needle.isEmpty()) if (!needle.isEmpty())
@@ -4394,10 +4424,6 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
enterCommandMode(g.returnToMode); enterCommandMode(g.returnToMode);
resetCommandMode(); resetCommandMode();
g.searchBuffer.clear(); g.searchBuffer.clear();
} else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
g.searchBuffer.historyUp();
} else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) {
g.searchBuffer.historyDown();
} else if (input.isKey(Key_Tab)) { } else if (input.isKey(Key_Tab)) {
g.searchBuffer.insertChar(QChar(9)); g.searchBuffer.insertChar(QChar(9));
} else if (!g.searchBuffer.handleInput(input)) { } else if (!g.searchBuffer.handleInput(input)) {
@@ -5647,7 +5673,10 @@ void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int curs
CommandBuffer &cmdBuf = (m_mode == ExMode) ? g.commandBuffer : g.searchBuffer; CommandBuffer &cmdBuf = (m_mode == ExMode) ? g.commandBuffer : g.searchBuffer;
// prepend prompt character if missing // prepend prompt character if missing
if (!text.startsWith(cmdBuf.prompt())) { if (!text.startsWith(cmdBuf.prompt())) {
emit q->commandBufferChanged(cmdBuf.prompt() + text, cmdBuf.cursorPos() + 1, 0, q); emit q->commandBufferChanged(cmdBuf.prompt() + text,
cmdBuf.cursorPos() + 1,
cmdBuf.anchorPos() + 1,
0, q);
cmdBuf.setContents(text, cursorPos - 1); cmdBuf.setContents(text, cursorPos - 1);
} else { } else {
cmdBuf.setContents(text.mid(1), cursorPos - 1); cmdBuf.setContents(text.mid(1), cursorPos - 1);

View File

@@ -130,7 +130,8 @@ public slots:
bool jumpToLocalMark(QChar mark, bool backTickMode); bool jumpToLocalMark(QChar mark, bool backTickMode);
signals: signals:
void commandBufferChanged(const QString &msg, int pos, int messageLevel, QObject *eventFilter); void commandBufferChanged(const QString &msg, int cursorPos,
int anchorPos, int messageLevel, QObject *eventFilter);
void statusDataChanged(const QString &msg); void statusDataChanged(const QString &msg);
void extraInformationChanged(const QString &msg); void extraInformationChanged(const QString &msg);
void selectionChanged(const QList<QTextEdit::ExtraSelection> &selection); void selectionChanged(const QList<QTextEdit::ExtraSelection> &selection);

View File

@@ -129,15 +129,18 @@ public:
addWidget(m_edit); addWidget(m_edit);
} }
void setContents(const QString &contents, int cursorPos, int messageLevel, QObject *eventFilter) void setContents(const QString &contents, int cursorPos, int anchorPos,
int messageLevel, QObject *eventFilter)
{ {
if (cursorPos != -1) { if (cursorPos != -1) {
m_edit->blockSignals(true); m_edit->blockSignals(true);
m_label->clear(); m_label->clear();
m_edit->setText(contents); m_edit->setText(contents);
m_edit->setCursorPosition(cursorPos); if (anchorPos != -1 && anchorPos != cursorPos)
m_edit->setSelection(anchorPos, cursorPos - anchorPos);
else
m_edit->setCursorPosition(cursorPos);
m_edit->blockSignals(false); m_edit->blockSignals(false);
setCurrentWidget(m_edit); setCurrentWidget(m_edit);
m_edit->setFocus(); m_edit->setFocus();
} else if (contents.isEmpty() && messageLevel != MessageShowCmd) { } else if (contents.isEmpty() && messageLevel != MessageShowCmd) {
@@ -863,8 +866,8 @@ private slots:
void hasBlockSelection(bool*); void hasBlockSelection(bool*);
void resetCommandBuffer(); void resetCommandBuffer();
void showCommandBuffer(const QString &contents, int cursorPos, int messageLevel, void showCommandBuffer(const QString &contents, int cursorPos, int anchorPos,
QObject *eventFilter); int messageLevel, QObject *eventFilter);
void showExtraInformation(const QString &msg); void showExtraInformation(const QString &msg);
void changeSelection(const QList<QTextEdit::ExtraSelection> &selections); void changeSelection(const QList<QTextEdit::ExtraSelection> &selections);
void highlightMatches(const QString &needle); void highlightMatches(const QString &needle);
@@ -1566,8 +1569,8 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
connect(handler, SIGNAL(extraInformationChanged(QString)), connect(handler, SIGNAL(extraInformationChanged(QString)),
SLOT(showExtraInformation(QString))); SLOT(showExtraInformation(QString)));
connect(handler, SIGNAL(commandBufferChanged(QString,int,int,QObject*)), connect(handler, SIGNAL(commandBufferChanged(QString,int,int,int,QObject*)),
SLOT(showCommandBuffer(QString,int,int,QObject*))); SLOT(showCommandBuffer(QString,int,int,int,QObject*)));
connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)), connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
SLOT(changeSelection(QList<QTextEdit::ExtraSelection>))); SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
connect(handler, SIGNAL(highlightMatches(QString)), connect(handler, SIGNAL(highlightMatches(QString)),
@@ -1906,15 +1909,15 @@ void FakeVimPluginPrivate::quitFakeVim()
void FakeVimPluginPrivate::resetCommandBuffer() void FakeVimPluginPrivate::resetCommandBuffer()
{ {
showCommandBuffer(QString(), -1, 0, 0); showCommandBuffer(QString(), -1, -1, 0, 0);
} }
void FakeVimPluginPrivate::showCommandBuffer(const QString &contents, int cursorPos, void FakeVimPluginPrivate::showCommandBuffer(const QString &contents,
int messageLevel, QObject *eventFilter) int cursorPos, int anchorPos, int messageLevel, QObject *eventFilter)
{ {
//qDebug() << "SHOW COMMAND BUFFER" << contents; //qDebug() << "SHOW COMMAND BUFFER" << contents;
if (MiniBuffer *w = qobject_cast<MiniBuffer *>(m_statusBar->widget())) if (MiniBuffer *w = qobject_cast<MiniBuffer *>(m_statusBar->widget()))
w->setContents(contents, cursorPos, messageLevel, eventFilter); w->setContents(contents, cursorPos, anchorPos, messageLevel, eventFilter);
} }
void FakeVimPluginPrivate::showExtraInformation(const QString &text) void FakeVimPluginPrivate::showExtraInformation(const QString &text)