mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59: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:
|
||||
|
||||
- `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 `~`;
|
||||
- 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`;
|
||||
- Registers `"`, `_`, `+`, `a-z`(`A-Z`);
|
||||
- Jump locations list (`Ctrl+O` and `Ctrl+I`);
|
||||
|
@ -162,9 +162,9 @@ 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`, `~`;
|
||||
- 移动 `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`);
|
||||
- 跳转位置列表 (`Ctrl+O` and `Ctrl+I`);
|
||||
|
@ -639,3 +639,34 @@ round:
|
||||
p_cursor.setPosition(closing, QTextCursor::KeepAnchor);
|
||||
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.
|
||||
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:
|
||||
VEditUtils() {}
|
||||
};
|
||||
|
@ -1030,6 +1030,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
||||
}
|
||||
|
||||
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;
|
||||
@ -2048,12 +2059,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
||||
addRangeToken(range);
|
||||
processCommand(m_tokens);
|
||||
break;
|
||||
} else if (hasActionToken() || !checkMode(VimMode::Normal)) {
|
||||
// Invalid sequence.
|
||||
break;
|
||||
} else if (checkPendingKey(Key(Qt::Key_BracketLeft))) {
|
||||
} else if (m_keys.isEmpty()) {
|
||||
// {, ParagraphUp movement.
|
||||
tryAddMoveAction();
|
||||
addMovementToken(Movement::ParagraphUp);
|
||||
processCommand(m_tokens);
|
||||
} else if (!hasActionToken()
|
||||
&& checkPendingKey(Key(Qt::Key_BracketLeft))) {
|
||||
// [{, goto previous title at one higher level.
|
||||
processTitleJump(m_tokens, false, -1);
|
||||
if (checkMode(VimMode::Normal)) {
|
||||
processTitleJump(m_tokens, false, -1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2077,12 +2093,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
||||
addRangeToken(range);
|
||||
processCommand(m_tokens);
|
||||
break;
|
||||
} else if (hasActionToken() || !checkMode(VimMode::Normal)) {
|
||||
// Invalid sequence.
|
||||
break;
|
||||
} else if (checkPendingKey(Key(Qt::Key_BracketRight))) {
|
||||
} else if (m_keys.isEmpty()) {
|
||||
// }, ParagraphDown movement.
|
||||
tryAddMoveAction();
|
||||
addMovementToken(Movement::ParagraphDown);
|
||||
processCommand(m_tokens);
|
||||
} else if (!hasActionToken()
|
||||
&& checkPendingKey(Key(Qt::Key_BracketRight))) {
|
||||
// ]}, goto next title at one higher level.
|
||||
processTitleJump(m_tokens, true, -1);
|
||||
if (checkMode(VimMode::Normal)) {
|
||||
processTitleJump(m_tokens, true, -1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -3101,6 +3122,36 @@ handle_target:
|
||||
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:
|
||||
break;
|
||||
}
|
||||
@ -3575,6 +3626,9 @@ void VVim::processDeleteAction(QList<Token> &p_tokens)
|
||||
break;
|
||||
}
|
||||
|
||||
// ParagraphUp and ParagraphDown are a little different from Vim in
|
||||
// block deletion.
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -415,6 +415,8 @@ private:
|
||||
FindPrevious,
|
||||
FindNextWordUnderCursor,
|
||||
FindPreviousWordUnderCursor,
|
||||
ParagraphUp,
|
||||
ParagraphDown,
|
||||
Invalid
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user