forked from qt-creator/qt-creator
fakevim: rework support for marks
This commit is contained in:
@@ -128,6 +128,7 @@ namespace Internal {
|
|||||||
#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s)
|
#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s)
|
||||||
|
|
||||||
const int ParagraphSeparator = 0x00002029;
|
const int ParagraphSeparator = 0x00002029;
|
||||||
|
typedef QLatin1String _;
|
||||||
|
|
||||||
using namespace Qt;
|
using namespace Qt;
|
||||||
|
|
||||||
@@ -232,6 +233,20 @@ enum EventResult
|
|||||||
EventPassedToCore
|
EventPassedToCore
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExCommand
|
||||||
|
{
|
||||||
|
ExCommand(const QString &c, int b = -1, int e = -1)
|
||||||
|
: line(c), beginLine(b), endLine(e) {}
|
||||||
|
QString line;
|
||||||
|
int beginLine;
|
||||||
|
int endLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug ts, const ExCommand &cmd)
|
||||||
|
{
|
||||||
|
return ts << cmd.line << cmd.beginLine << cmd.endLine;
|
||||||
|
}
|
||||||
|
|
||||||
struct Column
|
struct Column
|
||||||
{
|
{
|
||||||
Column(int p, int l) : physical(p), logical(l) {}
|
Column(int p, int l) : physical(p), logical(l) {}
|
||||||
@@ -251,6 +266,7 @@ struct CursorPosition
|
|||||||
struct Register
|
struct Register
|
||||||
{
|
{
|
||||||
Register() : rangemode(RangeCharMode) {}
|
Register() : rangemode(RangeCharMode) {}
|
||||||
|
Register(const QString &c) : contents(c), rangemode(RangeCharMode) {}
|
||||||
Register(const QString &c, RangeMode m) : contents(c), rangemode(m) {}
|
Register(const QString &c, RangeMode m) : contents(c), rangemode(m) {}
|
||||||
QString contents;
|
QString contents;
|
||||||
RangeMode rangemode;
|
RangeMode rangemode;
|
||||||
@@ -293,7 +309,7 @@ QString quoteUnprintable(const QString &ba)
|
|||||||
if (c.isPrint())
|
if (c.isPrint())
|
||||||
res += c;
|
res += c;
|
||||||
else if (cc == '\n')
|
else if (cc == '\n')
|
||||||
res += QLatin1String("<CR>");
|
res += _("<CR>");
|
||||||
else
|
else
|
||||||
res += QString("\\x%1").arg(c.unicode(), 2, 16, QLatin1Char('0'));
|
res += QString("\\x%1").arg(c.unicode(), 2, 16, QLatin1Char('0'));
|
||||||
}
|
}
|
||||||
@@ -313,7 +329,7 @@ static bool startsWithWhitespace(const QString &str, int col)
|
|||||||
|
|
||||||
inline QString msgMarkNotSet(const QString &text)
|
inline QString msgMarkNotSet(const QString &text)
|
||||||
{
|
{
|
||||||
return FakeVimHandler::tr("E20: Mark '%1' not set").arg(text);
|
return FakeVimHandler::tr("Mark '%1' not set").arg(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Input
|
class Input
|
||||||
@@ -378,6 +394,11 @@ public:
|
|||||||
|
|
||||||
QString text() const { return m_text; }
|
QString text() const { return m_text; }
|
||||||
|
|
||||||
|
QChar asChar() const
|
||||||
|
{
|
||||||
|
return (m_text.size() == 1 ? m_text.at(0) : QChar());
|
||||||
|
}
|
||||||
|
|
||||||
int key() const { return m_key; }
|
int key() const { return m_key; }
|
||||||
|
|
||||||
QDebug dump(QDebug ts) const
|
QDebug dump(QDebug ts) const
|
||||||
@@ -551,7 +572,7 @@ public:
|
|||||||
int lastPositionInLine(int line) const; // 1 based line, 0 based pos
|
int lastPositionInLine(int line) const; // 1 based line, 0 based pos
|
||||||
int lineForPosition(int pos) const; // 1 based line, 0 based pos
|
int lineForPosition(int pos) const; // 1 based line, 0 based pos
|
||||||
QString lineContents(int line) const; // 1 based line
|
QString lineContents(int line) const; // 1 based line
|
||||||
void setLineContents(int line, const QString &contents) const; // 1 based line
|
void setLineContents(int line, const QString &contents); // 1 based line
|
||||||
|
|
||||||
int linesOnScreen() const;
|
int linesOnScreen() const;
|
||||||
int columnsOnScreen() const;
|
int columnsOnScreen() const;
|
||||||
@@ -706,6 +727,7 @@ public:
|
|||||||
void transformText(const Range &range, Transformation transformation,
|
void transformText(const Range &range, Transformation transformation,
|
||||||
const QVariant &extraData = QVariant());
|
const QVariant &extraData = QVariant());
|
||||||
|
|
||||||
|
void insertText(const Register ®);
|
||||||
void removeSelectedText();
|
void removeSelectedText();
|
||||||
void removeText(const Range &range);
|
void removeText(const Range &range);
|
||||||
void removeTransform(TransformationData *td);
|
void removeTransform(TransformationData *td);
|
||||||
@@ -756,8 +778,9 @@ public:
|
|||||||
VisualMode m_visualMode;
|
VisualMode m_visualMode;
|
||||||
|
|
||||||
// marks as lines
|
// marks as lines
|
||||||
|
int mark(int code) const;
|
||||||
|
void setMark(int code, int position);
|
||||||
QHash<int, int> m_marks;
|
QHash<int, int> m_marks;
|
||||||
QString m_oldNeedle;
|
|
||||||
|
|
||||||
// vi style configuration
|
// vi style configuration
|
||||||
QVariant config(int code) const { return theFakeVimSetting(code)->value(); }
|
QVariant config(int code) const { return theFakeVimSetting(code)->value(); }
|
||||||
@@ -783,22 +806,23 @@ public:
|
|||||||
QVector<CursorPosition> m_jumpListRedo;
|
QVector<CursorPosition> m_jumpListRedo;
|
||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> m_searchSelections;
|
QList<QTextEdit::ExtraSelection> m_searchSelections;
|
||||||
|
QString m_oldNeedle;
|
||||||
|
|
||||||
bool handleExCommandHelper(const QString &cmd); // Returns success.
|
bool handleExCommandHelper(const ExCommand &cmd); // Returns success.
|
||||||
QString extractCommand(const QString &line, int *beginLine, int *endLine);
|
ExCommand extractExCommand(const QString &line);
|
||||||
bool handleExBangCommand(const QString &line);
|
bool handleExBangCommand(const ExCommand &cmd);
|
||||||
bool handleExDeleteCommand(const QString &line);
|
bool handleExDeleteCommand(const ExCommand &cmd);
|
||||||
bool handleExGotoCommand(const QString &line);
|
bool handleExGotoCommand(const ExCommand &cmd);
|
||||||
bool handleExHistoryCommand(const QString &line);
|
bool handleExHistoryCommand(const ExCommand &cmd);
|
||||||
bool handleExMapCommand(const QString &line);
|
bool handleExMapCommand(const ExCommand &cmd);
|
||||||
bool handleExNormalCommand(const QString &line);
|
bool handleExNormalCommand(const ExCommand &cmd);
|
||||||
bool handleExReadCommand(const QString &line);
|
bool handleExReadCommand(const ExCommand &cmd);
|
||||||
bool handleExRedoCommand(const QString &line);
|
bool handleExRedoCommand(const ExCommand &cmd);
|
||||||
bool handleExSetCommand(const QString &line);
|
bool handleExSetCommand(const ExCommand &cmd);
|
||||||
bool handleExShiftRightCommand(const QString &line);
|
bool handleExShiftRightCommand(const ExCommand &cmd);
|
||||||
bool handleExSourceCommand(const QString &line);
|
bool handleExSourceCommand(const ExCommand &cmd);
|
||||||
bool handleExSubstituteCommand(const QString &line);
|
bool handleExSubstituteCommand(const ExCommand &cmd);
|
||||||
bool handleExWriteCommand(const QString &line);
|
bool handleExWriteCommand(const ExCommand &cmd);
|
||||||
|
|
||||||
void timerEvent(QTimerEvent *ev);
|
void timerEvent(QTimerEvent *ev);
|
||||||
|
|
||||||
@@ -1028,8 +1052,8 @@ void FakeVimHandler::Private::importSelection()
|
|||||||
else
|
else
|
||||||
tc.movePosition(Left, KeepAnchor);
|
tc.movePosition(Left, KeepAnchor);
|
||||||
}
|
}
|
||||||
m_marks['<'] = anc;
|
setMark('<', anc);
|
||||||
m_marks['>'] = pos;
|
setMark('>', pos);
|
||||||
m_anchor = anc;
|
m_anchor = anc;
|
||||||
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
|
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
|
||||||
if (!tc.hasSelection())
|
if (!tc.hasSelection())
|
||||||
@@ -1067,15 +1091,15 @@ void FakeVimHandler::Private::restoreWidget(int tabSize)
|
|||||||
|
|
||||||
if (isVisualLineMode()) {
|
if (isVisualLineMode()) {
|
||||||
m_tc = EDITOR(textCursor());
|
m_tc = EDITOR(textCursor());
|
||||||
int beginLine = lineForPosition(m_marks['<']);
|
int beginLine = lineForPosition(mark('<'));
|
||||||
int endLine = lineForPosition(m_marks['>']);
|
int endLine = lineForPosition(mark('>'));
|
||||||
m_tc.setPosition(firstPositionInLine(beginLine), MoveAnchor);
|
m_tc.setPosition(firstPositionInLine(beginLine), MoveAnchor);
|
||||||
m_tc.setPosition(lastPositionInLine(endLine), KeepAnchor);
|
m_tc.setPosition(lastPositionInLine(endLine), KeepAnchor);
|
||||||
EDITOR(setTextCursor(m_tc));
|
EDITOR(setTextCursor(m_tc));
|
||||||
} else if (isVisualCharMode() || isVisualBlockMode()) {
|
} else if (isVisualCharMode() || isVisualBlockMode()) {
|
||||||
m_tc = EDITOR(textCursor());
|
m_tc = EDITOR(textCursor());
|
||||||
m_tc.setPosition(m_marks['<'], MoveAnchor);
|
m_tc.setPosition(mark('<'), MoveAnchor);
|
||||||
m_tc.setPosition(m_marks['>'], KeepAnchor);
|
m_tc.setPosition(mark('>'), KeepAnchor);
|
||||||
EDITOR(setTextCursor(m_tc));
|
EDITOR(setTextCursor(m_tc));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1172,7 +1196,7 @@ void FakeVimHandler::Private::setAnchor()
|
|||||||
if (!isVisualMode()) {
|
if (!isVisualMode()) {
|
||||||
m_anchor = m_tc.position();
|
m_anchor = m_tc.position();
|
||||||
} else {
|
} else {
|
||||||
// m_marks['<'] = m_tc.position();
|
// setMark('<', m_tc.position());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1246,7 +1270,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isVisualMode())
|
if (isVisualMode())
|
||||||
m_marks['>'] = m_tc.position();
|
setMark('>', m_tc.position());
|
||||||
|
|
||||||
if (m_submode == ChangeSubMode
|
if (m_submode == ChangeSubMode
|
||||||
|| m_submode == DeleteSubMode
|
|| m_submode == DeleteSubMode
|
||||||
@@ -1314,7 +1338,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
|
|||||||
const int la = lineForPosition(anchor());
|
const int la = lineForPosition(anchor());
|
||||||
const int lp = lineForPosition(position());
|
const int lp = lineForPosition(position());
|
||||||
if (m_register != '"') {
|
if (m_register != '"') {
|
||||||
setPosition(m_marks[m_register]);
|
setPosition(mark(m_register));
|
||||||
moveToStartOfLine();
|
moveToStartOfLine();
|
||||||
} else {
|
} else {
|
||||||
if (anchor() <= position())
|
if (anchor() <= position())
|
||||||
@@ -1394,7 +1418,7 @@ void FakeVimHandler::Private::updateSelection()
|
|||||||
sel.format.setBackground(Qt::black);
|
sel.format.setBackground(Qt::black);
|
||||||
#endif
|
#endif
|
||||||
const int cursorPos = m_tc.position();
|
const int cursorPos = m_tc.position();
|
||||||
const int anchorPos = m_marks['<'];
|
const int anchorPos = mark('<');
|
||||||
//qDebug() << "POS: " << cursorPos << " ANCHOR: " << anchorPos;
|
//qDebug() << "POS: " << cursorPos << " ANCHOR: " << anchorPos;
|
||||||
if (isVisualCharMode()) {
|
if (isVisualCharMode()) {
|
||||||
sel.cursor.setPosition(qMin(cursorPos, anchorPos), MoveAnchor);
|
sel.cursor.setPosition(qMin(cursorPos, anchorPos), MoveAnchor);
|
||||||
@@ -1602,12 +1626,13 @@ EventResult FakeVimHandler::Private::handleCommandSubSubMode(const Input &input)
|
|||||||
finishMovement();
|
finishMovement();
|
||||||
}
|
}
|
||||||
} else if (m_subsubmode == MarkSubSubMode) {
|
} else if (m_subsubmode == MarkSubSubMode) {
|
||||||
m_marks[input.key()] = m_tc.position();
|
setMark(input.asChar().unicode(), m_tc.position());
|
||||||
m_subsubmode = NoSubSubMode;
|
m_subsubmode = NoSubSubMode;
|
||||||
} else if (m_subsubmode == BackTickSubSubMode
|
} else if (m_subsubmode == BackTickSubSubMode
|
||||||
|| m_subsubmode == TickSubSubMode) {
|
|| m_subsubmode == TickSubSubMode) {
|
||||||
if (m_marks.contains(input.key())) {
|
int m = mark(input.asChar().unicode());
|
||||||
setPosition(m_marks[input.key()]);
|
if (m != -1) {
|
||||||
|
setPosition(m);
|
||||||
if (m_subsubmode == TickSubSubMode)
|
if (m_subsubmode == TickSubSubMode)
|
||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
finishMovement();
|
finishMovement();
|
||||||
@@ -1756,7 +1781,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
|
|||||||
} else if (input.is(':')) {
|
} else if (input.is(':')) {
|
||||||
enterExMode();
|
enterExMode();
|
||||||
m_currentMessage.clear();
|
m_currentMessage.clear();
|
||||||
m_commandPrefix = input.text().at(0);
|
m_commandPrefix = input.asChar();
|
||||||
m_commandBuffer.clear();
|
m_commandBuffer.clear();
|
||||||
if (isVisualMode())
|
if (isVisualMode())
|
||||||
m_commandBuffer = "'<,'>";
|
m_commandBuffer = "'<,'>";
|
||||||
@@ -2414,7 +2439,7 @@ EventResult FakeVimHandler::Private::handleReplaceMode(const Input &input)
|
|||||||
}
|
}
|
||||||
const QString text = input.text();
|
const QString text = input.text();
|
||||||
m_lastInsertion += text;
|
m_lastInsertion += text;
|
||||||
m_tc.insertText(text);
|
insertText(text);
|
||||||
//qDebug() << "REM/INS: " << m_lastDeletion << m_lastInsertion;
|
//qDebug() << "REM/INS: " << m_lastDeletion << m_lastInsertion;
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
// m_movetype = MoveExclusive;
|
// m_movetype = MoveExclusive;
|
||||||
@@ -2439,7 +2464,7 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
for (int i = 0; i < m_visualInsertCount; ++i) {
|
for (int i = 0; i < m_visualInsertCount; ++i) {
|
||||||
moveDown();
|
moveDown();
|
||||||
m_tc.insertText(m_lastInsertion);
|
insertText(m_lastInsertion);
|
||||||
}
|
}
|
||||||
moveLeft(1);
|
moveLeft(1);
|
||||||
Range range(pos, position(), RangeBlockMode);
|
Range range(pos, position(), RangeBlockMode);
|
||||||
@@ -2448,13 +2473,12 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
setDotCommand("p");
|
setDotCommand("p");
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
} else {
|
} else {
|
||||||
// normal insertion. start with '1', as one instance was
|
// Normal insertion. Start with '1', as one instance was
|
||||||
// already physically inserted while typing
|
// already physically inserted while typing.
|
||||||
QString data = m_lastInsertion;
|
QString data;
|
||||||
for (int i = 1; i < count(); ++i) {
|
for (int i = 1; i < count(); ++i)
|
||||||
m_tc.insertText(m_lastInsertion);
|
|
||||||
data += m_lastInsertion;
|
data += m_lastInsertion;
|
||||||
}
|
insertText(data);
|
||||||
moveLeft(qMin(1, leftDist()));
|
moveLeft(qMin(1, leftDist()));
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
@@ -2544,7 +2568,7 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
const int col = physicalCursorColumnInDocument();
|
const int col = physicalCursorColumnInDocument();
|
||||||
QString str = QString(ts - col % ts, ' ');
|
QString str = QString(ts - col % ts, ' ');
|
||||||
m_lastInsertion.append(str);
|
m_lastInsertion.append(str);
|
||||||
m_tc.insertText(str);
|
insertText(str);
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
} else if (input.isControl('d')) {
|
} else if (input.isControl('d')) {
|
||||||
// remove one level of indentation from the current line
|
// remove one level of indentation from the current line
|
||||||
@@ -2571,7 +2595,7 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
m_justAutoIndented = 0;
|
m_justAutoIndented = 0;
|
||||||
const QString text = input.text();
|
const QString text = input.text();
|
||||||
m_lastInsertion.append(text);
|
m_lastInsertion.append(text);
|
||||||
m_tc.insertText(text);
|
insertText(text);
|
||||||
if (hasConfig(ConfigSmartIndent) && isElectricCharacter(text.at(0))) {
|
if (hasConfig(ConfigSmartIndent) && isElectricCharacter(text.at(0))) {
|
||||||
const QString leftText = m_tc.block().text()
|
const QString leftText = m_tc.block().text()
|
||||||
.left(m_tc.position() - 1 - m_tc.block().position());
|
.left(m_tc.position() - 1 - m_tc.block().position());
|
||||||
@@ -2706,7 +2730,7 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
|
|||||||
return EventHandled;
|
return EventHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 based.
|
// This uses 1 based line counting.
|
||||||
int FakeVimHandler::Private::readLineCode(QString &cmd)
|
int FakeVimHandler::Private::readLineCode(QString &cmd)
|
||||||
{
|
{
|
||||||
//qDebug() << "CMD: " << cmd;
|
//qDebug() << "CMD: " << cmd;
|
||||||
@@ -2714,19 +2738,32 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
QChar c = cmd.at(0);
|
QChar c = cmd.at(0);
|
||||||
cmd = cmd.mid(1);
|
cmd = cmd.mid(1);
|
||||||
if (c == '.')
|
if (c == '.') {
|
||||||
|
if (cmd.isEmpty())
|
||||||
|
return cursorLineInDocument() + 1;
|
||||||
|
QChar c1 = cmd.at(0);
|
||||||
|
if (c1 == '+' || c1 == '-') {
|
||||||
|
// Repeat for things like .+4
|
||||||
|
cmd = cmd.mid(1);
|
||||||
|
return cursorLineInDocument() + readLineCode(cmd);
|
||||||
|
}
|
||||||
return cursorLineInDocument() + 1;
|
return cursorLineInDocument() + 1;
|
||||||
|
}
|
||||||
if (c == '$')
|
if (c == '$')
|
||||||
return linesInDocument();
|
return linesInDocument();
|
||||||
if (c == '\'' && !cmd.isEmpty()) {
|
if (c == '\'' && !cmd.isEmpty()) {
|
||||||
int mark = m_marks.value(cmd.at(0).unicode());
|
if (cmd.isEmpty()) {
|
||||||
if (!mark) {
|
showRedMessage(msgMarkNotSet(QString()));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int m = mark(cmd.at(0).unicode());
|
||||||
|
if (m == -1) {
|
||||||
showRedMessage(msgMarkNotSet(cmd.at(0)));
|
showRedMessage(msgMarkNotSet(cmd.at(0)));
|
||||||
cmd = cmd.mid(1);
|
cmd = cmd.mid(1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cmd = cmd.mid(1);
|
cmd = cmd.mid(1);
|
||||||
return lineForPosition(mark);
|
return lineForPosition(m);
|
||||||
}
|
}
|
||||||
if (c == '-') {
|
if (c == '-') {
|
||||||
int n = readLineCode(cmd);
|
int n = readLineCode(cmd);
|
||||||
@@ -2737,8 +2774,7 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
|
|||||||
return cursorLineInDocument() + 1 + (n == -1 ? 1 : n);
|
return cursorLineInDocument() + 1 + (n == -1 ? 1 : n);
|
||||||
}
|
}
|
||||||
if (c == '\'' && !cmd.isEmpty()) {
|
if (c == '\'' && !cmd.isEmpty()) {
|
||||||
int pos = m_marks.value(cmd.at(0).unicode(), -1);
|
int pos = mark(cmd.at(0).unicode());
|
||||||
//qDebug() << " MARK: " << cmd.at(0) << pos << lineForPosition(pos);
|
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
showRedMessage(msgMarkNotSet(cmd.at(0)));
|
showRedMessage(msgMarkNotSet(cmd.at(0)));
|
||||||
cmd = cmd.mid(1);
|
cmd = cmd.mid(1);
|
||||||
@@ -2756,16 +2792,17 @@ int FakeVimHandler::Private::readLineCode(QString &cmd)
|
|||||||
cmd = cmd.mid(1);
|
cmd = cmd.mid(1);
|
||||||
n = n * 10 + (c.unicode() - '0');
|
n = n * 10 + (c.unicode() - '0');
|
||||||
}
|
}
|
||||||
//qDebug() << "N: " << n;
|
qDebug() << "N: " << n;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
// not parsed
|
// Parsing failed.
|
||||||
cmd = c + cmd;
|
cmd = c + cmd;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::selectRange(int beginLine, int endLine)
|
void FakeVimHandler::Private::selectRange(int beginLine, int endLine)
|
||||||
{
|
{
|
||||||
|
m_rangemode = RangeLineMode;
|
||||||
if (beginLine == -1)
|
if (beginLine == -1)
|
||||||
beginLine = cursorLineInDocument();
|
beginLine = cursorLineInDocument();
|
||||||
if (endLine == -1)
|
if (endLine == -1)
|
||||||
@@ -2787,71 +2824,44 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd)
|
|||||||
EDITOR(setTextCursor(m_tc));
|
EDITOR(setTextCursor(m_tc));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FakeVimHandler::Private::extractCommand(const QString &line,
|
bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
|
||||||
int *beginLine, int *endLine)
|
|
||||||
{
|
|
||||||
QString cmd = line;
|
|
||||||
*beginLine = -1;
|
|
||||||
*endLine = -1;
|
|
||||||
|
|
||||||
// FIXME: that seems to be different for %w and %s
|
|
||||||
if (cmd.startsWith(QLatin1Char('%')))
|
|
||||||
cmd = "1,$" + cmd.mid(1);
|
|
||||||
|
|
||||||
int lineNumber = readLineCode(cmd);
|
|
||||||
if (lineNumber != -1)
|
|
||||||
*beginLine = lineNumber;
|
|
||||||
|
|
||||||
if (cmd.startsWith(',')) {
|
|
||||||
cmd = cmd.mid(1);
|
|
||||||
lineNumber = readLineCode(cmd);
|
|
||||||
if (lineNumber != -1)
|
|
||||||
*endLine = lineNumber;
|
|
||||||
}
|
|
||||||
//qDebug() << "RANGE: " << beginLine << endLine << cmd << lineNumber << m_marks;
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExSubstituteCommand(const QString &line)
|
|
||||||
// :substitute
|
// :substitute
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
QString line = cmd.line;
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
if (line.startsWith(_("substitute")))
|
||||||
|
line = line.mid(10);
|
||||||
if (cmd.startsWith(QLatin1String("substitute")))
|
else if (line.startsWith('s') && line.size() > 1
|
||||||
cmd = cmd.mid(10);
|
&& !isalpha(line.at(1).unicode()))
|
||||||
else if (cmd.startsWith('s') && line.size() > 1
|
line = line.mid(1);
|
||||||
&& !isalpha(cmd.at(1).unicode()))
|
|
||||||
cmd = cmd.mid(1);
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
// we have /{pattern}/{string}/[flags] now
|
// we have /{pattern}/{string}/[flags] now
|
||||||
if (cmd.isEmpty())
|
if (line.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
const QChar separator = cmd.at(0);
|
const QChar separator = line.at(0);
|
||||||
int pos1 = -1;
|
int pos1 = -1;
|
||||||
int pos2 = -1;
|
int pos2 = -1;
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i < cmd.size(); ++i) {
|
for (i = 1; i < line.size(); ++i) {
|
||||||
if (cmd.at(i) == separator && cmd.at(i - 1) != '\\') {
|
if (line.at(i) == separator && line.at(i - 1) != '\\') {
|
||||||
pos1 = i;
|
pos1 = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos1 == -1)
|
if (pos1 == -1)
|
||||||
return false;
|
return false;
|
||||||
for (++i; i < cmd.size(); ++i) {
|
for (++i; i < line.size(); ++i) {
|
||||||
if (cmd.at(i) == separator && cmd.at(i - 1) != '\\') {
|
if (line.at(i) == separator && line.at(i - 1) != '\\') {
|
||||||
pos2 = i;
|
pos2 = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pos2 == -1)
|
if (pos2 == -1)
|
||||||
pos2 = cmd.size();
|
pos2 = line.size();
|
||||||
|
|
||||||
QString needle = cmd.mid(1, pos1 - 1);
|
QString needle = line.mid(1, pos1 - 1);
|
||||||
const QString replacement = cmd.mid(pos1 + 1, pos2 - pos1 - 1);
|
const QString replacement = line.mid(pos1 + 1, pos2 - pos1 - 1);
|
||||||
QString flags = cmd.mid(pos2 + 1);
|
QString flags = line.mid(pos2 + 1);
|
||||||
|
|
||||||
needle.replace('$', '\n');
|
needle.replace('$', '\n');
|
||||||
needle.replace("\\\n", "\\$");
|
needle.replace("\\\n", "\\$");
|
||||||
@@ -2860,7 +2870,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const QString &line)
|
|||||||
pattern.setCaseSensitivity(Qt::CaseInsensitive);
|
pattern.setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
const bool global = flags.contains('g');
|
const bool global = flags.contains('g');
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
for (int line = endLine; line >= beginLine; --line) {
|
for (int line = cmd.endLine; line >= cmd.beginLine; --line) {
|
||||||
QString origText = lineContents(line);
|
QString origText = lineContents(line);
|
||||||
QString text = origText;
|
QString text = origText;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
@@ -2893,14 +2903,14 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const QString &line)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map
|
||||||
{
|
{
|
||||||
const int pos1 = line.indexOf(QLatin1Char(' '));
|
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 = line.left(pos1).toLatin1();
|
QByteArray cmd = cmd0.line.left(pos1).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
|
||||||
@@ -2938,15 +2948,15 @@ bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const int pos2 = line.indexOf(QLatin1Char(' '), pos1 + 1);
|
const int pos2 = cmd0.line.indexOf(QLatin1Char(' '), pos1 + 1);
|
||||||
if (pos1 == -1 || pos2 == -1) {
|
if (pos1 == -1 || pos2 == -1) {
|
||||||
// FIXME: Dump mappings here.
|
// FIXME: Dump mappings here.
|
||||||
//qDebug() << g.mappings;
|
//qDebug() << g.mappings;
|
||||||
return true;;
|
return true;;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString lhs = line.mid(pos1 + 1, pos2 - pos1 - 1);
|
QString lhs = cmd0.line.mid(pos1 + 1, pos2 - pos1 - 1);
|
||||||
QString rhs = line.mid(pos2 + 1);
|
QString rhs = cmd0.line.mid(pos2 + 1);
|
||||||
Inputs key;
|
Inputs key;
|
||||||
key.parseFrom(lhs);
|
key.parseFrom(lhs);
|
||||||
//qDebug() << "MAPPING: " << modes << lhs << rhs;
|
//qDebug() << "MAPPING: " << modes << lhs << rhs;
|
||||||
@@ -2969,10 +2979,10 @@ bool FakeVimHandler::Private::handleExMapCommand(const QString &line) // :map
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExHistoryCommand(const QString &cmd) // :history
|
bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd) // :history
|
||||||
{
|
{
|
||||||
static QRegExp reHistory("^his(tory)?( (.*))?$");
|
static QRegExp reHistory("^his(tory)?( (.*))?$");
|
||||||
if (reHistory.indexIn(cmd) == -1)
|
if (reHistory.indexIn(cmd.line) == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QString arg = reHistory.cap(3);
|
QString arg = reHistory.cap(3);
|
||||||
@@ -2992,10 +3002,10 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const QString &cmd) // :his
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExSetCommand(const QString &cmd) // :set
|
bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) // :set
|
||||||
{
|
{
|
||||||
static QRegExp reSet("^set?( (.*))?$");
|
static QRegExp reSet("^set?( (.*))?$");
|
||||||
if (reSet.indexIn(cmd) == -1)
|
if (reSet.indexIn(cmd.line) == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
showBlackMessage(QString());
|
showBlackMessage(QString());
|
||||||
@@ -3013,7 +3023,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const QString &cmd) // :set
|
|||||||
} else if (act) {
|
} else if (act) {
|
||||||
// non-boolean to show
|
// non-boolean to show
|
||||||
showBlackMessage(arg + '=' + act->value().toString());
|
showBlackMessage(arg + '=' + act->value().toString());
|
||||||
} else if (arg.startsWith(QLatin1String("no"))
|
} else if (arg.startsWith(_("no"))
|
||||||
&& (act = theFakeVimSettings()->item(arg.mid(2)))) {
|
&& (act = theFakeVimSettings()->item(arg.mid(2)))) {
|
||||||
// boolean config to be switched off
|
// boolean config to be switched off
|
||||||
bool oldValue = act->value().toBool();
|
bool oldValue = act->value().toBool();
|
||||||
@@ -3035,27 +3045,24 @@ bool FakeVimHandler::Private::handleExSetCommand(const QString &cmd) // :set
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExNormalCommand(const QString &cmd) // :normal
|
bool FakeVimHandler::Private::handleExNormalCommand(const ExCommand &cmd) // :normal
|
||||||
{
|
{
|
||||||
static QRegExp reNormal("^norm(al)?( (.*))?$");
|
static QRegExp reNormal("^norm(al)?( (.*))?$");
|
||||||
if (reNormal.indexIn(cmd) == -1)
|
if (reNormal.indexIn(cmd.line) == -1)
|
||||||
return false;
|
return false;
|
||||||
//qDebug() << "REPLAY NORMAL: " << quoteUnprintable(reNormal.cap(3));
|
//qDebug() << "REPLAY NORMAL: " << quoteUnprintable(reNormal.cap(3));
|
||||||
replay(reNormal.cap(3), 1);
|
replay(reNormal.cap(3), 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExDeleteCommand(const QString &line) // :d
|
bool FakeVimHandler::Private::handleExDeleteCommand(const ExCommand &cmd) // :d
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
static QRegExp reDelete("^d(elete)?( (.*))?$");
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
if (reDelete.indexIn(cmd.line) == -1)
|
||||||
|
|
||||||
static QRegExp reDelete("^d( (.*))?$");
|
|
||||||
if (reDelete.indexIn(cmd) != -1)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
selectRange(beginLine, endLine);
|
selectRange(cmd.beginLine, cmd.endLine);
|
||||||
QString reg = reDelete.cap(2);
|
QString reg = reDelete.cap(3);
|
||||||
QString text = selectedText();
|
QString text = selectedText();
|
||||||
removeSelectedText();
|
removeSelectedText();
|
||||||
if (!reg.isEmpty()) {
|
if (!reg.isEmpty()) {
|
||||||
@@ -3066,28 +3073,27 @@ bool FakeVimHandler::Private::handleExDeleteCommand(const QString &line) // :d
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExWriteCommand(const QString &line)
|
bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
|
||||||
// :w, :x, :q, :wq, ...
|
// :w, :x, :q, :wq, ...
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
|
||||||
|
|
||||||
static QRegExp reWrite("^[wx]q?a?!?( (.*))?$");
|
static QRegExp reWrite("^[wx]q?a?!?( (.*))?$");
|
||||||
if (reWrite.indexIn(cmd) == -1) // :w and :x
|
if (reWrite.indexIn(cmd.line) == -1) // :w and :x
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int beginLine = cmd.beginLine;
|
||||||
|
int endLine = cmd.endLine;
|
||||||
bool noArgs = (beginLine == -1);
|
bool noArgs = (beginLine == -1);
|
||||||
if (beginLine == -1)
|
if (beginLine == -1)
|
||||||
beginLine = 0;
|
beginLine = 0;
|
||||||
if (endLine == -1)
|
if (endLine == -1)
|
||||||
endLine = linesInDocument();
|
endLine = linesInDocument();
|
||||||
//qDebug() << "LINES: " << beginLine << endLine;
|
//qDebug() << "LINES: " << beginLine << endLine;
|
||||||
int indexOfSpace = cmd.indexOf(QChar(' '));
|
int indexOfSpace = cmd.line.indexOf(QChar(' '));
|
||||||
QString prefix;
|
QString prefix;
|
||||||
if (indexOfSpace < 0)
|
if (indexOfSpace < 0)
|
||||||
prefix = cmd;
|
prefix = cmd.line;
|
||||||
else
|
else
|
||||||
prefix = cmd.left(indexOfSpace);
|
prefix = cmd.line.left(indexOfSpace);
|
||||||
bool forced = prefix.contains(QChar('!'));
|
bool forced = prefix.contains(QChar('!'));
|
||||||
bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
|
bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
|
||||||
bool quitAll = quit && prefix.contains(QChar('a'));
|
bool quitAll = quit && prefix.contains(QChar('a'));
|
||||||
@@ -3140,16 +3146,16 @@ bool FakeVimHandler::Private::handleExWriteCommand(const QString &line)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExReadCommand(const QString &line) // :r
|
bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd) // :r
|
||||||
{
|
{
|
||||||
if (!line.startsWith(QLatin1String("r ")))
|
if (!cmd.line.startsWith(_("r ")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
moveToStartOfLine();
|
moveToStartOfLine();
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
moveDown();
|
moveDown();
|
||||||
m_currentFileName = line.mid(2);
|
m_currentFileName = cmd.line.mid(2).trimmed();
|
||||||
QFile file(m_currentFileName);
|
QFile file(m_currentFileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
QTextStream ts(&file);
|
QTextStream ts(&file);
|
||||||
@@ -3161,23 +3167,20 @@ bool FakeVimHandler::Private::handleExReadCommand(const QString &line) // :r
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExBangCommand(const QString &line) // :!
|
bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
if (!cmd.line.startsWith(QLatin1Char('!')))
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
|
||||||
|
|
||||||
if (!cmd.startsWith(QLatin1Char('!')))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
selectRange(beginLine, endLine);
|
selectRange(cmd.beginLine, cmd.endLine);
|
||||||
int targetPosition = firstPositionInLine(beginLine);
|
int targetPosition = firstPositionInLine(cmd.beginLine);
|
||||||
QString command = cmd.mid(1).trimmed();
|
QString command = cmd.line.mid(1).trimmed();
|
||||||
QString text = selectedText();
|
QString text = selectedText();
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(command);
|
proc.start(command);
|
||||||
proc.waitForStarted();
|
proc.waitForStarted();
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
text.replace(QLatin1String("\n"), QLatin1String("\r\n"));
|
text.replace(_("\n"), _("\r\n"));
|
||||||
#endif
|
#endif
|
||||||
proc.write(text.toUtf8());
|
proc.write(text.toUtf8());
|
||||||
proc.closeWriteChannel();
|
proc.closeWriteChannel();
|
||||||
@@ -3185,7 +3188,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const QString &line) // :!
|
|||||||
QString result = QString::fromUtf8(proc.readAllStandardOutput());
|
QString result = QString::fromUtf8(proc.readAllStandardOutput());
|
||||||
beginEditBlock(targetPosition);
|
beginEditBlock(targetPosition);
|
||||||
removeSelectedText();
|
removeSelectedText();
|
||||||
m_tc.insertText(result);
|
insertText(result);
|
||||||
setPosition(targetPosition);
|
setPosition(targetPosition);
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
@@ -3195,26 +3198,23 @@ bool FakeVimHandler::Private::handleExBangCommand(const QString &line) // :!
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExShiftRightCommand(const QString &line) // :>
|
bool FakeVimHandler::Private::handleExShiftRightCommand(const ExCommand &cmd) // :>
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
if (!cmd.line.startsWith(QLatin1Char('>')))
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
|
||||||
|
|
||||||
if (!cmd.startsWith(QLatin1Char('>')))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_anchor = firstPositionInLine(beginLine);
|
m_anchor = firstPositionInLine(cmd.beginLine);
|
||||||
setPosition(firstPositionInLine(endLine));
|
setPosition(firstPositionInLine(cmd.endLine));
|
||||||
shiftRegionRight(1);
|
shiftRegionRight(1);
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
showBlackMessage(FakeVimHandler::tr("%n lines >ed %1 time", 0,
|
showBlackMessage(FakeVimHandler::tr("%n lines >ed %1 time", 0,
|
||||||
(endLine - beginLine + 1)).arg(1));
|
(cmd.endLine - cmd.beginLine + 1)).arg(1));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExRedoCommand(const QString &line) // :redo
|
bool FakeVimHandler::Private::handleExRedoCommand(const ExCommand &cmd) // :redo
|
||||||
{
|
{
|
||||||
if (line != "red" && line != "redo")
|
if (cmd.line != "red" && cmd.line != "redo")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
redo();
|
redo();
|
||||||
@@ -3222,26 +3222,23 @@ bool FakeVimHandler::Private::handleExRedoCommand(const QString &line) // :redo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExGotoCommand(const QString &line) // :<nr>
|
bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd) // :<nr>
|
||||||
{
|
{
|
||||||
int beginLine, endLine;
|
if (!cmd.line.isEmpty())
|
||||||
QString cmd = extractCommand(line, &beginLine, &endLine);
|
|
||||||
|
|
||||||
if (!cmd.isEmpty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
setPosition(firstPositionInLine(beginLine));
|
setPosition(firstPositionInLine(cmd.beginLine));
|
||||||
showBlackMessage(QString());
|
showBlackMessage(QString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExSourceCommand(const QString &line) // :source
|
bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd) // :source
|
||||||
{
|
{
|
||||||
int pos = line.indexOf(' ');
|
const int pos = cmd.line.indexOf(' ');
|
||||||
if (line.leftRef(pos) != "so" && line.leftRef(pos) != "source")
|
if (cmd.line.leftRef(pos) != "so" && cmd.line.leftRef(pos) != "source")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QString fileName = line.mid(pos + 1);
|
QString fileName = cmd.line.mid(pos + 1).trimmed();
|
||||||
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));
|
||||||
@@ -3274,28 +3271,41 @@ bool FakeVimHandler::Private::handleExSourceCommand(const QString &line) // :sou
|
|||||||
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
|
||||||
|
if (line.startsWith(QLatin1Char('%')))
|
||||||
|
line = "1,$" + line.mid(1);
|
||||||
|
|
||||||
|
cmd.beginLine = readLineCode(line);
|
||||||
|
if (line.startsWith(',')) {
|
||||||
|
line = line.mid(1);
|
||||||
|
cmd.endLine = readLineCode(line);
|
||||||
|
}
|
||||||
|
cmd.line = line;
|
||||||
|
//qDebug() << "CMD: " << cmd;
|
||||||
|
|
||||||
enterCommandMode();
|
enterCommandMode();
|
||||||
showBlackMessage(QString());
|
showBlackMessage(QString());
|
||||||
if (handleExCommandHelper(line))
|
if (!handleExCommandHelper(cmd))
|
||||||
return;
|
passUnknownExCommand(cmd.line);
|
||||||
int beginLine, endLine;
|
|
||||||
passUnknownExCommand(extractCommand(line, &beginLine, &endLine));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::handleExCommandHelper(const QString &line)
|
bool FakeVimHandler::Private::handleExCommandHelper(const ExCommand &cmd)
|
||||||
{
|
{
|
||||||
return handleExGotoCommand(line)
|
return handleExGotoCommand(cmd)
|
||||||
|| handleExBangCommand(line)
|
|| handleExBangCommand(cmd)
|
||||||
|| handleExHistoryCommand(line)
|
|| handleExHistoryCommand(cmd)
|
||||||
|| handleExMapCommand(line)
|
|| handleExDeleteCommand(cmd)
|
||||||
|| handleExNormalCommand(line)
|
|| handleExMapCommand(cmd)
|
||||||
|| handleExReadCommand(line)
|
|| handleExNormalCommand(cmd)
|
||||||
|| handleExRedoCommand(line)
|
|| handleExReadCommand(cmd)
|
||||||
|| handleExSetCommand(line)
|
|| handleExRedoCommand(cmd)
|
||||||
|| handleExShiftRightCommand(line)
|
|| handleExSetCommand(cmd)
|
||||||
|| handleExSourceCommand(line)
|
|| handleExShiftRightCommand(cmd)
|
||||||
|| handleExSubstituteCommand(line)
|
|| handleExSourceCommand(cmd)
|
||||||
|| handleExWriteCommand(line);
|
|| handleExSubstituteCommand(cmd)
|
||||||
|
|| handleExWriteCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::passUnknownExCommand(const QString &cmd)
|
void FakeVimHandler::Private::passUnknownExCommand(const QString &cmd)
|
||||||
@@ -3311,17 +3321,17 @@ void FakeVimHandler::Private::passUnknownSetCommand(const QString &arg)
|
|||||||
bool handled = false;
|
bool handled = false;
|
||||||
emit q->handleSetCommandRequested(&handled, arg);
|
emit q->handleSetCommandRequested(&handled, arg);
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
showRedMessage(FakeVimHandler::tr("E512: Unknown option: ") + arg);
|
showRedMessage(FakeVimHandler::tr("Unknown option: ") + arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vimPatternToQtPattern(QString *needle, QTextDocument::FindFlags *flags)
|
static void vimPatternToQtPattern(QString *needle, QTextDocument::FindFlags *flags)
|
||||||
{
|
{
|
||||||
// FIXME: Rough mapping of a common case
|
// FIXME: Rough mapping of a common case
|
||||||
if (needle->startsWith(QLatin1String("\\<")) && needle->endsWith(QLatin1String("\\>")))
|
if (needle->startsWith(_("\\<")) && needle->endsWith(_("\\>")))
|
||||||
(*flags) |= QTextDocument::FindWholeWords;
|
(*flags) |= QTextDocument::FindWholeWords;
|
||||||
needle->remove(QLatin1String("\\<")); // start of word
|
needle->remove(_("\\<")); // start of word
|
||||||
needle->remove(QLatin1String("\\>")); // end of word
|
needle->remove(_("\\>")); // end of word
|
||||||
//qDebug() << "NEEDLE " << needle0 << needle;
|
//qDebug() << "NEEDLE " << needle0 << needle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3462,6 +3472,7 @@ int 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(&amount, beginLine-1, endLine-1, typedChar);
|
emit q->indentRegion(&amount, beginLine-1, endLine-1, typedChar);
|
||||||
|
|
||||||
|
showBlackMessage("MARKS ARE OFF NOW");
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3970,6 +3981,14 @@ void FakeVimHandler::Private::transformText(const Range &range,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::insertText(const Register ®)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(reg.rangemode == RangeCharMode,
|
||||||
|
qDebug() << "WRONG INSERT MODE: " << reg.rangemode; return);
|
||||||
|
fixMarks(position(), reg.contents.length());
|
||||||
|
m_tc.insertText(reg.contents);
|
||||||
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::removeSelectedText()
|
void FakeVimHandler::Private::removeSelectedText()
|
||||||
{
|
{
|
||||||
Range range(anchor(), position(), m_rangemode);
|
Range range(anchor(), position(), m_rangemode);
|
||||||
@@ -4047,8 +4066,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
|
|||||||
for (int i = count(); --i >= 0; ) {
|
for (int i = count(); --i >= 0; ) {
|
||||||
if (afterCursor && rightDist() > 0)
|
if (afterCursor && rightDist() > 0)
|
||||||
moveRight();
|
moveRight();
|
||||||
fixMarks(position(), text.length());
|
insertText(text);
|
||||||
m_tc.insertText(text);
|
|
||||||
if (!afterCursor && atEndOfLine())
|
if (!afterCursor && atEndOfLine())
|
||||||
moveLeft();
|
moveLeft();
|
||||||
moveLeft();
|
moveLeft();
|
||||||
@@ -4062,8 +4080,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
|
|||||||
for (int i = count(); --i >= 0; ) {
|
for (int i = count(); --i >= 0; ) {
|
||||||
if (afterCursor)
|
if (afterCursor)
|
||||||
moveDown();
|
moveDown();
|
||||||
fixMarks(position(), text.length());
|
insertText(text);
|
||||||
m_tc.insertText(text);
|
|
||||||
moveUp(lines.size() - 1);
|
moveUp(lines.size() - 1);
|
||||||
}
|
}
|
||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
@@ -4088,8 +4105,8 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
|
|||||||
} else {
|
} else {
|
||||||
tc.movePosition(Right, MoveAnchor, col - 1 + afterCursor);
|
tc.movePosition(Right, MoveAnchor, col - 1 + afterCursor);
|
||||||
}
|
}
|
||||||
qDebug() << "INSERT " << line << " AT " << tc.position()
|
//qDebug() << "INSERT " << line << " AT " << tc.position()
|
||||||
<< "COL: " << col;
|
// << "COL: " << col;
|
||||||
fixMarks(position(), line.length());
|
fixMarks(position(), line.length());
|
||||||
tc.insertText(line);
|
tc.insertText(line);
|
||||||
tc.movePosition(StartOfLine, MoveAnchor);
|
tc.movePosition(StartOfLine, MoveAnchor);
|
||||||
@@ -4109,16 +4126,38 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: This needs to called after undo/insert
|
//FIXME: This needs to called after undo/insert
|
||||||
void FakeVimHandler::Private::fixMarks(int positionAction, int positionChange)
|
// The position 'from' is the cursor position after the change. If 'delta'
|
||||||
|
// is positive there was a string of size 'delta' inserted after 'from'
|
||||||
|
// and consequently all marks beyond 'from + delta' need to be incremented
|
||||||
|
// by 'delta'. If text was removed, 'delta' is negative. All marks between
|
||||||
|
// 'from' and 'from - delta' need to be removed, everything behing
|
||||||
|
// 'from - delta' adjusted by 'delta'.
|
||||||
|
void FakeVimHandler::Private::fixMarks(int from, int delta)
|
||||||
{
|
{
|
||||||
QHashIterator<int, int> i(m_marks);
|
//qDebug() << "ADJUSTING MARKS FROM " << from << " BY " << delta;
|
||||||
while (i.hasNext()) {
|
if (delta == 0)
|
||||||
i.next();
|
return;
|
||||||
if (i.value() >= positionAction) {
|
QHashIterator<int, int> it(m_marks);
|
||||||
if (i.value() + positionChange > 0)
|
while (it.hasNext()) {
|
||||||
m_marks[i.key()] = i.value() + positionChange;
|
it.next();
|
||||||
else
|
int pos = it.value();
|
||||||
m_marks.remove(i.key());
|
if (delta > 0) {
|
||||||
|
// Inserted text.
|
||||||
|
if (pos >= from) {
|
||||||
|
//qDebug() << "MODIFIED: " << it.key() << pos;
|
||||||
|
setMark(it.key(), pos + delta);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Removed text.
|
||||||
|
if (pos < from) {
|
||||||
|
// Nothing to do.
|
||||||
|
} else if (pos < from - delta) {
|
||||||
|
//qDebug() << "GONE: " << it.key();
|
||||||
|
m_marks.remove(it.key());
|
||||||
|
} else {
|
||||||
|
//qDebug() << "MODIFIED: " << it.key() << pos;
|
||||||
|
setMark(it.key(), pos + delta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4128,13 +4167,15 @@ QString FakeVimHandler::Private::lineContents(int line) const
|
|||||||
return m_tc.document()->findBlockByNumber(line - 1).text();
|
return m_tc.document()->findBlockByNumber(line - 1).text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::setLineContents(int line, const QString &contents) const
|
void FakeVimHandler::Private::setLineContents(int line, const QString &contents)
|
||||||
{
|
{
|
||||||
QTextBlock block = m_tc.document()->findBlockByNumber(line - 1);
|
QTextBlock block = m_tc.document()->findBlockByNumber(line - 1);
|
||||||
QTextCursor tc = m_tc;
|
QTextCursor tc = m_tc;
|
||||||
tc.setPosition(block.position());
|
tc.setPosition(block.position());
|
||||||
tc.setPosition(block.position() + block.length() - 1, KeepAnchor);
|
tc.setPosition(block.position() + block.length() - 1, KeepAnchor);
|
||||||
tc.removeSelectedText();
|
tc.removeSelectedText();
|
||||||
|
fixMarks(block.position(),
|
||||||
|
block.position() + block.length() - 1 - contents.size());
|
||||||
tc.insertText(contents);
|
tc.insertText(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4161,8 +4202,8 @@ void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode)
|
|||||||
setAnchor();
|
setAnchor();
|
||||||
m_positionPastEnd = m_anchorPastEnd = false;
|
m_positionPastEnd = m_anchorPastEnd = false;
|
||||||
m_visualMode = visualMode;
|
m_visualMode = visualMode;
|
||||||
m_marks['<'] = m_tc.position();
|
setMark('<', m_tc.position());
|
||||||
m_marks['>'] = m_tc.position();
|
setMark('>', m_tc.position());
|
||||||
updateMiniBuffer();
|
updateMiniBuffer();
|
||||||
updateSelection();
|
updateSelection();
|
||||||
}
|
}
|
||||||
@@ -4189,11 +4230,16 @@ QWidget *FakeVimHandler::Private::editor() const
|
|||||||
void FakeVimHandler::Private::undo()
|
void FakeVimHandler::Private::undo()
|
||||||
{
|
{
|
||||||
//qDebug() << " CURSOR POS: " << m_undoCursorPosition;
|
//qDebug() << " CURSOR POS: " << m_undoCursorPosition;
|
||||||
int current = m_tc.document()->availableUndoSteps();
|
QTextDocument *doc = m_tc.document();
|
||||||
//endEditBlock();
|
// FIXME: That's only an approximaxtion. The real solution might
|
||||||
|
// be to store marks and old userData with QTextBlock setUserData
|
||||||
|
// and retrieve them afterward.
|
||||||
|
const int current = doc->availableUndoSteps();
|
||||||
|
const int oldCount = doc->characterCount();
|
||||||
EDITOR(undo());
|
EDITOR(undo());
|
||||||
//beginEditBlock();
|
const int delta = doc->characterCount() - oldCount;
|
||||||
int rev = m_tc.document()->availableUndoSteps();
|
fixMarks(position(), delta);
|
||||||
|
const int rev = doc->availableUndoSteps();
|
||||||
if (current == rev)
|
if (current == rev)
|
||||||
showBlackMessage(FakeVimHandler::tr("Already at oldest change"));
|
showBlackMessage(FakeVimHandler::tr("Already at oldest change"));
|
||||||
else
|
else
|
||||||
@@ -4207,11 +4253,13 @@ void FakeVimHandler::Private::undo()
|
|||||||
|
|
||||||
void FakeVimHandler::Private::redo()
|
void FakeVimHandler::Private::redo()
|
||||||
{
|
{
|
||||||
int current = m_tc.document()->availableUndoSteps();
|
QTextDocument *doc = m_tc.document();
|
||||||
//endEditBlock();
|
const int current = m_tc.document()->availableUndoSteps();
|
||||||
|
const int oldCount = doc->characterCount();
|
||||||
EDITOR(redo());
|
EDITOR(redo());
|
||||||
//beginEditBlock();
|
const int delta = doc->characterCount() - oldCount;
|
||||||
int rev = m_tc.document()->availableUndoSteps();
|
fixMarks(position(), delta);
|
||||||
|
const int rev = doc->availableUndoSteps();
|
||||||
if (rev == current)
|
if (rev == current)
|
||||||
showBlackMessage(FakeVimHandler::tr("Already at newest change"));
|
showBlackMessage(FakeVimHandler::tr("Already at newest change"));
|
||||||
else
|
else
|
||||||
@@ -4319,6 +4367,7 @@ void FakeVimHandler::Private::insertAutomaticIndentation(bool goingDown)
|
|||||||
if (hasConfig(ConfigSmartIndent)) {
|
if (hasConfig(ConfigSmartIndent)) {
|
||||||
Range range(m_tc.block().position(), m_tc.block().position());
|
Range range(m_tc.block().position(), m_tc.block().position());
|
||||||
m_justAutoIndented = indentText(range, QLatin1Char('\n'));
|
m_justAutoIndented = indentText(range, QLatin1Char('\n'));
|
||||||
|
fixMarks(m_tc.block().position(), m_justAutoIndented);
|
||||||
} else {
|
} else {
|
||||||
QTextBlock block = goingDown ? m_tc.block().previous() : m_tc.block().next();
|
QTextBlock block = goingDown ? m_tc.block().previous() : m_tc.block().next();
|
||||||
QString text = block.text();
|
QString text = block.text();
|
||||||
@@ -4328,7 +4377,7 @@ void FakeVimHandler::Private::insertAutomaticIndentation(bool goingDown)
|
|||||||
++pos;
|
++pos;
|
||||||
text.truncate(pos);
|
text.truncate(pos);
|
||||||
// FIXME: handle 'smartindent' and 'cindent'
|
// FIXME: handle 'smartindent' and 'cindent'
|
||||||
m_tc.insertText(text);
|
insertText(text);
|
||||||
m_justAutoIndented = text.size();
|
m_justAutoIndented = text.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4339,6 +4388,7 @@ bool FakeVimHandler::Private::removeAutomaticIndentation()
|
|||||||
return false;
|
return false;
|
||||||
m_tc.movePosition(StartOfLine, KeepAnchor);
|
m_tc.movePosition(StartOfLine, KeepAnchor);
|
||||||
m_tc.removeSelectedText();
|
m_tc.removeSelectedText();
|
||||||
|
fixMarks(m_tc.position(), -m_justAutoIndented);
|
||||||
m_lastInsertion.chop(m_justAutoIndented);
|
m_lastInsertion.chop(m_justAutoIndented);
|
||||||
m_justAutoIndented = 0;
|
m_justAutoIndented = 0;
|
||||||
return true;
|
return true;
|
||||||
@@ -4371,7 +4421,7 @@ void FakeVimHandler::Private::selectWordTextObject(bool inner)
|
|||||||
setAnchor();
|
setAnchor();
|
||||||
// FIXME: Rework the 'anchor' concept.
|
// FIXME: Rework the 'anchor' concept.
|
||||||
if (isVisualMode())
|
if (isVisualMode())
|
||||||
m_marks['<'] = m_tc.position();
|
setMark('<', m_tc.position());
|
||||||
moveToWordBoundary(false, true, true);
|
moveToWordBoundary(false, true, true);
|
||||||
m_movetype = MoveInclusive;
|
m_movetype = MoveInclusive;
|
||||||
}
|
}
|
||||||
@@ -4384,7 +4434,7 @@ void FakeVimHandler::Private::selectWORDTextObject(bool inner)
|
|||||||
setAnchor();
|
setAnchor();
|
||||||
// FIXME: Rework the 'anchor' concept.
|
// FIXME: Rework the 'anchor' concept.
|
||||||
if (isVisualMode())
|
if (isVisualMode())
|
||||||
m_marks['<'] = m_tc.position();
|
setMark('<', m_tc.position());
|
||||||
moveToWordBoundary(true, true, true);
|
moveToWordBoundary(true, true, true);
|
||||||
m_movetype = MoveInclusive;
|
m_movetype = MoveInclusive;
|
||||||
}
|
}
|
||||||
@@ -4412,6 +4462,18 @@ void FakeVimHandler::Private::selectQuotedStringTextObject(bool inner, int type)
|
|||||||
Q_UNUSED(type);
|
Q_UNUSED(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FakeVimHandler::Private::mark(int code) const
|
||||||
|
{
|
||||||
|
// FIXME: distinguish local and global marks.
|
||||||
|
//qDebug() << "MARK: " << code << m_marks.value(code, -1) << m_marks;
|
||||||
|
return m_marks.value(code, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::setMark(int code, int position)
|
||||||
|
{
|
||||||
|
// FIXME: distinguish local and global marks.
|
||||||
|
m_marks[code] = position;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user