Browse Source

vim-mode: support DELETE action

Actions related to `d` and `x`.
Le Tan 8 years ago
parent
commit
eba2556a3a
8 changed files with 605 additions and 179 deletions
  1. 4 2
      src/src.pro
  2. 41 0
      src/utils/veditutils.cpp
  3. 24 0
      src/utils/veditutils.h
  4. 2 2
      src/utils/vutils.h
  5. 473 165
      src/utils/vvim.cpp
  6. 51 4
      src/utils/vvim.h
  7. 2 3
      src/vimagepreviewer.cpp
  8. 8 3
      src/vmdedit.cpp

+ 4 - 2
src/src.pro

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

+ 41 - 0
src/utils/veditutils.cpp

@@ -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 - 0
src/utils/veditutils.h

@@ -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

+ 2 - 2
src/utils/vutils.h

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

File diff suppressed because it is too large
+ 473 - 165
src/utils/vvim.cpp


+ 51 - 4
src/utils/vvim.h

@@ -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;
         QString m_value;
 
@@ -267,6 +284,9 @@ private:
     // @p_tokens is the arguments of the Action::Move action.
     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.
     // Returns true if there is selection.
     bool clearSelection();
@@ -274,9 +294,9 @@ private:
     // Get the block count of one page step in vertical scroll bar.
     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.
-    void expandSelectionInVisualLineMode(QTextCursor &p_cursor);
+    void expandSelectionToWholeLines(QTextCursor &p_cursor);
 
     // Init m_registers.
     // Currently supported registers:
@@ -293,9 +313,36 @@ private:
     // Check if @m_tokens contains an action token.
     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.
-    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;
     const VEditConfig *m_editConfig;

+ 2 - 3
src/vimagepreviewer.cpp

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

+ 8 - 3
src/vmdedit.cpp

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

Some files were not shown because too many files changed in this diff