fakevim: Improved command line buffers

Command line history should be global.

Keep last submitted command/search visible.

Change-Id: I0fc60786d486eb07c849d016aa23f71875d2cede
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Lukas Holecek
2012-09-17 17:44:05 +02:00
committed by hjk
parent 9b7d1901ba
commit 12f1098329

View File

@@ -871,7 +871,7 @@ const QString &History::move(const QStringRef &prefix, int skip)
return current(); return current();
} }
// This wraps a string and a "cursor position". // Command line buffer with prompt (i.e. :, / or ? characters), text contents and cursor position.
class CommandBuffer class CommandBuffer
{ {
public: public:
@@ -1364,10 +1364,7 @@ public:
int m_gflag; // whether current command started with 'g' int m_gflag; // whether current command started with 'g'
CommandBuffer m_commandBuffer;
CommandBuffer m_searchBuffer;
QString m_currentFileName; QString m_currentFileName;
QString m_currentMessage;
bool m_lastSearchForward; bool m_lastSearchForward;
bool m_findPending; bool m_findPending;
@@ -1523,6 +1520,7 @@ public:
{ {
// default mapping state - shouldn't be removed // default mapping state - shouldn't be removed
mapStates << MappingState(); mapStates << MappingState();
commandBuffer.setPrompt(':');
} }
// Repetition. // Repetition.
@@ -1539,6 +1537,13 @@ public:
int inputTimer; int inputTimer;
int lastMapCode; int lastMapCode;
QStack<MappingState> mapStates; QStack<MappingState> mapStates;
// Command line buffers.
CommandBuffer commandBuffer;
CommandBuffer searchBuffer;
// Current mini buffer message.
QString currentMessage;
} g; } g;
}; };
@@ -1586,7 +1591,6 @@ void FakeVimHandler::Private::init()
m_breakEditBlock = false; m_breakEditBlock = false;
m_searchStartPosition = 0; m_searchStartPosition = 0;
m_searchFromScreenLine = 0; m_searchFromScreenLine = 0;
m_commandBuffer.setPrompt(':');
setupCharClass(); setupCharClass();
} }
@@ -1900,7 +1904,7 @@ EventResult FakeVimHandler::Private::handleKey(const Input &input)
QTC_CHECK(!g.mapStates.empty()); QTC_CHECK(!g.mapStates.empty());
endEditBlock(); endEditBlock();
if (g.mapStates.size() == 1) if (g.mapStates.size() == 1)
m_commandBuffer.setHistoryAutoSave(true); g.commandBuffer.setHistoryAutoSave(true);
if (m_mode == ExMode || m_subsubmode == SearchSubSubMode) if (m_mode == ExMode || m_subsubmode == SearchSubSubMode)
updateMiniBuffer(); // update cursor position on command line updateMiniBuffer(); // update cursor position on command line
} else { } else {
@@ -1972,7 +1976,7 @@ void FakeVimHandler::Private::handleMappedKeys()
g.pendingInput.clear(); g.pendingInput.clear();
g.pendingInput << inputs << Input() << rest; g.pendingInput << inputs << Input() << rest;
g.mapStates << MappingState(maxMapDepth, inputs.noremap(), inputs.silent()); g.mapStates << MappingState(maxMapDepth, inputs.noremap(), inputs.silent());
m_commandBuffer.setHistoryAutoSave(false); g.commandBuffer.setHistoryAutoSave(false);
beginEditBlock(); beginEditBlock();
} }
g.currentMap.reset(); g.currentMap.reset();
@@ -2127,8 +2131,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
int endLine = lineForPosition(position()); int endLine = lineForPosition(position());
setPosition(qMin(anchor(), position())); setPosition(qMin(anchor(), position()));
enterExMode(); enterExMode();
m_currentMessage.clear(); g.currentMessage.clear();
m_commandBuffer.setContents(QString(".,+%1!").arg(qAbs(endLine - beginLine))); g.commandBuffer.setContents(QString(".,+%1!").arg(qAbs(endLine - beginLine)));
updateMiniBuffer(); updateMiniBuffer();
return; return;
} }
@@ -2331,19 +2335,22 @@ void FakeVimHandler::Private::updateMiniBuffer()
QString msg; QString msg;
int cursorPos = -1; int cursorPos = -1;
if (g.mapStates.last().silent)
g.currentMessage.clear();
if (m_passing) { if (m_passing) {
msg = "-- PASSING -- "; msg = "-- PASSING -- ";
} else if (m_subsubmode == SearchSubSubMode) { } else if (m_subsubmode == SearchSubSubMode) {
msg = m_searchBuffer.display(); msg = g.searchBuffer.display();
if (g.mapStates.size() == 1) if (g.mapStates.size() == 1)
cursorPos = m_searchBuffer.cursorPos() + 1; cursorPos = g.searchBuffer.cursorPos() + 1;
} else if (m_mode == ExMode) { } else if (m_mode == ExMode) {
msg = m_commandBuffer.display(); msg = g.commandBuffer.display();
if (g.mapStates.size() == 1) if (g.mapStates.size() == 1)
cursorPos = m_commandBuffer.cursorPos() + 1; cursorPos = g.commandBuffer.cursorPos() + 1;
} else if (!m_currentMessage.isEmpty()) { } else if (!g.currentMessage.isEmpty()) {
msg = m_currentMessage; msg = g.currentMessage;
m_currentMessage.clear(); g.currentMessage.clear();
} else if (g.mapStates.size() > 1 && !g.mapStates.last().silent) { } else if (g.mapStates.size() > 1 && !g.mapStates.last().silent) {
// Do not reset previous message when after running a mapped command. // Do not reset previous message when after running a mapped command.
return; return;
@@ -2383,14 +2390,14 @@ void FakeVimHandler::Private::updateMiniBuffer()
void FakeVimHandler::Private::showRedMessage(const QString &msg) void FakeVimHandler::Private::showRedMessage(const QString &msg)
{ {
//qDebug() << "MSG: " << msg; //qDebug() << "MSG: " << msg;
m_currentMessage = msg; g.currentMessage = msg;
updateMiniBuffer(); updateMiniBuffer();
} }
void FakeVimHandler::Private::showBlackMessage(const QString &msg) void FakeVimHandler::Private::showBlackMessage(const QString &msg)
{ {
//qDebug() << "MSG: " << msg; //qDebug() << "MSG: " << msg;
m_currentMessage = msg; g.currentMessage = msg;
updateMiniBuffer(); updateMiniBuffer();
} }
@@ -2706,10 +2713,10 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
handleExCommand(m_gflag ? "%s//~/&" : "s"); handleExCommand(m_gflag ? "%s//~/&" : "s");
} else if (input.is(':')) { } else if (input.is(':')) {
enterExMode(); enterExMode();
m_currentMessage.clear(); g.currentMessage.clear();
m_commandBuffer.clear(); g.commandBuffer.clear();
if (isVisualMode()) if (isVisualMode())
m_commandBuffer.setContents("'<,'>"); g.commandBuffer.setContents("'<,'>");
updateMiniBuffer(); updateMiniBuffer();
} else if (input.is('/') || input.is('?')) { } else if (input.is('/') || input.is('?')) {
m_lastSearchForward = input.is('/'); m_lastSearchForward = input.is('/');
@@ -2723,13 +2730,13 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
} else { } else {
// FIXME: make core find dialog sufficiently flexible to // FIXME: make core find dialog sufficiently flexible to
// produce the "default vi" behaviour too. For now, roll our own. // produce the "default vi" behaviour too. For now, roll our own.
m_currentMessage.clear(); g.currentMessage.clear();
m_movetype = MoveExclusive; m_movetype = MoveExclusive;
m_subsubmode = SearchSubSubMode; m_subsubmode = SearchSubSubMode;
m_searchBuffer.setPrompt(m_lastSearchForward ? '/' : '?'); g.searchBuffer.setPrompt(m_lastSearchForward ? '/' : '?');
m_searchStartPosition = position(); m_searchStartPosition = position();
m_searchFromScreenLine = firstVisibleLine(); m_searchFromScreenLine = firstVisibleLine();
m_searchBuffer.clear(); g.searchBuffer.clear();
updateMiniBuffer(); updateMiniBuffer();
} }
} else if (input.is('`')) { } else if (input.is('`')) {
@@ -2743,7 +2750,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
tc.select(QTextCursor::WordUnderCursor); tc.select(QTextCursor::WordUnderCursor);
needle = "\\<" + tc.selection().toPlainText() + "\\>"; needle = "\\<" + tc.selection().toPlainText() + "\\>";
setAnchorAndPosition(tc.position(), tc.anchor()); setAnchorAndPosition(tc.position(), tc.anchor());
m_searchBuffer.historyPush(needle); g.searchBuffer.historyPush(needle);
m_lastSearchForward = input.is('*'); m_lastSearchForward = input.is('*');
searchNext(); searchNext();
finishMovement(); finishMovement();
@@ -2760,8 +2767,8 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
m_submode = FilterSubMode; m_submode = FilterSubMode;
} else if (input.is('!') && isVisualMode()) { } else if (input.is('!') && isVisualMode()) {
enterExMode(); enterExMode();
m_currentMessage.clear(); g.currentMessage.clear();
m_commandBuffer.setContents("'<,'>!"); g.commandBuffer.setContents("'<,'>!");
updateMiniBuffer(); updateMiniBuffer();
} else if (input.is('"')) { } else if (input.is('"')) {
m_submode = RegisterSubMode; m_submode = RegisterSubMode;
@@ -3708,38 +3715,40 @@ void FakeVimHandler::Private::insertInInsertMode(const QString &text)
EventResult FakeVimHandler::Private::handleExMode(const Input &input) EventResult FakeVimHandler::Private::handleExMode(const Input &input)
{ {
if (input.isEscape()) { if (input.isEscape()) {
m_commandBuffer.clear(); g.commandBuffer.clear();
enterCommandMode(); enterCommandMode();
m_ctrlVActive = false; m_ctrlVActive = false;
} else if (m_ctrlVActive) { } else if (m_ctrlVActive) {
m_commandBuffer.insertChar(input.raw()); g.commandBuffer.insertChar(input.raw());
m_ctrlVActive = false; m_ctrlVActive = false;
} else if (input.isControl('v')) { } else if (input.isControl('v')) {
m_ctrlVActive = true; m_ctrlVActive = true;
return EventHandled; return EventHandled;
} else if (input.isBackspace()) { } else if (input.isBackspace()) {
if (m_commandBuffer.isEmpty()) if (g.commandBuffer.isEmpty())
enterCommandMode(); enterCommandMode();
else else
m_commandBuffer.deleteChar(); g.commandBuffer.deleteChar();
} else if (input.isKey(Key_Tab)) { } else if (input.isKey(Key_Tab)) {
// FIXME: Complete actual commands. // FIXME: Complete actual commands.
m_commandBuffer.historyUp(); g.commandBuffer.historyUp();
} else if (input.isKey(Key_Left)) { } else if (input.isKey(Key_Left)) {
m_commandBuffer.moveLeft(); g.commandBuffer.moveLeft();
} else if (input.isReturn()) { } else if (input.isReturn()) {
if (!m_commandBuffer.isEmpty()) { if (!g.commandBuffer.isEmpty()) {
//g.commandHistory.takeLast(); //g.commandHistory.takeLast();
handleExCommand(m_commandBuffer.contents()); handleExCommand(g.commandBuffer.contents());
m_commandBuffer.clear(); if (g.currentMessage.isEmpty())
g.currentMessage = g.commandBuffer.display();
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)) { } else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
m_commandBuffer.historyUp(); g.commandBuffer.historyUp();
} else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) { } else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) {
m_commandBuffer.historyDown(); g.commandBuffer.historyDown();
} else if (!m_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;
} }
@@ -3750,27 +3759,27 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
{ {
if (input.isEscape()) { if (input.isEscape()) {
m_currentMessage.clear(); g.currentMessage.clear();
m_searchBuffer.clear(); g.searchBuffer.clear();
m_searchCursor = QTextCursor(); m_searchCursor = QTextCursor();
setPosition(m_searchStartPosition); setPosition(m_searchStartPosition);
scrollToLine(m_searchFromScreenLine); scrollToLine(m_searchFromScreenLine);
updateSelection(); updateSelection();
enterCommandMode(); enterCommandMode();
} else if (input.isBackspace()) { } else if (input.isBackspace()) {
if (m_searchBuffer.isEmpty()) { if (g.searchBuffer.isEmpty()) {
m_searchCursor = QTextCursor(); m_searchCursor = QTextCursor();
enterCommandMode(); enterCommandMode();
} else { } else {
m_searchBuffer.deleteChar(); g.searchBuffer.deleteChar();
} }
} else if (input.isKey(Key_Left)) { } else if (input.isKey(Key_Left)) {
m_searchBuffer.moveLeft(); g.searchBuffer.moveLeft();
} else if (input.isKey(Key_Right)) { } else if (input.isKey(Key_Right)) {
m_searchBuffer.moveRight(); g.searchBuffer.moveRight();
} else if (input.isReturn()) { } else if (input.isReturn()) {
m_searchCursor = QTextCursor(); m_searchCursor = QTextCursor();
const QString &needle = m_searchBuffer.contents(); const QString &needle = g.searchBuffer.contents();
if (!needle.isEmpty()) { if (!needle.isEmpty()) {
if (!hasConfig(ConfigIncSearch)) { if (!hasConfig(ConfigIncSearch)) {
SearchData sd; SearchData sd;
@@ -3780,27 +3789,29 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
sd.highlightMatches = true; sd.highlightMatches = true;
search(sd); search(sd);
} }
finishMovement(m_searchBuffer.prompt() + needle + '\n'); finishMovement(g.searchBuffer.prompt() + needle + '\n');
} else { } else {
finishMovement(); finishMovement();
} }
if (g.currentMessage.isEmpty())
g.currentMessage = g.searchBuffer.display();
enterCommandMode(); enterCommandMode();
highlightMatches(needle); highlightMatches(needle);
m_searchBuffer.clear(); g.searchBuffer.clear();
} else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) { } else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
m_searchBuffer.historyUp(); g.searchBuffer.historyUp();
} else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) { } else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) {
m_searchBuffer.historyDown(); g.searchBuffer.historyDown();
} else if (input.isKey(Key_Tab)) { } else if (input.isKey(Key_Tab)) {
m_searchBuffer.insertChar(QChar(9)); g.searchBuffer.insertChar(QChar(9));
} else if (!m_searchBuffer.handleInput(input)) { } else if (!g.searchBuffer.handleInput(input)) {
return EventUnhandled; return EventUnhandled;
} }
updateMiniBuffer(); updateMiniBuffer();
if (hasConfig(ConfigIncSearch) && !input.isReturn() && !input.isEscape()) { if (hasConfig(ConfigIncSearch) && !input.isReturn() && !input.isEscape()) {
SearchData sd; SearchData sd;
sd.needle = m_searchBuffer.contents(); sd.needle = g.searchBuffer.contents();
sd.forward = m_lastSearchForward; sd.forward = m_lastSearchForward;
sd.highlightCursor = true; sd.highlightCursor = true;
sd.highlightMatches = false; sd.highlightMatches = false;
@@ -4133,7 +4144,7 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd)
QString info; QString info;
info += "# command history\n"; info += "# command history\n";
int i = 0; int i = 0;
foreach (const QString &item, m_commandBuffer.historyItems()) { foreach (const QString &item, g.commandBuffer.historyItems()) {
++i; ++i;
info += QString("%1 %2\n").arg(i, -8).arg(item); info += QString("%1 %2\n").arg(i, -8).arg(item);
} }
@@ -4468,7 +4479,7 @@ bool FakeVimHandler::Private::handleExEchoCommand(const ExCommand &cmd)
// :echo // :echo
if (cmd.cmd != "echo") if (cmd.cmd != "echo")
return false; return false;
m_currentMessage = cmd.args; g.currentMessage = cmd.args;
return true; return true;
} }
@@ -4647,16 +4658,14 @@ void FakeVimHandler::Private::search(const SearchData &sd)
void FakeVimHandler::Private::searchNext(bool forward) void FakeVimHandler::Private::searchNext(bool forward)
{ {
SearchData sd; SearchData sd;
sd.needle = m_searchBuffer.last(); sd.needle = g.searchBuffer.last();
sd.forward = forward ? m_lastSearchForward : !m_lastSearchForward; sd.forward = forward ? m_lastSearchForward : !m_lastSearchForward;
sd.highlightCursor = false; sd.highlightCursor = false;
sd.highlightMatches = true; sd.highlightMatches = true;
m_searchStartPosition = position(); m_searchStartPosition = position();
m_currentMessage.clear(); g.currentMessage = (m_lastSearchForward ? '/' : '?') + sd.needle;
updateMiniBuffer();
search(sd); search(sd);
m_searchBuffer.setPrompt(m_lastSearchForward ? '/' : '?');
m_searchBuffer.setContents(sd.needle);
} }
void FakeVimHandler::Private::highlightMatches(const QString &needle) void FakeVimHandler::Private::highlightMatches(const QString &needle)