mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
vim-mode: support S, { and }
Thanks to xianzhon@github
This commit is contained in:
parent
bb7e6e196c
commit
9523168fc3
@ -161,9 +161,9 @@ VNote supports a simple but useful Vim mode, including **Normal**, **Insert**, *
|
|||||||
|
|
||||||
VNote supports following features of Vim:
|
VNote supports following features of Vim:
|
||||||
|
|
||||||
- `r`, `s`, `i`, `I`, `a`, `A`, `o`, and `O`;
|
- `r`, `s`, `S`, `i`, `I`, `a`, `A`, `c`, `C`, `o`, and `O`;
|
||||||
- Actions `d`, `c`, `y`, `p`, `<`, `>`, `gu`, `gU`, and `~`;
|
- Actions `d`, `c`, `y`, `p`, `<`, `>`, `gu`, `gU`, and `~`;
|
||||||
- Movements `h/j/k/l`, `gj/gk`, `Ctrl+U`, `Ctrl+D`, `gg`, `G`, `0`, `^`, and `$`;
|
- Movements `h/j/k/l`, `gj/gk`, `Ctrl+U`, `Ctrl+D`, `gg`, `G`, `0`, `^`, `{`, `}`, and `$`;
|
||||||
- Marks `a-z`;
|
- Marks `a-z`;
|
||||||
- Registers `"`, `_`, `+`, `a-z`(`A-Z`);
|
- Registers `"`, `_`, `+`, `a-z`(`A-Z`);
|
||||||
- Jump locations list (`Ctrl+O` and `Ctrl+I`);
|
- Jump locations list (`Ctrl+O` and `Ctrl+I`);
|
||||||
|
@ -162,9 +162,9 @@ VNote支持一个简单但有用的Vim模式,包括 **正常**, **插入**
|
|||||||
|
|
||||||
VNote支持以下几个Vim的特性:
|
VNote支持以下几个Vim的特性:
|
||||||
|
|
||||||
- `r`, `s`, `i`, `I`, `a`, `A`, `o`, `O`;
|
- `r`, `s`, `S`, `i`, `I`, `a`, `A`, `c`, `C`, `o`, `O`;
|
||||||
- 操作 `d`, `c`, `y`, `p`, `<`, `>`, `gu`, `gU`, `~`;
|
- 操作 `d`, `c`, `y`, `p`, `<`, `>`, `gu`, `gU`, `~`;
|
||||||
- 移动 `h/j/k/l`, `gj/gk`, `Ctrl+U`, `Ctrl+D`, `gg`, `G`, `0`, `^`, `$`;
|
- 移动 `h/j/k/l`, `gj/gk`, `Ctrl+U`, `Ctrl+D`, `gg`, `G`, `0`, `^`, `{`, `}`, `$`;
|
||||||
- 标记 `a-z`;
|
- 标记 `a-z`;
|
||||||
- 寄存器 `"`, `_`, `+`, `a-z`(`A-Z`);
|
- 寄存器 `"`, `_`, `+`, `a-z`(`A-Z`);
|
||||||
- 跳转位置列表 (`Ctrl+O` and `Ctrl+I`);
|
- 跳转位置列表 (`Ctrl+O` and `Ctrl+I`);
|
||||||
|
@ -639,3 +639,34 @@ round:
|
|||||||
p_cursor.setPosition(closing, QTextCursor::KeepAnchor);
|
p_cursor.setPosition(closing, QTextCursor::KeepAnchor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VEditUtils::findNextEmptyBlock(const QTextCursor &p_cursor,
|
||||||
|
bool p_forward,
|
||||||
|
int p_repeat)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_repeat > 0);
|
||||||
|
int res = -1;
|
||||||
|
QTextBlock block = p_cursor.block();
|
||||||
|
if (p_forward) {
|
||||||
|
block = block.next();
|
||||||
|
} else {
|
||||||
|
block = block.previous();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (block.isValid()) {
|
||||||
|
if (block.length() == 1) {
|
||||||
|
res = block.position();
|
||||||
|
if (--p_repeat == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_forward) {
|
||||||
|
block = block.next();
|
||||||
|
} else {
|
||||||
|
block = block.previous();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_repeat > 0 ? -1 : res;
|
||||||
|
}
|
||||||
|
@ -124,6 +124,12 @@ public:
|
|||||||
// Need to call setTextCursor() to make it take effect.
|
// Need to call setTextCursor() to make it take effect.
|
||||||
static void deleteIndentAndListMark(QTextCursor &p_cursor);
|
static void deleteIndentAndListMark(QTextCursor &p_cursor);
|
||||||
|
|
||||||
|
// Find next @p_repeat empty block.
|
||||||
|
// Returns the position of that block if found. Otherwise, returns -1.
|
||||||
|
static int findNextEmptyBlock(const QTextCursor &p_cursor,
|
||||||
|
bool p_forward,
|
||||||
|
int p_repeat);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VEditUtils() {}
|
VEditUtils() {}
|
||||||
};
|
};
|
||||||
|
@ -1030,6 +1030,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setMode(VimMode::Insert);
|
setMode(VimMode::Insert);
|
||||||
|
} else if (modifiers == Qt::ShiftModifier) {
|
||||||
|
// S, change current line.
|
||||||
|
tryGetRepeatToken(m_keys, m_tokens);
|
||||||
|
if (hasActionToken() || !m_keys.isEmpty()) {
|
||||||
|
// Invalid sequence.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addActionToken(Action::Change);
|
||||||
|
addRangeToken(Range::Line);
|
||||||
|
processCommand(m_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2048,12 +2059,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
addRangeToken(range);
|
addRangeToken(range);
|
||||||
processCommand(m_tokens);
|
processCommand(m_tokens);
|
||||||
break;
|
break;
|
||||||
} else if (hasActionToken() || !checkMode(VimMode::Normal)) {
|
} else if (m_keys.isEmpty()) {
|
||||||
// Invalid sequence.
|
// {, ParagraphUp movement.
|
||||||
break;
|
tryAddMoveAction();
|
||||||
} else if (checkPendingKey(Key(Qt::Key_BracketLeft))) {
|
addMovementToken(Movement::ParagraphUp);
|
||||||
|
processCommand(m_tokens);
|
||||||
|
} else if (!hasActionToken()
|
||||||
|
&& checkPendingKey(Key(Qt::Key_BracketLeft))) {
|
||||||
// [{, goto previous title at one higher level.
|
// [{, goto previous title at one higher level.
|
||||||
processTitleJump(m_tokens, false, -1);
|
if (checkMode(VimMode::Normal)) {
|
||||||
|
processTitleJump(m_tokens, false, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2077,12 +2093,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
addRangeToken(range);
|
addRangeToken(range);
|
||||||
processCommand(m_tokens);
|
processCommand(m_tokens);
|
||||||
break;
|
break;
|
||||||
} else if (hasActionToken() || !checkMode(VimMode::Normal)) {
|
} else if (m_keys.isEmpty()) {
|
||||||
// Invalid sequence.
|
// }, ParagraphDown movement.
|
||||||
break;
|
tryAddMoveAction();
|
||||||
} else if (checkPendingKey(Key(Qt::Key_BracketRight))) {
|
addMovementToken(Movement::ParagraphDown);
|
||||||
|
processCommand(m_tokens);
|
||||||
|
} else if (!hasActionToken()
|
||||||
|
&& checkPendingKey(Key(Qt::Key_BracketRight))) {
|
||||||
// ]}, goto next title at one higher level.
|
// ]}, goto next title at one higher level.
|
||||||
processTitleJump(m_tokens, true, -1);
|
if (checkMode(VimMode::Normal)) {
|
||||||
|
processTitleJump(m_tokens, true, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -3101,6 +3122,36 @@ handle_target:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Movement::ParagraphUp:
|
||||||
|
forward = false;
|
||||||
|
// Fall through.
|
||||||
|
case Movement::ParagraphDown:
|
||||||
|
{
|
||||||
|
if (p_repeat == -1) {
|
||||||
|
p_repeat = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record current location.
|
||||||
|
m_locations.addLocation(p_cursor);
|
||||||
|
|
||||||
|
int oriPos = p_cursor.position();
|
||||||
|
|
||||||
|
int position = VEditUtils::findNextEmptyBlock(p_cursor,
|
||||||
|
forward,
|
||||||
|
p_repeat);
|
||||||
|
if (position == -1) {
|
||||||
|
// No empty block. Move to the first/last character.
|
||||||
|
p_cursor.movePosition(forward ? QTextCursor::End : QTextCursor::Start,
|
||||||
|
p_moveMode);
|
||||||
|
hasMoved = p_cursor.position() != oriPos;
|
||||||
|
} else {
|
||||||
|
p_cursor.setPosition(position, p_moveMode);
|
||||||
|
hasMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3575,6 +3626,9 @@ void VVim::processDeleteAction(QList<Token> &p_tokens)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParagraphUp and ParagraphDown are a little different from Vim in
|
||||||
|
// block deletion.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -415,6 +415,8 @@ private:
|
|||||||
FindPrevious,
|
FindPrevious,
|
||||||
FindNextWordUnderCursor,
|
FindNextWordUnderCursor,
|
||||||
FindPreviousWordUnderCursor,
|
FindPreviousWordUnderCursor,
|
||||||
|
ParagraphUp,
|
||||||
|
ParagraphDown,
|
||||||
Invalid
|
Invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user