fakevim: handle block mode for yank, cut and paste

This commit is contained in:
hjk
2009-08-11 14:39:44 +02:00
parent 8dfa8af69b
commit bc61f9ddd9
3 changed files with 315 additions and 128 deletions

1
dist/changes-1.3.0 vendored
View File

@@ -25,6 +25,7 @@ Editing
* Objective-C: Added partial semantic checking and symbol navigation * Objective-C: Added partial semantic checking and symbol navigation
* Fixed searching in files to take open documents into account * Fixed searching in files to take open documents into account
* Added a Locator filter for symbols in the current document * Added a Locator filter for symbols in the current document
* Handle block selection in fakevim
Project support Project support
* Added support for adding and removing files from a generic Makefile-based * Added support for adding and removing files from a generic Makefile-based

View File

@@ -172,6 +172,52 @@ enum MoveType
MoveLineWise, MoveLineWise,
}; };
enum RangeMode
{
RangeCharMode,
RangeLineMode,
RangeBlockMode,
};
enum EventResult
{
EventHandled,
EventUnhandled,
EventPassedToCore
};
struct CursorPosition
{
// for jump history
CursorPosition() : position(-1), scrollLine(-1) {}
CursorPosition(int pos, int line) : position(pos), scrollLine(line) {}
int position; // Position in document
int scrollLine; // First visible line
};
struct Register
{
Register() : rangemode(RangeCharMode) {}
Register(const QString &c, RangeMode m) : contents(c), rangemode(m) {}
QString contents;
RangeMode rangemode;
};
struct Range
{
Range()
: beginPos(-1), endPos(-1), rangemode(RangeCharMode)
{}
Range(int b, int e, RangeMode m = RangeCharMode)
: beginPos(qMin(b, e)), endPos(qMax(b, e)), rangemode(m)
{}
int beginPos;
int endPos;
RangeMode rangemode;
};
QDebug &operator<<(QDebug &ts, const QList<QTextEdit::ExtraSelection> &sels) QDebug &operator<<(QDebug &ts, const QList<QTextEdit::ExtraSelection> &sels)
{ {
foreach (QTextEdit::ExtraSelection sel, sels) foreach (QTextEdit::ExtraSelection sel, sels)
@@ -192,21 +238,6 @@ QString quoteUnprintable(const QString &ba)
return res; return res;
} }
enum EventResult
{
EventHandled,
EventUnhandled,
EventPassedToCore
};
struct CursorPosition
{
CursorPosition() : position(-1), scrollLine(-1) {}
CursorPosition(int pos, int line) : position(pos), scrollLine(line) {}
int position; // Position in document
int scrollLine; // First visible line
};
class FakeVimHandler::Private class FakeVimHandler::Private
{ {
public: public:
@@ -335,11 +366,12 @@ public:
QTextCursor m_tc; QTextCursor m_tc;
QTextCursor m_oldTc; // copy from last event to check for external changes QTextCursor m_oldTc; // copy from last event to check for external changes
int m_anchor; int m_anchor;
static QHash<int, QString> m_registers; static QHash<int, Register> m_registers;
int m_register; int m_register;
QString m_mvcount; QString m_mvcount;
QString m_opcount; QString m_opcount;
MoveType m_moveType; MoveType m_movetype;
RangeMode m_rangemode;
bool m_fakeEnd; bool m_fakeEnd;
@@ -354,10 +386,19 @@ public:
bool m_lastSearchForward; bool m_lastSearchForward;
QString m_lastInsertion; QString m_lastInsertion;
QString removeSelectedText();
int anchor() const { return m_anchor; } int anchor() const { return m_anchor; }
int position() const { return m_tc.position(); } int position() const { return m_tc.position(); }
QString selectedText(MoveType moveType = MoveExclusive) const;
void removeSelectedText();
void removeText(const Range &range);
QString selectedText() const { return text(Range(position(), anchor())); }
QString text(const Range &range) const;
void yankSelectedText();
void yankText(const Range &range, int toregister = '"');
void pasteText(bool afterCursor);
// undo handling // undo handling
void undo(); void undo();
@@ -423,7 +464,7 @@ public:
QStringList FakeVimHandler::Private::m_searchHistory; QStringList FakeVimHandler::Private::m_searchHistory;
QStringList FakeVimHandler::Private::m_commandHistory; QStringList FakeVimHandler::Private::m_commandHistory;
QHash<int, QString> FakeVimHandler::Private::m_registers; QHash<int, Register> FakeVimHandler::Private::m_registers;
FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget) FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
{ {
@@ -445,12 +486,13 @@ void FakeVimHandler::Private::init()
m_gflag = false; m_gflag = false;
m_visualMode = NoVisualMode; m_visualMode = NoVisualMode;
m_targetColumn = 0; m_targetColumn = 0;
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
m_anchor = 0; m_anchor = 0;
m_savedYankPosition = 0; m_savedYankPosition = 0;
m_cursorWidth = EDITOR(cursorWidth()); m_cursorWidth = EDITOR(cursorWidth());
m_inReplay = false; m_inReplay = false;
m_justAutoIndented = 0; m_justAutoIndented = 0;
m_rangemode = RangeCharMode;
} }
bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
@@ -688,32 +730,35 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
m_marks['>'] = m_tc.position(); m_marks['>'] = m_tc.position();
if (m_submode == ChangeSubMode) { if (m_submode == ChangeSubMode) {
if (m_moveType == MoveInclusive) if (m_movetype == MoveInclusive)
moveRight(); // correction moveRight(); // correction
if (anchor() >= position()) if (anchor() >= position())
m_anchor++; m_anchor++;
if (!dotCommand.isEmpty()) if (!dotCommand.isEmpty())
setDotCommand("c" + dotCommand); setDotCommand("c" + dotCommand);
QString text = removeSelectedText(); //QString text = removeSelectedText();
//qDebug() << "CHANGING TO INSERT MODE" << text; //qDebug() << "CHANGING TO INSERT MODE" << text;
m_registers[m_register] = text; //m_registers[m_register] = text;
yankSelectedText();
removeSelectedText();
enterInsertMode(); enterInsertMode();
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == DeleteSubMode) { } else if (m_submode == DeleteSubMode) {
if (m_moveType == MoveInclusive) if (m_movetype == MoveInclusive)
moveRight(); // correction moveRight(); // correction
if (anchor() >= position()) if (anchor() >= position())
m_anchor++; m_anchor++;
if (!dotCommand.isEmpty()) if (!dotCommand.isEmpty())
setDotCommand("d" + dotCommand); setDotCommand("d" + dotCommand);
m_registers[m_register] = removeSelectedText(); yankSelectedText();
removeSelectedText();
m_submode = NoSubMode; m_submode = NoSubMode;
if (atEndOfLine()) if (atEndOfLine())
moveLeft(); moveLeft();
else else
setTargetColumn(); setTargetColumn();
} else if (m_submode == YankSubMode) { } else if (m_submode == YankSubMode) {
m_registers[m_register] = selectedText(); yankSelectedText();
setPosition(m_savedYankPosition); setPosition(m_savedYankPosition);
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == ReplaceSubMode) { } else if (m_submode == ReplaceSubMode) {
@@ -735,12 +780,13 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
updateMiniBuffer(); updateMiniBuffer();
} }
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
m_mvcount.clear(); m_mvcount.clear();
m_opcount.clear(); m_opcount.clear();
m_gflag = false; m_gflag = false;
m_register = '"'; m_register = '"';
m_tc.clearSelection(); m_tc.clearSelection();
m_rangemode = RangeCharMode;
updateSelection(); updateSelection();
updateMiniBuffer(); updateMiniBuffer();
@@ -901,7 +947,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveToStartOfLine(); moveToStartOfLine();
setTargetColumn(); setTargetColumn();
moveUp(count() - 1); moveUp(count() - 1);
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
m_lastInsertion.clear(); m_lastInsertion.clear();
setDotCommand("%1cc", count()); setDotCommand("%1cc", count());
finishMovement(); finishMovement();
@@ -910,32 +956,33 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setTargetColumn(); setTargetColumn();
setAnchor(); setAnchor();
moveDown(count()); moveDown(count());
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
setDotCommand("%1dd", count()); setDotCommand("%1dd", count());
finishMovement(); finishMovement();
} else if (m_submode == YankSubMode && key == 'y') { } else if (m_submode == YankSubMode && key == 'y') {
moveToStartOfLine(); m_movetype = MoveLineWise;
setAnchor(); int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1);
moveDown(count() - 1); Range range(position(), endPos, RangeLineMode);
moveBehindEndOfLine(); ///range.extendByLines(count() - 1);
m_moveType = MoveLineWise; yankText(range);
m_submode = NoSubMode;
finishMovement(); finishMovement();
} else if (m_submode == ShiftLeftSubMode && key == '<') { } else if (m_submode == ShiftLeftSubMode && key == '<') {
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
setDotCommand("%1<<", count()); setDotCommand("%1<<", count());
finishMovement(); finishMovement();
} else if (m_submode == ShiftRightSubMode && key == '>') { } else if (m_submode == ShiftRightSubMode && key == '>') {
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
setDotCommand("%1>>", count()); setDotCommand("%1>>", count());
finishMovement(); finishMovement();
} else if (m_submode == IndentSubMode && key == '=') { } else if (m_submode == IndentSubMode && key == '=') {
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
setDotCommand("%1==", count()); setDotCommand("%1==", count());
finishMovement(); finishMovement();
} else if (m_submode == ZSubMode) { } else if (m_submode == ZSubMode) {
@@ -988,9 +1035,9 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveLeft(); moveLeft();
setAnchor(); setAnchor();
moveRight(count()); moveRight(count());
QString rem = removeSelectedText(); removeSelectedText();
m_tc.insertText(QString(count(), text.at(0))); m_tc.insertText(QString(count(), text.at(0)));
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
setDotCommand("%1r" + text, count()); setDotCommand("%1r" + text, count());
} }
setTargetColumn(); setTargetColumn();
@@ -1105,7 +1152,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (key == '$' || key == Key_End) { } else if (key == '$' || key == Key_End) {
int submode = m_submode; int submode = m_submode;
moveToEndOfLine(); moveToEndOfLine();
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
setTargetColumn(); setTargetColumn();
if (submode == NoSubMode) if (submode == NoSubMode)
m_targetColumn = -1; m_targetColumn = -1;
@@ -1138,7 +1185,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
indentRegion(); indentRegion();
leaveVisualMode(); leaveVisualMode();
} else if (key == '%') { } else if (key == '%') {
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
moveToMatchingParanthesis(); moveToMatchingParanthesis();
finishMovement(); finishMovement();
} else if (key == 'a') { } else if (key == 'a') {
@@ -1155,11 +1202,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (key == control('a')) { } else if (key == control('a')) {
// FIXME: eat it to prevent the global "select all" shortcut to trigger // FIXME: eat it to prevent the global "select all" shortcut to trigger
} else if (key == 'b') { } else if (key == 'b') {
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
moveToWordBoundary(false, false); moveToWordBoundary(false, false);
finishMovement(); finishMovement();
} else if (key == 'B') { } else if (key == 'B') {
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
moveToWordBoundary(true, false); moveToWordBoundary(true, false);
finishMovement(); finishMovement();
} else if (key == 'c' && m_visualMode == NoVisualMode) { } else if (key == 'c' && m_visualMode == NoVisualMode) {
@@ -1172,7 +1219,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (key == 'C') { } else if (key == 'C') {
setAnchor(); setAnchor();
moveToEndOfLine(); moveToEndOfLine();
m_registers[m_register] = removeSelectedText(); yankSelectedText();
removeSelectedText();
enterInsertMode(); enterInsertMode();
setDotCommand("C"); setDotCommand("C");
finishMovement(); finishMovement();
@@ -1191,15 +1239,20 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
finishMovement(); finishMovement();
} else if ((key == 'd' || key == 'x') && m_visualMode == VisualLineMode) { } else if ((key == 'd' || key == 'x') && m_visualMode == VisualLineMode) {
leaveVisualMode(); leaveVisualMode();
int beginLine = lineForPosition(m_marks['<']); m_rangemode = RangeLineMode;
int endLine = lineForPosition(m_marks['>']); yankSelectedText();
selectRange(beginLine, endLine); removeSelectedText();
m_registers[m_register] = removeSelectedText(); } else if ((key == 'd' || key == 'x') && m_visualMode == VisualBlockMode) {
leaveVisualMode();
m_rangemode = RangeBlockMode;
yankSelectedText();
removeSelectedText();
setPosition(qMin(position(), anchor()));
} else if (key == 'D') { } else if (key == 'D') {
setAnchor(); setAnchor();
m_submode = DeleteSubMode; m_submode = DeleteSubMode;
moveDown(qMax(count() - 1, 0)); moveDown(qMax(count() - 1, 0));
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
moveToEndOfLine(); moveToEndOfLine();
setDotCommand("D"); setDotCommand("D");
finishMovement(); finishMovement();
@@ -1211,11 +1264,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
scrollToLineInDocument(cursorLineInDocument() - sline); scrollToLineInDocument(cursorLineInDocument() - sline);
finishMovement(); finishMovement();
} else if (key == 'e') { // tested } else if (key == 'e') { // tested
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
moveToWordBoundary(false, true); moveToWordBoundary(false, true);
finishMovement(); finishMovement();
} else if (key == 'E') { } else if (key == 'E') {
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
moveToWordBoundary(true, true); moveToWordBoundary(true, true);
finishMovement(); finishMovement();
} else if (key == control('e')) { } else if (key == control('e')) {
@@ -1226,11 +1279,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
finishMovement(); finishMovement();
} else if (key == 'f') { } else if (key == 'f') {
m_subsubmode = FtSubSubMode; m_subsubmode = FtSubSubMode;
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
m_subsubdata = key; m_subsubdata = key;
} else if (key == 'F') { } else if (key == 'F') {
m_subsubmode = FtSubSubMode; m_subsubmode = FtSubSubMode;
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
m_subsubdata = key; m_subsubdata = key;
} else if (key == 'g') { } else if (key == 'g') {
if (m_gflag) { if (m_gflag) {
@@ -1284,7 +1337,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
|| m_submode == CapitalZSubMode || m_submode == RegisterSubMode) { || m_submode == CapitalZSubMode || m_submode == RegisterSubMode) {
moveDown(count()); moveDown(count());
} else { } else {
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
moveToStartOfLine(); moveToStartOfLine();
setAnchor(); setAnchor();
moveDown(count() + 1); moveDown(count() + 1);
@@ -1310,7 +1363,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
|| m_submode == CapitalZSubMode || m_submode == RegisterSubMode) { || m_submode == CapitalZSubMode || m_submode == RegisterSubMode) {
moveUp(count()); moveUp(count());
} else { } else {
m_moveType = MoveLineWise; m_movetype = MoveLineWise;
moveToStartOfLine(); moveToStartOfLine();
moveDown(); moveDown();
setAnchor(); setAnchor();
@@ -1318,7 +1371,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} }
finishMovement("k"); finishMovement("k");
} else if (key == 'l' || key == Key_Right || key == ' ') { } else if (key == 'l' || key == Key_Right || key == ' ') {
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
moveRight(qMin(count(), rightDist())); moveRight(qMin(count(), rightDist()));
setTargetColumn(); setTargetColumn();
finishMovement("l"); finishMovement("l");
@@ -1363,29 +1416,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
m_jumpListUndo.pop_back(); m_jumpListUndo.pop_back();
} }
} else if (key == 'p' || key == 'P') { } else if (key == 'p' || key == 'P') {
QString text = m_registers[m_register]; pasteText(key == 'p');
int n = text.count(QChar('\n')); setTargetColumn();
//qDebug() << "REGISTERS: " << m_registers << "MOVE: " << m_moveType;
//qDebug() << "LINES: " << n << text << m_register;
if (n > 0) {
moveToStartOfLine();
m_targetColumn = 0;
for (int i = count(); --i >= 0; ) {
if (key == 'p')
moveDown();
m_tc.insertText(text);
moveUp(n);
}
moveToFirstNonBlankOnLine();
} else {
m_targetColumn = 0;
for (int i = count(); --i >= 0; ) {
if (key == 'p')
moveRight();
m_tc.insertText(text);
moveLeft();
}
}
setDotCommand("%1p", count()); setDotCommand("%1p", count());
finishMovement(); finishMovement();
} else if (key == 'r') { } else if (key == 'r') {
@@ -1405,17 +1437,18 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveLeft(); moveLeft();
setAnchor(); setAnchor();
moveRight(qMin(count(), rightDist())); moveRight(qMin(count(), rightDist()));
m_registers[m_register] = removeSelectedText(); yankSelectedText();
removeSelectedText();
setDotCommand("s"); // setDotCommand("%1s", count()); setDotCommand("s"); // setDotCommand("%1s", count());
m_opcount.clear(); m_opcount.clear();
m_mvcount.clear(); m_mvcount.clear();
enterInsertMode(); enterInsertMode();
} else if (key == 't') { } else if (key == 't') {
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
m_subsubmode = FtSubSubMode; m_subsubmode = FtSubSubMode;
m_subsubdata = key; m_subsubdata = key;
} else if (key == 'T') { } else if (key == 'T') {
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
m_subsubmode = FtSubSubMode; m_subsubmode = FtSubSubMode;
m_subsubdata = key; m_subsubdata = key;
} else if (key == 'u') { } else if (key == 'u') {
@@ -1438,25 +1471,25 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
// cursor is on a non-blank. // cursor is on a non-blank.
if (m_submode == ChangeSubMode) { if (m_submode == ChangeSubMode) {
moveToWordBoundary(false, true); moveToWordBoundary(false, true);
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
} else { } else {
moveToNextWord(false); moveToNextWord(false);
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
} }
finishMovement("w"); finishMovement("w");
} else if (key == 'W') { } else if (key == 'W') {
if (m_submode == ChangeSubMode) { if (m_submode == ChangeSubMode) {
moveToWordBoundary(true, true); moveToWordBoundary(true, true);
m_moveType = MoveInclusive; m_movetype = MoveInclusive;
} else { } else {
moveToNextWord(true); moveToNextWord(true);
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
} }
finishMovement("W"); finishMovement("W");
} else if (key == control('w')) { } else if (key == control('w')) {
m_submode = WindowSubMode; m_submode = WindowSubMode;
} else if (key == 'x' && m_visualMode == NoVisualMode) { // = "dl" } else if (key == 'x' && m_visualMode == NoVisualMode) { // = "dl"
m_moveType = MoveExclusive; m_movetype = MoveExclusive;
if (atEndOfLine()) if (atEndOfLine())
moveLeft(); moveLeft();
setAnchor(); setAnchor();
@@ -1468,7 +1501,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
if (leftDist() > 0) { if (leftDist() > 0) {
setAnchor(); setAnchor();
moveLeft(qMin(count(), leftDist())); moveLeft(qMin(count(), leftDist()));
m_registers[m_register] = removeSelectedText(); yankSelectedText();
removeSelectedText();
} }
finishMovement(); finishMovement();
} else if (key == 'y' && m_visualMode == NoVisualMode) { } else if (key == 'y' && m_visualMode == NoVisualMode) {
@@ -1477,30 +1511,36 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveLeft(); moveLeft();
setAnchor(); setAnchor();
m_submode = YankSubMode; m_submode = YankSubMode;
m_rangemode = RangeCharMode;
} else if (key == 'y' && m_visualMode == VisualCharMode) { } else if (key == 'y' && m_visualMode == VisualCharMode) {
m_registers[m_register] = selectedText(MoveInclusive); Range range(position(), anchor(), RangeCharMode);
range.endPos++; // MoveInclusive
yankText(range, m_register);
setPosition(qMin(position(), anchor())); setPosition(qMin(position(), anchor()));
leaveVisualMode(); leaveVisualMode();
finishMovement(); finishMovement();
} else if (key == 'Y' && m_visualMode == NoVisualMode) { } else if (key == 'Y' && m_visualMode == NoVisualMode) {
const int line = cursorLineInDocument() + 1; const int line = cursorLineInDocument() + 1;
selectRange(line, line + count() - 1); selectRange(line, line + count() - 1);
m_registers[m_register] = selectedText(); m_rangemode = RangeLineMode;
yankSelectedText();
setPosition(qMin(position(), anchor())); setPosition(qMin(position(), anchor()));
finishMovement(); finishMovement();
} else if ((key == 'y' && m_visualMode == VisualLineMode) } else if ((key == 'y' && m_visualMode == VisualLineMode)
|| (key == 'Y' && m_visualMode == VisualLineMode) || (key == 'Y' && m_visualMode == VisualLineMode)
|| (key == 'Y' && m_visualMode == VisualCharMode)) { || (key == 'Y' && m_visualMode == VisualCharMode)) {
int beginLine = lineForPosition(m_marks['<']); m_rangemode = RangeLineMode;
int endLine = lineForPosition(m_marks['>']); yankSelectedText();
selectRange(beginLine, endLine);
m_registers[m_register] = selectedText();
setPosition(qMin(position(), anchor())); setPosition(qMin(position(), anchor()));
moveToStartOfLine(); moveToStartOfLine();
leaveVisualMode(); leaveVisualMode();
finishMovement(); finishMovement();
} else if ((key == 'y' || key == 'Y') && m_visualMode == VisualBlockMode) { } else if ((key == 'y' || key == 'Y') && m_visualMode == VisualBlockMode) {
// not implemented m_rangemode = RangeBlockMode;
yankSelectedText();
setPosition(qMin(position(), anchor()));
leaveVisualMode();
finishMovement();
} else if (key == 'z') { } else if (key == 'z') {
m_submode = ZSubMode; m_submode = ZSubMode;
} else if (key == 'Z') { } else if (key == 'Z') {
@@ -1508,7 +1548,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (key == '~' && !atEndOfLine()) { } else if (key == '~' && !atEndOfLine()) {
setAnchor(); setAnchor();
moveRight(qMin(count(), rightDist())); moveRight(qMin(count(), rightDist()));
QString str = removeSelectedText(); QString str = selectedText();
removeSelectedText();
for (int i = str.size(); --i >= 0; ) { for (int i = str.size(); --i >= 0; ) {
QChar c = str.at(i); QChar c = str.at(i);
str[i] = c.isUpper() ? c.toLower() : c.toUpper(); str[i] = c.isUpper() ? c.toLower() : c.toUpper();
@@ -1840,9 +1881,13 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
} else if (reDelete.indexIn(cmd) != -1) { // :d } else if (reDelete.indexIn(cmd) != -1) { // :d
selectRange(beginLine, endLine); selectRange(beginLine, endLine);
QString reg = reDelete.cap(2); QString reg = reDelete.cap(2);
QString text = removeSelectedText(); QString text = selectedText();
if (!reg.isEmpty()) removeSelectedText();
m_registers[reg.at(0).unicode()] = text; if (!reg.isEmpty()) {
Register &r = m_registers[reg.at(0).unicode()];
r.contents = text;
r.rangemode = RangeLineMode;
}
} else if (reWrite.indexIn(cmd) != -1) { // :w and :x } else if (reWrite.indexIn(cmd) != -1) { // :w and :x
bool noArgs = (beginLine == -1); bool noArgs = (beginLine == -1);
if (beginLine == -1) if (beginLine == -1)
@@ -1869,8 +1914,9 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
} else if (file1.open(QIODevice::ReadWrite)) { } else if (file1.open(QIODevice::ReadWrite)) {
file1.close(); file1.close();
QTextCursor tc = m_tc; QTextCursor tc = m_tc;
selectRange(beginLine, endLine); Range range(firstPositionInLine(beginLine),
QString contents = selectedText(); firstPositionInLine(endLine), RangeLineMode);
QString contents = text(range);
m_tc = tc; m_tc = tc;
qDebug() << "LINES: " << beginLine << endLine; qDebug() << "LINES: " << beginLine << endLine;
bool handled = false; bool handled = false;
@@ -1913,7 +1959,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
} else if (cmd.startsWith(QLatin1Char('!'))) { } else if (cmd.startsWith(QLatin1Char('!'))) {
selectRange(beginLine, endLine); selectRange(beginLine, endLine);
QString command = cmd.mid(1).trimmed(); QString command = cmd.mid(1).trimmed();
QString text = removeSelectedText(); QString text = selectedText();
removeSelectedText();
QProcess proc; QProcess proc;
proc.start(cmd.mid(1)); proc.start(cmd.mid(1));
proc.waitForStarted(); proc.waitForStarted();
@@ -2203,7 +2250,8 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
break; break;
} }
setPosition(pos + i); setPosition(pos + i);
text = removeSelectedText(); text = selectedText();
removeSelectedText();
setPosition(pos); setPosition(pos);
} }
@@ -2413,17 +2461,169 @@ QString FakeVimHandler::Private::lastSearchString() const
return m_searchHistory.empty() ? QString() : m_searchHistory.back(); return m_searchHistory.empty() ? QString() : m_searchHistory.back();
} }
QString FakeVimHandler::Private::selectedText(MoveType moveType) const QString FakeVimHandler::Private::text(const Range &range) const
{ {
int beginPos = qMin(position(), anchor()); if (range.rangemode == RangeCharMode) {
int endPos = qMax(position(), anchor());
if (moveType == MoveInclusive)
++endPos;
QTextCursor tc = m_tc; QTextCursor tc = m_tc;
tc.setPosition(beginPos, MoveAnchor); tc.setPosition(range.beginPos, MoveAnchor);
tc.setPosition(endPos, KeepAnchor); tc.setPosition(range.endPos, KeepAnchor);
return tc.selection().toPlainText(); return tc.selection().toPlainText();
} }
// FIXME: Performance?
int beginLine = lineForPosition(range.beginPos);
int endLine = lineForPosition(range.endPos);
int beginColumn = 0;
int endColumn = INT_MAX;
if (range.rangemode == RangeBlockMode) {
int column1 = range.beginPos - firstPositionInLine(beginLine);
int column2 = range.endPos - firstPositionInLine(endLine);
beginColumn = qMin(column1, column2);
endColumn = qMax(column1, column2);
qDebug() << "COLS: " << beginColumn << endColumn;
}
int len = endColumn - beginColumn + 1;
QString contents;
QTextBlock block = m_tc.document()->findBlockByNumber(beginLine - 1);
for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
QString line = block.text();
if (range.rangemode == RangeBlockMode) {
line = line.mid(beginColumn, len);
if (line.size() < len)
line += QString(len - line.size(), QChar(' '));
}
contents += line;
if (!contents.endsWith('\n'))
contents += '\n';
block = block.next();
}
//qDebug() << "SELECTED: " << contents;
return contents;
}
void FakeVimHandler::Private::yankSelectedText()
{
Range range(anchor(), position());
range.rangemode = m_rangemode;
yankText(range, m_register);
}
void FakeVimHandler::Private::yankText(const Range &range, int toregister)
{
Register &reg = m_registers[toregister];
reg.contents = text(range);
reg.rangemode = range.rangemode;
//qDebug() << "YANKED: " << reg.contents;
}
void FakeVimHandler::Private::removeSelectedText()
{
Range range(anchor(), position());
range.rangemode = m_rangemode;
removeText(range);
}
void FakeVimHandler::Private::removeText(const Range &range)
{
QTextCursor tc = m_tc;
switch (range.rangemode) {
case RangeCharMode: {
tc.setPosition(range.beginPos, MoveAnchor);
tc.setPosition(range.endPos, KeepAnchor);
tc.removeSelectedText();
return;
}
case RangeLineMode: {
tc.setPosition(range.beginPos, MoveAnchor);
tc.movePosition(StartOfLine, MoveAnchor);
tc.setPosition(range.endPos, KeepAnchor);
tc.movePosition(EndOfLine, KeepAnchor);
tc.movePosition(Right, KeepAnchor, 1);
tc.removeSelectedText();
return;
}
case RangeBlockMode: {
int beginLine = lineForPosition(range.beginPos);
int endLine = lineForPosition(range.endPos);
int column1 = range.beginPos - firstPositionInLine(beginLine);
int column2 = range.endPos - firstPositionInLine(endLine);
int beginColumn = qMin(column1, column2);
int endColumn = qMax(column1, column2);
qDebug() << "COLS: " << beginColumn << endColumn;
QTextBlock block = m_tc.document()->findBlockByNumber(endLine - 1);
beginEditBlock();
for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
int bCol = qMin(beginColumn, block.length() - 1);
int eCol = qMin(endColumn, block.length() - 1);
tc.setPosition(block.position() + bCol, MoveAnchor);
tc.setPosition(block.position() + eCol, KeepAnchor);
tc.removeSelectedText();
block = block.previous();
}
endEditBlock();
}
}
}
void FakeVimHandler::Private::pasteText(bool afterCursor)
{
const QString text = m_registers[m_register].contents;
const QStringList lines = text.split(QChar('\n'));
switch (m_registers[m_register].rangemode) {
case RangeCharMode: {
m_targetColumn = 0;
for (int i = count(); --i >= 0; ) {
if (afterCursor && rightDist() > 0)
moveRight();
m_tc.insertText(text);
moveLeft();
}
break;
}
case RangeLineMode: {
moveToStartOfLine();
m_targetColumn = 0;
for (int i = count(); --i >= 0; ) {
if (afterCursor)
moveDown();
m_tc.insertText(text);
moveUp(lines.size() - 1);
}
moveToFirstNonBlankOnLine();
break;
}
case RangeBlockMode: {
beginEditBlock();
QTextBlock block = m_tc.block();
moveRight();
QTextCursor tc = m_tc;
const int col = tc.position() - block.position();
//for (int i = lines.size(); --i >= 0; ) {
for (int i = 0; i < lines.size(); ++i) {
const QString line = lines.at(i);
tc.movePosition(StartOfLine, MoveAnchor);
if (col >= block.length()) {
tc.movePosition(EndOfLine, MoveAnchor);
tc.insertText(QString(col - line.size() + 1, QChar(' ')));
} else {
tc.movePosition(Right, MoveAnchor, col);
}
qDebug() << "INSERT " << line << " AT " << tc.position()
<< "COL: " << col;
tc.insertText(line);
tc.movePosition(StartOfLine, MoveAnchor);
tc.movePosition(Down, MoveAnchor, 1);
if (tc.position() >= lastPositionInDocument() - 1) {
tc.insertText(QString(QChar('\n')));
tc.movePosition(Up, MoveAnchor, 1);
}
block = block.next();
}
endEditBlock();
break;
}
}
}
int FakeVimHandler::Private::firstPositionInLine(int line) const int FakeVimHandler::Private::firstPositionInLine(int line) const
{ {
@@ -2497,20 +2697,6 @@ void FakeVimHandler::Private::redo()
m_tc.setPosition(m_undoCursorPosition[rev]); m_tc.setPosition(m_undoCursorPosition[rev]);
} }
QString FakeVimHandler::Private::removeSelectedText()
{
//qDebug() << "POS: " << position() << " ANCHOR: " << anchor() << m_tc.anchor();
int pos = m_tc.position();
if (pos == anchor())
return QString();
m_tc.setPosition(anchor(), MoveAnchor);
m_tc.setPosition(pos, KeepAnchor);
QString from = m_tc.selection().toPlainText();
m_tc.removeSelectedText();
setAnchor();
return from;
}
void FakeVimHandler::Private::enterInsertMode() void FakeVimHandler::Private::enterInsertMode()
{ {
EDITOR(setCursorWidth(m_cursorWidth)); EDITOR(setCursorWidth(m_cursorWidth));

View File

@@ -108,8 +108,8 @@ int main(int argc, char *argv[])
QObject::connect(&handler, SIGNAL(commandBufferChanged(QString)), QObject::connect(&handler, SIGNAL(commandBufferChanged(QString)),
&proxy, SLOT(changeStatusMessage(QString))); &proxy, SLOT(changeStatusMessage(QString)));
QObject::connect(&handler, SIGNAL(quitRequested(bool)), //QObject::connect(&handler, SIGNAL(quitRequested(bool)),
&app, SLOT(quit())); // &app, SLOT(quit()));
QObject::connect(&handler, QObject::connect(&handler,
SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)), SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
&proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>))); &proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));