Browse Source

bug-fix: add code block indentation in VTextBlockData to get a correct highlight

- Won't treat all the text to the end as code block once we add a new
line within a code block;
- Fix color column by adding the code block indentation bias.
Le Tan 8 years ago
parent
commit
6ba12f7932
4 changed files with 64 additions and 6 deletions
  1. 25 5
      src/hgmarkdownhighlighter.cpp
  2. 21 0
      src/hgmarkdownhighlighter.h
  3. 2 1
      src/vtextblockdata.cpp
  4. 16 0
      src/vtextblockdata.h

+ 25 - 5
src/hgmarkdownhighlighter.cpp

@@ -5,7 +5,6 @@
 #include "hgmarkdownhighlighter.h"
 #include "vconfigmanager.h"
 #include "utils/vutils.h"
-#include "vtextblockdata.h"
 
 extern VConfigManager *g_config;
 
@@ -98,7 +97,7 @@ void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p
 {
     Q_UNUSED(p_text);
 
-    VTextBlockData *blockData = dynamic_cast<VTextBlockData *>(currentBlockUserData());
+    VTextBlockData *blockData = currentBlockData();
     if (!blockData) {
         blockData = new VTextBlockData();
         setCurrentBlockUserData(blockData);
@@ -109,6 +108,8 @@ void HGMarkdownHighlighter::updateBlockUserData(int p_blockNum, const QString &p
     } else {
         m_possiblePreviewBlocks.insert(p_blockNum);
     }
+
+    blockData->setCodeBlockIndentation(-1);
 }
 
 void HGMarkdownHighlighter::highlightBlock(const QString &text)
@@ -377,7 +378,9 @@ void HGMarkdownHighlighter::initBlockHighlihgtOne(unsigned long pos,
 
 void HGMarkdownHighlighter::highlightCodeBlock(const QString &text)
 {
-    static int startLeadingSpaces = -1;
+    VTextBlockData *blockData = currentBlockData();
+    Q_ASSERT(blockData);
+
     int length = 0;
     int index = -1;
     int preState = previousBlockState();
@@ -393,14 +396,21 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text)
             state = HighlightBlockState::CodeBlockStart;
 
             // The leading spaces of code block start and end must be identical.
-            startLeadingSpaces = codeBlockStartExp.capturedTexts()[1].size();
+            int startLeadingSpaces = codeBlockStartExp.capturedTexts()[1].size();
+            blockData->setCodeBlockIndentation(startLeadingSpaces);
         } else {
             // A normal block.
-            startLeadingSpaces = -1;
+            blockData->setCodeBlockIndentation(-1);
             return;
         }
     } else {
         // Need to find a code block end.
+        int startLeadingSpaces = 0;
+        VTextBlockData *preBlockData = previousBlockData();
+        if (preBlockData) {
+            startLeadingSpaces = preBlockData->getCodeBlockIndentation();
+        }
+
         index = codeBlockEndExp.indexIn(text);
 
         // The closing ``` should have the same indentation as the open ```.
@@ -415,6 +425,8 @@ void HGMarkdownHighlighter::highlightCodeBlock(const QString &text)
             length = text.length();
             state = HighlightBlockState::CodeBlock;
         }
+
+        blockData->setCodeBlockIndentation(startLeadingSpaces);
     }
 
     setCurrentBlockState(state);
@@ -428,6 +440,14 @@ void HGMarkdownHighlighter::highlightCodeBlockColorColumn(const QString &p_text)
         return;
     }
 
+    VTextBlockData *blockData = currentBlockData();
+    Q_ASSERT(blockData);
+    int indent = blockData->getCodeBlockIndentation();
+    if (indent == -1) {
+        return;
+    }
+
+    cc += indent;
     if (p_text.size() < cc) {
         return;
     }

+ 21 - 0
src/hgmarkdownhighlighter.h

@@ -8,6 +8,8 @@
 #include <QSet>
 #include <QString>
 
+#include "vtextblockdata.h"
+
 extern "C" {
 #include <pmh_parser.h>
 }
@@ -255,6 +257,10 @@ private:
 
     // Check if [p_pos, p_end) is a valid header.
     bool isValidHeader(unsigned long p_pos, unsigned long p_end);
+
+    VTextBlockData *currentBlockData() const;
+
+    VTextBlockData *previousBlockData() const;
 };
 
 inline const QVector<VElementRegion> &HGMarkdownHighlighter::getHeaderRegions() const
@@ -273,4 +279,19 @@ inline void HGMarkdownHighlighter::clearPossiblePreviewBlocks(const QVector<int>
         m_possiblePreviewBlocks.remove(i);
     }
 }
+
+inline VTextBlockData *HGMarkdownHighlighter::currentBlockData() const
+{
+    return static_cast<VTextBlockData *>(currentBlockUserData());
+}
+
+inline VTextBlockData *HGMarkdownHighlighter::previousBlockData() const
+{
+    QTextBlock block = currentBlock().previous();
+    if (!block.isValid()) {
+        return NULL;
+    }
+
+    return static_cast<VTextBlockData *>(block.userData());
+}
 #endif

+ 2 - 1
src/vtextblockdata.cpp

@@ -3,7 +3,8 @@
 #include <QDebug>
 
 VTextBlockData::VTextBlockData()
-    : QTextBlockUserData()
+    : QTextBlockUserData(),
+      m_codeBlockIndentation(-1)
 {
 }
 

+ 16 - 0
src/vtextblockdata.h

@@ -147,12 +147,19 @@ public:
     // Return true if there have obsolete preview being deleted.
     bool clearObsoletePreview(long long p_timeStamp, PreviewSource p_source);
 
+    int getCodeBlockIndentation() const;
+
+    void setCodeBlockIndentation(int p_indent);
+
 private:
     // Check the order of elements.
     bool checkOrder() const;
 
     // Sorted by m_imageInfo.m_startPos, with no two element's position intersected.
     QVector<VPreviewInfo *> m_previews;
+
+    // Indentation of the this code block if this block is a fenced code block.
+    int m_codeBlockIndentation;
 };
 
 inline const QVector<VPreviewInfo *> &VTextBlockData::getPreviews() const
@@ -160,4 +167,13 @@ inline const QVector<VPreviewInfo *> &VTextBlockData::getPreviews() const
     return m_previews;
 }
 
+inline int VTextBlockData::getCodeBlockIndentation() const
+{
+    return m_codeBlockIndentation;
+}
+
+inline void VTextBlockData::setCodeBlockIndentation(int p_indent)
+{
+    m_codeBlockIndentation = p_indent;
+}
 #endif // VTEXTBLOCKDATA_H