diff options
author | Leandro Melo <leandro.melo@nokia.com> | 2010-06-21 13:37:53 +0200 |
---|---|---|
committer | Leandro Melo <leandro.melo@nokia.com> | 2010-06-21 16:10:42 +0200 |
commit | 15faf23e07dc206215841cb87e10a95d89ee0c25 (patch) | |
tree | ee34d8c2d2f760aafff47faa3a8241944fc4c451 /src/plugins | |
parent | ec249304e64eb14f9b24fc2692c03734213f48b9 (diff) | |
download | qt-creator-15faf23e07dc206215841cb87e10a95d89ee0c25.tar.gz |
Generic highlighter: Indentation based code folding.
Diffstat (limited to 'src/plugins')
8 files changed, 114 insertions, 24 deletions
diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp index 4d6d92c897..c06b49d1e0 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp +++ b/src/plugins/texteditor/generichighlighter/highlightdefinition.cpp @@ -42,7 +42,8 @@ using namespace Internal; HighlightDefinition::HighlightDefinition() : m_delimiters(QLatin1String(".():!+,-<=>%&/;?[]^{|}~\\*, \t")), m_singleLineCommentAfterWhiteSpaces(false), - m_keywordCaseSensitivity(Qt::CaseSensitive) + m_keywordCaseSensitivity(Qt::CaseSensitive), + m_indentationBasedFolding(false) {} HighlightDefinition::~HighlightDefinition() @@ -165,3 +166,9 @@ void HighlightDefinition::setKeywordsSensitive(const QString &sensitivity) Qt::CaseSensitivity HighlightDefinition::keywordsSensitive() const { return m_keywordCaseSensitivity; } + +void HighlightDefinition::setIndentationBasedFolding(const QString &indentationBasedFolding) +{ m_indentationBasedFolding = toBool(indentationBasedFolding); } + +bool HighlightDefinition::isIndentationBasedFolding() const +{ return m_indentationBasedFolding; } diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinition.h b/src/plugins/texteditor/generichighlighter/highlightdefinition.h index dd94838d87..ca7afd9376 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinition.h +++ b/src/plugins/texteditor/generichighlighter/highlightdefinition.h @@ -80,6 +80,9 @@ public: void setMultiLineCommentRegion(const QString ®ion); const QString &multiLineCommentRegion() const; + void setIndentationBasedFolding(const QString &indentationBasedFolding); + bool isIndentationBasedFolding() const; + private: Q_DISABLE_COPY(HighlightDefinition) @@ -109,6 +112,8 @@ private: QString m_multiLineCommentRegion; Qt::CaseSensitivity m_keywordCaseSensitivity; + + bool m_indentationBasedFolding; }; } // namespace Internal diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp index a157d94461..58a7b4bcd3 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp @@ -103,6 +103,8 @@ namespace { static const QLatin1String kLanguage("language"); static const QLatin1String kExtensions("extensions"); static const QLatin1String kIncludeAttrib("includeAttrib"); + static const QLatin1String kFolding("folding"); + static const QLatin1String kIndentationSensitive("indentationsensitive"); static const QLatin1String kHash("#"); static const QLatin1String kDoubleHash("##"); } @@ -145,6 +147,8 @@ bool HighlightDefinitionHandler::startElement(const QString &, commentElementStarted(atts); } else if (qName == kKeywords) { keywordsElementStarted(atts); + } else if (qName == kFolding) { + foldingElementStarted(atts); } else if (qName == kDetectChar) { detectCharStarted(atts); } else if (qName == kDetect2Chars) { @@ -290,6 +294,11 @@ void HighlightDefinitionHandler::keywordsElementStarted(const QXmlAttributes &at //@todo: wordWrapDelimiters? } +void HighlightDefinitionHandler::foldingElementStarted(const QXmlAttributes &atts) const +{ + m_definition->setIndentationBasedFolding(atts.value(kIndentationSensitive)); +} + void HighlightDefinitionHandler::detectCharStarted(const QXmlAttributes &atts) { DetectCharRule *rule = new DetectCharRule; diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h index e08be97649..672a368488 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h @@ -65,6 +65,7 @@ private: void itemDataElementStarted(const QXmlAttributes &atts) const; void commentElementStarted(const QXmlAttributes &atts) const; void keywordsElementStarted(const QXmlAttributes &atts) const; + void foldingElementStarted(const QXmlAttributes &atts) const; void ruleElementStarted(const QXmlAttributes &atts, const QSharedPointer<Rule> &rule); // Specific rules. diff --git a/src/plugins/texteditor/generichighlighter/highlighter.cpp b/src/plugins/texteditor/generichighlighter/highlighter.cpp index aba84b8c4f..9ec1046431 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.cpp +++ b/src/plugins/texteditor/generichighlighter/highlighter.cpp @@ -35,6 +35,7 @@ #include "highlighterexception.h" #include "progressdata.h" #include "reuse.h" +#include "tabsettings.h" #include <QtCore/QLatin1String> #include <QtCore/QLatin1Char> @@ -54,6 +55,8 @@ const Highlighter::KateFormatMap Highlighter::m_kateFormats; Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent), m_regionDepth(0), + m_indentationBasedFolding(false), + m_tabSettings(0), m_persistentObservableStatesCounter(PersistentsStart), m_dynamicContextsCounter(0), m_isBroken(false) @@ -95,6 +98,12 @@ void Highlighter::setDefaultContext(const QSharedPointer<Context> &defaultConte { m_defaultContext = defaultContext; m_persistentObservableStates.insert(m_defaultContext->name(), Default); + m_indentationBasedFolding = defaultContext->definition()->isIndentationBasedFolding(); +} + +void Highlighter::setTabSettings(const TabSettings &ts) +{ + m_tabSettings = &ts; } void Highlighter::highlightBlock(const QString &text) @@ -118,11 +127,14 @@ void Highlighter::highlightBlock(const QString &text) false); m_contexts.clear(); - applyFolding(); + if (m_indentationBasedFolding) { + applyIndentationBasedFolding(text); + } else { + applyRegionBasedFolding(); - // Takes into the account any change that might have affected the region depth since - // the last time the state was set. - setCurrentBlockState(computeState(extractObservableState(currentBlockState()))); + // In the case region depth has changed since the last time the state was set. + setCurrentBlockState(computeState(extractObservableState(currentBlockState()))); + } } catch (const HighlighterException &) { m_isBroken = true; } @@ -220,24 +232,25 @@ void Highlighter::iterateThroughRules(const QString &text, if (rule->matchSucceed(text, length, progress)) { atLeastOneMatch = true; - // Code folding. - if (!rule->beginRegion().isEmpty()) { - blockData(currentBlockUserData())->m_foldingRegions.push(rule->beginRegion()); - ++m_regionDepth; - if (progress->isOpeningBraceMatchAtFirstNonSpace()) - ++blockData(currentBlockUserData())->m_foldingIndentDelta; - } - if (!rule->endRegion().isEmpty()) { - QStack<QString> *currentRegions = - &blockData(currentBlockUserData())->m_foldingRegions; - if (!currentRegions->isEmpty() && rule->endRegion() == currentRegions->top()) { - currentRegions->pop(); - --m_regionDepth; - if (progress->isClosingBraceMatchAtNonEnd()) - --blockData(currentBlockUserData())->m_foldingIndentDelta; + if (!m_indentationBasedFolding) { + if (!rule->beginRegion().isEmpty()) { + blockData(currentBlockUserData())->m_foldingRegions.push(rule->beginRegion()); + ++m_regionDepth; + if (progress->isOpeningBraceMatchAtFirstNonSpace()) + ++blockData(currentBlockUserData())->m_foldingIndentDelta; } + if (!rule->endRegion().isEmpty()) { + QStack<QString> *currentRegions = + &blockData(currentBlockUserData())->m_foldingRegions; + if (!currentRegions->isEmpty() && rule->endRegion() == currentRegions->top()) { + currentRegions->pop(); + --m_regionDepth; + if (progress->isClosingBraceMatchAtNonEnd()) + --blockData(currentBlockUserData())->m_foldingIndentDelta; + } + } + progress->clearBracesMatches(); } - progress->clearBracesMatches(); if (progress->isWillContinueLine()) { createWillContinueBlock(); @@ -524,7 +537,7 @@ int Highlighter::computeState(const int observableState) const return m_regionDepth << 12 | observableState; } -void Highlighter::applyFolding() const +void Highlighter::applyRegionBasedFolding() const { int folding = 0; BlockData *data = blockData(currentBlockUserData()); @@ -543,3 +556,38 @@ void Highlighter::applyFolding() const data->setFoldingEndIncluded(true); data->setFoldingIndent(folding); } + +void Highlighter::applyIndentationBasedFolding(const QString &text) const +{ + BlockData *data = blockData(currentBlockUserData()); + data->setFoldingEndIncluded(true); + + // If this line is empty, check its neighbours. They all might be part of the same block. + if (text.trimmed().isEmpty()) { + data->setFoldingIndent(0); + const int previousIndent = neighbouringNonEmptyBlockIndent(currentBlock().previous(), true); + if (previousIndent > 0) { + const int nextIndent = neighbouringNonEmptyBlockIndent(currentBlock().next(), false); + if (previousIndent == nextIndent) + data->setFoldingIndent(previousIndent); + } + } else { + data->setFoldingIndent(m_tabSettings->indentationColumn(text)); + } +} + +int Highlighter::neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const +{ + while (true) { + if (!block.isValid()) + return 0; + if (block.text().trimmed().isEmpty()) { + if (previous) + block = block.previous(); + else + block = block.next(); + } else { + return m_tabSettings->indentationColumn(block.text()); + } + } +} diff --git a/src/plugins/texteditor/generichighlighter/highlighter.h b/src/plugins/texteditor/generichighlighter/highlighter.h index 7ca7e9d649..ee3b94019c 100644 --- a/src/plugins/texteditor/generichighlighter/highlighter.h +++ b/src/plugins/texteditor/generichighlighter/highlighter.h @@ -42,6 +42,9 @@ #include <QtGui/QTextCharFormat> namespace TextEditor { + +struct TabSettings; + namespace Internal { class Rule; @@ -72,8 +75,9 @@ public: RegionMarker, Others }; - void configureFormat(TextFormatId id, const QTextCharFormat &format); + void configureFormat(TextFormatId id, const QTextCharFormat &format); + void setTabSettings(const TabSettings &ts); void setDefaultContext(const QSharedPointer<Context> &defaultContext); protected: @@ -118,7 +122,9 @@ private: const QSharedPointer<HighlightDefinition> &definition); void applyVisualWhitespaceFormat(const QString &text); - void applyFolding() const; + void applyRegionBasedFolding() const; + void applyIndentationBasedFolding(const QString &text) const; + int neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const; // Mapping from Kate format strings to format ids. struct KateFormatMap @@ -166,6 +172,8 @@ private: static int extractObservableState(const int state); int m_regionDepth; + bool m_indentationBasedFolding; + const TabSettings *m_tabSettings; int m_persistentObservableStatesCounter; int m_dynamicContextsCounter; diff --git a/src/plugins/texteditor/plaintexteditor.cpp b/src/plugins/texteditor/plaintexteditor.cpp index d945b16671..ce933292c0 100644 --- a/src/plugins/texteditor/plaintexteditor.cpp +++ b/src/plugins/texteditor/plaintexteditor.cpp @@ -153,6 +153,17 @@ void PlainTextEditor::setFontSettings(const FontSettings &fs) } } +void PlainTextEditor::setTabSettings(const TextEditor::TabSettings &ts) +{ + BaseTextEditor::setTabSettings(ts); + + if (baseTextDocument()->syntaxHighlighter()) { + Highlighter *highlighter = + static_cast<Highlighter *>(baseTextDocument()->syntaxHighlighter()); + highlighter->setTabSettings(ts); + } +} + void PlainTextEditor::fileChanged() { configure(Core::ICore::instance()->mimeDatabase()->findByFile(file()->fileName())); diff --git a/src/plugins/texteditor/plaintexteditor.h b/src/plugins/texteditor/plaintexteditor.h index d027ef07ff..c57aba920c 100644 --- a/src/plugins/texteditor/plaintexteditor.h +++ b/src/plugins/texteditor/plaintexteditor.h @@ -76,6 +76,7 @@ public: public slots: virtual void unCommentSelection(); virtual void setFontSettings(const FontSettings &fs); + virtual void setTabSettings(const TextEditor::TabSettings &); private slots: void fileChanged(); |