mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
vim-mode
- `Ctrl+Tab` and `Ctrl+Shift+Tab` in Normal mode to alternate tabs; - Support `:<num>` command for line jump; - Support `%`;
This commit is contained in:
parent
33146efcd9
commit
71bcfe3019
@ -254,6 +254,50 @@ bool VEditUtils::findTargetWithinBlock(QTextCursor &p_cursor,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VEditUtils::findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||||
|
QTextCursor::MoveMode p_mode,
|
||||||
|
const QList<QChar> &p_targets,
|
||||||
|
bool p_forward,
|
||||||
|
bool p_inclusive)
|
||||||
|
{
|
||||||
|
if (p_targets.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetIdx = -1;
|
||||||
|
QTextBlock block = p_cursor.block();
|
||||||
|
QString text = block.text();
|
||||||
|
int pib = p_cursor.positionInBlock();
|
||||||
|
int delta = p_forward ? 1 : -1;
|
||||||
|
|
||||||
|
// The index to start searching.
|
||||||
|
int idx = pib + (p_inclusive ? delta : 2 * delta);
|
||||||
|
|
||||||
|
for (; idx < text.size() && idx >= 0; idx += delta) {
|
||||||
|
int index = p_targets.indexOf(text[idx]);
|
||||||
|
if (index != -1) {
|
||||||
|
targetIdx = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= text.size()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
--idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_cursor.setPosition(block.position() + idx, p_mode);
|
||||||
|
return targetIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int VEditUtils::selectedBlockCount(const QTextCursor &p_cursor)
|
int VEditUtils::selectedBlockCount(const QTextCursor &p_cursor)
|
||||||
{
|
{
|
||||||
if (!p_cursor.hasSelection()) {
|
if (!p_cursor.hasSelection()) {
|
||||||
|
@ -65,8 +65,10 @@ public:
|
|||||||
static void unindentBlock(QTextCursor &p_cursor,
|
static void unindentBlock(QTextCursor &p_cursor,
|
||||||
const QString &p_indentationText);
|
const QString &p_indentationText);
|
||||||
|
|
||||||
// Find @p_repeat th occurence a char within a block.
|
// Find @p_repeat th occurence of a char within a block.
|
||||||
// Returns true if target is found.
|
// Returns true if target is found.
|
||||||
|
// Please pay attention to the one-step-forward/backward in KeepAnchor mode
|
||||||
|
// and exclusive case.
|
||||||
static bool findTargetWithinBlock(QTextCursor &p_cursor,
|
static bool findTargetWithinBlock(QTextCursor &p_cursor,
|
||||||
QTextCursor::MoveMode p_mode,
|
QTextCursor::MoveMode p_mode,
|
||||||
QChar p_target,
|
QChar p_target,
|
||||||
@ -74,6 +76,17 @@ public:
|
|||||||
bool p_inclusive,
|
bool p_inclusive,
|
||||||
int p_repeat);
|
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.
|
||||||
|
static int findTargetsWithinBlock(QTextCursor &p_cursor,
|
||||||
|
QTextCursor::MoveMode p_mode,
|
||||||
|
const QList<QChar> &p_targets,
|
||||||
|
bool p_forward,
|
||||||
|
bool p_inclusive);
|
||||||
|
|
||||||
// Find a pair target (@p_opening, @p_closing) containing current cursor and
|
// Find a pair target (@p_opening, @p_closing) containing current cursor and
|
||||||
// select the range between them.
|
// select the range between them.
|
||||||
// Need to call setTextCursor() to make it take effect.
|
// Need to call setTextCursor() to make it take effect.
|
||||||
|
@ -485,6 +485,13 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
goto accept;
|
goto accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl+Tab and Ctrl+Shift+BackTab to alternate tabs.
|
||||||
|
if ((key == Qt::Key_Tab && modifiers == Qt::ControlModifier)
|
||||||
|
|| (key == Qt::Key_Backtab && modifiers == (Qt::ShiftModifier | Qt::ControlModifier))) {
|
||||||
|
// Let it be handled outside VVim.
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_replayLeaderSequence) {
|
if (m_replayLeaderSequence) {
|
||||||
qDebug() << "replaying sequence" << keyToChar(key, modifiers);
|
qDebug() << "replaying sequence" << keyToChar(key, modifiers);
|
||||||
}
|
}
|
||||||
@ -1794,6 +1801,13 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
case Qt::Key_Percent:
|
case Qt::Key_Percent:
|
||||||
{
|
{
|
||||||
if (modifiers == Qt::ShiftModifier) {
|
if (modifiers == Qt::ShiftModifier) {
|
||||||
|
if (m_keys.isEmpty()) {
|
||||||
|
// %, FindPair movement.
|
||||||
|
tryAddMoveAction();
|
||||||
|
addMovementToken(Movement::FindPair);
|
||||||
|
processCommand(m_tokens);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
tryGetRepeatToken(m_keys, m_tokens);
|
tryGetRepeatToken(m_keys, m_tokens);
|
||||||
if (m_keys.isEmpty() && hasRepeatToken()) {
|
if (m_keys.isEmpty() && hasRepeatToken()) {
|
||||||
// xx%, jump to a certain line (percentage of the documents).
|
// xx%, jump to a certain line (percentage of the documents).
|
||||||
@ -1812,6 +1826,7 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
|||||||
processCommand(m_tokens);
|
processCommand(m_tokens);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2199,8 +2214,7 @@ void VVim::processMoveAction(QList<Token> &p_tokens)
|
|||||||
|| m_mode == VimMode::VisualLine)
|
|| m_mode == VimMode::VisualLine)
|
||||||
? QTextCursor::KeepAnchor
|
? QTextCursor::KeepAnchor
|
||||||
: QTextCursor::MoveAnchor;
|
: QTextCursor::MoveAnchor;
|
||||||
bool hasMoved = processMovement(cursor, m_editor->document(),
|
bool hasMoved = processMovement(cursor, moveMode, mvToken, repeat);
|
||||||
moveMode, mvToken, repeat);
|
|
||||||
|
|
||||||
if (hasMoved) {
|
if (hasMoved) {
|
||||||
// Maintain positionInBlock.
|
// Maintain positionInBlock.
|
||||||
@ -2231,15 +2245,17 @@ void VVim::processMoveAction(QList<Token> &p_tokens)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
bool VVim::processMovement(QTextCursor &p_cursor,
|
||||||
QTextCursor::MoveMode p_moveMode,
|
QTextCursor::MoveMode p_moveMode,
|
||||||
const Token &p_token, int p_repeat)
|
const Token &p_token,
|
||||||
|
int p_repeat)
|
||||||
{
|
{
|
||||||
V_ASSERT(p_token.isMovement());
|
V_ASSERT(p_token.isMovement());
|
||||||
|
|
||||||
bool hasMoved = false;
|
bool hasMoved = false;
|
||||||
bool inclusive = true;
|
bool inclusive = true;
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
|
QTextDocument *doc = p_cursor.document();
|
||||||
|
|
||||||
switch (p_token.m_movement) {
|
switch (p_token.m_movement) {
|
||||||
case Movement::Left:
|
case Movement::Left:
|
||||||
@ -2301,7 +2317,7 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
p_repeat = 1;
|
p_repeat = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blockCount = p_doc->blockCount();
|
int blockCount = doc->blockCount();
|
||||||
p_repeat = qMin(blockCount - 1 - p_cursor.block().blockNumber(), p_repeat);
|
p_repeat = qMin(blockCount - 1 - p_cursor.block().blockNumber(), p_repeat);
|
||||||
|
|
||||||
if (p_repeat > 0) {
|
if (p_repeat > 0) {
|
||||||
@ -2343,7 +2359,7 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
int blockStep = blockCountOfPageStep() * p_repeat;
|
int blockStep = blockCountOfPageStep() * p_repeat;
|
||||||
int block = p_cursor.block().blockNumber();
|
int block = p_cursor.block().blockNumber();
|
||||||
block = qMax(0, block - blockStep);
|
block = qMax(0, block - blockStep);
|
||||||
p_cursor.setPosition(p_doc->findBlockByNumber(block).position(), p_moveMode);
|
p_cursor.setPosition(doc->findBlockByNumber(block).position(), p_moveMode);
|
||||||
hasMoved = true;
|
hasMoved = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2357,8 +2373,8 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
|
|
||||||
int blockStep = blockCountOfPageStep() * p_repeat;
|
int blockStep = blockCountOfPageStep() * p_repeat;
|
||||||
int block = p_cursor.block().blockNumber();
|
int block = p_cursor.block().blockNumber();
|
||||||
block = qMin(block + blockStep, p_doc->blockCount() - 1);
|
block = qMin(block + blockStep, doc->blockCount() - 1);
|
||||||
p_cursor.setPosition(p_doc->findBlockByNumber(block).position(), p_moveMode);
|
p_cursor.setPosition(doc->findBlockByNumber(block).position(), p_moveMode);
|
||||||
hasMoved = true;
|
hasMoved = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2375,7 +2391,7 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
blockStep = p_repeat * halfBlockStep;
|
blockStep = p_repeat * halfBlockStep;
|
||||||
int block = p_cursor.block().blockNumber();
|
int block = p_cursor.block().blockNumber();
|
||||||
block = qMax(0, block - blockStep);
|
block = qMax(0, block - blockStep);
|
||||||
p_cursor.setPosition(p_doc->findBlockByNumber(block).position(), p_moveMode);
|
p_cursor.setPosition(doc->findBlockByNumber(block).position(), p_moveMode);
|
||||||
hasMoved = true;
|
hasMoved = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2391,8 +2407,8 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
int halfBlockStep = qMax(blockStep / 2, 1);
|
int halfBlockStep = qMax(blockStep / 2, 1);
|
||||||
blockStep = p_repeat * halfBlockStep;
|
blockStep = p_repeat * halfBlockStep;
|
||||||
int block = p_cursor.block().blockNumber();
|
int block = p_cursor.block().blockNumber();
|
||||||
block = qMin(block + blockStep, p_doc->blockCount() - 1);
|
block = qMin(block + blockStep, doc->blockCount() - 1);
|
||||||
p_cursor.setPosition(p_doc->findBlockByNumber(block).position(), p_moveMode);
|
p_cursor.setPosition(doc->findBlockByNumber(block).position(), p_moveMode);
|
||||||
hasMoved = true;
|
hasMoved = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2446,7 +2462,7 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
|||||||
m_locations.addLocation(p_cursor);
|
m_locations.addLocation(p_cursor);
|
||||||
|
|
||||||
// @p_repeat starts from 1 while block number starts from 0.
|
// @p_repeat starts from 1 while block number starts from 0.
|
||||||
QTextBlock block = p_doc->findBlockByNumber(p_repeat - 1);
|
QTextBlock block = doc->findBlockByNumber(p_repeat - 1);
|
||||||
if (block.isValid()) {
|
if (block.isValid()) {
|
||||||
p_cursor.setPosition(block.position(), p_moveMode);
|
p_cursor.setPosition(block.position(), p_moveMode);
|
||||||
} else {
|
} else {
|
||||||
@ -2693,7 +2709,7 @@ handle_target:
|
|||||||
QChar target = keyToChar(key.m_key, key.m_modifiers);
|
QChar target = keyToChar(key.m_key, key.m_modifiers);
|
||||||
Location loc = m_marks.getMarkLocation(target);
|
Location loc = m_marks.getMarkLocation(target);
|
||||||
if (loc.isValid()) {
|
if (loc.isValid()) {
|
||||||
if (loc.m_blockNumber >= p_doc->blockCount()) {
|
if (loc.m_blockNumber >= doc->blockCount()) {
|
||||||
// Invalid block number.
|
// Invalid block number.
|
||||||
message(tr("Mark not set"));
|
message(tr("Mark not set"));
|
||||||
m_marks.clearMark(target);
|
m_marks.clearMark(target);
|
||||||
@ -2703,7 +2719,7 @@ handle_target:
|
|||||||
// Different from Vim:
|
// Different from Vim:
|
||||||
// We just use the block number for mark, so if we delete the line
|
// We just use the block number for mark, so if we delete the line
|
||||||
// where the mark locates, we could not detect if it is set or not.
|
// where the mark locates, we could not detect if it is set or not.
|
||||||
QTextBlock block = p_doc->findBlockByNumber(loc.m_blockNumber);
|
QTextBlock block = doc->findBlockByNumber(loc.m_blockNumber);
|
||||||
p_cursor.setPosition(block.position(), p_moveMode);
|
p_cursor.setPosition(block.position(), p_moveMode);
|
||||||
if (p_token.m_movement == Movement::MarkJump) {
|
if (p_token.m_movement == Movement::MarkJump) {
|
||||||
setCursorPositionInBlock(p_cursor, loc.m_positionInBlock, p_moveMode);
|
setCursorPositionInBlock(p_cursor, loc.m_positionInBlock, p_moveMode);
|
||||||
@ -2718,6 +2734,80 @@ handle_target:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Movement::FindPair:
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_repeat == -1);
|
||||||
|
int anchor = p_cursor.anchor();
|
||||||
|
int position = p_cursor.position();
|
||||||
|
QList<QPair<QChar, QChar>> pairs;
|
||||||
|
pairs.append(QPair<QChar, QChar>('(', ')'));
|
||||||
|
pairs.append(QPair<QChar, QChar>('[', ']'));
|
||||||
|
pairs.append(QPair<QChar, QChar>('{', '}'));
|
||||||
|
|
||||||
|
// Find forward for a pair (), [], and {}.
|
||||||
|
QList<QChar> targets;
|
||||||
|
for (auto const & pair : pairs) {
|
||||||
|
targets.append(pair.first);
|
||||||
|
targets.append(pair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check if current char hits the targets.
|
||||||
|
QChar ch = doc->characterAt(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,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx /= 2;
|
||||||
|
int pairPosition = p_cursor.position();
|
||||||
|
bool ret = VEditUtils::selectPairTargetAround(p_cursor,
|
||||||
|
pairs.at(idx).first,
|
||||||
|
pairs.at(idx).second,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
1);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
// Found matched pair.
|
||||||
|
int first = p_cursor.position();
|
||||||
|
int second = p_cursor.anchor();
|
||||||
|
if (first > second) {
|
||||||
|
int tmp = first;
|
||||||
|
first = second;
|
||||||
|
second = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
--second;
|
||||||
|
|
||||||
|
int target = first;
|
||||||
|
if (first == pairPosition) {
|
||||||
|
target = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_cursor.setPosition(anchor);
|
||||||
|
p_cursor.setPosition(target, p_moveMode);
|
||||||
|
hasMoved = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Restore the cursor position.
|
||||||
|
p_cursor.setPosition(anchor);
|
||||||
|
if (anchor != position) {
|
||||||
|
p_cursor.setPosition(position, QTextCursor::KeepAnchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3133,7 +3223,7 @@ void VVim::processDeleteAction(QList<Token> &p_tokens)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
hasMoved = processMovement(cursor, doc, moveMode, to, repeat);
|
hasMoved = processMovement(cursor, moveMode, to, repeat);
|
||||||
if (repeat == -1) {
|
if (repeat == -1) {
|
||||||
repeat = 1;
|
repeat = 1;
|
||||||
}
|
}
|
||||||
@ -3345,7 +3435,7 @@ void VVim::processCopyAction(QList<Token> &p_tokens)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
changed = processMovement(cursor, doc, moveMode, to, repeat);
|
changed = processMovement(cursor, moveMode, to, repeat);
|
||||||
if (repeat == -1) {
|
if (repeat == -1) {
|
||||||
repeat = 1;
|
repeat = 1;
|
||||||
}
|
}
|
||||||
@ -3591,7 +3681,7 @@ void VVim::processChangeAction(QList<Token> &p_tokens)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
hasMoved = processMovement(cursor, doc, moveMode, to, repeat);
|
hasMoved = processMovement(cursor, moveMode, to, repeat);
|
||||||
if (repeat == -1) {
|
if (repeat == -1) {
|
||||||
repeat = 1;
|
repeat = 1;
|
||||||
}
|
}
|
||||||
@ -3885,7 +3975,6 @@ void VVim::processIndentAction(QList<Token> &p_tokens, bool p_isIndent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
processMovement(cursor,
|
processMovement(cursor,
|
||||||
doc,
|
|
||||||
QTextCursor::KeepAnchor,
|
QTextCursor::KeepAnchor,
|
||||||
to,
|
to,
|
||||||
repeat);
|
repeat);
|
||||||
@ -3959,7 +4048,6 @@ void VVim::processToLowerAction(QList<Token> &p_tokens, bool p_toLower)
|
|||||||
|
|
||||||
cursor.beginEditBlock();
|
cursor.beginEditBlock();
|
||||||
changed = processMovement(cursor,
|
changed = processMovement(cursor,
|
||||||
doc,
|
|
||||||
moveMode,
|
moveMode,
|
||||||
to,
|
to,
|
||||||
repeat);
|
repeat);
|
||||||
@ -4667,8 +4755,10 @@ void VVim::repeatLastFindMovement(bool p_reverse)
|
|||||||
|
|
||||||
void VVim::message(const QString &p_msg)
|
void VVim::message(const QString &p_msg)
|
||||||
{
|
{
|
||||||
|
if (!p_msg.isEmpty()) {
|
||||||
qDebug() << "vim msg:" << p_msg;
|
qDebug() << "vim msg:" << p_msg;
|
||||||
emit vimMessage(p_msg);
|
emit vimMessage(p_msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QMap<QChar, VVim::Register> &VVim::getRegisters() const
|
const QMap<QChar, VVim::Register> &VVim::getRegisters() const
|
||||||
@ -4713,7 +4803,7 @@ bool VVim::processCommandLine(const Key &p_key)
|
|||||||
if (p_key == Key(Qt::Key_Return)
|
if (p_key == Key(Qt::Key_Return)
|
||||||
|| p_key == Key(Qt::Key_Enter, Qt::KeypadModifier)) {
|
|| p_key == Key(Qt::Key_Enter, Qt::KeypadModifier)) {
|
||||||
// Enter, try to execute the command and exit cmd line mode.
|
// Enter, try to execute the command and exit cmd line mode.
|
||||||
executeCommand(m_keys);
|
executeCommand();
|
||||||
m_cmdMode = false;
|
m_cmdMode = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4771,15 +4861,15 @@ bool VVim::processCommandLine(const Key &p_key)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VVim::executeCommand(const QList<Key> &p_keys)
|
void VVim::executeCommand()
|
||||||
{
|
{
|
||||||
bool validCommand = true;
|
bool validCommand = true;
|
||||||
QString msg;
|
QString msg;
|
||||||
|
|
||||||
if (p_keys.isEmpty()) {
|
if (m_keys.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
} if (p_keys.size() == 1) {
|
} if (m_keys.size() == 1) {
|
||||||
const Key &key0 = p_keys.first();
|
const Key &key0 = m_keys.first();
|
||||||
if (key0 == Key(Qt::Key_W)) {
|
if (key0 == Key(Qt::Key_W)) {
|
||||||
// :w, save current file.
|
// :w, save current file.
|
||||||
emit m_editor->saveNote();
|
emit m_editor->saveNote();
|
||||||
@ -4795,9 +4885,9 @@ void VVim::executeCommand(const QList<Key> &p_keys)
|
|||||||
} else {
|
} else {
|
||||||
validCommand = false;
|
validCommand = false;
|
||||||
}
|
}
|
||||||
} else if (p_keys.size() == 2) {
|
} else if (m_keys.size() == 2) {
|
||||||
const Key &key0 = p_keys.first();
|
const Key &key0 = m_keys.first();
|
||||||
const Key &key1 = p_keys.at(1);
|
const Key &key1 = m_keys.at(1);
|
||||||
if (key0 == Key(Qt::Key_W) && key1 == Key(Qt::Key_Q)) {
|
if (key0 == Key(Qt::Key_W) && key1 == Key(Qt::Key_Q)) {
|
||||||
// :wq, save change and quit edit mode.
|
// :wq, save change and quit edit mode.
|
||||||
// We treat it same as :x.
|
// We treat it same as :x.
|
||||||
@ -4814,9 +4904,19 @@ void VVim::executeCommand(const QList<Key> &p_keys)
|
|||||||
validCommand = false;
|
validCommand = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!validCommand && !hasNonDigitPendingKeys() && m_tokens.isEmpty()) {
|
||||||
|
// All digits.
|
||||||
|
// Jump to a specific line.
|
||||||
|
tryGetRepeatToken(m_keys, m_tokens);
|
||||||
|
tryAddMoveAction();
|
||||||
|
addMovementToken(Movement::LineJump);
|
||||||
|
processCommand(m_tokens);
|
||||||
|
validCommand = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!validCommand) {
|
if (!validCommand) {
|
||||||
QString str;
|
QString str;
|
||||||
for (auto const & key : p_keys) {
|
for (auto const & key : m_keys) {
|
||||||
str.append(keyToChar(key.m_key, key.m_modifiers));
|
str.append(keyToChar(key.m_key, key.m_modifiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4826,9 +4926,9 @@ void VVim::executeCommand(const QList<Key> &p_keys)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VVim::hasNonDigitPendingKeys()
|
bool VVim::hasNonDigitPendingKeys(const QList<Key> &p_keys)
|
||||||
{
|
{
|
||||||
for (auto const &key : m_keys) {
|
for (auto const &key : p_keys) {
|
||||||
if (!key.isDigit()) {
|
if (!key.isDigit()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4837,6 +4937,11 @@ bool VVim::hasNonDigitPendingKeys()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VVim::hasNonDigitPendingKeys()
|
||||||
|
{
|
||||||
|
return hasNonDigitPendingKeys(m_keys);
|
||||||
|
}
|
||||||
|
|
||||||
bool VVim::processLeaderSequence(const Key &p_key)
|
bool VVim::processLeaderSequence(const Key &p_key)
|
||||||
{
|
{
|
||||||
// Different from Vim:
|
// Different from Vim:
|
||||||
|
@ -300,6 +300,7 @@ private:
|
|||||||
TillBackward,
|
TillBackward,
|
||||||
MarkJump,
|
MarkJump,
|
||||||
MarkJumpLine,
|
MarkJumpLine,
|
||||||
|
FindPair,
|
||||||
Invalid
|
Invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -617,9 +618,10 @@ private:
|
|||||||
|
|
||||||
// Move @p_cursor according to @p_moveMode and @p_token.
|
// Move @p_cursor according to @p_moveMode and @p_token.
|
||||||
// Return true if it has moved @p_cursor.
|
// Return true if it has moved @p_cursor.
|
||||||
bool processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
|
bool processMovement(QTextCursor &p_cursor,
|
||||||
QTextCursor::MoveMode p_moveMode,
|
QTextCursor::MoveMode p_moveMode,
|
||||||
const Token &p_token, int p_repeat);
|
const Token &p_token,
|
||||||
|
int p_repeat);
|
||||||
|
|
||||||
// Move @p_cursor according to @p_moveMode and @p_range.
|
// Move @p_cursor according to @p_moveMode and @p_range.
|
||||||
// Return true if it has moved @p_cursor.
|
// Return true if it has moved @p_cursor.
|
||||||
@ -647,15 +649,17 @@ private:
|
|||||||
// Returns true if a command has been completed, otherwise returns false.
|
// Returns true if a command has been completed, otherwise returns false.
|
||||||
bool processCommandLine(const Key &p_key);
|
bool processCommandLine(const Key &p_key);
|
||||||
|
|
||||||
// Execute command specified by @p_keys.
|
// Execute command specified by m_keys.
|
||||||
// @p_keys does not contain the leading colon.
|
// @p_keys does not contain the leading colon.
|
||||||
// Following commands are supported:
|
// Following commands are supported:
|
||||||
// :w, :wq, :q, :q!, :x
|
// :w, :wq, :q, :q!, :x
|
||||||
void executeCommand(const QList<Key> &p_keys);
|
void executeCommand();
|
||||||
|
|
||||||
// Check if m_keys has non-digit key.
|
// Check if m_keys has non-digit key.
|
||||||
bool hasNonDigitPendingKeys();
|
bool hasNonDigitPendingKeys();
|
||||||
|
|
||||||
|
bool hasNonDigitPendingKeys(const QList<Key> &p_keys);
|
||||||
|
|
||||||
// Reading a leader sequence, read input @p_key and process it.
|
// Reading a leader sequence, read input @p_key and process it.
|
||||||
// Returns true if a sequence has been replayed or it is being read,
|
// Returns true if a sequence has been replayed or it is being read,
|
||||||
// otherwise returns false.
|
// otherwise returns false.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user