vim-mode: support DELETE action

Actions related to `d` and `x`.
This commit is contained in:
Le Tan 2017-06-13 21:22:38 +08:00
parent 88fa722868
commit eba2556a3a
8 changed files with 682 additions and 188 deletions

View File

@ -65,7 +65,8 @@ SOURCES += main.cpp\
vexporter.cpp \ vexporter.cpp \
vmdtab.cpp \ vmdtab.cpp \
vhtmltab.cpp \ vhtmltab.cpp \
utils/vvim.cpp utils/vvim.cpp \
utils/veditutils.cpp
HEADERS += vmainwindow.h \ HEADERS += vmainwindow.h \
vdirectorytree.h \ vdirectorytree.h \
@ -117,7 +118,8 @@ HEADERS += vmainwindow.h \
vexporter.h \ vexporter.h \
vmdtab.h \ vmdtab.h \
vhtmltab.h \ vhtmltab.h \
utils/vvim.h utils/vvim.h \
utils/veditutils.h
RESOURCES += \ RESOURCES += \
vnote.qrc \ vnote.qrc \

41
src/utils/veditutils.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "veditutils.h"
#include <QTextDocument>
#include <QDebug>
void VEditUtils::removeBlock(QTextBlock &p_block, QString *p_text)
{
QTextCursor cursor(p_block);
removeBlock(cursor, p_text);
}
void VEditUtils::removeBlock(QTextCursor &p_cursor, QString *p_text)
{
const QTextDocument *doc = p_cursor.document();
int blockCount = doc->blockCount();
int blockNum = p_cursor.block().blockNumber();
p_cursor.select(QTextCursor::BlockUnderCursor);
if (p_text) {
*p_text = p_cursor.selectedText() + "\n";
}
p_cursor.deleteChar();
// Deleting the first block will leave an empty block.
// Deleting the last empty block will not work with deleteChar().
if (blockCount == doc->blockCount()) {
if (blockNum == blockCount - 1) {
// The last block.
p_cursor.deletePreviousChar();
} else {
p_cursor.deleteChar();
}
}
if (p_cursor.block().blockNumber() < blockNum) {
p_cursor.movePosition(QTextCursor::NextBlock);
}
p_cursor.movePosition(QTextCursor::StartOfBlock);
}

24
src/utils/veditutils.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef VEDITUTILS_H
#define VEDITUTILS_H
#include <QTextBlock>
#include <QTextCursor>
// Utils for text edit.
class VEditUtils
{
public:
// Remove the whole block @p_block.
// If @p_text is not NULL, return the deleted text here.
static void removeBlock(QTextBlock &p_block, QString *p_text = NULL);
// Remove the whole block under @p_cursor.
// If @p_text is not NULL, return the deleted text here.
// Need to call setTextCursor() to make it take effect.
static void removeBlock(QTextCursor &p_cursor, QString *p_text = NULL);
private:
VEditUtils() {}
};
#endif // VEDITUTILS_H

View File

@ -42,8 +42,6 @@ struct ImageLink
class VUtils class VUtils
{ {
public: public:
VUtils();
static QString readFileFromDisk(const QString &filePath); static QString readFileFromDisk(const QString &filePath);
static bool writeFileToDisk(const QString &filePath, const QString &text); static bool writeFileToDisk(const QString &filePath, const QString &text);
// Transform FFFFFF string to QRgb // Transform FFFFFF string to QRgb
@ -117,6 +115,8 @@ public:
static const QString c_fencedCodeBlockEndRegExp; static const QString c_fencedCodeBlockEndRegExp;
private: private:
VUtils();
static void initAvailableLanguage(); static void initAvailableLanguage();
// <value, name> // <value, name>

File diff suppressed because it is too large Load Diff

View File

@ -240,6 +240,23 @@ private:
{ {
} }
// Register a-z.
bool isNamedRegister() const
{
char ch = m_name.toLatin1();
return ch >= 'a' && ch <= 'z';
}
bool isUnnamedRegister() const
{
return m_name == c_unnamedRegister;
}
bool isBlackHoleRegister() const
{
return m_name == c_blackHoleRegister;
}
QChar m_name; QChar m_name;
QString m_value; QString m_value;
@ -267,6 +284,9 @@ private:
// @p_tokens is the arguments of the Action::Move action. // @p_tokens is the arguments of the Action::Move action.
void processMoveAction(QList<Token> &p_tokens); void processMoveAction(QList<Token> &p_tokens);
// @p_tokens is the arguments of the Action::Delete action.
void processDeleteAction(QList<Token> &p_tokens);
// Clear selection if there is any. // Clear selection if there is any.
// Returns true if there is selection. // Returns true if there is selection.
bool clearSelection(); bool clearSelection();
@ -274,9 +294,9 @@ private:
// Get the block count of one page step in vertical scroll bar. // Get the block count of one page step in vertical scroll bar.
int blockCountOfPageStep() const; int blockCountOfPageStep() const;
// Expand selection in the VisualLiine mode which will change the position // Expand selection to whole lines which will change the position
// of @p_cursor. // of @p_cursor.
void expandSelectionInVisualLineMode(QTextCursor &p_cursor); void expandSelectionToWholeLines(QTextCursor &p_cursor);
// Init m_registers. // Init m_registers.
// Currently supported registers: // Currently supported registers:
@ -293,9 +313,36 @@ private:
// Check if @m_tokens contains an action token. // Check if @m_tokens contains an action token.
bool hasActionToken() const; bool hasActionToken() const;
// Try to insert a Action::Move action at the front if there is no any action // Try to add an Action::Move action at the front if there is no any action
// token. // token.
void tryInsertMoveAction(); void tryAddMoveAction();
// Add an Action token in front of m_tokens.
void addActionToken(Action p_action);
// Get the action token from m_tokens.
const Token *getActionToken() const;
// Add an Range token at the end of m_tokens.
void addRangeToken(Range p_range);
// Add an Movement token at the end of m_tokens.
void addMovementToken(Movement p_movement);
// Delete selected text if there is any.
// @p_clearEmptyBlock: whether to remove the empty block after deletion.
void deleteSelectedText(bool p_clearEmptyBlock);
void deleteSelectedText(QTextCursor &p_cursor, bool p_clearEmptyBlock);
// Save @p_text to the Register pointed by m_register.
void saveToRegister(const QString &p_text);
// Move @p_cursor according to @p_moveMode and @p_movement.
// Return true if it has moved @p_cursor.
bool processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc,
QTextCursor::MoveMode &p_moveMode,
Movement p_movement, int p_repeat);
VEdit *m_editor; VEdit *m_editor;
const VEditConfig *m_editConfig; const VEditConfig *m_editConfig;

View File

@ -8,6 +8,7 @@
#include "vmdedit.h" #include "vmdedit.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "utils/veditutils.h"
#include "vfile.h" #include "vfile.h"
#include "vdownloader.h" #include "vdownloader.h"
#include "hgmarkdownhighlighter.h" #include "hgmarkdownhighlighter.h"
@ -302,9 +303,7 @@ void VImagePreviewer::removeBlock(QTextBlock &p_block)
{ {
bool modified = m_edit->isModified(); bool modified = m_edit->isModified();
QTextCursor cursor(p_block); VEditUtils::removeBlock(p_block);
cursor.select(QTextCursor::BlockUnderCursor);
cursor.removeSelectedText();
m_edit->setModified(modified); m_edit->setModified(modified);
} }

View File

@ -31,9 +31,14 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted, connect(m_mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
this, [this]() { this, [this]() {
QRect rect = this->cursorRect(); QRect rect = this->cursorRect();
QRect viewRect = this->rect(); int height = this->rect().height();
if ((rect.y() < viewRect.height() QScrollBar *sbar = this->horizontalScrollBar();
&& rect.y() + rect.height() > viewRect.height()) if (sbar && sbar->isVisible()) {
height -= sbar->height();
}
if ((rect.y() < height
&& rect.y() + rect.height() > height)
|| (rect.y() < 0 && rect.y() + rect.height() > 0)) { || (rect.y() < 0 && rect.y() + rect.height() > 0)) {
this->ensureCursorVisible(); this->ensureCursorVisible();
} }