fakevim: prepare for better integration with creator core

For :ex commands, the plugin is now asked first unconditionally.
The handler only provides fallbacks for the standalone case.
This commit is contained in:
hjk
2010-05-18 14:48:12 +02:00
parent dcda5099a3
commit 2f99706031
5 changed files with 221 additions and 226 deletions

View File

@@ -209,11 +209,6 @@ FakeVimSettings *theFakeVimSettings()
item->setSettingsKey(group, _("IsKeyword")); item->setSettingsKey(group, _("IsKeyword"));
instance->insertItem(ConfigIsKeyword, item, _("iskeyword"), _("isk")); instance->insertItem(ConfigIsKeyword, item, _("iskeyword"), _("isk"));
item = new SavedAction(instance);
item->setText(QCoreApplication::translate("FakeVim::Internal",
"FakeVim properties..."));
instance->insertItem(SettingsDialog, item);
// Invented here. // Invented here.
item = new SavedAction(instance); item = new SavedAction(instance);
item->setDefaultValue(false); item->setDefaultValue(false);

View File

@@ -64,7 +64,6 @@ enum FakeVimSettingsCode
ConfigIsKeyword, ConfigIsKeyword,
// other actions // other actions
SettingsDialog,
ConfigShowMarks, ConfigShowMarks,
}; };

View File

@@ -217,14 +217,6 @@ enum MoveType
all characters in the affected lines up to the end all characters in the affected lines up to the end
of these lines. of these lines.
*/ */
enum RangeMode
{
RangeCharMode, // v
RangeLineMode, // V
RangeLineModeExclusive,
RangeBlockMode, // Ctrl-v
RangeBlockAndTailMode, // Ctrl-v for D and X
};
enum EventResult enum EventResult
{ {
@@ -258,38 +250,36 @@ struct Register
RangeMode rangemode; RangeMode rangemode;
}; };
struct Range
{
Range() Range::Range()
: beginPos(-1), endPos(-1), rangemode(RangeCharMode) : beginPos(-1), endPos(-1), rangemode(RangeCharMode)
{} {}
Range(int b, int e, RangeMode m = RangeCharMode) Range::Range(int b, int e, RangeMode m)
: beginPos(qMin(b, e)), endPos(qMax(b, e)), rangemode(m) : beginPos(qMin(b, e)), endPos(qMax(b, e)), rangemode(m)
{} {}
QString toString() const QString Range::toString() const
{ {
return QString("%1-%2 (mode: %3)").arg(beginPos).arg(endPos) return QString("%1-%2 (mode: %3)").arg(beginPos).arg(endPos)
.arg(rangemode); .arg(rangemode);
} }
int beginPos; QDebug operator<<(QDebug ts, const Range &range)
int endPos;
RangeMode rangemode;
};
struct ExCommand
{ {
ExCommand(const QString &c, int b = -1, int e = -1) return ts << '[' << range.beginPos << ',' << range.endPos << ']';
: line(c), range(b, e, RangeLineMode) {} }
QString line;
Range range;
};
ExCommand::ExCommand(const QString &c, const QString &a, const Range &r)
: cmd(c), hasBang(false), args(a), range(r)
{}
QDebug operator<<(QDebug ts, const ExCommand &cmd) QDebug operator<<(QDebug ts, const ExCommand &cmd)
{ {
return ts << cmd.line << cmd.range.beginPos << cmd.range.endPos; return ts << cmd.cmd << ' ' << cmd.args << ' ' << cmd.range;
} }
QDebug operator<<(QDebug ts, const QList<QTextEdit::ExtraSelection> &sels) QDebug operator<<(QDebug ts, const QList<QTextEdit::ExtraSelection> &sels)
@@ -650,13 +640,6 @@ public:
{ m_tc.beginEditBlock(); m_tc.insertText("x"); { m_tc.beginEditBlock(); m_tc.insertText("x");
m_tc.deletePreviousChar(); m_tc.endEditBlock(); } m_tc.deletePreviousChar(); m_tc.endEditBlock(); }
// this asks the layer above (e.g. the fake vim plugin or the
// stand-alone test application to handle the command)
void passUnknownExCommand(const QString &cmd);
// this asks the layer above (e.g. the fake vim plugin or the
// stand-alone test application to handle the set command)
void passUnknownSetCommand(const QString &cmd);
bool isVisualMode() const { return m_visualMode != NoVisualMode; } bool isVisualMode() const { return m_visualMode != NoVisualMode; }
bool isNoVisualMode() const { return m_visualMode == NoVisualMode; } bool isNoVisualMode() const { return m_visualMode == NoVisualMode; }
bool isVisualCharMode() const { return m_visualMode == VisualCharMode; } bool isVisualCharMode() const { return m_visualMode == VisualCharMode; }
@@ -806,6 +789,7 @@ public:
QString m_oldNeedle; QString m_oldNeedle;
bool handleExCommandHelper(const ExCommand &cmd); // Returns success. bool handleExCommandHelper(const ExCommand &cmd); // Returns success.
bool handleExPluginCommand(const ExCommand &cmd); // Handled by plugin?
bool handleExBangCommand(const ExCommand &cmd); bool handleExBangCommand(const ExCommand &cmd);
bool handleExDeleteCommand(const ExCommand &cmd); bool handleExDeleteCommand(const ExCommand &cmd);
bool handleExGotoCommand(const ExCommand &cmd); bool handleExGotoCommand(const ExCommand &cmd);
@@ -815,7 +799,7 @@ public:
bool handleExReadCommand(const ExCommand &cmd); bool handleExReadCommand(const ExCommand &cmd);
bool handleExRedoCommand(const ExCommand &cmd); bool handleExRedoCommand(const ExCommand &cmd);
bool handleExSetCommand(const ExCommand &cmd); bool handleExSetCommand(const ExCommand &cmd);
bool handleExShiftRightCommand(const ExCommand &cmd); bool handleExShiftCommand(const ExCommand &cmd);
bool handleExSourceCommand(const ExCommand &cmd); bool handleExSourceCommand(const ExCommand &cmd);
bool handleExSubstituteCommand(const ExCommand &cmd); bool handleExSubstituteCommand(const ExCommand &cmd);
bool handleExWriteCommand(const ExCommand &cmd); bool handleExWriteCommand(const ExCommand &cmd);
@@ -2819,7 +2803,8 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd)
bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
// :substitute // :substitute
{ {
QString line = cmd.line; QString line = cmd.cmd + ' ' + cmd.args;
line = line.trimmed();
if (line.startsWith(_("substitute"))) if (line.startsWith(_("substitute")))
line = line.mid(10); line = line.mid(10);
else if (line.startsWith('s') && line.size() > 1 else if (line.startsWith('s') && line.size() > 1
@@ -2827,6 +2812,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
line = line.mid(1); line = line.mid(1);
else else
return false; return false;
// we have /{pattern}/{string}/[flags] now // we have /{pattern}/{string}/[flags] now
if (line.isEmpty()) if (line.isEmpty())
return false; return false;
@@ -2899,12 +2885,10 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
{ {
const int pos1 = cmd0.line.indexOf(QLatin1Char(' '));
QByteArray modes; QByteArray modes;
enum Type { Map, Noremap, Unmap } type; enum Type { Map, Noremap, Unmap } type;
QByteArray cmd = cmd0.line.left(pos1).toLatin1(); QByteArray cmd = cmd0.cmd.toLatin1();
// Strange formatting. But everything else is even uglier. // Strange formatting. But everything else is even uglier.
if (cmd == "map") { modes = "nvo"; type = Map; } else if (cmd == "map") { modes = "nvo"; type = Map; } else
@@ -2942,15 +2926,15 @@ bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
else else
return false; return false;
const int pos2 = cmd0.line.indexOf(QLatin1Char(' '), pos1 + 1); const int pos = cmd0.args.indexOf(QLatin1Char(' '));
if (pos1 == -1 || pos2 == -1) { if (pos == -1) {
// FIXME: Dump mappings here. // FIXME: Dump mappings here.
//qDebug() << g.mappings; //qDebug() << g.mappings;
return true;; return true;;
} }
QString lhs = cmd0.line.mid(pos1 + 1, pos2 - pos1 - 1); QString lhs = cmd0.args.left(pos);
QString rhs = cmd0.line.mid(pos2 + 1); QString rhs = cmd0.args.mid(pos + 1);
Inputs key; Inputs key;
key.parseFrom(lhs); key.parseFrom(lhs);
//qDebug() << "MAPPING: " << modes << lhs << rhs; //qDebug() << "MAPPING: " << modes << lhs << rhs;
@@ -2973,14 +2957,13 @@ bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
return true; return true;
} }
bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd) // :history bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd)
{ {
static QRegExp reHistory("^his(tory)?( (.*))?$"); // :history
if (reHistory.indexIn(cmd.line) == -1) if (cmd.cmd != "his" && cmd.cmd != "history")
return false; return false;
QString arg = reHistory.cap(3); if (cmd.args.isEmpty()) {
if (arg.isEmpty()) {
QString info; QString info;
info += "# command history\n"; info += "# command history\n";
int i = 0; int i = 0;
@@ -2996,67 +2979,65 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd) // :h
return true; return true;
} }
bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) // :set bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd)
{ {
static QRegExp reSet("^set?( (.*))?$"); // :set
if (reSet.indexIn(cmd.line) == -1) if (cmd.cmd != "se" && cmd.cmd != "set")
return false; return false;
showBlackMessage(QString()); showBlackMessage(QString());
QString arg = reSet.cap(2).trimmed(); SavedAction *act = theFakeVimSettings()->item(cmd.args);
SavedAction *act = theFakeVimSettings()->item(arg); QTC_ASSERT(!cmd.args.isEmpty(), /**/); // Handled by plugin.
if (arg.isEmpty()) { if (act && act->value().type() == QVariant::Bool) {
theFakeVimSetting(SettingsDialog)->trigger(QVariant()); // Boolean config to be switched on.
} else if (act && act->value().type() == QVariant::Bool) {
// boolean config to be switched on
bool oldValue = act->value().toBool(); bool oldValue = act->value().toBool();
if (oldValue == false) if (oldValue == false)
act->setValue(true); act->setValue(true);
else if (oldValue == true) else if (oldValue == true)
{} // nothing to do {} // nothing to do
} else if (act) { } else if (act) {
// non-boolean to show // Non-boolean to show.
showBlackMessage(arg + '=' + act->value().toString()); showBlackMessage(cmd.args + '=' + act->value().toString());
} else if (arg.startsWith(_("no")) } else if (cmd.args.startsWith(_("no"))
&& (act = theFakeVimSettings()->item(arg.mid(2)))) { && (act = theFakeVimSettings()->item(cmd.args.mid(2)))) {
// boolean config to be switched off // Boolean config to be switched off.
bool oldValue = act->value().toBool(); bool oldValue = act->value().toBool();
if (oldValue == true) if (oldValue == true)
act->setValue(false); act->setValue(false);
else if (oldValue == false) else if (oldValue == false)
{} // nothing to do {} // nothing to do
} else if (arg.contains('=')) { } else if (cmd.args.contains('=')) {
// non-boolean config to set // Non-boolean config to set.
int p = arg.indexOf('='); int p = cmd.args.indexOf('=');
act = theFakeVimSettings()->item(arg.left(p)); act = theFakeVimSettings()->item(cmd.args.left(p));
if (act) if (act)
act->setValue(arg.mid(p + 1)); act->setValue(cmd.args.mid(p + 1));
} else { } else {
passUnknownSetCommand(arg); showRedMessage(FakeVimHandler::tr("Unknown option: ") + cmd.args);
} }
updateMiniBuffer(); updateMiniBuffer();
updateEditor(); updateEditor();
return true; return true;
} }
bool FakeVimHandler::Private::handleExNormalCommand(const ExCommand &cmd) // :normal bool FakeVimHandler::Private::handleExNormalCommand(const ExCommand &cmd)
{ {
static QRegExp reNormal("^norm(al)?( (.*))?$"); // :normal
if (reNormal.indexIn(cmd.line) == -1) if (cmd.cmd != "norm" && cmd.cmd != "normal")
return false; return false;
//qDebug() << "REPLAY NORMAL: " << quoteUnprintable(reNormal.cap(3)); //qDebug() << "REPLAY NORMAL: " << quoteUnprintable(reNormal.cap(3));
replay(reNormal.cap(3), 1); replay(cmd.args, 1);
return true; return true;
} }
bool FakeVimHandler::Private::handleExDeleteCommand(const ExCommand &cmd) // :d bool FakeVimHandler::Private::handleExDeleteCommand(const ExCommand &cmd)
{ {
static QRegExp reDelete("^d(elete)?( (.*))?$"); // :delete
if (reDelete.indexIn(cmd.line) == -1) if (cmd.cmd != "d" && cmd.cmd != "delete")
return false; return false;
setCurrentRange(cmd.range); setCurrentRange(cmd.range);
QString reg = reDelete.cap(3); QString reg = cmd.args;
QString text = selectText(cmd.range); QString text = selectText(cmd.range);
removeText(currentRange()); removeText(currentRange());
if (!reg.isEmpty()) { if (!reg.isEmpty()) {
@@ -3068,10 +3049,10 @@ bool FakeVimHandler::Private::handleExDeleteCommand(const ExCommand &cmd) // :d
} }
bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd) bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
// :w, :x, :q, :wq, ...
{ {
static QRegExp reWrite("^[wx]q?a?!?( (.*))?$"); // :w, :x, :wq, ...
if (reWrite.indexIn(cmd.line) == -1) // :w and :x //static QRegExp reWrite("^[wx]q?a?!?( (.*))?$");
if (cmd.cmd != "w" && cmd.cmd != "x" && cmd.cmd != "wq")
return false; return false;
int beginLine = lineForPosition(cmd.range.beginPos); int beginLine = lineForPosition(cmd.range.beginPos);
@@ -3082,16 +3063,11 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
if (endLine == -1) if (endLine == -1)
endLine = linesInDocument(); endLine = linesInDocument();
//qDebug() << "LINES: " << beginLine << endLine; //qDebug() << "LINES: " << beginLine << endLine;
int indexOfSpace = cmd.line.indexOf(QChar(' ')); QString prefix = cmd.args;
QString prefix; const bool forced = cmd.hasBang;
if (indexOfSpace < 0) //const bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
prefix = cmd.line; //const bool quitAll = quit && prefix.contains(QChar('a'));
else QString fileName = cmd.args;
prefix = cmd.line.left(indexOfSpace);
const bool forced = prefix.contains(QChar('!'));
const bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
const bool quitAll = quit && prefix.contains(QChar('a'));
QString fileName = reWrite.cap(2);
if (fileName.isEmpty()) if (fileName.isEmpty())
fileName = m_currentFileName; fileName = m_currentFileName;
QFile file1(fileName); QFile file1(fileName);
@@ -3100,16 +3076,13 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
showRedMessage(FakeVimHandler::tr showRedMessage(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.
file1.close(); file1.close();
QTextCursor tc = m_tc; QTextCursor tc = m_tc;
Range range(firstPositionInLine(beginLine), Range range(firstPositionInLine(beginLine),
firstPositionInLine(endLine), RangeLineMode); firstPositionInLine(endLine), RangeLineMode);
QString contents = selectText(range); QString contents = selectText(range);
m_tc = tc; m_tc = tc;
bool handled = false;
emit q->writeFileRequested(&handled, fileName, contents);
// Nobody cared, so act ourselves.
if (!handled) {
QFile::remove(fileName); QFile::remove(fileName);
QFile file2(fileName); QFile file2(fileName);
if (file2.open(QIODevice::ReadWrite)) { if (file2.open(QIODevice::ReadWrite)) {
@@ -3119,7 +3092,6 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
showRedMessage(FakeVimHandler::tr showRedMessage(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);
@@ -3127,10 +3099,10 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written")
.arg(fileName).arg(exists ? " " : " [New] ") .arg(fileName).arg(exists ? " " : " [New] ")
.arg(ba.count('\n')).arg(ba.size())); .arg(ba.count('\n')).arg(ba.size()));
if (quitAll) //if (quitAll)
passUnknownExCommand(forced ? "qa!" : "qa"); // passUnknownExCommand(forced ? "qa!" : "qa");
else if (quit) //else if (quit)
passUnknownExCommand(forced ? "q!" : "q"); // passUnknownExCommand(forced ? "q!" : "q");
} else { } else {
showRedMessage(FakeVimHandler::tr showRedMessage(FakeVimHandler::tr
("Cannot open file \"%1\" for reading").arg(fileName)); ("Cannot open file \"%1\" for reading").arg(fileName));
@@ -3138,16 +3110,17 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
return true; return true;
} }
bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd) // :r bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd)
{ {
if (!cmd.line.startsWith(_("r "))) // :read
if (cmd.cmd != "r" && cmd.cmd != "read")
return false; return false;
beginEditBlock(); beginEditBlock();
moveToStartOfLine(); moveToStartOfLine();
setTargetColumn(); setTargetColumn();
moveDown(); moveDown();
m_currentFileName = cmd.line.mid(2).trimmed(); m_currentFileName = cmd.args;
QFile file(m_currentFileName); QFile file(m_currentFileName);
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QTextStream ts(&file); QTextStream ts(&file);
@@ -3161,12 +3134,12 @@ bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd) // :r
bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
{ {
if (!cmd.line.startsWith(QLatin1Char('!'))) if (!cmd.cmd.startsWith(QLatin1Char('!')))
return false; return false;
setCurrentRange(cmd.range); setCurrentRange(cmd.range);
int targetPosition = firstPositionInLine(lineForPosition(cmd.range.beginPos)); int targetPosition = firstPositionInLine(lineForPosition(cmd.range.beginPos));
QString command = cmd.line.mid(1).trimmed(); QString command = QString(cmd.cmd.mid(1) + ' ' + cmd.args).trimmed();
QString text = selectText(cmd.range); QString text = selectText(cmd.range);
QProcess proc; QProcess proc;
proc.start(command); proc.start(command);
@@ -3190,24 +3163,29 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
return true; return true;
} }
bool FakeVimHandler::Private::handleExShiftRightCommand(const ExCommand &cmd) // :> bool FakeVimHandler::Private::handleExShiftCommand(const ExCommand &cmd)
{ {
if (!cmd.line.startsWith(QLatin1Char('>'))) if (cmd.cmd != "<" && cmd.cmd != ">")
return false; return false;
setCurrentRange(cmd.range); setCurrentRange(cmd.range);
shiftRegionRight(1); int count = qMin(1, cmd.args.toInt());
if (cmd.cmd == "<")
shiftRegionLeft(count);
else
shiftRegionRight(count);
leaveVisualMode(); leaveVisualMode();
const int beginLine = lineForPosition(cmd.range.beginPos); const int beginLine = lineForPosition(cmd.range.beginPos);
const int endLine = lineForPosition(cmd.range.endPos); const int endLine = lineForPosition(cmd.range.endPos);
showBlackMessage(FakeVimHandler::tr("%n lines >ed %1 time", 0, showBlackMessage(FakeVimHandler::tr("%n lines %1ed %2 time", 0,
(endLine - beginLine + 1)).arg(1)); (endLine - beginLine + 1)).arg(cmd.cmd).arg(count));
return true; return true;
} }
bool FakeVimHandler::Private::handleExRedoCommand(const ExCommand &cmd) // :redo bool FakeVimHandler::Private::handleExRedoCommand(const ExCommand &cmd)
{ {
if (cmd.line != "red" && cmd.line != "redo") // :redo
if (cmd.cmd != "red" && cmd.cmd != "redo")
return false; return false;
redo(); redo();
@@ -3215,10 +3193,10 @@ bool FakeVimHandler::Private::handleExRedoCommand(const ExCommand &cmd) // :redo
return true; return true;
} }
bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd) // :<nr> bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd)
{ {
// Only "range" given. // :<nr>
if (!cmd.line.isEmpty()) if (!cmd.cmd.isEmpty())
return false; return false;
const int beginLine = lineForPosition(cmd.range.beginPos); const int beginLine = lineForPosition(cmd.range.beginPos);
@@ -3227,13 +3205,13 @@ bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd) // :<nr>
return true; return true;
} }
bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd) // :source bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd)
{ {
const int pos = cmd.line.indexOf(' '); // :source
if (cmd.line.leftRef(pos) != "so" && cmd.line.leftRef(pos) != "source") if (cmd.cmd != "so" && cmd.cmd != "source")
return false; return false;
QString fileName = cmd.line.mid(pos + 1).trimmed(); QString fileName = cmd.args;
QFile file(fileName); QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
showRedMessage(FakeVimHandler::tr("Can't open file %1").arg(fileName)); showRedMessage(FakeVimHandler::tr("Can't open file %1").arg(fileName));
@@ -3266,8 +3244,6 @@ bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd) // :so
void FakeVimHandler::Private::handleExCommand(const QString &line0) void FakeVimHandler::Private::handleExCommand(const QString &line0)
{ {
QString line = line0; // Make sure we have a copy to prevent aliasing. QString line = line0; // Make sure we have a copy to prevent aliasing.
ExCommand cmd(line, -1, -1);
// FIXME: that seems to be different for %w and %s // FIXME: that seems to be different for %w and %s
if (line.startsWith(QLatin1Char('%'))) if (line.startsWith(QLatin1Char('%')))
line = "1,$" + line.mid(1); line = "1,$" + line.mid(1);
@@ -3282,19 +3258,26 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0)
endLine = beginLine; endLine = beginLine;
const int beginPos = firstPositionInLine(beginLine); const int beginPos = firstPositionInLine(beginLine);
const int endPos = lastPositionInLine(endLine); const int endPos = lastPositionInLine(endLine);
ExCommand cmd;
const QString arg0 = line.section(' ', 0, 0);
cmd.cmd = arg0;
cmd.args = line.mid(arg0.size() + 1).trimmed();
cmd.range = Range(beginPos, endPos, RangeLineMode); cmd.range = Range(beginPos, endPos, RangeLineMode);
cmd.line = line; cmd.hasBang = arg0.endsWith('!');
if (cmd.hasBang)
cmd.cmd.chop(1);
//qDebug() << "CMD: " << cmd; //qDebug() << "CMD: " << cmd;
enterCommandMode(); enterCommandMode();
showBlackMessage(QString()); showBlackMessage(QString());
if (!handleExCommandHelper(cmd)) if (!handleExCommandHelper(cmd))
passUnknownExCommand(cmd.line); showRedMessage(tr("Not an editor command: %1").arg(cmd.cmd));
} }
bool FakeVimHandler::Private::handleExCommandHelper(const ExCommand &cmd) bool FakeVimHandler::Private::handleExCommandHelper(const ExCommand &cmd)
{ {
return handleExGotoCommand(cmd) return handleExPluginCommand(cmd)
|| handleExGotoCommand(cmd)
|| handleExBangCommand(cmd) || handleExBangCommand(cmd)
|| handleExHistoryCommand(cmd) || handleExHistoryCommand(cmd)
|| handleExDeleteCommand(cmd) || handleExDeleteCommand(cmd)
@@ -3303,27 +3286,21 @@ bool FakeVimHandler::Private::handleExCommandHelper(const ExCommand &cmd)
|| handleExReadCommand(cmd) || handleExReadCommand(cmd)
|| handleExRedoCommand(cmd) || handleExRedoCommand(cmd)
|| handleExSetCommand(cmd) || handleExSetCommand(cmd)
|| handleExShiftRightCommand(cmd) || handleExShiftCommand(cmd)
|| handleExSourceCommand(cmd) || handleExSourceCommand(cmd)
|| handleExSubstituteCommand(cmd) || handleExSubstituteCommand(cmd)
|| handleExWriteCommand(cmd); || handleExWriteCommand(cmd);
} }
void FakeVimHandler::Private::passUnknownExCommand(const QString &cmd) bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd)
{ {
EDITOR(setTextCursor(m_tc)); EDITOR(setTextCursor(m_tc));
emit q->handleExCommandRequested(cmd); bool handled = false;
emit q->handleExCommandRequested(&handled, cmd);
if (m_plaintextedit || m_textedit) if (m_plaintextedit || m_textedit)
m_tc = EDITOR(textCursor()); m_tc = EDITOR(textCursor());
} //qDebug() << "HANDLER REQUEST: " << cmd.cmd << handled;
return handled;
void FakeVimHandler::Private::passUnknownSetCommand(const QString &arg)
{
bool handled = false;
emit q->handleSetCommandRequested(&handled, arg);
if (!handled) {
showRedMessage(FakeVimHandler::tr("Unknown option: ") + arg);
}
} }
static void vimPatternToQtPattern(QString *needle, QTextDocument::FindFlags *flags) static void vimPatternToQtPattern(QString *needle, QTextDocument::FindFlags *flags)
@@ -4585,6 +4562,11 @@ void FakeVimHandler::setCurrentFileName(const QString &fileName)
d->m_currentFileName = fileName; d->m_currentFileName = fileName;
} }
QString FakeVimHandler::currentFileName() const
{
return d->m_currentFileName;
}
void FakeVimHandler::showBlackMessage(const QString &msg) void FakeVimHandler::showBlackMessage(const QString &msg)
{ {
d->showBlackMessage(msg); d->showBlackMessage(msg);

View File

@@ -38,6 +38,38 @@
namespace FakeVim { namespace FakeVim {
namespace Internal { namespace Internal {
enum RangeMode
{
RangeCharMode, // v
RangeLineMode, // V
RangeLineModeExclusive,
RangeBlockMode, // Ctrl-v
RangeBlockAndTailMode, // Ctrl-v for D and X
};
struct Range
{
Range();
Range(int b, int e, RangeMode m = RangeCharMode);
QString toString() const;
int beginPos;
int endPos;
RangeMode rangemode;
};
struct ExCommand
{
ExCommand() : hasBang(false) {}
ExCommand(const QString &cmd, const QString &args = QString(),
const Range &range = Range());
QString cmd;
bool hasBang;
QString args;
Range range;
};
class FakeVimHandler : public QObject class FakeVimHandler : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -53,6 +85,8 @@ public:
public slots: public slots:
void setCurrentFileName(const QString &fileName); void setCurrentFileName(const QString &fileName);
QString currentFileName() const;
void showBlackMessage(const QString &msg); void showBlackMessage(const QString &msg);
void showRedMessage(const QString &msg); void showRedMessage(const QString &msg);
@@ -76,8 +110,6 @@ signals:
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);
void writeFileRequested(bool *handled,
const QString &fileName, const QString &contents);
void writeAllRequested(QString *error); void writeAllRequested(QString *error);
void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor);
void checkForElectricCharacter(bool *result, QChar c); void checkForElectricCharacter(bool *result, QChar c);
@@ -86,8 +118,7 @@ signals:
void windowCommandRequested(int key); void windowCommandRequested(int key);
void findRequested(bool reverse); void findRequested(bool reverse);
void findNextRequested(bool reverse); void findNextRequested(bool reverse);
void handleExCommandRequested(const QString &cmd); void handleExCommandRequested(bool *handled, const ExCommand &cmd);
void handleSetCommandRequested(bool *handled, const QString &cmd);
public: public:
class Private; class Private;
@@ -101,4 +132,7 @@ private:
} // namespace Internal } // namespace Internal
} // namespace FakeVim } // namespace FakeVim
Q_DECLARE_METATYPE(FakeVim::Internal::ExCommand);
#endif // FAKEVIM_HANDLER_H #endif // FAKEVIM_HANDLER_H

View File

@@ -73,9 +73,9 @@
#include <indenter.h> #include <indenter.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QtPlugin> #include <QtCore/QtPlugin>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QSettings> #include <QtCore/QSettings>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
@@ -503,12 +503,10 @@ private slots:
void showCommandBuffer(const QString &contents); void showCommandBuffer(const QString &contents);
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 writeFile(bool *handled, const QString &fileName, const QString &contents);
void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor);
void checkForElectricCharacter(bool *result, QChar c); void checkForElectricCharacter(bool *result, QChar c);
void indentRegion(int *amount, int beginLine, int endLine, QChar typedChar); void indentRegion(int *amount, int beginLine, int endLine, QChar typedChar);
void handleExCommand(const QString &cmd); void handleExCommand(bool *handled, const ExCommand &cmd);
void handleSetCommand(bool *handled, QString cmd);
void handleDelayedQuitAll(bool forced); void handleDelayedQuitAll(bool forced);
void handleDelayedQuit(bool forced, Core::IEditor *editor); void handleDelayedQuit(bool forced, Core::IEditor *editor);
@@ -611,8 +609,6 @@ bool FakeVimPluginPrivate::initialize()
connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)), connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
this, SLOT(editorOpened(Core::IEditor*))); this, SLOT(editorOpened(Core::IEditor*)));
connect(theFakeVimSetting(SettingsDialog), SIGNAL(triggered()),
this, SLOT(showSettingsDialog()));
connect(theFakeVimSetting(ConfigUseFakeVim), SIGNAL(valueChanged(QVariant)), connect(theFakeVimSetting(ConfigUseFakeVim), SIGNAL(valueChanged(QVariant)),
this, SLOT(setUseFakeVim(QVariant))); this, SLOT(setUseFakeVim(QVariant)));
connect(theFakeVimSetting(ConfigReadVimRc), SIGNAL(valueChanged(QVariant)), connect(theFakeVimSetting(ConfigReadVimRc), SIGNAL(valueChanged(QVariant)),
@@ -628,7 +624,7 @@ bool FakeVimPluginPrivate::initialize()
cmd->setAttribute(Command::CA_Hide); cmd->setAttribute(Command::CA_Hide);
connect(switchFilePrevAction, SIGNAL(triggered()), this, SLOT(switchFilePrev())); connect(switchFilePrevAction, SIGNAL(triggered()), this, SLOT(switchFilePrev()));
// Delayed operatiosn // Delayed operations.
connect(this, SIGNAL(delayedQuitRequested(bool,Core::IEditor*)), connect(this, SIGNAL(delayedQuitRequested(bool,Core::IEditor*)),
this, SLOT(handleDelayedQuit(bool,Core::IEditor*)), Qt::QueuedConnection); this, SLOT(handleDelayedQuit(bool,Core::IEditor*)), Qt::QueuedConnection);
connect(this, SIGNAL(delayedQuitAllRequested(bool)), connect(this, SIGNAL(delayedQuitAllRequested(bool)),
@@ -830,8 +826,6 @@ void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)
this, SLOT(showExtraInformation(QString))); this, SLOT(showExtraInformation(QString)));
connect(handler, SIGNAL(commandBufferChanged(QString)), connect(handler, SIGNAL(commandBufferChanged(QString)),
this, SLOT(showCommandBuffer(QString))); this, SLOT(showCommandBuffer(QString)));
connect(handler, SIGNAL(writeFileRequested(bool*,QString,QString)),
this, SLOT(writeFile(bool*,QString,QString)));
connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)), connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
this, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>))); this, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
connect(handler, SIGNAL(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)), connect(handler, SIGNAL(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)),
@@ -849,10 +843,8 @@ void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)
connect(handler, SIGNAL(findNextRequested(bool)), connect(handler, SIGNAL(findNextRequested(bool)),
this, SLOT(findNext(bool))); this, SLOT(findNext(bool)));
connect(handler, SIGNAL(handleExCommandRequested(QString)), connect(handler, SIGNAL(handleExCommandRequested(bool*,ExCommand)),
this, SLOT(handleExCommand(QString))); this, SLOT(handleExCommand(bool*,ExCommand)));
connect(handler, SIGNAL(handleSetCommandRequested(bool *,QString)),
this, SLOT(handleSetCommand(bool *,QString)));
handler->setCurrentFileName(editor->file()->fileName()); handler->setCurrentFileName(editor->file()->fileName());
handler->installEventFilter(); handler->installEventFilter();
@@ -913,36 +905,12 @@ void FakeVimPluginPrivate::checkForElectricCharacter(bool *result, QChar c)
*result = bt->isElectricCharacter(c); *result = bt->isElectricCharacter(c);
} }
void FakeVimPluginPrivate::writeFile(bool *handled, void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
const QString &fileName, const QString &contents)
{
Q_UNUSED(contents)
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
if (!handler)
return;
Core::IEditor *editor = m_editorToHandler.key(handler);
if (editor && editor->file()->fileName() == fileName) {
// Handle that as a special case for nicer interaction with core
Core::IFile *file = editor->file();
Core::ICore::instance()->fileManager()->blockFileChange(file);
file->save(fileName);
Core::ICore::instance()->fileManager()->unblockFileChange(file);
*handled = true;
}
}
void FakeVimPluginPrivate::handleExCommand(const QString &cmd)
{ {
using namespace Core; using namespace Core;
//qDebug() << "PLUGIN HANDLE: " << cmd.cmd;
QString cmd0 = cmd.section(QLatin1Char(' '), 0, 0); *handled = false;
bool hasBang = false;
if (cmd.endsWith('!')) {
hasBang = true;
cmd0.chop(1);
}
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender()); FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
if (!handler) if (!handler)
@@ -951,7 +919,27 @@ void FakeVimPluginPrivate::handleExCommand(const QString &cmd)
EditorManager *editorManager = EditorManager::instance(); EditorManager *editorManager = EditorManager::instance();
QTC_ASSERT(editorManager, return); QTC_ASSERT(editorManager, return);
if (cmd0 == "wa" || cmd0 == "wall") { *handled = true;
if (cmd.cmd == "w" || cmd.cmd == "write") {
Core::IEditor *editor = m_editorToHandler.key(handler);
const QString fileName = handler->currentFileName();
if (editor && editor->file()->fileName() == fileName) {
// Handle that as a special case for nicer interaction with core
Core::IFile *file = editor->file();
Core::ICore::instance()->fileManager()->blockFileChange(file);
file->save(fileName);
Core::ICore::instance()->fileManager()->unblockFileChange(file);
// Check result by reading back.
QFile file3(fileName);
file3.open(QIODevice::ReadOnly);
QByteArray ba = file3.readAll();
handler->showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written")
.arg(fileName).arg(" ")
.arg(ba.count('\n')).arg(ba.size()));
} else {
handler->showRedMessage(tr("File not saved"));
}
} else if (cmd.cmd == "wa" || cmd.cmd == "wall") {
// :wa // :wa
FileManager *fm = ICore::instance()->fileManager(); FileManager *fm = ICore::instance()->fileManager();
QList<IFile *> toSave = fm->modifiedFiles(); QList<IFile *> toSave = fm->modifiedFiles();
@@ -960,50 +948,47 @@ void FakeVimPluginPrivate::handleExCommand(const QString &cmd)
handler->showBlackMessage(tr("Saving succeeded")); handler->showBlackMessage(tr("Saving succeeded"));
else else
handler->showRedMessage(tr("%n files not saved", 0, failed.size())); handler->showRedMessage(tr("%n files not saved", 0, failed.size()));
} else if (cmd0 == "q" || cmd0 == "quit") { } else if (cmd.cmd == "q" || cmd.cmd == "quit") {
// :q[uit] // :q[uit]
emit delayedQuitRequested(hasBang, m_editorToHandler.key(handler)); emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
} else if (cmd0 == "qa" || cmd0 == "qall") { } else if (cmd.cmd == "qa" || cmd.cmd == "qall") {
// :qa // :qa
emit delayedQuitAllRequested(hasBang); emit delayedQuitAllRequested(cmd.hasBang);
} else if (cmd0 == "sp" || cmd0 == "split") { } else if (cmd.cmd == "sp" || cmd.cmd == "split") {
// :sp[lit] // :sp[lit]
triggerAction(Core::Constants::SPLIT); triggerAction(Core::Constants::SPLIT);
} else if (cmd0 == "vs" || cmd0 == "vsplit") { } else if (cmd.cmd == "vs" || cmd.cmd == "vsplit") {
// :vs[plit] // :vs[plit]
triggerAction(Core::Constants::SPLIT_SIDE_BY_SIDE); triggerAction(Core::Constants::SPLIT_SIDE_BY_SIDE);
} else if (cmd0 == "mak" || cmd0 == "make") { } else if (cmd.cmd == "mak" || cmd.cmd == "make") {
// :mak[e][!] [arguments] // :mak[e][!] [arguments]
triggerAction(ProjectExplorer::Constants::BUILD); triggerAction(ProjectExplorer::Constants::BUILD);
} else if (cmd.cmd == "se" || cmd.cmd == "set") {
if (cmd.args.isEmpty()) {
// :set
showSettingsDialog();
} else if (cmd.args == "ic" || cmd.args == "ignorecase") {
// :set noic
setActionChecked(Find::Constants::CASE_SENSITIVE, false);
*handled = false; // Let the handler see it as well.
} else if (cmd.args == "noic" || cmd.args == "noignorecase") {
// :set noic
setActionChecked(Find::Constants::CASE_SENSITIVE, true);
*handled = false; // Let the handler see it as well.
}
} else { } else {
// Check whether one of the configure commands matches.
typedef QMap<QString, QRegExp>::const_iterator Iterator; typedef QMap<QString, QRegExp>::const_iterator Iterator;
const Iterator end = s_exCommandMap.constEnd(); const Iterator end = s_exCommandMap.constEnd();
for (Iterator it = s_exCommandMap.constBegin(); it != end; ++it) { for (Iterator it = s_exCommandMap.constBegin(); it != end; ++it) {
const QString &id = it.key(); const QString &id = it.key();
const QRegExp &re = it.value(); const QRegExp &re = it.value();
if (!re.pattern().isEmpty() && re.indexIn(cmd.args) != -1) {
if (!re.pattern().isEmpty() && re.indexIn(cmd) != -1) {
triggerAction(id); triggerAction(id);
return; return;
} }
} }
handler->showRedMessage(tr("Not an editor command: %1").arg(cmd));
}
}
void FakeVimPluginPrivate::handleSetCommand(bool *handled, QString cmd)
{
*handled = false; *handled = false;
bool value = true;
if (cmd.startsWith("no")) {
value = false;
cmd = cmd.mid(2);
}
if (cmd == "ic" || cmd == "ignorecase") {
setActionChecked(Find::Constants::CASE_SENSITIVE, value);
*handled = true;
} }
} }