forked from qt-creator/qt-creator
Generic highlighter: Refactored how format configuration is done.
Now the highlighter engine does not directly depend on TextEditor::FontSettings. This also makes things easier for unit testing.
This commit is contained in:
@@ -35,8 +35,6 @@
|
|||||||
#include "highlighterexception.h"
|
#include "highlighterexception.h"
|
||||||
#include "progressdata.h"
|
#include "progressdata.h"
|
||||||
#include "reuse.h"
|
#include "reuse.h"
|
||||||
#include "texteditorconstants.h"
|
|
||||||
#include "fontsettings.h"
|
|
||||||
|
|
||||||
#include <QtCore/QLatin1String>
|
#include <QtCore/QLatin1String>
|
||||||
#include <QtCore/QLatin1Char>
|
#include <QtCore/QLatin1Char>
|
||||||
@@ -51,6 +49,8 @@ namespace {
|
|||||||
static const QLatin1Char kHash('#');
|
static const QLatin1Char kHash('#');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Highlighter::KateFormatMap Highlighter::m_kateFormats;
|
||||||
|
|
||||||
Highlighter::Highlighter(const QSharedPointer<Context> &defaultContext,QTextDocument *parent) :
|
Highlighter::Highlighter(const QSharedPointer<Context> &defaultContext,QTextDocument *parent) :
|
||||||
QSyntaxHighlighter(parent),
|
QSyntaxHighlighter(parent),
|
||||||
m_persistentStatesCounter(PersistentsStart),
|
m_persistentStatesCounter(PersistentsStart),
|
||||||
@@ -70,6 +70,24 @@ Highlighter::BlockData::BlockData()
|
|||||||
Highlighter::BlockData::~BlockData()
|
Highlighter::BlockData::~BlockData()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Highlighter::KateFormatMap::KateFormatMap()
|
||||||
|
{
|
||||||
|
m_ids.insert(QLatin1String("dsNormal"), Highlighter::Normal);
|
||||||
|
m_ids.insert(QLatin1String("dsKeyword"), Highlighter::Keyword);
|
||||||
|
m_ids.insert(QLatin1String("dsDataType"), Highlighter::DataType);
|
||||||
|
m_ids.insert(QLatin1String("dsDecVal"), Highlighter::Decimal);
|
||||||
|
m_ids.insert(QLatin1String("dsBaseN"), Highlighter::BaseN);
|
||||||
|
m_ids.insert(QLatin1String("dsFloat"), Highlighter::Float);
|
||||||
|
m_ids.insert(QLatin1String("dsChar"), Highlighter::Char);
|
||||||
|
m_ids.insert(QLatin1String("dsString"), Highlighter::String);
|
||||||
|
m_ids.insert(QLatin1String("dsComment"), Highlighter::Comment);
|
||||||
|
m_ids.insert(QLatin1String("dsOthers"), Highlighter::Others);
|
||||||
|
m_ids.insert(QLatin1String("dsAlert"), Highlighter::Alert);
|
||||||
|
m_ids.insert(QLatin1String("dsFunction"), Highlighter::Function);
|
||||||
|
m_ids.insert(QLatin1String("dsRegionMarker"), Highlighter::RegionMarker);
|
||||||
|
m_ids.insert(QLatin1String("dsError"), Highlighter::Error);
|
||||||
|
}
|
||||||
|
|
||||||
void Highlighter::highlightBlock(const QString &text)
|
void Highlighter::highlightBlock(const QString &text)
|
||||||
{
|
{
|
||||||
if (m_isBroken)
|
if (m_isBroken)
|
||||||
@@ -304,8 +322,9 @@ void Highlighter::applyFormat(int offset,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemData->style() != ItemData::kDsNormal) {
|
TextFormatId formatId = m_kateFormats.m_ids.value(itemData->style());
|
||||||
QTextCharFormat format = m_genericFormats.value(itemData->style());
|
if (formatId != Normal) {
|
||||||
|
QTextCharFormat format = m_creatorFormats.value(formatId);
|
||||||
|
|
||||||
if (itemData->isCustomized()) {
|
if (itemData->isCustomized()) {
|
||||||
// Please notice that the following are applied every time for item datas which have
|
// Please notice that the following are applied every time for item datas which have
|
||||||
@@ -340,7 +359,7 @@ void Highlighter::applyVisualWhitespaceFormat(const QString &text)
|
|||||||
int start = offset++;
|
int start = offset++;
|
||||||
while (offset < length && text.at(offset).isSpace())
|
while (offset < length && text.at(offset).isSpace())
|
||||||
++offset;
|
++offset;
|
||||||
setFormat(start, offset - start, m_visualWhitespaceFormat);
|
setFormat(start, offset - start, m_creatorFormats.value(VisualWhitespace));
|
||||||
} else {
|
} else {
|
||||||
++offset;
|
++offset;
|
||||||
}
|
}
|
||||||
@@ -438,41 +457,7 @@ void Highlighter::setCurrentContext()
|
|||||||
m_currentContext = m_contexts.back();
|
m_currentContext = m_contexts.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Highlighter::configureFormats(const FontSettings & fs)
|
void Highlighter::configureFormat(TextFormatId id, const QTextCharFormat &format)
|
||||||
{
|
{
|
||||||
m_visualWhitespaceFormat = fs.toTextCharFormat(
|
m_creatorFormats[id] = format;
|
||||||
QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE));
|
|
||||||
|
|
||||||
m_genericFormats[ItemData::kDsKeyword] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_KEYWORD));
|
|
||||||
m_genericFormats[ItemData::kDsDataType] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_TYPE));
|
|
||||||
// Currenlty using C_NUMBER for all kinds of numbers.
|
|
||||||
m_genericFormats[ItemData::kDsDecVal] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_NUMBER));
|
|
||||||
m_genericFormats[ItemData::kDsBaseN] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_NUMBER));
|
|
||||||
m_genericFormats[ItemData::kDsFloat] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_NUMBER));
|
|
||||||
// Currently using C_STRING for strings and chars.
|
|
||||||
m_genericFormats[ItemData::kDsChar] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_STRING));
|
|
||||||
m_genericFormats[ItemData::kDsString] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_STRING));
|
|
||||||
m_genericFormats[ItemData::kDsComment] = fs.toTextCharFormat(
|
|
||||||
QLatin1String(TextEditor::Constants::C_COMMENT));
|
|
||||||
|
|
||||||
// Currently Creator does not have corresponding formats for the following items. We can
|
|
||||||
// implement them... Just for now I will leave hardcoded colors.
|
|
||||||
QTextCharFormat format;
|
|
||||||
format.setForeground(Qt::blue);
|
|
||||||
m_genericFormats[ItemData::kDsOthers] = format;
|
|
||||||
format.setForeground(Qt::red);
|
|
||||||
m_genericFormats[ItemData::kDsAlert] = format;
|
|
||||||
format.setForeground(Qt::darkBlue);
|
|
||||||
m_genericFormats[ItemData::kDsFunction] = format;
|
|
||||||
format.setForeground(Qt::darkGray);
|
|
||||||
m_genericFormats[ItemData::kDsRegionMarker] = format;
|
|
||||||
format.setForeground(Qt::darkRed);
|
|
||||||
m_genericFormats[ItemData::kDsError] = format;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,7 @@
|
|||||||
#include <QtCore/QStringList>
|
#include <QtCore/QStringList>
|
||||||
|
|
||||||
#include <QtGui/QSyntaxHighlighter>
|
#include <QtGui/QSyntaxHighlighter>
|
||||||
|
#include <QtGui/QTextCharFormat>
|
||||||
namespace TextEditor {
|
|
||||||
class FontSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -57,7 +54,24 @@ public:
|
|||||||
Highlighter(const QSharedPointer<Context> &defaultContext, QTextDocument *parent = 0);
|
Highlighter(const QSharedPointer<Context> &defaultContext, QTextDocument *parent = 0);
|
||||||
virtual ~Highlighter();
|
virtual ~Highlighter();
|
||||||
|
|
||||||
void configureFormats(const FontSettings &fs);
|
enum TextFormatId {
|
||||||
|
Normal,
|
||||||
|
VisualWhitespace,
|
||||||
|
Keyword,
|
||||||
|
DataType,
|
||||||
|
Decimal,
|
||||||
|
BaseN,
|
||||||
|
Float,
|
||||||
|
Char,
|
||||||
|
String,
|
||||||
|
Comment,
|
||||||
|
Alert,
|
||||||
|
Error,
|
||||||
|
Function,
|
||||||
|
RegionMarker,
|
||||||
|
Others
|
||||||
|
};
|
||||||
|
void configureFormat(TextFormatId id, const QTextCharFormat &format);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void highlightBlock(const QString &text);
|
virtual void highlightBlock(const QString &text);
|
||||||
@@ -76,6 +90,7 @@ private:
|
|||||||
const bool childRule,
|
const bool childRule,
|
||||||
const QList<QSharedPointer<Rule> > &rules);
|
const QList<QSharedPointer<Rule> > &rules);
|
||||||
|
|
||||||
|
void setCurrentContext();
|
||||||
bool contextChangeRequired(const QString &contextName) const;
|
bool contextChangeRequired(const QString &contextName) const;
|
||||||
void handleContextChange(const QString &contextName,
|
void handleContextChange(const QString &contextName,
|
||||||
const QSharedPointer<HighlightDefinition> &definition,
|
const QSharedPointer<HighlightDefinition> &definition,
|
||||||
@@ -84,21 +99,28 @@ private:
|
|||||||
const QSharedPointer<HighlightDefinition> &definition,
|
const QSharedPointer<HighlightDefinition> &definition,
|
||||||
const bool setCurrent = true);
|
const bool setCurrent = true);
|
||||||
|
|
||||||
|
QString currentContextSequence() const;
|
||||||
|
void mapContextSequence(const QString &contextSequence);
|
||||||
|
void pushContextSequence(int state);
|
||||||
|
void pushDynamicContext(const QSharedPointer<Context> &baseContext);
|
||||||
|
|
||||||
|
void createWillContinueBlock();
|
||||||
|
void analyseConsistencyOfWillContinueBlock(const QString &text);
|
||||||
|
|
||||||
void applyFormat(int offset,
|
void applyFormat(int offset,
|
||||||
int count,
|
int count,
|
||||||
const QString &itemDataName,
|
const QString &itemDataName,
|
||||||
const QSharedPointer<HighlightDefinition> &definition);
|
const QSharedPointer<HighlightDefinition> &definition);
|
||||||
void applyVisualWhitespaceFormat(const QString &text);
|
void applyVisualWhitespaceFormat(const QString &text);
|
||||||
|
|
||||||
QString currentContextSequence() const;
|
// Mapping from Kate format strings to format ids.
|
||||||
void mapContextSequence(const QString &contextSequence);
|
struct KateFormatMap
|
||||||
void pushContextSequence(int state);
|
{
|
||||||
void pushDynamicContext(const QSharedPointer<Context> &baseContext);
|
KateFormatMap();
|
||||||
|
QHash<QString, TextFormatId> m_ids;
|
||||||
void setCurrentContext();
|
};
|
||||||
|
static const KateFormatMap m_kateFormats;
|
||||||
void createWillContinueBlock();
|
QHash<TextFormatId, QTextCharFormat> m_creatorFormats;
|
||||||
void analyseConsistencyOfWillContinueBlock(const QString &text);
|
|
||||||
|
|
||||||
struct BlockData : TextBlockUserData
|
struct BlockData : TextBlockUserData
|
||||||
{
|
{
|
||||||
@@ -143,9 +165,6 @@ private:
|
|||||||
|
|
||||||
// Captures used in dynamic rules.
|
// Captures used in dynamic rules.
|
||||||
QStringList m_currentCaptures;
|
QStringList m_currentCaptures;
|
||||||
|
|
||||||
QTextCharFormat m_visualWhitespaceFormat;
|
|
||||||
QHash<QString, QTextCharFormat> m_genericFormats;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -33,21 +33,6 @@
|
|||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
|
|
||||||
const QLatin1String ItemData::kDsNormal("dsNormal");
|
|
||||||
const QLatin1String ItemData::kDsKeyword("dsKeyword");
|
|
||||||
const QLatin1String ItemData::kDsDataType("dsDataType");
|
|
||||||
const QLatin1String ItemData::kDsDecVal("dsDecVal");
|
|
||||||
const QLatin1String ItemData::kDsBaseN("dsBaseN");
|
|
||||||
const QLatin1String ItemData::kDsFloat("dsFloat");
|
|
||||||
const QLatin1String ItemData::kDsChar("dsChar");
|
|
||||||
const QLatin1String ItemData::kDsString("dsString");
|
|
||||||
const QLatin1String ItemData::kDsComment("dsComment");
|
|
||||||
const QLatin1String ItemData::kDsOthers("dsOthers");
|
|
||||||
const QLatin1String ItemData::kDsAlert("dsAlert");
|
|
||||||
const QLatin1String ItemData::kDsFunction("dsFunction");
|
|
||||||
const QLatin1String ItemData::kDsRegionMarker("dsRegionMarker");
|
|
||||||
const QLatin1String ItemData::kDsError("dsError");
|
|
||||||
|
|
||||||
ItemData::ItemData() :
|
ItemData::ItemData() :
|
||||||
m_italicSpecified(false),
|
m_italicSpecified(false),
|
||||||
m_boldSpecified(false),
|
m_boldSpecified(false),
|
||||||
|
|||||||
@@ -68,21 +68,6 @@ public:
|
|||||||
|
|
||||||
bool isCustomized() const;
|
bool isCustomized() const;
|
||||||
|
|
||||||
static const QLatin1String kDsNormal;
|
|
||||||
static const QLatin1String kDsKeyword;
|
|
||||||
static const QLatin1String kDsDataType;
|
|
||||||
static const QLatin1String kDsDecVal;
|
|
||||||
static const QLatin1String kDsBaseN;
|
|
||||||
static const QLatin1String kDsFloat;
|
|
||||||
static const QLatin1String kDsChar;
|
|
||||||
static const QLatin1String kDsString;
|
|
||||||
static const QLatin1String kDsComment;
|
|
||||||
static const QLatin1String kDsOthers;
|
|
||||||
static const QLatin1String kDsAlert;
|
|
||||||
static const QLatin1String kDsFunction;
|
|
||||||
static const QLatin1String kDsRegionMarker;
|
|
||||||
static const QLatin1String kDsError;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_style;
|
QString m_style;
|
||||||
QColor m_color;
|
QColor m_color;
|
||||||
|
|||||||
@@ -185,8 +185,7 @@ bool RegExprRule::doMatchSucceed(const QString &text,
|
|||||||
Q_UNUSED(length)
|
Q_UNUSED(length)
|
||||||
|
|
||||||
// This is not documented but a regular expression match is considered valid if it starts
|
// This is not documented but a regular expression match is considered valid if it starts
|
||||||
// at the current position and if the match length is not zero. Checked in Kate's source code
|
// at the current position and if the match length is not zero.
|
||||||
// after some unexpected problems.
|
|
||||||
const int offset = progress->offset();
|
const int offset = progress->offset();
|
||||||
if (m_expression.indexIn(text, offset, QRegExp::CaretAtZero) == offset) {
|
if (m_expression.indexIn(text, offset, QRegExp::CaretAtZero) == offset) {
|
||||||
if (m_expression.matchedLength() == 0)
|
if (m_expression.matchedLength() == 0)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "highlighterexception.h"
|
#include "highlighterexception.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "normalindenter.h"
|
#include "normalindenter.h"
|
||||||
|
#include "fontsettings.h"
|
||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/uniqueidmanager.h>
|
#include <coreplugin/uniqueidmanager.h>
|
||||||
@@ -103,14 +104,49 @@ void PlainTextEditor::unCommentSelection()
|
|||||||
Utils::unCommentSelection(this, m_commentDefinition);
|
Utils::unCommentSelection(this, m_commentDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlainTextEditor::setFontSettings(const FontSettings & fs)
|
void PlainTextEditor::setFontSettings(const FontSettings &fs)
|
||||||
{
|
{
|
||||||
BaseTextEditor::setFontSettings(fs);
|
BaseTextEditor::setFontSettings(fs);
|
||||||
|
|
||||||
if (baseTextDocument()->syntaxHighlighter()) {
|
if (baseTextDocument()->syntaxHighlighter()) {
|
||||||
Highlighter *highlighter =
|
Highlighter *highlighter =
|
||||||
static_cast<Highlighter *>(baseTextDocument()->syntaxHighlighter());
|
static_cast<Highlighter *>(baseTextDocument()->syntaxHighlighter());
|
||||||
highlighter->configureFormats(fs);
|
|
||||||
|
highlighter->configureFormat(Highlighter::VisualWhitespace, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_VISUAL_WHITESPACE)));
|
||||||
|
highlighter->configureFormat(Highlighter::Keyword, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_KEYWORD)));
|
||||||
|
highlighter->configureFormat(Highlighter::DataType, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_TYPE)));
|
||||||
|
highlighter->configureFormat(Highlighter::Comment, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_COMMENT)));
|
||||||
|
// Using C_NUMBER for all kinds of numbers.
|
||||||
|
highlighter->configureFormat(Highlighter::Decimal, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_NUMBER)));
|
||||||
|
highlighter->configureFormat(Highlighter::BaseN, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_NUMBER)));
|
||||||
|
highlighter->configureFormat(Highlighter::Float, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_NUMBER)));
|
||||||
|
// Using C_STRING for strings and chars.
|
||||||
|
highlighter->configureFormat(Highlighter::Char, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_STRING)));
|
||||||
|
highlighter->configureFormat(Highlighter::String, fs.toTextCharFormat(
|
||||||
|
QLatin1String(Constants::C_STRING)));
|
||||||
|
|
||||||
|
// Creator does not have corresponding formats for the following ones. Implement them?
|
||||||
|
// For now I will leave hardcoded values.
|
||||||
|
QTextCharFormat format;
|
||||||
|
format.setForeground(Qt::blue);
|
||||||
|
highlighter->configureFormat(Highlighter::Others, format);
|
||||||
|
format.setForeground(Qt::red);
|
||||||
|
highlighter->configureFormat(Highlighter::Alert, format);
|
||||||
|
format.setForeground(Qt::darkBlue);
|
||||||
|
highlighter->configureFormat(Highlighter::Function, format);
|
||||||
|
format.setForeground(Qt::darkGray);
|
||||||
|
highlighter->configureFormat(Highlighter::RegionMarker, format);
|
||||||
|
format.setForeground(Qt::darkRed);
|
||||||
|
highlighter->configureFormat(Highlighter::Error, format);
|
||||||
|
|
||||||
highlighter->rehighlight();
|
highlighter->rehighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,8 +176,6 @@ void PlainTextEditor::configure(const Core::MimeType &mimeType)
|
|||||||
Manager::instance()->definition(definitionId);
|
Manager::instance()->definition(definitionId);
|
||||||
|
|
||||||
Highlighter *highlighter = new Highlighter(definition->initialContext());
|
Highlighter *highlighter = new Highlighter(definition->initialContext());
|
||||||
highlighter->configureFormats(TextEditorSettings::instance()->fontSettings());
|
|
||||||
|
|
||||||
baseTextDocument()->setSyntaxHighlighter(highlighter);
|
baseTextDocument()->setSyntaxHighlighter(highlighter);
|
||||||
|
|
||||||
m_commentDefinition.setAfterWhiteSpaces(definition->isCommentAfterWhiteSpaces());
|
m_commentDefinition.setAfterWhiteSpaces(definition->isCommentAfterWhiteSpaces());
|
||||||
@@ -149,6 +183,8 @@ void PlainTextEditor::configure(const Core::MimeType &mimeType)
|
|||||||
m_commentDefinition.setMultiLineStart(definition->multiLineCommentStart());
|
m_commentDefinition.setMultiLineStart(definition->multiLineCommentStart());
|
||||||
m_commentDefinition.setMultiLineEnd(definition->multiLineCommentEnd());
|
m_commentDefinition.setMultiLineEnd(definition->multiLineCommentEnd());
|
||||||
|
|
||||||
|
setFontSettings(TextEditorSettings::instance()->fontSettings());
|
||||||
|
|
||||||
m_isMissingSyntaxDefinition = false;
|
m_isMissingSyntaxDefinition = false;
|
||||||
} catch (const HighlighterException &) {
|
} catch (const HighlighterException &) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user