mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
vim-mode: fix movement with block cursor
This commit is contained in:
parent
f6cf98c827
commit
d46917d6a9
@ -283,6 +283,7 @@ bool VEditUtils::findTargetWithinBlock(QTextCursor &p_cursor,
|
||||
QChar p_target,
|
||||
bool p_forward,
|
||||
bool p_inclusive,
|
||||
bool p_leftSideOfCursor,
|
||||
int p_repeat)
|
||||
{
|
||||
if (p_repeat < 1) {
|
||||
@ -296,6 +297,9 @@ bool VEditUtils::findTargetWithinBlock(QTextCursor &p_cursor,
|
||||
|
||||
// The index to start searching.
|
||||
int idx = pib + (p_inclusive ? delta : 2 * delta);
|
||||
if (p_leftSideOfCursor) {
|
||||
--idx;
|
||||
}
|
||||
|
||||
for (; idx < text.size() && idx >= 0; idx += delta) {
|
||||
if (text[idx] == p_target) {
|
||||
@ -322,9 +326,9 @@ bool VEditUtils::findTargetWithinBlock(QTextCursor &p_cursor,
|
||||
}
|
||||
|
||||
int VEditUtils::findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||
QTextCursor::MoveMode p_mode,
|
||||
const QList<QChar> &p_targets,
|
||||
bool p_forward,
|
||||
bool p_leftSideOfCursor,
|
||||
bool p_inclusive)
|
||||
{
|
||||
if (p_targets.isEmpty()) {
|
||||
@ -339,6 +343,9 @@ int VEditUtils::findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||
|
||||
// The index to start searching.
|
||||
int idx = pib + (p_inclusive ? delta : 2 * delta);
|
||||
if (p_leftSideOfCursor) {
|
||||
--idx;
|
||||
}
|
||||
|
||||
for (; idx < text.size() && idx >= 0; idx += delta) {
|
||||
int index = p_targets.indexOf(text[idx]);
|
||||
@ -353,14 +360,11 @@ int VEditUtils::findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||
}
|
||||
|
||||
// text[idx] is the target character.
|
||||
if ((p_forward && p_inclusive && p_mode == QTextCursor::KeepAnchor)
|
||||
|| (!p_forward && !p_inclusive)) {
|
||||
++idx;
|
||||
} else if (p_forward && !p_inclusive && p_mode == QTextCursor::MoveAnchor) {
|
||||
if (p_forward && !p_inclusive) {
|
||||
--idx;
|
||||
}
|
||||
|
||||
p_cursor.setPosition(block.position() + idx, p_mode);
|
||||
p_cursor.setPosition(block.position() + idx);
|
||||
return targetIdx;
|
||||
}
|
||||
|
||||
|
@ -89,17 +89,18 @@ public:
|
||||
QChar p_target,
|
||||
bool p_forward,
|
||||
bool p_inclusive,
|
||||
bool p_leftSideOfCursor,
|
||||
int p_repeat);
|
||||
|
||||
// Find th first occurence of a char in @p_targets within a block.
|
||||
// Returns the index of the found char in @p_targets if found.
|
||||
// Returns -1 if none of the @p_targets is found.
|
||||
// Please pay attention to the one-step-forward/backward in KeepAnchor mode
|
||||
// and exclusive case.
|
||||
// Different from findTargetWithinBlock(), will not modify the ucrsor position
|
||||
// even in KeepAnchor mode.
|
||||
static int findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||
QTextCursor::MoveMode p_mode,
|
||||
const QList<QChar> &p_targets,
|
||||
bool p_forward,
|
||||
bool p_leftSideOfCursor,
|
||||
bool p_inclusive);
|
||||
|
||||
// Find a pair target (@p_opening, @p_closing) containing current cursor and
|
||||
|
@ -178,7 +178,8 @@ static void findCurrentSpace(const QTextCursor &p_cursor, int &p_start, int &p_e
|
||||
// Backward: wwww|ssssswwww
|
||||
static void moveCursorAcrossSpaces(QTextCursor &p_cursor,
|
||||
QTextCursor::MoveMode p_mode,
|
||||
bool p_forward)
|
||||
bool p_forward,
|
||||
bool p_stopAtBoundary = false)
|
||||
{
|
||||
while (true) {
|
||||
QTextBlock block = p_cursor.block();
|
||||
@ -192,7 +193,7 @@ static void moveCursorAcrossSpaces(QTextCursor &p_cursor,
|
||||
}
|
||||
}
|
||||
|
||||
if (pib == text.size()) {
|
||||
if (pib == text.size() && !p_stopAtBoundary) {
|
||||
// Move to next block.
|
||||
p_cursor.movePosition(QTextCursor::Down, p_mode, 1);
|
||||
if (block.blockNumber() == p_cursor.block().blockNumber()) {
|
||||
@ -218,7 +219,7 @@ static void moveCursorAcrossSpaces(QTextCursor &p_cursor,
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
if (idx == -1 && !p_stopAtBoundary) {
|
||||
// Move to previous block.
|
||||
p_cursor.movePosition(QTextCursor::Up, p_mode, 1);
|
||||
if (block.blockNumber() == p_cursor.block().blockNumber()) {
|
||||
@ -2551,6 +2552,13 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
p_repeat = 1;
|
||||
}
|
||||
|
||||
if (checkMode(VimMode::Visual)) {
|
||||
int pos = p_cursor.position();
|
||||
if (pos == p_cursor.anchor() - 1 && pos == m_positionBeforeVisualMode) {
|
||||
++p_repeat;
|
||||
}
|
||||
}
|
||||
|
||||
int pib = p_cursor.positionInBlock();
|
||||
int length = p_cursor.block().length();
|
||||
if (length - pib <= p_repeat) {
|
||||
@ -2730,6 +2738,12 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
// If all the block is space, just move to the end of block; otherwise,
|
||||
// move to the first non-space character.
|
||||
VEditUtils::moveCursorFirstNonSpaceCharacter(p_cursor, p_moveMode);
|
||||
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
break;
|
||||
}
|
||||
@ -2752,6 +2766,11 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
}
|
||||
|
||||
VEditUtils::moveCursorFirstNonSpaceCharacter(p_cursor, p_moveMode);
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
break;
|
||||
}
|
||||
@ -2766,6 +2785,11 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
|
||||
p_cursor.movePosition(QTextCursor::Start, p_moveMode, 1);
|
||||
VEditUtils::moveCursorFirstNonSpaceCharacter(p_cursor, p_moveMode);
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
break;
|
||||
}
|
||||
@ -2780,6 +2804,11 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
|
||||
p_cursor.movePosition(QTextCursor::End, p_moveMode, 1);
|
||||
VEditUtils::moveCursorFirstNonSpaceCharacter(p_cursor, p_moveMode);
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
break;
|
||||
}
|
||||
@ -2797,7 +2826,17 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
}
|
||||
|
||||
p_cursor.movePosition(QTextCursor::NextWord, p_moveMode);
|
||||
if (p_cursor.atBlockEnd() || VEditUtils::isSpaceBlock(p_cursor.block())) {
|
||||
if (p_cursor.atBlockEnd()) {
|
||||
// dw/yw/cw will stop at the end of the line.
|
||||
if (p_repeat == 1
|
||||
&& checkMode(VimMode::Normal)
|
||||
&& p_moveMode == QTextCursor::KeepAnchor) {
|
||||
--p_repeat;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (doc->characterAt(p_cursor.position()).isSpace()
|
||||
|| VEditUtils::isSpaceBlock(p_cursor.block())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2830,6 +2869,18 @@ bool VVim::processMovement(QTextCursor &p_cursor,
|
||||
VEditUtils::findCurrentWORD(p_cursor, start, end);
|
||||
// Move cursor to end of current WORD.
|
||||
p_cursor.setPosition(end, p_moveMode);
|
||||
|
||||
if (p_repeat == 1
|
||||
&& checkMode(VimMode::Normal)
|
||||
&& p_moveMode == QTextCursor::KeepAnchor) {
|
||||
// dW/yW/cW will stop at the end of the line.
|
||||
moveCursorAcrossSpaces(p_cursor, p_moveMode, true, true);
|
||||
if (p_cursor.atBlockEnd()) {
|
||||
--p_repeat;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip spaces.
|
||||
moveCursorAcrossSpaces(p_cursor, p_moveMode, true);
|
||||
if (p_cursor.atBlockEnd()) {
|
||||
@ -3193,6 +3244,7 @@ handle_target:
|
||||
target,
|
||||
forward,
|
||||
inclusive,
|
||||
useLeftSideOfCursor(p_cursor),
|
||||
p_repeat);
|
||||
}
|
||||
|
||||
@ -3227,6 +3279,11 @@ handle_target:
|
||||
VEditUtils::moveCursorFirstNonSpaceCharacter(p_cursor, p_moveMode);
|
||||
}
|
||||
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
}
|
||||
|
||||
@ -3251,15 +3308,19 @@ handle_target:
|
||||
}
|
||||
|
||||
// First check if current char hits the targets.
|
||||
QChar ch = doc->characterAt(position);
|
||||
bool useLeftSideBefore = useLeftSideOfCursor(p_cursor);
|
||||
QChar ch = doc->characterAt(useLeftSideBefore ? position - 1
|
||||
: position);
|
||||
int idx = targets.indexOf(ch);
|
||||
if (idx == -1) {
|
||||
// Use MoveAnchor to avoid the one-step-forward.
|
||||
idx = VEditUtils::findTargetsWithinBlock(p_cursor,
|
||||
QTextCursor::MoveAnchor,
|
||||
targets,
|
||||
true,
|
||||
useLeftSideOfCursor(p_cursor),
|
||||
true);
|
||||
} else if (useLeftSideBefore) {
|
||||
// Move one character back to let p_cursor position at the pair.
|
||||
p_cursor.movePosition(QTextCursor::PreviousCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
@ -3294,6 +3355,12 @@ handle_target:
|
||||
|
||||
p_cursor.setPosition(anchor);
|
||||
p_cursor.setPosition(target, p_moveMode);
|
||||
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
// Move one character forward.
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
hasMoved = true;
|
||||
break;
|
||||
} else {
|
||||
@ -3323,11 +3390,27 @@ handle_target:
|
||||
// Record current location.
|
||||
m_locations.addLocation(p_cursor);
|
||||
|
||||
bool useLeftSideBefore = useLeftSideOfCursor(p_cursor);
|
||||
const SearchItem &item = m_searchHistory.lastItem();
|
||||
while (--p_repeat >= 0) {
|
||||
hasMoved = m_editor->findText(item.m_text, item.m_options,
|
||||
bool found = m_editor->findText(item.m_text,
|
||||
item.m_options,
|
||||
forward ? item.m_forward : !item.m_forward,
|
||||
&p_cursor, p_moveMode);
|
||||
&p_cursor,
|
||||
p_moveMode,
|
||||
useLeftSideBefore);
|
||||
if (found) {
|
||||
hasMoved = true;
|
||||
useLeftSideBefore = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasMoved) {
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -3396,6 +3479,9 @@ handle_target:
|
||||
}
|
||||
|
||||
Q_ASSERT(hasMoved);
|
||||
if (!p_cursor.atEnd() && useLeftSideOfCursor(p_cursor)) {
|
||||
p_cursor.movePosition(QTextCursor::NextCharacter, p_moveMode);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -424,7 +424,8 @@ bool VEditor::findText(const QString &p_text,
|
||||
uint p_options,
|
||||
bool p_forward,
|
||||
QTextCursor *p_cursor,
|
||||
QTextCursor::MoveMode p_moveMode)
|
||||
QTextCursor::MoveMode p_moveMode,
|
||||
bool p_useLeftSideOfCursor)
|
||||
{
|
||||
clearIncrementalSearchedWordHighlight();
|
||||
|
||||
@ -442,6 +443,10 @@ bool VEditor::findText(const QString &p_text,
|
||||
start = p_forward ? p_cursor->position() + 1 : p_cursor->position();
|
||||
}
|
||||
|
||||
if (p_useLeftSideOfCursor) {
|
||||
--start;
|
||||
}
|
||||
|
||||
bool found = findTextHelper(p_text, p_options, p_forward, start,
|
||||
wrapped, retCursor);
|
||||
if (found) {
|
||||
@ -541,11 +546,12 @@ bool VEditor::findTextHelper(const QString &p_text,
|
||||
} else if (p_start > m_document->characterCount()) {
|
||||
p_start = m_document->characterCount();
|
||||
}
|
||||
}
|
||||
|
||||
QTextCursor startCursor = cursor;
|
||||
// Will clear the selection.
|
||||
startCursor.setPosition(p_start);
|
||||
setTextCursorW(startCursor);
|
||||
}
|
||||
|
||||
while (!found) {
|
||||
if (useRegExp) {
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
uint p_options,
|
||||
bool p_forward,
|
||||
QTextCursor *p_cursor = nullptr,
|
||||
QTextCursor::MoveMode p_moveMode = QTextCursor::MoveAnchor);
|
||||
QTextCursor::MoveMode p_moveMode = QTextCursor::MoveAnchor,
|
||||
bool p_useLeftSideOfCursor = false);
|
||||
|
||||
void replaceText(const QString &p_text,
|
||||
uint p_options,
|
||||
|
Loading…
x
Reference in New Issue
Block a user