mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
HGMarkdownHighlighter: use cached header info to highlight headers fast
This commit is contained in:
parent
0b885e1639
commit
b1f7760ea2
@ -58,6 +58,13 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &s
|
|||||||
m_colorColumnFormat.setForeground(QColor(g_config->getEditorColorColumnFg()));
|
m_colorColumnFormat.setForeground(QColor(g_config->getEditorColorColumnFg()));
|
||||||
m_colorColumnFormat.setBackground(QColor(g_config->getEditorColorColumnBg()));
|
m_colorColumnFormat.setBackground(QColor(g_config->getEditorColorColumnBg()));
|
||||||
|
|
||||||
|
m_headerStyles.resize(6);
|
||||||
|
for (auto const & it : highlightingStyles) {
|
||||||
|
if (it.type >= pmh_H1 && it.type <= pmh_H6) {
|
||||||
|
m_headerStyles[it.type - pmh_H1] = it.format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resizeBuffer(initCapacity);
|
resizeBuffer(initCapacity);
|
||||||
document = parent;
|
document = parent;
|
||||||
|
|
||||||
@ -145,9 +152,12 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
// fix this.
|
// fix this.
|
||||||
// highlightLinkWithSpacesInURL(text);
|
// highlightLinkWithSpacesInURL(text);
|
||||||
|
|
||||||
|
highlightHeaderFast(blockNum, text);
|
||||||
|
|
||||||
// Highlight CodeBlock using VCodeBlockHighlightHelper.
|
// Highlight CodeBlock using VCodeBlockHighlightHelper.
|
||||||
if (m_codeBlockHighlights.size() > blockNum) {
|
if (m_codeBlockHighlights.size() > blockNum) {
|
||||||
const QVector<HLUnitStyle> &units = m_codeBlockHighlights[blockNum];
|
const QVector<HLUnitStyle> &units = m_codeBlockHighlights[blockNum];
|
||||||
|
if (!units.isEmpty()) {
|
||||||
// Manually simply merge the format of all the units within the same block.
|
// Manually simply merge the format of all the units within the same block.
|
||||||
// Using QTextCursor to get the char format after setFormat() seems
|
// Using QTextCursor to get the char format after setFormat() seems
|
||||||
// not to work.
|
// not to work.
|
||||||
@ -178,6 +188,7 @@ void HGMarkdownHighlighter::highlightBlock(const QString &text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
highlightCodeBlockColorColumn(text);
|
highlightCodeBlockColorColumn(text);
|
||||||
|
|
||||||
@ -294,6 +305,8 @@ void HGMarkdownHighlighter::initImageRegionsFromResult()
|
|||||||
|
|
||||||
void HGMarkdownHighlighter::initHeaderRegionsFromResult()
|
void HGMarkdownHighlighter::initHeaderRegionsFromResult()
|
||||||
{
|
{
|
||||||
|
m_headerBlocks.clear();
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
// From Qt5.7, the capacity is preserved.
|
// From Qt5.7, the capacity is preserved.
|
||||||
m_headerRegions.clear();
|
m_headerRegions.clear();
|
||||||
@ -324,6 +337,11 @@ void HGMarkdownHighlighter::initHeaderRegionsFromResult()
|
|||||||
m_headerRegions.push_back(VElementRegion(elem->pos, elem->end));
|
m_headerRegions.push_back(VElementRegion(elem->pos, elem->end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTextBlock block = document->findBlock(elem->pos);
|
||||||
|
if (block.isValid()) {
|
||||||
|
m_headerBlocks.insert(block.blockNumber(), i);
|
||||||
|
}
|
||||||
|
|
||||||
++idx;
|
++idx;
|
||||||
elem = elem->next;
|
elem = elem->next;
|
||||||
}
|
}
|
||||||
@ -747,7 +765,7 @@ bool HGMarkdownHighlighter::isValidHeader(unsigned long p_pos, unsigned long p_e
|
|||||||
for (unsigned long i = p_pos; i < p_end; ++i) {
|
for (unsigned long i = p_pos; i < p_end; ++i) {
|
||||||
QChar ch = document->characterAt(i);
|
QChar ch = document->characterAt(i);
|
||||||
if (ch.isSpace()) {
|
if (ch.isSpace()) {
|
||||||
return true;
|
return nrNumberSign > 0;
|
||||||
} else if (ch == QChar('#')) {
|
} else if (ch == QChar('#')) {
|
||||||
if (++nrNumberSign > 6) {
|
if (++nrNumberSign > 6) {
|
||||||
return false;
|
return false;
|
||||||
@ -759,3 +777,41 @@ bool HGMarkdownHighlighter::isValidHeader(unsigned long p_pos, unsigned long p_e
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HGMarkdownHighlighter::isValidHeader(const QString &p_text)
|
||||||
|
{
|
||||||
|
// There must exist spaces after #s.
|
||||||
|
// No more than 6 #s.
|
||||||
|
int nrNumberSign = 0;
|
||||||
|
for (int i = 0; i < p_text.size(); ++i) {
|
||||||
|
QChar ch = p_text[i];
|
||||||
|
if (ch.isSpace()) {
|
||||||
|
return nrNumberSign > 0;
|
||||||
|
} else if (ch == QChar('#')) {
|
||||||
|
if (++nrNumberSign > 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HGMarkdownHighlighter::highlightHeaderFast(int p_blockNumber, const QString &p_text)
|
||||||
|
{
|
||||||
|
if (currentBlockState() != HighlightBlockState::Normal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_headerBlocks.find(p_blockNumber);
|
||||||
|
if (it != m_headerBlocks.end()) {
|
||||||
|
if (isValidHeader(p_text)) {
|
||||||
|
setFormat(0, p_text.size(), m_headerStyles[it.value()]);
|
||||||
|
} else {
|
||||||
|
// Set an empty format to clear formats. It seems to work.
|
||||||
|
setFormat(0, p_text.size(), QTextCharFormat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -178,6 +178,9 @@ private:
|
|||||||
|
|
||||||
QVector<QVector<HLUnit> > blockHighlights;
|
QVector<QVector<HLUnit> > blockHighlights;
|
||||||
|
|
||||||
|
// Used for cache, [0, 6].
|
||||||
|
QVector<QTextCharFormat> m_headerStyles;
|
||||||
|
|
||||||
// Use another member to store the codeblocks highlights, because the highlight
|
// Use another member to store the codeblocks highlights, because the highlight
|
||||||
// sequence is blockHighlights, regular-expression-based highlihgts, and then
|
// sequence is blockHighlights, regular-expression-based highlihgts, and then
|
||||||
// codeBlockHighlights.
|
// codeBlockHighlights.
|
||||||
@ -197,6 +200,9 @@ private:
|
|||||||
// Sorted by start position.
|
// Sorted by start position.
|
||||||
QVector<VElementRegion> m_headerRegions;
|
QVector<VElementRegion> m_headerRegions;
|
||||||
|
|
||||||
|
// [block number] -> header level based on 0
|
||||||
|
QHash<int, int> m_headerBlocks;
|
||||||
|
|
||||||
// Timer to signal highlightCompleted().
|
// Timer to signal highlightCompleted().
|
||||||
QTimer *m_completeTimer;
|
QTimer *m_completeTimer;
|
||||||
|
|
||||||
@ -265,9 +271,15 @@ private:
|
|||||||
// Check if [p_pos, p_end) is a valid header.
|
// Check if [p_pos, p_end) is a valid header.
|
||||||
bool isValidHeader(unsigned long p_pos, unsigned long p_end);
|
bool isValidHeader(unsigned long p_pos, unsigned long p_end);
|
||||||
|
|
||||||
|
bool isValidHeader(const QString &p_text);
|
||||||
|
|
||||||
VTextBlockData *currentBlockData() const;
|
VTextBlockData *currentBlockData() const;
|
||||||
|
|
||||||
VTextBlockData *previousBlockData() const;
|
VTextBlockData *previousBlockData() const;
|
||||||
|
|
||||||
|
// Highlight headers using regular expression first instead of waiting for
|
||||||
|
// another parse.
|
||||||
|
void highlightHeaderFast(int p_blockNumber, const QString &p_text);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const QVector<VElementRegion> &HGMarkdownHighlighter::getHeaderRegions() const
|
inline const QVector<VElementRegion> &HGMarkdownHighlighter::getHeaderRegions() const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user