Browse Source

VSnippet: support auto indent

Le Tan 8 years ago
parent
commit
94260b3df8

+ 11 - 0
src/dialog/veditsnippetdialog.cpp

@@ -72,6 +72,11 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info)
     m_selectionMarkEdit = new QLineEdit(m_snippet.getSelectionMark());
     m_selectionMarkEdit->setToolTip(tr("String in the content to be replaced with selected text"));
 
+    // Auto Indent.
+    m_autoIndentCB = new QCheckBox(tr("Auto indent"), this);
+    m_autoIndentCB->setToolTip(tr("Auto indent the content according to the first line"));
+    m_autoIndentCB->setChecked(m_snippet.getAutoIndent());
+
     // Content.
     m_contentEdit = new QTextEdit();
     setContentEditByType();
@@ -82,6 +87,7 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info)
     topLayout->addRow(tr("Shortc&ut:"), m_shortcutCB);
     topLayout->addRow(tr("Cursor &mark:"), m_cursorMarkEdit);
     topLayout->addRow(tr("&Selection mark:"), m_selectionMarkEdit);
+    topLayout->addWidget(m_autoIndentCB);
     topLayout->addRow(tr("&Content:"), m_contentEdit);
 
     m_warnLabel = new QLabel();
@@ -275,6 +281,11 @@ QChar VEditSnippetDialog::getShortcutInput() const
     return m_shortcutCB->currentData().toChar();
 }
 
+bool VEditSnippetDialog::getAutoIndentInput() const
+{
+    return m_autoIndentCB->isChecked();
+}
+
 QVector<QChar> VEditSnippetDialog::getAvailableShortcuts() const
 {
     QVector<QChar> ret = VSnippet::getAllShortcuts();

+ 4 - 0
src/dialog/veditsnippetdialog.h

@@ -12,6 +12,7 @@ class QLabel;
 class QDialogButtonBox;
 class QComboBox;
 class QTextEdit;
+class QCheckBox;
 
 
 class VEditSnippetDialog : public QDialog
@@ -36,6 +37,8 @@ public:
 
     QChar getShortcutInput() const;
 
+    bool getAutoIndentInput() const;
+
 private slots:
     void handleInputChanged();
 
@@ -53,6 +56,7 @@ private:
     QComboBox *m_shortcutCB;
     QLineEdit *m_cursorMarkEdit;
     QLineEdit *m_selectionMarkEdit;
+    QCheckBox *m_autoIndentCB;
     QTextEdit *m_contentEdit;
 
     QLabel *m_warnLabel;

+ 3 - 2
src/utils/veditutils.cpp

@@ -200,10 +200,11 @@ void VEditUtils::indentSelectedBlocks(const QTextDocument *p_doc,
 }
 
 void VEditUtils::indentBlock(QTextCursor &p_cursor,
-                             const QString &p_indentationText)
+                             const QString &p_indentationText,
+                             bool p_skipEmpty)
 {
     QTextBlock block = p_cursor.block();
-    if (block.length() > 1) {
+    if (block.length() > 1 || !p_skipEmpty) {
         p_cursor.movePosition(QTextCursor::StartOfBlock);
         p_cursor.insertText(p_indentationText);
     }

+ 3 - 2
src/utils/veditutils.h

@@ -63,9 +63,10 @@ public:
                                      bool p_isIndent);
 
     // Indent current block.
-    // Skip empty block.
+    // @p_skipEmpty: skip empty block.
     static void indentBlock(QTextCursor &p_cursor,
-                            const QString &p_indentationText);
+                            const QString &p_indentationText,
+                            bool p_skipEmpty = true);
 
     static void unindentBlock(QTextCursor &p_cursor,
                               const QString &p_indentationText);

+ 1 - 0
src/vconstants.h

@@ -60,6 +60,7 @@ namespace SnippetConfig
     static const QString c_cursorMark = "cursor_mark";
     static const QString c_selectionMark = "selection_mark";
     static const QString c_shortcut = "shortcut";
+    static const QString c_autoIndent = "auto_indent";
 }
 
 static const QString c_emptyHeaderName = "[EMPTY]";

+ 46 - 7
src/vsnippet.cpp

@@ -18,7 +18,8 @@ QVector<QChar> VSnippet::s_allShortcuts;
 
 VSnippet::VSnippet()
     : m_type(Type::PlainText),
-      m_cursorMark(c_defaultCursorMark)
+      m_cursorMark(c_defaultCursorMark),
+      m_autoIndent(false)
 {
 }
 
@@ -27,13 +28,15 @@ VSnippet::VSnippet(const QString &p_name,
                    const QString &p_content,
                    const QString &p_cursorMark,
                    const QString &p_selectionMark,
-                   QChar p_shortcut)
+                   QChar p_shortcut,
+                   bool p_autoIndent)
     : m_name(p_name),
       m_type(p_type),
       m_content(p_content),
       m_cursorMark(p_cursorMark),
       m_selectionMark(p_selectionMark),
-      m_shortcut(p_shortcut)
+      m_shortcut(p_shortcut),
+      m_autoIndent(p_autoIndent)
 {
     Q_ASSERT(m_selectionMark != m_cursorMark);
 }
@@ -43,7 +46,8 @@ bool VSnippet::update(const QString &p_name,
                       const QString &p_content,
                       const QString &p_cursorMark,
                       const QString &p_selectionMark,
-                      QChar p_shortcut)
+                      QChar p_shortcut,
+                      bool p_autoIndent)
 {
     bool updated = false;
     if (m_name != p_name) {
@@ -76,6 +80,11 @@ bool VSnippet::update(const QString &p_name,
         updated = true;
     }
 
+    if (m_autoIndent != p_autoIndent) {
+        m_autoIndent = p_autoIndent;
+        updated = true;
+    }
+
     qDebug() << "snippet" << m_name << "updated" << updated;
 
     return updated;
@@ -103,6 +112,7 @@ QJsonObject VSnippet::toJson() const
     snip[SnippetConfig::c_cursorMark] = m_cursorMark;
     snip[SnippetConfig::c_selectionMark] = m_selectionMark;
     snip[SnippetConfig::c_shortcut] = m_shortcut.isNull() ? "" : QString(m_shortcut);
+    snip[SnippetConfig::c_autoIndent] = m_autoIndent;
 
     return snip;
 }
@@ -120,7 +130,8 @@ VSnippet VSnippet::fromJson(const QJsonObject &p_json)
                   "",
                   p_json[SnippetConfig::c_cursorMark].toString(),
                   p_json[SnippetConfig::c_selectionMark].toString(),
-                  shortcut);
+                  shortcut,
+                  p_json[SnippetConfig::c_autoIndent].toBool());
 
     return snip;
 }
@@ -193,11 +204,15 @@ bool VSnippet::apply(QTextCursor &p_cursor) const
 
     content += secondPart;
 
+    // Auto indent.
+    QTextBlock startBlock = p_cursor.block();
+    QTextBlock endBlock;
+    QString indentation = VEditUtils::fetchIndentSpaces(startBlock);
+
     // Insert it.
     switch (m_type) {
     case Type::Html:
         p_cursor.insertHtml(content);
-        // TODO: set the position of the cursor.
         break;
 
     case Type::PlainText:
@@ -205,10 +220,34 @@ bool VSnippet::apply(QTextCursor &p_cursor) const
 
     default:
         p_cursor.insertText(content);
-        p_cursor.setPosition(pos);
         break;
     }
 
+    endBlock = p_cursor.block();
+
+    if (m_autoIndent
+        && startBlock != endBlock
+        && !indentation.isEmpty()) {
+        // Indent (startBlock, endBlock].
+        startBlock = startBlock.next();
+        while (startBlock.isValid()) {
+            int tmpPos = startBlock.position();
+            p_cursor.setPosition(tmpPos);
+            VEditUtils::indentBlock(p_cursor, indentation, false);
+            if (tmpPos <= pos) {
+                pos += indentation.size();
+            }
+
+            if (startBlock == endBlock) {
+                break;
+            }
+
+            startBlock = startBlock.next();
+        }
+    }
+
+    p_cursor.setPosition(pos);
+
     p_cursor.endEditBlock();
     return true;
 }

+ 12 - 2
src/vsnippet.h

@@ -23,7 +23,8 @@ public:
              const QString &p_content = QString(),
              const QString &p_cursorMark = c_defaultCursorMark,
              const QString &p_selectionMark = c_defaultSelectionMark,
-             QChar p_shortcut = QChar());
+             QChar p_shortcut = QChar(),
+             bool p_autoIndent = false);
 
     // Return true if there is any update.
     bool update(const QString &p_name,
@@ -31,7 +32,8 @@ public:
                 const QString &p_content,
                 const QString &p_cursorMark,
                 const QString &p_selectionMark,
-                QChar p_shortcut);
+                QChar p_shortcut,
+                bool p_autoIndent);
 
     const QString &getName() const
     {
@@ -63,6 +65,11 @@ public:
         return m_shortcut;
     }
 
+    bool getAutoIndent() const
+    {
+        return m_autoIndent;
+    }
+
     void setContent(const QString &p_content)
     {
         m_content = p_content;
@@ -103,6 +110,9 @@ private:
     // Shortcut to apply this snippet.
     QChar m_shortcut;
 
+    // Auto indent with the first line.
+    bool m_autoIndent;
+
     static const QString c_defaultCursorMark;
 
     static const QString c_defaultSelectionMark;

+ 4 - 2
src/vsnippetlist.cpp

@@ -145,7 +145,8 @@ void VSnippetList::newSnippet()
                          dialog.getContentInput(),
                          dialog.getCursorMarkInput(),
                          dialog.getSelectionMarkInput(),
-                         dialog.getShortcutInput());
+                         dialog.getShortcutInput(),
+                         dialog.getAutoIndentInput());
 
         QString errMsg;
         if (!addSnippet(snippet, &errMsg)) {
@@ -336,7 +337,8 @@ void VSnippetList::snippetInfo()
                          dialog.getContentInput(),
                          dialog.getCursorMarkInput(),
                          dialog.getSelectionMarkInput(),
-                         dialog.getShortcutInput())) {
+                         dialog.getShortcutInput(),
+                         dialog.getAutoIndentInput())) {
             if (!writeSnippetFile(*snip, &errMsg)) {
                 ret = false;
             }