summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeandro Melo <leandro.melo@nokia.com>2010-06-21 13:37:53 +0200
committerLeandro Melo <leandro.melo@nokia.com>2010-06-21 16:10:42 +0200
commit15faf23e07dc206215841cb87e10a95d89ee0c25 (patch)
treeee34d8c2d2f760aafff47faa3a8241944fc4c451 /src
parentec249304e64eb14f9b24fc2692c03734213f48b9 (diff)
downloadqt-creator-15faf23e07dc206215841cb87e10a95d89ee0c25.tar.gz
Generic highlighter: Indentation based code folding.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinition.cpp9
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinition.h5
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp9
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.h1
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.cpp90
-rw-r--r--src/plugins/texteditor/generichighlighter/highlighter.h12
-rw-r--r--src/plugins/texteditor/plaintexteditor.cpp11
-rw-r--r--src/plugins/texteditor/plaintexteditor.h1
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 &region);
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();