fakevim: Appearance of command line widget.

Widget for Ex and search mode is QLineEdit.

Messages are displayed using QLabel widget with different style for
error, warnings etc.

Change-Id: I4d4f799bbe261febaf6c2c21c01f6b66e1beec6e
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Lukas Holecek
2012-09-10 22:10:23 +02:00
committed by hjk
parent 3934b9b976
commit 1264d0ea5e
3 changed files with 241 additions and 143 deletions

View File

@@ -880,6 +880,8 @@ public:
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_pos = s.size(); }
void setContents(const QString &s, int pos) { m_buffer = s; 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; }
@@ -1143,11 +1145,12 @@ public:
void finishMovement(const QString &dotCommand = QString()); void finishMovement(const QString &dotCommand = QString());
void finishMovement(const QString &dotCommand, int count); void finishMovement(const QString &dotCommand, int count);
void resetCommandMode(); void resetCommandMode();
void search(const SearchData &sd); void search(const SearchData &sd, bool showMessages = true);
void searchNext(bool forward = true); void searchNext(bool forward = true);
void searchBalanced(bool forward, QChar needle, QChar other); void searchBalanced(bool forward, QChar needle, QChar other);
void highlightMatches(const QString &needle); void highlightMatches(const QString &needle);
void stopIncrementalFind(); void stopIncrementalFind();
void updateFind(bool isComplete);
int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); } int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); }
int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); } int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); }
@@ -1286,8 +1289,8 @@ public:
void enterReplaceMode(); void enterReplaceMode();
void enterCommandMode(); void enterCommandMode();
void enterExMode(); void enterExMode();
void showRedMessage(const QString &msg); void showMessage(MessageLevel level, const QString &msg);
void showBlackMessage(const QString &msg); void clearMessage() { showMessage(MessageInfo, QString()); }
void notImplementedYet(); void notImplementedYet();
void updateMiniBuffer(); void updateMiniBuffer();
void updateSelection(); void updateSelection();
@@ -1514,9 +1517,12 @@ public:
signed char m_charClass[256]; signed char m_charClass[256];
bool m_ctrlVActive; bool m_ctrlVActive;
void miniBufferTextEdited(const QString &text, int cursorPos);
static struct GlobalData static struct GlobalData
{ {
GlobalData() : mappings(), currentMap(&mappings), inputTimer(-1) GlobalData()
: mappings(), currentMap(&mappings), inputTimer(-1), currentMessageLevel(MessageInfo)
{ {
// default mapping state - shouldn't be removed // default mapping state - shouldn't be removed
mapStates << MappingState(); mapStates << MappingState();
@@ -1544,6 +1550,7 @@ public:
// Current mini buffer message. // Current mini buffer message.
QString currentMessage; QString currentMessage;
MessageLevel currentMessageLevel;
} g; } g;
}; };
@@ -1847,7 +1854,7 @@ void FakeVimHandler::Private::updateEditor()
void FakeVimHandler::Private::restoreWidget(int tabSize) void FakeVimHandler::Private::restoreWidget(int tabSize)
{ {
//showBlackMessage(QString()); //clearMessage();
//updateMiniBuffer(); //updateMiniBuffer();
//EDITOR(removeEventFilter(q)); //EDITOR(removeEventFilter(q));
//EDITOR(setReadOnly(m_wasReadOnly)); //EDITOR(setReadOnly(m_wasReadOnly));
@@ -1968,7 +1975,7 @@ void FakeVimHandler::Private::handleMappedKeys()
} }
if (maxMapDepth <= 0) { if (maxMapDepth <= 0) {
showRedMessage("recursive mapping"); showMessage(MessageError, "recursive mapping");
g.pendingInput.remove(0, g.currentMap.mapLength() + invalidCount); g.pendingInput.remove(0, g.currentMap.mapLength() + invalidCount);
} else { } else {
const Inputs &inputs = g.currentMap.inputs(); const Inputs &inputs = g.currentMap.inputs();
@@ -2002,6 +2009,22 @@ void FakeVimHandler::Private::stopIncrementalFind()
} }
} }
void FakeVimHandler::Private::updateFind(bool isComplete)
{
if (!isComplete && !hasConfig(ConfigIncSearch))
return;
g.currentMessage.clear();
const QString &needle = g.searchBuffer.contents();
SearchData sd;
sd.needle = needle;
sd.forward = m_lastSearchForward;
sd.highlightCursor = !isComplete;
sd.highlightMatches = isComplete;
search(sd, isComplete);
}
bool FakeVimHandler::Private::atEmptyLine(const QTextCursor &tc) const bool FakeVimHandler::Private::atEmptyLine(const QTextCursor &tc) const
{ {
if (tc.isNull()) if (tc.isNull())
@@ -2245,7 +2268,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
setPosition(anchor()); setPosition(anchor());
} }
if (la != lp) if (la != lp)
showBlackMessage(QString("%1 lines yanked").arg(qAbs(la - lp) + 1)); showMessage(MessageInfo, QString("%1 lines yanked").arg(qAbs(la - lp) + 1));
} else if (m_submode == TransformSubMode) { } else if (m_submode == TransformSubMode) {
if (m_subsubmode == InvertCaseSubSubMode) { if (m_subsubmode == InvertCaseSubSubMode) {
invertCase(currentRange()); invertCase(currentRange());
@@ -2334,12 +2357,13 @@ void FakeVimHandler::Private::updateMiniBuffer()
QString msg; QString msg;
int cursorPos = -1; int cursorPos = -1;
MessageLevel messageLevel = MessageMode;
if (g.mapStates.last().silent) if (g.mapStates.last().silent && g.currentMessageLevel < MessageInfo)
g.currentMessage.clear(); g.currentMessage.clear();
if (m_passing) { if (m_passing) {
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)
@@ -2351,27 +2375,28 @@ void FakeVimHandler::Private::updateMiniBuffer()
} else if (!g.currentMessage.isEmpty()) { } else if (!g.currentMessage.isEmpty()) {
msg = g.currentMessage; msg = g.currentMessage;
g.currentMessage.clear(); g.currentMessage.clear();
messageLevel = g.currentMessageLevel;
} 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;
} else if (m_mode == CommandMode && isVisualMode()) { } else if (m_mode == CommandMode && isVisualMode()) {
if (isVisualCharMode()) { if (isVisualCharMode()) {
msg = "-- VISUAL --"; msg = "VISUAL";
} else if (isVisualLineMode()) { } else if (isVisualLineMode()) {
msg = "-- VISUAL LINE --"; msg = "VISUAL LINE";
} else if (isVisualBlockMode()) { } else if (isVisualBlockMode()) {
msg = "-- VISUAL BLOCK --"; msg = "VISUAL BLOCK";
} }
} else if (m_mode == InsertMode) { } else if (m_mode == InsertMode) {
msg = "-- INSERT --"; msg = "INSERT";
} else if (m_mode == ReplaceMode) { } else if (m_mode == ReplaceMode) {
msg = "-- REPLACE --"; msg = "REPLACE";
} else { } else {
QTC_CHECK(m_mode == CommandMode && m_subsubmode != SearchSubSubMode); QTC_CHECK(m_mode == CommandMode && m_subsubmode != SearchSubSubMode);
msg = "-- COMMAND --"; msg = "COMMAND";
} }
emit q->commandBufferChanged(msg, cursorPos); emit q->commandBufferChanged(msg, cursorPos, messageLevel, q);
int linesInDoc = linesInDocument(); int linesInDoc = linesInDocument();
int l = cursorLine(); int l = cursorLine();
@@ -2387,24 +2412,18 @@ void FakeVimHandler::Private::updateMiniBuffer()
emit q->statusDataChanged(status); emit q->statusDataChanged(status);
} }
void FakeVimHandler::Private::showRedMessage(const QString &msg) void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg)
{
//qDebug() << "MSG: " << msg;
g.currentMessage = msg;
updateMiniBuffer();
}
void FakeVimHandler::Private::showBlackMessage(const QString &msg)
{ {
//qDebug() << "MSG: " << msg; //qDebug() << "MSG: " << msg;
g.currentMessage = msg; g.currentMessage = msg;
g.currentMessageLevel = level;
updateMiniBuffer(); updateMiniBuffer();
} }
void FakeVimHandler::Private::notImplementedYet() void FakeVimHandler::Private::notImplementedYet()
{ {
qDebug() << "Not implemented in FakeVim"; qDebug() << "Not implemented in FakeVim";
showRedMessage(FakeVimHandler::tr("Not implemented in FakeVim")); showMessage(MessageError, FakeVimHandler::tr("Not implemented in FakeVim"));
updateMiniBuffer(); updateMiniBuffer();
} }
@@ -2486,7 +2505,7 @@ EventResult FakeVimHandler::Private::handleCommandSubSubMode(const Input &input)
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
finishMovement(); finishMovement();
} else { } else {
showRedMessage(msgMarkNotSet(input.text())); showMessage(MessageError, msgMarkNotSet(input.text()));
} }
m_subsubmode = NoSubSubMode; m_subsubmode = NoSubSubMode;
} else { } else {
@@ -2896,7 +2915,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
finishMovement(); finishMovement();
} else if (input.isControl('c')) { } else if (input.isControl('c')) {
if (isNoVisualMode()) if (isNoVisualMode())
showBlackMessage("Type Alt-v,Alt-v to quit FakeVim mode"); showMessage(MessageInfo, "Type Alt-v,Alt-v to quit FakeVim mode");
else else
leaveVisualMode(); leaveVisualMode();
} else if (input.is('d') && isNoVisualMode()) { } else if (input.is('d') && isNoVisualMode()) {
@@ -3460,6 +3479,7 @@ EventResult FakeVimHandler::Private::handleReplaceMode(const Input &input)
m_submode = NoSubMode; m_submode = NoSubMode;
m_mode = CommandMode; m_mode = CommandMode;
finishMovement(); finishMovement();
updateMiniBuffer();
} else if (input.isKey(Key_Left)) { } else if (input.isKey(Key_Left)) {
breakEditBlock(); breakEditBlock();
moveLeft(1); moveLeft(1);
@@ -3735,15 +3755,11 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
} else if (input.isKey(Key_Left)) { } else if (input.isKey(Key_Left)) {
g.commandBuffer.moveLeft(); g.commandBuffer.moveLeft();
} else if (input.isReturn()) { } else if (input.isReturn()) {
if (!g.commandBuffer.isEmpty()) { showMessage(MessageCommand, g.commandBuffer.display());
//g.commandHistory.takeLast(); handleExCommand(g.commandBuffer.contents());
handleExCommand(g.commandBuffer.contents()); g.commandBuffer.clear();
if (g.currentMessage.isEmpty()) if (m_textedit || m_plaintextedit)
g.currentMessage = g.commandBuffer.display(); leaveVisualMode();
g.commandBuffer.clear();
if (m_textedit || m_plaintextedit)
leaveVisualMode();
}
} else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) { } else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) {
g.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)) {
@@ -3781,20 +3797,13 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
m_searchCursor = QTextCursor(); m_searchCursor = QTextCursor();
const QString &needle = g.searchBuffer.contents(); const QString &needle = g.searchBuffer.contents();
if (!needle.isEmpty()) { if (!needle.isEmpty()) {
if (!hasConfig(ConfigIncSearch)) { updateFind(true);
SearchData sd;
sd.needle = needle;
sd.forward = m_lastSearchForward;
sd.highlightCursor = false;
sd.highlightMatches = true;
search(sd);
}
finishMovement(g.searchBuffer.prompt() + needle + '\n'); finishMovement(g.searchBuffer.prompt() + needle + '\n');
} else { } else {
finishMovement(); finishMovement();
} }
if (g.currentMessage.isEmpty()) if (g.currentMessage.isEmpty())
g.currentMessage = g.searchBuffer.display(); showMessage(MessageCommand, g.searchBuffer.display());
enterCommandMode(); enterCommandMode();
highlightMatches(needle); highlightMatches(needle);
g.searchBuffer.clear(); g.searchBuffer.clear();
@@ -3805,23 +3814,15 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
} 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)) {
//qDebug() << "IGNORED IN SEARCH MODE: " << input.key() << input.text();
return EventUnhandled; return EventUnhandled;
} }
updateMiniBuffer(); updateMiniBuffer();
if (hasConfig(ConfigIncSearch) && !input.isReturn() && !input.isEscape()) { if (!input.isReturn() && !input.isEscape())
SearchData sd; updateFind(false);
sd.needle = g.searchBuffer.contents();
sd.forward = m_lastSearchForward;
sd.highlightCursor = true;
sd.highlightMatches = false;
search(sd);
}
//else {
// qDebug() << "IGNORED IN SEARCH MODE: " << input.key() << input.text();
// return EventUnhandled;
//}
return EventHandled; return EventHandled;
} }
@@ -3848,12 +3849,12 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
return linesInDocument(); return linesInDocument();
if (c == '\'' && !cmd.isEmpty()) { if (c == '\'' && !cmd.isEmpty()) {
if (cmd.isEmpty()) { if (cmd.isEmpty()) {
showRedMessage(msgMarkNotSet(QString())); showMessage(MessageError, msgMarkNotSet(QString()));
return -1; return -1;
} }
int m = mark(cmd.at(0).unicode()); int m = mark(cmd.at(0).unicode());
if (m == -1) { if (m == -1) {
showRedMessage(msgMarkNotSet(cmd.at(0))); showMessage(MessageError, msgMarkNotSet(cmd.at(0)));
cmd = cmd.mid(1); cmd = cmd.mid(1);
return -1; return -1;
} }
@@ -3871,7 +3872,7 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
if (c == '\'' && !cmd.isEmpty()) { if (c == '\'' && !cmd.isEmpty()) {
int pos = mark(cmd.at(0).unicode()); int pos = mark(cmd.at(0).unicode());
if (pos == -1) { if (pos == -1) {
showRedMessage(msgMarkNotSet(cmd.at(0))); showMessage(MessageError, msgMarkNotSet(cmd.at(0)));
cmd = cmd.mid(1); cmd = cmd.mid(1);
return -1; return -1;
} }
@@ -4189,7 +4190,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd)
if (!cmd.matches("se", "set")) if (!cmd.matches("se", "set"))
return false; return false;
showBlackMessage(QString()); clearMessage();
SavedAction *act = theFakeVimSettings()->item(cmd.args); SavedAction *act = theFakeVimSettings()->item(cmd.args);
QTC_CHECK(!cmd.args.isEmpty()); // Handled by plugin. QTC_CHECK(!cmd.args.isEmpty()); // Handled by plugin.
if (act && act->value().canConvert(QVariant::Bool)) { if (act && act->value().canConvert(QVariant::Bool)) {
@@ -4201,7 +4202,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd)
{} // nothing to do {} // nothing to do
} else if (act) { } else if (act) {
// Non-boolean to show. // Non-boolean to show.
showBlackMessage(cmd.args + '=' + act->value().toString()); showMessage(MessageInfo, cmd.args + '=' + act->value().toString());
} else if (cmd.args.startsWith(_("no")) } else if (cmd.args.startsWith(_("no"))
&& (act = theFakeVimSettings()->item(cmd.args.mid(2)))) { && (act = theFakeVimSettings()->item(cmd.args.mid(2)))) {
// Boolean config to be switched off. // Boolean config to be switched off.
@@ -4216,9 +4217,9 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd)
QString error = theFakeVimSettings() QString error = theFakeVimSettings()
->trySetValue(cmd.args.left(p), cmd.args.mid(p + 1)); ->trySetValue(cmd.args.left(p), cmd.args.mid(p + 1));
if (!error.isEmpty()) if (!error.isEmpty())
showRedMessage(error); showMessage(MessageError, error);
} else { } else {
showRedMessage(FakeVimHandler::tr("Unknown option: ") + cmd.args); showMessage(MessageError, FakeVimHandler::tr("Unknown option: ") + cmd.args);
} }
updateMiniBuffer(); updateMiniBuffer();
updateEditor(); updateEditor();
@@ -4278,7 +4279,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
QFile file1(fileName); QFile file1(fileName);
const bool exists = file1.exists(); const bool exists = file1.exists();
if (exists && !forced && !noArgs) { if (exists && !forced && !noArgs) {
showRedMessage(FakeVimHandler::tr showMessage(MessageError, FakeVimHandler::tr
("File \"%1\" exists (add ! to override)").arg(fileName)); ("File \"%1\" exists (add ! to override)").arg(fileName));
} else if (file1.open(QIODevice::ReadWrite)) { } else if (file1.open(QIODevice::ReadWrite)) {
// Nobody cared, so act ourselves. // Nobody cared, so act ourselves.
@@ -4292,14 +4293,14 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
QTextStream ts(&file2); QTextStream ts(&file2);
ts << contents; ts << contents;
} else { } else {
showRedMessage(FakeVimHandler::tr showMessage(MessageError, FakeVimHandler::tr
("Cannot open file \"%1\" for writing").arg(fileName)); ("Cannot open file \"%1\" for writing").arg(fileName));
} }
// Check result by reading back. // Check result by reading back.
QFile file3(fileName); QFile file3(fileName);
file3.open(QIODevice::ReadOnly); file3.open(QIODevice::ReadOnly);
QByteArray ba = file3.readAll(); QByteArray ba = file3.readAll();
showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2 %3L, %4C written")
.arg(fileName).arg(exists ? " " : tr(" [New] ")) .arg(fileName).arg(exists ? " " : tr(" [New] "))
.arg(ba.count('\n')).arg(ba.size())); .arg(ba.count('\n')).arg(ba.size()));
//if (quitAll) //if (quitAll)
@@ -4307,7 +4308,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
//else if (quit) //else if (quit)
// passUnknownExCommand(forced ? "q!" : "q"); // passUnknownExCommand(forced ? "q!" : "q");
} else { } else {
showRedMessage(FakeVimHandler::tr showMessage(MessageError, FakeVimHandler::tr
("Cannot open file \"%1\" for reading").arg(fileName)); ("Cannot open file \"%1\" for reading").arg(fileName));
} }
return true; return true;
@@ -4330,7 +4331,7 @@ bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd)
QString data = ts.readAll(); QString data = ts.readAll();
insertText(data); insertText(data);
endEditBlock(); endEditBlock();
showBlackMessage(FakeVimHandler::tr("\"%1\" %2L, %3C") showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2L, %3C")
.arg(m_currentFileName).arg(data.count('\n')).arg(data.size())); .arg(m_currentFileName).arg(data.count('\n')).arg(data.size()));
return true; return true;
} }
@@ -4363,7 +4364,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
endEditBlock(); endEditBlock();
leaveVisualMode(); leaveVisualMode();
//qDebug() << "FILTER: " << command; //qDebug() << "FILTER: " << command;
showBlackMessage(FakeVimHandler::tr("%n lines filtered", 0, showMessage(MessageInfo, FakeVimHandler::tr("%n lines filtered", 0,
text.count('\n'))); text.count('\n')));
} }
return true; return true;
@@ -4386,7 +4387,7 @@ bool FakeVimHandler::Private::handleExShiftCommand(const ExCommand &cmd)
leaveVisualMode(); leaveVisualMode();
const int beginLine = lineForPosition(range.beginPos); const int beginLine = lineForPosition(range.beginPos);
const int endLine = lineForPosition(range.endPos); const int endLine = lineForPosition(range.endPos);
showBlackMessage(FakeVimHandler::tr("%n lines %1ed %2 time", 0, showMessage(MessageInfo, FakeVimHandler::tr("%n lines %1ed %2 time", 0,
(endLine - beginLine + 1)).arg(cmd.cmd).arg(count)); (endLine - beginLine + 1)).arg(cmd.cmd).arg(count));
return true; return true;
} }
@@ -4432,7 +4433,7 @@ bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd)
const int beginLine = lineForPosition(cmd.range.beginPos); const int beginLine = lineForPosition(cmd.range.beginPos);
setPosition(firstPositionInLine(beginLine)); setPosition(firstPositionInLine(beginLine));
showBlackMessage(QString()); clearMessage();
return true; return true;
} }
@@ -4445,7 +4446,7 @@ bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd)
QString fileName = cmd.args; QString fileName = cmd.args;
QFile file(fileName); QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
showRedMessage(FakeVimHandler::tr("Cannot open file %1").arg(fileName)); showMessage(MessageError, FakeVimHandler::tr("Cannot open file %1").arg(fileName));
return true; return true;
} }
@@ -4479,7 +4480,7 @@ bool FakeVimHandler::Private::handleExEchoCommand(const ExCommand &cmd)
// :echo // :echo
if (cmd.cmd != "echo") if (cmd.cmd != "echo")
return false; return false;
g.currentMessage = cmd.args; showMessage(MessageInfo, cmd.args);
return true; return true;
} }
@@ -4491,7 +4492,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0)
line.chop(1); line.chop(1);
int percent = line.toInt(); int percent = line.toInt();
setPosition(firstPositionInLine(percent * linesInDocument() / 100)); setPosition(firstPositionInLine(percent * linesInDocument() / 100));
showBlackMessage(QString()); clearMessage();
return; return;
} }
@@ -4517,9 +4518,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0)
} }
//qDebug() << "CMD: " << cmd; //qDebug() << "CMD: " << cmd;
showBlackMessage(QString());
if (!handleExCommandHelper(cmd)) if (!handleExCommandHelper(cmd))
showRedMessage(tr("Not an editor command: %1").arg(cmd.cmd)); showMessage(MessageError, tr("Not an editor command: %1").arg(cmd.cmd));
enterCommandMode(); enterCommandMode();
} }
@@ -4584,7 +4584,7 @@ void FakeVimHandler::Private::searchBalanced(bool forward, QChar needle, QChar o
} }
} }
void FakeVimHandler::Private::search(const SearchData &sd) void FakeVimHandler::Private::search(const SearchData &sd, bool showMessages)
{ {
QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively; QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively;
if (!sd.forward) if (!sd.forward)
@@ -4610,19 +4610,22 @@ void FakeVimHandler::Private::search(const SearchData &sd)
tc = document()->find(needleExp, tc, flags); tc = document()->find(needleExp, tc, flags);
if (tc.isNull()) { if (tc.isNull()) {
highlightMatches(QString()); highlightMatches(QString());
showRedMessage(FakeVimHandler::tr("Pattern not found: %1").arg(sd.needle)); if (showMessages) {
showMessage(MessageError,
FakeVimHandler::tr("Pattern not found: %1").arg(sd.needle));
}
updateSelection(); updateSelection();
} else { } else if (showMessages) {
QString msg = sd.forward QString msg = sd.forward
? FakeVimHandler::tr("search hit BOTTOM, continuing at TOP") ? FakeVimHandler::tr("search hit BOTTOM, continuing at TOP")
: FakeVimHandler::tr("search hit TOP, continuing at BOTTOM"); : FakeVimHandler::tr("search hit TOP, continuing at BOTTOM");
showRedMessage(msg); showMessage(MessageWarning, msg);
} }
} else { } else if (showMessages) {
QString msg = sd.forward QString msg = sd.forward
? FakeVimHandler::tr("search hit BOTTOM without match for: %1") ? FakeVimHandler::tr("search hit BOTTOM without match for: %1")
: FakeVimHandler::tr("search hit TOP without match for: %1"); : FakeVimHandler::tr("search hit TOP without match for: %1");
showRedMessage(msg.arg(sd.needle)); showMessage(MessageError, msg.arg(sd.needle));
} }
} }
@@ -4663,8 +4666,7 @@ void FakeVimHandler::Private::searchNext(bool forward)
sd.highlightCursor = false; sd.highlightCursor = false;
sd.highlightMatches = true; sd.highlightMatches = true;
m_searchStartPosition = position(); m_searchStartPosition = position();
g.currentMessage = (m_lastSearchForward ? '/' : '?') + sd.needle; showMessage(MessageCommand, (m_lastSearchForward ? '/' : '?') + sd.needle);
updateMiniBuffer();
search(sd); search(sd);
} }
@@ -4683,7 +4685,7 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle)
QRegExp needleExp = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase)); QRegExp needleExp = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase));
if (!needleExp.isValid()) { if (!needleExp.isValid()) {
QString error = needleExp.errorString(); QString error = needleExp.errorString();
showRedMessage( showMessage(MessageError,
FakeVimHandler::tr("Invalid regular expression: %1").arg(error)); FakeVimHandler::tr("Invalid regular expression: %1").arg(error));
return; return;
} }
@@ -4753,7 +4755,7 @@ void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar)
// LineForPosition has returned 1-based line numbers. // LineForPosition has returned 1-based line numbers.
emit q->indentRegion(beginLine - 1, endLine - 1, typedChar); emit q->indentRegion(beginLine - 1, endLine - 1, typedChar);
if (beginLine != endLine) if (beginLine != endLine)
showBlackMessage("MARKS ARE OFF NOW"); showMessage(MessageError, "MARKS ARE OFF NOW");
} }
bool FakeVimHandler::Private::isElectricCharacter(QChar c) const bool FakeVimHandler::Private::isElectricCharacter(QChar c) const
@@ -4877,6 +4879,32 @@ int FakeVimHandler::Private::charClass(QChar c, bool simple) const
return c.isSpace() ? 0 : 1; return c.isSpace() ? 0 : 1;
} }
void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int cursorPos)
{
if (m_subsubmode != SearchSubSubMode && m_mode != ExMode) {
editor()->setFocus();
} else if (text.isEmpty()) {
// editing cancelled
handleDefaultKey(Input(Qt::Key_Escape, Qt::NoModifier, QString()));
editor()->setFocus();
updateCursorShape();
} else {
CommandBuffer &cmdBuf = (m_mode == ExMode) ? g.commandBuffer : g.searchBuffer;
// prepend prompt character if missing
if (!text.startsWith(cmdBuf.prompt())) {
emit q->commandBufferChanged(cmdBuf.prompt() + text, cmdBuf.cursorPos() + 1, 0, q);
cmdBuf.setContents(text, cursorPos - 1);
} else {
cmdBuf.setContents(text.mid(1), cursorPos - 1);
}
// update search expression
if (m_subsubmode == SearchSubSubMode) {
updateFind(false);
exportSelection();
}
}
}
// Helper to parse a-z,A-Z,48-57,_ // Helper to parse a-z,A-Z,48-57,_
static int someInt(const QString &str) static int someInt(const QString &str)
{ {
@@ -5657,10 +5685,10 @@ void FakeVimHandler::Private::undo()
m_undo.pop(); m_undo.pop();
if (current == rev) { if (current == rev) {
showBlackMessage(FakeVimHandler::tr("Already at oldest change")); showMessage(MessageInfo, FakeVimHandler::tr("Already at oldest change"));
return; return;
} }
showBlackMessage(QString()); clearMessage();
if (!m_undo.empty()) { if (!m_undo.empty()) {
State &state = m_undo.top(); State &state = m_undo.top();
@@ -5689,10 +5717,10 @@ void FakeVimHandler::Private::redo()
m_redo.pop(); m_redo.pop();
if (rev == current) { if (rev == current) {
showBlackMessage(FakeVimHandler::tr("Already at newest change")); showMessage(MessageInfo, FakeVimHandler::tr("Already at newest change"));
return; return;
} }
showBlackMessage(QString()); clearMessage();
if (!m_redo.empty()) { if (!m_redo.empty()) {
State &state = m_redo.top(); State &state = m_redo.top();
@@ -6224,7 +6252,7 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
return res == EventHandled; return res == EventHandled;
} }
if (active && ev->type() == QEvent::KeyPress && ob == d->editor()) { if (active && ev->type() == QEvent::KeyPress) {
QKeyEvent *kev = static_cast<QKeyEvent *>(ev); QKeyEvent *kev = static_cast<QKeyEvent *>(ev);
KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key())); KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key()));
EventResult res = d->handleEvent(kev); EventResult res = d->handleEvent(kev);
@@ -6300,14 +6328,9 @@ QString FakeVimHandler::currentFileName() const
return d->m_currentFileName; return d->m_currentFileName;
} }
void FakeVimHandler::showBlackMessage(const QString &msg) void FakeVimHandler::showMessage(MessageLevel level, const QString &msg)
{ {
d->showBlackMessage(msg); d->showMessage(level, msg);
}
void FakeVimHandler::showRedMessage(const QString &msg)
{
d->showRedMessage(msg);
} }
QWidget *FakeVimHandler::widget() QWidget *FakeVimHandler::widget()
@@ -6333,6 +6356,11 @@ QString FakeVimHandler::tabExpand(int n) const
return d->tabExpand(n); return d->tabExpand(n);
} }
void FakeVimHandler::miniBufferTextEdited(const QString &text, int cursorPos)
{
d->miniBufferTextEdited(text, cursorPos);
}
} // namespace Internal } // namespace Internal
} // namespace FakeVim } // namespace FakeVim

View File

@@ -77,6 +77,16 @@ struct ExCommand
int count; int count;
}; };
// message levels sorted by severity
enum MessageLevel
{
MessageMode, // show current mode (format "-- %1 --")
MessageCommand, // show last Ex command or search
MessageInfo, // result of a command
MessageWarning, // warning
MessageError // error
};
class FakeVimHandler : public QObject class FakeVimHandler : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -94,8 +104,7 @@ public slots:
void setCurrentFileName(const QString &fileName); void setCurrentFileName(const QString &fileName);
QString currentFileName() const; QString currentFileName() const;
void showBlackMessage(const QString &msg); void showMessage(MessageLevel level, const QString &msg);
void showRedMessage(const QString &msg);
// This executes an "ex" style command taking context // This executes an "ex" style command taking context
// information from the current widget. // information from the current widget.
@@ -114,8 +123,10 @@ public slots:
int logicalIndentation(const QString &line) const; int logicalIndentation(const QString &line) const;
QString tabExpand(int n) const; QString tabExpand(int n) const;
void miniBufferTextEdited(const QString &text, int cursorPos);
signals: signals:
void commandBufferChanged(const QString &msg, int pos); void commandBufferChanged(const QString &msg, int pos, 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

@@ -86,6 +86,7 @@
#include <QtPlugin> #include <QtPlugin>
#include <QObject> #include <QObject>
#include <QSettings> #include <QSettings>
#include <QStackedWidget>
#include <QTextStream> #include <QTextStream>
#include <QDesktopServices> #include <QDesktopServices>
@@ -111,49 +112,99 @@ const char SETTINGS_ID[] = "A.General";
const char SETTINGS_EX_CMDS_ID[] = "B.ExCommands"; const char SETTINGS_EX_CMDS_ID[] = "B.ExCommands";
const char SETTINGS_USER_CMDS_ID[] = "C.UserCommands"; const char SETTINGS_USER_CMDS_ID[] = "C.UserCommands";
class MiniBuffer : public QLabel class MiniBuffer : public QStackedWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
void setContents(const QString &contents, int cursorPos) MiniBuffer() : m_label(new QLabel(this)), m_edit(new QLineEdit(this)), m_eventFilter(0)
{ {
QString msg = contents; m_edit->installEventFilter(this);
if (cursorPos != -1) connect(m_edit, SIGNAL(textEdited(QString)), SLOT(changed()));
msg = contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos); connect(m_edit, SIGNAL(cursorPositionChanged(int,int)), SLOT(changed()));
setText(" " + msg); m_label->setTextInteractionFlags(Qt::TextSelectableByMouse);
}
};
class MiniBuffer1 : public QLineEdit addWidget(m_label);
{ addWidget(m_edit);
Q_OBJECT }
public: void setContents(const QString &contents, int cursorPos, int messageLevel, QObject *eventFilter)
MiniBuffer1()
{ {
setFrame(false); if (cursorPos != -1) {
m_edit->blockSignals(true);
m_label->clear();
m_edit->setText(contents);
m_edit->setCursorPosition(cursorPos);
m_edit->blockSignals(false);
setCurrentWidget(m_edit);
m_edit->setFocus();
} else {
m_label->setText(messageLevel == MessageMode ? "-- " + contents + " --" : contents);
QString css;
if (messageLevel == MessageError) {
css = QString("border:1px solid rgba(255,255,255,150);"
"background-color:rgba(255,0,0,100);");
} else if (messageLevel == MessageWarning) {
css = QString("border:1px solid rgba(255,255,255,120);"
"background-color:rgba(255,255,0,20);");
}
m_label->setStyleSheet(QString(
"*{border-radius:2px;padding-left:4px;padding-right:4px;%1}").arg(css));
if (m_edit->hasFocus())
emit edited(QString(), -1);
setCurrentWidget(m_label);
}
if (m_eventFilter != eventFilter) {
if (m_eventFilter != 0) {
m_edit->removeEventFilter(m_eventFilter);
disconnect(SIGNAL(edited(QString,int)));
}
if (eventFilter != 0) {
m_edit->installEventFilter(eventFilter);
connect(this, SIGNAL(edited(QString,int)),
eventFilter, SLOT(miniBufferTextEdited(QString,int)));
}
m_eventFilter = eventFilter;
}
} }
void showEvent(QShowEvent *ev)
QSize sizeHint() const
{ {
QLineEdit::showEvent(ev); QSize size = QWidget::sizeHint();
QColor color = Qt::black; // reserve maximal width for line edit widget
QPalette pal = parentWidget()->palette(); return currentWidget() == m_edit ? QSize(maximumWidth(), size.height()) : size;
pal.setBrush(QPalette::All, QPalette::WindowText, color);
pal.setBrush(QPalette::All, QPalette::ButtonText, color);
pal.setBrush(QPalette::All, QPalette::Foreground, color);
pal.setBrush(QPalette::All, QPalette::Background, color);
//color.setAlpha(100);
//pal.setBrush(QPalette::Disabled, QPalette::WindowText, color);
//pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
//pal.setBrush(QPalette::Disabled, QPalette::Foreground, color);
setPalette(pal);
} }
void setContents(const QString &contents, int cursorPos)
signals:
void edited(const QString &text, int cursorPos);
private slots:
void changed()
{ {
setText(contents); emit edited(m_edit->text(), m_edit->cursorPosition());
setCursorPosition(cursorPos);
} }
bool eventFilter(QObject *ob, QEvent *ev)
{
// cancel editing on escape
if (m_eventFilter != 0 && ob == m_edit && ev->type() == QEvent::ShortcutOverride
&& static_cast<QKeyEvent*>(ev)->key() == Qt::Key_Escape) {
emit edited(QString(), -1);
ev->accept();
return true;
}
return false;
}
private:
QLabel *m_label;
QLineEdit *m_edit;
QObject *m_eventFilter;
}; };
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -797,7 +848,9 @@ private slots:
void setBlockSelection(bool); void setBlockSelection(bool);
void hasBlockSelection(bool*); void hasBlockSelection(bool*);
void showCommandBuffer(const QString &contents, int cursorPos); void resetCommandBuffer();
void showCommandBuffer(const QString &contents, int cursorPos, 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 moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor);
@@ -1340,8 +1393,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)), connect(handler, SIGNAL(commandBufferChanged(QString,int,int,QObject*)),
SLOT(showCommandBuffer(QString,int))); SLOT(showCommandBuffer(QString,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(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)), connect(handler, SIGNAL(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)),
@@ -1376,7 +1429,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor)
// pop up the bar // pop up the bar
if (theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) { if (theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) {
showCommandBuffer(QString(), -1); resetCommandBuffer();
handler->setupWidget(); handler->setupWidget();
} }
} }
@@ -1408,7 +1461,7 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on)
//ICore *core = ICore::instance(); //ICore *core = ICore::instance();
//core->updateAdditionalContexts(Context(), //core->updateAdditionalContexts(Context(),
// Context(FAKEVIM_CONTEXT)); // Context(FAKEVIM_CONTEXT));
showCommandBuffer(QString(), -1); resetCommandBuffer();
foreach (IEditor *editor, m_editorToHandler.keys()) { foreach (IEditor *editor, m_editorToHandler.keys()) {
if (BaseTextEditorWidget *textEditor = if (BaseTextEditorWidget *textEditor =
qobject_cast<BaseTextEditorWidget *>(editor->widget())) { qobject_cast<BaseTextEditorWidget *>(editor->widget())) {
@@ -1485,22 +1538,22 @@ void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
QFile file3(fileName); QFile file3(fileName);
file3.open(QIODevice::ReadOnly); file3.open(QIODevice::ReadOnly);
QByteArray ba = file3.readAll(); QByteArray ba = file3.readAll();
handler->showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") handler->showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2 %3L, %4C written")
.arg(fileName).arg(" ") .arg(fileName).arg(" ")
.arg(ba.count('\n')).arg(ba.size())); .arg(ba.count('\n')).arg(ba.size()));
if (cmd.cmd == "wq") if (cmd.cmd == "wq")
delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler)); delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
} else { } else {
handler->showRedMessage(tr("File not saved")); handler->showMessage(MessageError, tr("File not saved"));
} }
} else if (cmd.matches("wa", "wall")) { } else if (cmd.matches("wa", "wall")) {
// :w[all] // :w[all]
QList<IDocument *> toSave = DocumentManager::modifiedDocuments(); QList<IDocument *> toSave = DocumentManager::modifiedDocuments();
QList<IDocument *> failed = DocumentManager::saveModifiedDocumentsSilently(toSave); QList<IDocument *> failed = DocumentManager::saveModifiedDocumentsSilently(toSave);
if (failed.isEmpty()) if (failed.isEmpty())
handler->showBlackMessage(tr("Saving succeeded")); handler->showMessage(MessageInfo, tr("Saving succeeded"));
else else
handler->showRedMessage(tr("%n files not saved", 0, failed.size())); handler->showMessage(MessageError, tr("%n files not saved", 0, failed.size()));
} else if (cmd.matches("q", "quit")) { } else if (cmd.matches("q", "quit")) {
// :q[uit] // :q[uit]
emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler)); emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
@@ -1666,11 +1719,17 @@ void FakeVimPluginPrivate::quitFakeVim()
theFakeVimSetting(ConfigUseFakeVim)->setValue(false); theFakeVimSetting(ConfigUseFakeVim)->setValue(false);
} }
void FakeVimPluginPrivate::showCommandBuffer(const QString &contents, int cursorPos) void FakeVimPluginPrivate::resetCommandBuffer()
{
showCommandBuffer(QString(), -1, 0, 0);
}
void FakeVimPluginPrivate::showCommandBuffer(const QString &contents, int cursorPos,
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); w->setContents(contents, cursorPos, messageLevel, eventFilter);
} }
void FakeVimPluginPrivate::showExtraInformation(const QString &text) void FakeVimPluginPrivate::showExtraInformation(const QString &text)