9#include "definition_p.h"
10#include "repository_p.h"
12#include "themedata_p.h"
13#include "wildcardmatcher.h"
17#include <QDirIterator>
24#ifndef NO_STANDARD_PATHS
25#include <QStandardPaths>
44 const auto strings = def.extensions();
45 return std::any_of(strings.cbegin(), strings.cend(), [str](
QStringView wildcard) {
46 return WildcardMatcher::exactMatch(str, wildcard);
54 const auto strings = def.mimeTypes();
55 return std::any_of(strings.cbegin(), strings.cend(), [mimeTypeName](
QStringView name) {
56 return mimeTypeName == name;
63template<
typename UnaryPredicate>
67 auto matchPriority = std::numeric_limits<int>::lowest();
69 const auto defPriority = def.priority();
70 if (defPriority > matchPriority && predicate(def)) {
72 matchPriority = defPriority;
78template<
typename UnaryPredicate>
82 std::copy_if(defs.
cbegin(), defs.
cend(), std::back_inserter(matches), predicate);
84 return lhs.priority() > rhs.priority();
90static void initResource()
92#ifdef HAS_SYNTAX_RESOURCE
93 Q_INIT_RESOURCE(syntax_data);
95 Q_INIT_RESOURCE(theme_data);
98RepositoryPrivate *RepositoryPrivate::get(
Repository *repo)
100 return repo->d.get();
103Repository::Repository()
104 : d(new RepositoryPrivate)
110Repository::~Repository()
114 for (
const auto &def : std::as_const(d->m_flatDefs)) {
115 DefinitionData::get(def)->repo =
nullptr;
121 return d->m_fullDefs.value(defName.
toLower());
126 return findHighestPriorityDefinitionIf(d->m_flatDefs, anyWildcardMatches(fileNameFromFilePath(fileName)));
131 return findDefinitionsIf(d->m_flatDefs, anyWildcardMatches(fileNameFromFilePath(fileName)));
136 return findHighestPriorityDefinitionIf(d->m_flatDefs, anyMimeTypeEquals(mimeType));
141 return findDefinitionsIf(d->m_flatDefs, anyMimeTypeEquals(mimeType));
146 return d->m_sortedDefs;
157 return lhs.name() < rhs;
163 const auto &themes = d->m_themes;
164 const auto it = lowerBoundTheme(themes, themeName);
165 if (it != themes.end() && (*it).name() == themeName) {
174 return theme(QStringLiteral(
"Breeze Dark"));
176 return theme(QStringLiteral(
"Breeze Light"));
185 const Theme *firstMatchingTheme =
nullptr;
186 for (
const auto &
theme : std::as_const(d->m_themes)) {
188 if (background == base.rgb()) {
191 if (selection == highlight) {
194 if (!firstMatchingTheme) {
195 firstMatchingTheme = &
theme;
199 if (firstMatchingTheme) {
200 return *firstMatchingTheme;
213#ifndef NO_STANDARD_PATHS
215#ifndef HAS_SYNTAX_RESOURCE
217 QStringLiteral(
"org.kde.syntax-highlighting/syntax-bundled"),
219 if (!loadSyntaxFolderFromIndex(repo, dir)) {
220 loadSyntaxFolder(repo, dir);
226 QStringLiteral(
"org.kde.syntax-highlighting/syntax"),
228 loadSyntaxFolder(repo, dir);
233 loadSyntaxFolderFromIndex(repo, QStringLiteral(
":/org.kde.syntax-highlighting/syntax"));
236 loadSyntaxFolder(repo, QStringLiteral(
":/org.kde.syntax-highlighting/syntax-addons"));
239 for (
const auto &path : std::as_const(m_customSearchPaths)) {
240 loadSyntaxFolder(repo, path + QStringLiteral(
"/syntax"));
243 computeAlternativeDefLists();
248#ifndef NO_STANDARD_PATHS
250 QStringLiteral(
"org.kde.syntax-highlighting/themes"),
252 loadThemeFolder(dir);
257 loadThemeFolder(QStringLiteral(
":/org.kde.syntax-highlighting/themes"));
260 loadThemeFolder(QStringLiteral(
":/org.kde.syntax-highlighting/themes-addons"));
263 for (
const auto &path : std::as_const(m_customSearchPaths)) {
264 loadThemeFolder(path + QStringLiteral(
"/themes"));
268void RepositoryPrivate::computeAlternativeDefLists()
271 m_flatDefs.reserve(m_defs.size());
272 for (
const auto &[_, def] : m_defs) {
273 m_flatDefs.push_back(def);
276 m_sortedDefs = m_flatDefs;
277 std::sort(m_sortedDefs.begin(), m_sortedDefs.end(), [](
const Definition &left,
const Definition &right) {
278 auto comparison = left.translatedSection().compare(right.translatedSection(), Qt::CaseInsensitive);
279 if (comparison == 0) {
280 comparison = left.translatedName().compare(right.translatedName(), Qt::CaseInsensitive);
282 return comparison < 0;
286 for (
const auto &def : std::as_const(m_sortedDefs)) {
287 m_fullDefs.insert(def.name().toLower(), def);
288 const auto &alternativeNames = def.alternativeNames();
289 for (
const auto &altName : alternativeNames) {
290 m_fullDefs.insert(altName.toLower(), def);
298 while (it.hasNext()) {
300 auto defData = DefinitionData::get(def);
301 defData->repo = repo;
302 if (defData->loadMetaData(it.next())) {
303 addDefinition(std::move(def));
308bool RepositoryPrivate::loadSyntaxFolderFromIndex(
Repository *repo,
const QString &path)
316 const auto index = indexDoc.toMap();
317 for (
auto it = index.begin(); it != index.end(); ++it) {
318 if (!it.value().isMap()) {
322 const auto defMap = it.value().toMap();
324 auto defData = DefinitionData::get(def);
325 defData->repo = repo;
326 if (defData->loadMetaData(fileName, defMap)) {
327 addDefinition(std::move(def));
334void RepositoryPrivate::addDefinition(
Definition &&def)
336 const auto [it, inserted] = m_defs.try_emplace(def.name(), std::move(def));
341 if (it->second.version() >= def.
version()) {
344 it->second = std::move(def);
347void RepositoryPrivate::loadThemeFolder(
const QString &path)
350 while (it.hasNext()) {
351 auto themeData = std::unique_ptr<ThemeData>(
new ThemeData);
352 if (themeData->load(it.next())) {
353 addTheme(
Theme(themeData.release()));
358static int themeRevision(
const Theme &theme)
360 auto data = ThemeData::get(theme);
361 return data->revision();
364void RepositoryPrivate::addTheme(
const Theme &theme)
366 const auto &constThemes = m_themes;
367 const auto themeName = theme.name();
368 const auto constIt = lowerBoundTheme(constThemes, themeName);
369 const auto index = constIt - constThemes.begin();
370 if (constIt == constThemes.end() || (*constIt).name() != themeName) {
371 m_themes.insert(index, theme);
374 if (themeRevision(*constIt) < themeRevision(theme)) {
375 m_themes[index] = theme;
379int RepositoryPrivate::foldingRegionId(
const QString &defName,
const QString &foldName)
381 const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName));
382 if (it != m_foldingRegionIds.constEnd()) {
385 Q_ASSERT(m_foldingRegionId < std::numeric_limits<int>::max());
386 m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId);
387 return m_foldingRegionId;
390int RepositoryPrivate::nextFormatId()
392 Q_ASSERT(m_formatId < std::numeric_limits<int>::max());
400 for (
const auto &def : std::as_const(d->m_flatDefs)) {
401 DefinitionData::get(def)->clear();
404 d->m_flatDefs.clear();
405 d->m_sortedDefs.clear();
406 d->m_fullDefs.clear();
410 d->m_foldingRegionId = 0;
411 d->m_foldingRegionIds.clear();
424 d->m_customSearchPaths.append(path);
425 d->loadThemeFolder(path + QStringLiteral(
"/themes"));
426 d->loadSyntaxFolder(
this, path + QStringLiteral(
"/syntax"));
427 d->computeAlternativeDefLists();
434 return d->m_customSearchPaths;
437#include "moc_repository.cpp"
Represents a syntax definition.
int version() const
Returns the definition version.
Syntax highlighting repository.
DefaultTheme
Built-in default theme types.
@ DarkTheme
Theme with a dark background color.
@ LightTheme
Theme with a light background color.
Q_INVOKABLE QList< KSyntaxHighlighting::Definition > definitionsForMimeType(const QString &mimeType) const
Returns all Definitions to the type named mimeType sorted by priority.
void reload()
Reloads the repository.
void addCustomSearchPath(const QString &path)
Add a custom search path to the repository.
Q_INVOKABLE KSyntaxHighlighting::Theme defaultTheme(DefaultTheme t=LightTheme) const
Returns a default theme instance of the given type.
void aboutToReload()
This signal is emitted before the reload is started.
Theme themeForPalette(const QPalette &palette) const
Returns the best matching theme for the given palette.
Q_INVOKABLE KSyntaxHighlighting::Definition definitionForMimeType(const QString &mimeType) const
Returns the best matching Definition to the type named mimeType.
Q_INVOKABLE QList< KSyntaxHighlighting::Definition > definitionsForFileName(const QString &fileName) const
Returns all Definitions for the file named fileName sorted by priority.
Q_INVOKABLE KSyntaxHighlighting::Theme theme(const QString &themeName) const
Returns the theme called themeName.
Q_INVOKABLE KSyntaxHighlighting::Definition definitionForName(const QString &defName) const
Returns the Definition named defName.
QList< QString > customSearchPaths() const
Returns the list of custom search paths added to the repository.
void reloaded()
This signal is emitted when the reload is finished.
Q_INVOKABLE KSyntaxHighlighting::Definition definitionForFileName(const QString &fileName) const
Returns the best matching Definition for the file named fileName.
Color theme definition used for highlighting.
@ BackgroundColor
Background color for the editing area.
@ TextSelection
Background color for selected text.
QRgb editorColor(EditorColorRole role) const
Returns the editor color for the requested role.
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
Syntax highlighting engine for Kate syntax definitions.
QCborValue fromCbor(QCborStreamReader &reader)
QString fileName() const const
const_iterator cbegin() const const
const_iterator cend() const const
const QColor & color(ColorGroup group, ColorRole role) const const
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
QString toLower() const const