Editor: update ksyntaxhighlighting engine to v5.87.0

Change-Id: If9dab8b321799f0ce908c831e812c20301a714e1
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
David Schulz
2021-10-19 09:46:07 +02:00
parent e77e57420a
commit fc11797218
78 changed files with 2607 additions and 805 deletions

View File

@@ -0,0 +1,4 @@
# clang-format
56ed6f3f5f505eb0dbffc630729d67c3fb510546
#clang-tidy
0960472cc3f57831a97697a4ae0cd139e2cc5551

View File

@@ -9,6 +9,11 @@ callgrind.*
heaptrack.* heaptrack.*
/build*/ /build*/
*.unc-backup* *.unc-backup*
.clang-format /.clang-format
.cmake/ /.cmake/
*.code-workspace /*.code-workspace
/compile_commands.json
.clangd
.idea
/cmake-build*
.cache

View File

@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml

View File

@@ -0,0 +1,7 @@
Dependencies:
- 'on': ['@all']
'require':
'frameworks/extra-cmake-modules': '@same'
Options:
test-before-installing: True

View File

@@ -10,11 +10,12 @@ add_qtc_library(KSyntaxHighlighting SHARED
PUBLIC_INCLUDES PUBLIC_INCLUDES
src/lib src/lib
autogenerated/src/lib autogenerated/src/lib
DEFINES KSYNTAXHIGHLIGHTING_LIBRARY DEFINES KF5SyntaxHighlighting_EXPORTS
DEPENDS Qt5::Network Qt5::Widgets DEPENDS Qt5::Network Qt5::Widgets
SOURCES SOURCES
autogenerated/src/lib/ksyntaxhighlighting_logging.cpp autogenerated/src/lib/ksyntaxhighlighting_logging.h autogenerated/src/lib/ksyntaxhighlighting_logging.cpp autogenerated/src/lib/ksyntaxhighlighting_logging.h
autogenerated/ksyntaxhighlighting_version.h autogenerated/ksyntaxhighlighting_version.h
autogenerated/src/lib/ksyntaxhighlighting_export.h
data/themes/theme-data.qrc data/themes/theme-data.qrc
@@ -29,7 +30,6 @@ add_qtc_library(KSyntaxHighlighting SHARED
src/lib/format.cpp src/lib/format.h src/lib/format_p.h src/lib/format.cpp src/lib/format.h src/lib/format_p.h
src/lib/htmlhighlighter.cpp src/lib/htmlhighlighter.h src/lib/htmlhighlighter.cpp src/lib/htmlhighlighter.h
src/lib/keywordlist.cpp src/lib/keywordlist_p.h src/lib/keywordlist.cpp src/lib/keywordlist_p.h
src/lib/ksyntaxhighlighting_export.h
src/lib/matchresult_p.h src/lib/matchresult_p.h
src/lib/repository.cpp src/lib/repository.h src/lib/repository_p.h src/lib/repository.cpp src/lib/repository.h src/lib/repository_p.h
src/lib/rule.cpp src/lib/rule_p.h src/lib/rule.cpp src/lib/rule_p.h

View File

@@ -23,6 +23,8 @@ It's meant as a building block for text editors as well as for simple highlighte
text rendering (e.g. as HTML), supporting both integration with a custom editor text rendering (e.g. as HTML), supporting both integration with a custom editor
as well as a ready-to-use QSyntaxHighlighter sub-class. as well as a ready-to-use QSyntaxHighlighter sub-class.
Besides a C++ API, a [QML API](@ref qml_api) is also provided.
## Out of scope ## Out of scope
To not turn this into yet another text editor, the following things are considered To not turn this into yet another text editor, the following things are considered
@@ -46,7 +48,7 @@ in **data/syntax/** and have the **.xml** extension. Additional ones are
picked up from the file system if present, so you can easily extend this picked up from the file system if present, so you can easily extend this
by application-specific syntax definitions for example. by application-specific syntax definitions for example.
To install or test a syntax definiton file locally, place it in To install or test a syntax definition file locally, place it in
**org.kde.syntax-highlighting/syntax/**, which is located in your user directory. **org.kde.syntax-highlighting/syntax/**, which is located in your user directory.
Usually it is: Usually it is:
@@ -56,47 +58,56 @@ Usually it is:
<td>$HOME/.local/share/org.kde.syntax-highlighting/syntax/</td> <td>$HOME/.local/share/org.kde.syntax-highlighting/syntax/</td>
</tr> </tr>
<tr> <tr>
<td>For <a href="https://flathub.org/apps/details/org.kde.kate">Kate's Flatpak package</a></td> <td>For Flatpak packages</td>
<td>$HOME/.var/app/org.kde.kate/data/org.kde.syntax-highlighting/syntax/</td> <td>$HOME/.var/app/<em>package-name</em>/data/org.kde.syntax-highlighting/syntax/</td>
</tr> </tr>
<tr> <tr>
<td>For <a href="https://snapcraft.io/kate">Kate's Snap package</a></td> <td>For Snap packages</a></td>
<td>$HOME/snap/kate/current/.local/share/org.kde.syntax-highlighting/syntax/</td> <td>$HOME/snap/<em>package-name</em>/current/.local/share/org.kde.syntax-highlighting/syntax/</td>
</tr> </tr>
<tr> <tr>
<td>On Windows®</td> <td>On Windows®</td>
<td>&#37;USERPROFILE&#37;&#92;AppData&#92;Local&#92;org.kde.syntax-highlighting&#92;syntax&#92;</td> <td>&#37;USERPROFILE&#37;&#92;AppData&#92;Local&#92;org.kde.syntax-highlighting&#92;syntax&#92;</td>
</tr> </tr>
<tr>
<td>On macOS®</td>
<td>$HOME/Library/Application Support/org.kde.syntax-highlighting/syntax/</td>
</tr>
</table> </table>
For more details, see ["The Highlight Definition XML Format" (Working with Syntax Highlighting, KDE Documentation)](https://docs.kde.org/?application=katepart&branch=trunk5&path=highlight.html#katehighlight-xml-format). For more details, see ["The Highlight Definition XML Format" (Working with Syntax Highlighting, KDE Documentation)](https://docs.kde.org/?application=katepart&branch=trunk5&path=highlight.html#katehighlight-xml-format).
Also, in **data/schema/** there is a script to validate the syntax definiton XML Also, in **data/schema/** there is a script to validate the syntax definition XML
files. Use the command `validatehl.sh mySyntax.xml`. files. Use the command `validatehl.sh mySyntax.xml`.
## Color theme files ## Color theme files
This library includes the color themes, the theme files use the **JSON** This library includes the color themes, which are documented
format and are located in **data/themes/** with the **.theme** extension. [here](https://docs.kde.org/?application=katepart&branch=trunk5&path=color-themes.html).
The color theme files use the JSON format and are located in **data/themes/**
with the **.theme** extension.
Additional ones are also picked up from the file system if present, Additional ones are also picked up from the file system if present,
in the **org.kde.syntax-highlighting/themes/** folder of your user directory, in the **org.kde.syntax-highlighting/themes/** folder of your user directory,
allowing you to easily add custom color theme files. allowing you to easily add custom color theme files. This location is the same
The location of **org.kde.syntax-highlighting/themes/** is the same
as shown in the table of the [previous section](#syntax-definition-files), as shown in the table of the [previous section](#syntax-definition-files),
replacing the **syntax** folder with **themes**. replacing the **syntax** folder with **themes**.
For more details, see ["The Color Themes JSON Format" (Working with Color Themes, KDE Documentation)](https://docs.kde.org/?application=katepart&branch=trunk5&path=color-themes.html#color-themes-json).
The [KTextEditor](https://api.kde.org/frameworks/ktexteditor/html/) library The [KTextEditor](https://api.kde.org/frameworks/ktexteditor/html/) library
(used by Kate, Kile and KDevelop, for example) provides (used by Kate, Kile and KDevelop, for example) provides a
a user interface for editing and creating KSyntaxHighlighting color themes, including [user interface](https://docs.kde.org/?application=katepart&branch=trunk5&path=color-themes.html#color-themes-gui)
for editing and creating KSyntaxHighlighting color themes, including
a tool for exporting and importing the JSON theme files. a tool for exporting and importing the JSON theme files.
Note that in KDE text editors, the KSyntaxHighlighting color themes are used
[since KDE Frameworks 5.75](https://kate-editor.org/post/2020/2020-09-13-kate-color-themes-5.75/),
released on October 10, 2020. Previously, Kate's color schemes
(KConfig based schema config) were used and are now deprecated.
The tool **utils/schema-converter/** and the script **utils/kateschema_to_theme_converter.py** The tool **utils/schema-converter/** and the script **utils/kateschema_to_theme_converter.py**
convert the old Kate schemas to KSyntaxHighlighting themes. convert the old Kate schemas to KSyntaxHighlighting themes.
For more information, see: Also see ["Submit a KSyntaxHighlighting Color Theme" (Kate Editor Website)](https://kate-editor.org/post/2020/2020-09-18-submit-a-ksyntaxhighlighting-color-theme/).
* [Kate - Color Themes with Frameworks 5.75 (Kate Editor Website)](https://kate-editor.org/post/2020/2020-09-13-kate-color-themes-5.75/)
* [Submit a KSyntaxHighlighting Color Theme (Kate Editor Website)](https://kate-editor.org/post/2020/2020-09-18-submit-a-ksyntaxhighlighting-color-theme/)
## Build it ## Build it

View File

@@ -6,4 +6,5 @@ SOURCES += \
HEADERS += \ HEADERS += \
$$PWD/ksyntaxhighlighting_version.h \ $$PWD/ksyntaxhighlighting_version.h \
$$PWD/src/lib/ksyntaxhighlighting_logging.h $$PWD/src/lib/ksyntaxhighlighting_logging.h \
$$PWD/src/lib/ksyntaxhighlighting_export.h

View File

@@ -3,10 +3,10 @@
#ifndef SyntaxHighlighting_VERSION_H #ifndef SyntaxHighlighting_VERSION_H
#define SyntaxHighlighting_VERSION_H #define SyntaxHighlighting_VERSION_H
#define SyntaxHighlighting_VERSION_STRING "5.80.0" #define SyntaxHighlighting_VERSION_STRING "5.87.0"
#define SyntaxHighlighting_VERSION_MAJOR 5 #define SyntaxHighlighting_VERSION_MAJOR 5
#define SyntaxHighlighting_VERSION_MINOR 80 #define SyntaxHighlighting_VERSION_MINOR 87
#define SyntaxHighlighting_VERSION_PATCH 0 #define SyntaxHighlighting_VERSION_PATCH 0
#define SyntaxHighlighting_VERSION ((5<<16)|(80<<8)|(0)) #define SyntaxHighlighting_VERSION ((5<<16)|(87<<8)|(0))
#endif #endif

View File

@@ -0,0 +1 @@
#include "wildcardmatcher.h"

View File

@@ -0,0 +1,218 @@
#ifndef KSYNTAXHIGHLIGHTING_EXPORT_H
#define KSYNTAXHIGHLIGHTING_EXPORT_H
#include <QtGlobal>
#ifdef KSYNTAXHIGHLIGHTING_STATIC_DEFINE
# define KSYNTAXHIGHLIGHTING_EXPORT
# define KSYNTAXHIGHLIGHTING_NO_EXPORT
#else
# ifndef KSYNTAXHIGHLIGHTING_EXPORT
# ifdef KF5SyntaxHighlighting_EXPORTS
/* We are building this library */
# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_EXPORT
# else
/* We are using this library */
# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_IMPORT
# endif
# endif
# ifndef KSYNTAXHIGHLIGHTING_NO_EXPORT
# define KSYNTAXHIGHLIGHTING_NO_EXPORT
# endif
#endif
#ifndef KSYNTAXHIGHLIGHTING_DECL_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED __declspec(deprecated)
#endif
#ifndef KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_EXPORT
# define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED
#endif
#ifndef KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_NO_EXPORT
# define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED
#endif
#if 0 /* DEFINE_NO_DEPRECATED */
# ifndef KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# endif
#endif
#define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) __declspec(deprecated(text))
#define ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
/* Take any defaults from group settings */
#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED) && !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT)
# ifdef KF_NO_DEPRECATED
# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# elif defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
# endif
#endif
#if !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) && defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
#endif
#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS) && !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE)
# ifdef KF_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# elif defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
# endif
#endif
#if !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE) && defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
#endif
#if defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED)
# undef KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT
#elif defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS)
# define KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT
#else
# define KSYNTAXHIGHLIGHTING_DEPRECATED KSYNTAXHIGHLIGHTING_DECL_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_NO_EXPORT
#endif
/* No deprecated API had been removed from build */
#define KSYNTAXHIGHLIGHTING_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0
#define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55700
#endif
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0
#endif
#ifndef KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE
# ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# else
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55700
# endif
#endif
#ifndef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0
#endif
#ifdef KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) (ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, 0) > KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT)
#else
# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) 0
#endif
#if KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE >= 0x55700
# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text)
#else
# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text)
#endif
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5(minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_##minor(text)
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION(major, minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#major"."#minor". " text)
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#textmajor"."#textminor". " text)
// Not yet implemented for MSVC
#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION(major, minor, text)
#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text)
#endif /* KSYNTAXHIGHLIGHTING_EXPORT_H */
#ifndef ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H
#define ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H
#define KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text) __declspec(deprecated(text))
#define ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
/* Take any defaults from group settings */
#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED) && !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT)
# ifdef KF_NO_DEPRECATED
# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# elif defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
# endif
#endif
#if !defined(KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT) && defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
#endif
#if !defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS) && !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE)
# ifdef KF_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# elif defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
# endif
#endif
#if !defined(KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE) && defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
#endif
#if defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED)
# undef KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT
#elif defined(KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS)
# define KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_NO_EXPORT
#else
# define KSYNTAXHIGHLIGHTING_DEPRECATED KSYNTAXHIGHLIGHTING_DECL_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DEPRECATED_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_EXPORT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_NO_EXPORT KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_NO_EXPORT
#endif
/* No deprecated API had been removed from build */
#define KSYNTAXHIGHLIGHTING_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0
#define KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(major, minor) 1
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0x55700
#endif
#ifdef KSYNTAXHIGHLIGHTING_NO_DEPRECATED_WARNINGS
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0
#endif
#ifndef KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE
# ifdef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# else
# define KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE 0x55700
# endif
#endif
#ifndef KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT 0
#endif
#ifdef KSYNTAXHIGHLIGHTING_DEPRECATED
# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) (ECM_GENERATEEXPORTHEADER_VERSION_VALUE(major, minor, 0) > KSYNTAXHIGHLIGHTING_DISABLE_DEPRECATED_BEFORE_AND_AT)
#else
# define KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(major, minor) 0
#endif
#if KSYNTAXHIGHLIGHTING_DEPRECATED_WARNINGS_SINCE >= 0x55700
# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text) KSYNTAXHIGHLIGHTING_DECL_DEPRECATED_TEXT(text)
#else
# define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_87(text)
#endif
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5(minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_5_##minor(text)
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION(major, minor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#major"."#minor". " text)
#define KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text) KSYNTAXHIGHLIGHTING_DEPRECATED_VERSION_##major(minor, "Since "#textmajor"."#textminor". " text)
// Not yet implemented for MSVC
#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION(major, minor, text)
#define KSYNTAXHIGHLIGHTING_ENUMERATOR_DEPRECATED_VERSION_BELATED(major, minor, textmajor, textminor, text)
#endif /* ECM_GENERATEEXPORTHEADER_KSYNTAXHIGHLIGHTING_EXPORT_H */

View File

@@ -38,8 +38,11 @@ generate_syntax_definition(generate-doxygenlua.pl doxygenlua.xml doxygen.xml)
file(GLOB src_defs "${CMAKE_CURRENT_SOURCE_DIR}/syntax/*.xml") file(GLOB src_defs "${CMAKE_CURRENT_SOURCE_DIR}/syntax/*.xml")
set(defs ${src_defs} ${gen_defs}) set(defs ${src_defs} ${gen_defs})
# object library to make cross-folder dependencies work
add_library(SyntaxHighlightingData OBJECT)
# theme data resource # theme data resource
qt5_add_resources(themes_QRC ${CMAKE_CURRENT_SOURCE_DIR}/themes/theme-data.qrc) target_sources(SyntaxHighlightingData PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/themes/theme-data.qrc)
# do we want syntax files bundled in the library? # do we want syntax files bundled in the library?
if (QRC_SYNTAX) if (QRC_SYNTAX)
@@ -66,14 +69,10 @@ if (QRC_SYNTAX)
) )
set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/qrc_syntax-data.cpp" PROPERTIES SKIP_AUTOMOC ON) set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/qrc_syntax-data.cpp" PROPERTIES SKIP_AUTOMOC ON)
# object library to make cross-folder dependencies work, themes + syntax files target_sources(SyntaxHighlightingData PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/qrc_syntax-data.cpp)
add_library(SyntaxHighlightingData OBJECT ${themes_QRC} ${CMAKE_CURRENT_BINARY_DIR}/qrc_syntax-data.cpp)
else() else()
# install the syntax files as normal files into the prefix # install the syntax files as normal files into the prefix
install (FILES ${defs} DESTINATION ${KDE_INSTALL_DATADIR}/org.kde.syntax-highlighting/syntax) install (FILES ${defs} DESTINATION ${KDE_INSTALL_DATADIR}/org.kde.syntax-highlighting/syntax)
# object library to make cross-folder dependencies work, only themes
add_library(SyntaxHighlightingData OBJECT ${themes_QRC})
endif() endif()
# set PIC to allow use in static and shared libs # set PIC to allow use in static and shared libs

View File

@@ -22,7 +22,7 @@
<language <language
name="CMake" name="CMake"
version="31" version="<!--{version}-->"
kateversion="5.0" kateversion="5.0"
section="Other" section="Other"
extensions="CMakeLists.txt;*.cmake;*.cmake.in" extensions="CMakeLists.txt;*.cmake;*.cmake.in"

View File

@@ -1,3 +1,5 @@
version: 34
global-properties: global-properties:
- ALLOW_DUPLICATE_CUSTOM_TARGETS - ALLOW_DUPLICATE_CUSTOM_TARGETS
- AUTOGEN_SOURCE_GROUP - AUTOGEN_SOURCE_GROUP
@@ -56,6 +58,7 @@ directory-properties:
- DEFINITIONS - DEFINITIONS
- EXCLUDE_FROM_ALL - EXCLUDE_FROM_ALL
- IMPLICIT_DEPENDS_INCLUDE_TRANSFORM - IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
- IMPORTED_TARGETS # Since 3.21
- INCLUDE_DIRECTORIES - INCLUDE_DIRECTORIES
- INCLUDE_REGULAR_EXPRESSION - INCLUDE_REGULAR_EXPRESSION
- INTERPROCEDURAL_OPTIMIZATION_<CONFIG> - INTERPROCEDURAL_OPTIMIZATION_<CONFIG>
@@ -172,6 +175,7 @@ target-properties:
- EXCLUDE_FROM_ALL - EXCLUDE_FROM_ALL
- EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG> - EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG>
- EXCLUDE_FROM_DEFAULT_BUILD - EXCLUDE_FROM_DEFAULT_BUILD
- EXPORT_COMPILE_COMMANDS # Since 3.20
- EXPORT_NAME - EXPORT_NAME
- EXPORT_PROPERTIES # Since 3.12 - EXPORT_PROPERTIES # Since 3.12
- FOLDER - FOLDER
@@ -243,6 +247,7 @@ target-properties:
- <LANG>_CPPCHECK # Since 3.10 - <LANG>_CPPCHECK # Since 3.10
- <LANG>_CPPLINT - <LANG>_CPPLINT
- <LANG>_INCLUDE_WHAT_YOU_USE - <LANG>_INCLUDE_WHAT_YOU_USE
- <LANG>_LINKER_LAUNCHER # Sine 3.21
- <LANG>_VISIBILITY_PRESET - <LANG>_VISIBILITY_PRESET
- LIBRARY_OUTPUT_DIRECTORY_<CONFIG> - LIBRARY_OUTPUT_DIRECTORY_<CONFIG>
- LIBRARY_OUTPUT_DIRECTORY - LIBRARY_OUTPUT_DIRECTORY
@@ -284,7 +289,6 @@ target-properties:
- OBJCXX_STANDARD # Since 3.16 - OBJCXX_STANDARD # Since 3.16
- OBJCXX_STANDARD_REQUIRED # Since 3.16 - OBJCXX_STANDARD_REQUIRED # Since 3.16
- OPTIMIZE_DEPENDENCIES # Since 3.19 - OPTIMIZE_DEPENDENCIES # Since 3.19
- OBJC_STANDARD
- OSX_ARCHITECTURES_<CONFIG> - OSX_ARCHITECTURES_<CONFIG>
- OSX_ARCHITECTURES - OSX_ARCHITECTURES
- OSX_CURRENT_VERSION # Since 3.17 - OSX_CURRENT_VERSION # Since 3.17
@@ -329,6 +333,7 @@ target-properties:
- UNITY_BUILD_CODE_AFTER_INCLUDE # Since 3.16 - UNITY_BUILD_CODE_AFTER_INCLUDE # Since 3.16
- UNITY_BUILD_CODE_BEFORE_INCLUDE # Since 3.16 - UNITY_BUILD_CODE_BEFORE_INCLUDE # Since 3.16
- UNITY_BUILD_MODE # Since 3.18 - UNITY_BUILD_MODE # Since 3.18
- UNITY_BUILD_UNIQUE_ID # Since 3.20
- VERSION - VERSION
- VISIBILITY_INLINES_HIDDEN - VISIBILITY_INLINES_HIDDEN
- VS_CONFIGURATION_TYPE - VS_CONFIGURATION_TYPE
@@ -372,6 +377,10 @@ target-properties:
- WIN32_EXECUTABLE - WIN32_EXECUTABLE
- WINDOWS_EXPORT_ALL_SYMBOLS - WINDOWS_EXPORT_ALL_SYMBOLS
- XCODE_ATTRIBUTE_<an-attribute> - XCODE_ATTRIBUTE_<an-attribute>
- XCODE_EMBED_<type>_CODE_SIGN_ON_COPY # Since 3.20
- XCODE_EMBED_<type>_PATH # Since 3.20
- XCODE_EMBED_<type>_REMOVE_HEADERS_ON_COPY # Since 3.20
- XCODE_EMBED_<type> # Since 3.20
- XCODE_EXPLICIT_FILE_TYPE - XCODE_EXPLICIT_FILE_TYPE
- XCODE_GENERATE_SCHEME # Since 3.15 - XCODE_GENERATE_SCHEME # Since 3.15
- XCODE_LINK_BUILD_PHASE_MODE # Since 3.19 - XCODE_LINK_BUILD_PHASE_MODE # Since 3.19
@@ -572,6 +581,7 @@ generator-expressions:
- TARGET_BUNDLE_DIR - TARGET_BUNDLE_DIR
- TARGET_BUNDLE_CONTENT_DIR - TARGET_BUNDLE_CONTENT_DIR
- TARGET_PROPERTY - TARGET_PROPERTY
- TARGET_RUNTIME_DLLS # Since 3.21
- INSTALL_PREFIX - INSTALL_PREFIX
# Output-Related Expressions # Output-Related Expressions
- TARGET_NAME - TARGET_NAME
@@ -581,6 +591,8 @@ generator-expressions:
- MAKE_C_IDENTIFIER - MAKE_C_IDENTIFIER
- TARGET_OBJECTS - TARGET_OBJECTS
- SHELL_PATH - SHELL_PATH
- OUTPUT_CONFIG # Since 3.20
- COMMAND_CONFIG # Since 3.20
variables: variables:
# Variables that Provide Information # Variables that Provide Information
@@ -687,6 +699,7 @@ variables:
- CMAKE_XCODE_PLATFORM_TOOLSET - CMAKE_XCODE_PLATFORM_TOOLSET
- <PROJECT-NAME>_BINARY_DIR - <PROJECT-NAME>_BINARY_DIR
- <PROJECT-NAME>_DESCRIPTION # Since 3.12 - <PROJECT-NAME>_DESCRIPTION # Since 3.12
- <PROJECT-NAME>_IS_TOP_LEVEL # Since 3.21
- <PROJECT-NAME>_HOMEPAGE_URL # Since 3.12 - <PROJECT-NAME>_HOMEPAGE_URL # Since 3.12
- <PROJECT-NAME>_SOURCE_DIR - <PROJECT-NAME>_SOURCE_DIR
- <PROJECT-NAME>_VERSION - <PROJECT-NAME>_VERSION
@@ -696,6 +709,7 @@ variables:
- <PROJECT-NAME>_VERSION_TWEAK - <PROJECT-NAME>_VERSION_TWEAK
- PROJECT_BINARY_DIR - PROJECT_BINARY_DIR
- PROJECT_DESCRIPTION # Since 3.9 - PROJECT_DESCRIPTION # Since 3.9
- PROJECT_IS_TOP_LEVEL # Since 3.21
- PROJECT_HOMEPAGE_URL # Since 3.12 - PROJECT_HOMEPAGE_URL # Since 3.12
- PROJECT_NAME - PROJECT_NAME
- PROJECT_SOURCE_DIR - PROJECT_SOURCE_DIR
@@ -819,6 +833,7 @@ variables:
- ANDROID - ANDROID
- APPLE - APPLE
- BORLAND - BORLAND
- CMAKE_ANDROID_NDK_VERSION # Since 3.20
- CMAKE_CL_64 - CMAKE_CL_64
- CMAKE_COMPILER_2005 - CMAKE_COMPILER_2005
- CMAKE_HOST_APPLE - CMAKE_HOST_APPLE
@@ -949,6 +964,9 @@ variables:
- CMAKE_<LANG>_CPPCHECK # Since 3.10 - CMAKE_<LANG>_CPPCHECK # Since 3.10
- CMAKE_<LANG>_CPPLINT - CMAKE_<LANG>_CPPLINT
- CMAKE_<LANG>_INCLUDE_WHAT_YOU_USE - CMAKE_<LANG>_INCLUDE_WHAT_YOU_USE
- CMAKE_<LANG>_LINKER_LAUNCHER # Sine 3.21
- CMAKE_<LANG>_LINK_LIBRARY_FILE_FLAG # Sine 3.16
- CMAKE_<LANG>_LINK_LIBRARY_FLAG # Sine 3.16
- CMAKE_<LANG>_VISIBILITY_PRESET - CMAKE_<LANG>_VISIBILITY_PRESET
- CMAKE_LIBRARY_OUTPUT_DIRECTORY - CMAKE_LIBRARY_OUTPUT_DIRECTORY
- CMAKE_LIBRARY_OUTPUT_DIRECTORY_<CONFIG> - CMAKE_LIBRARY_OUTPUT_DIRECTORY_<CONFIG>
@@ -1046,6 +1064,7 @@ variables:
- CMAKE_<LANG>_ARCHIVE_APPEND - CMAKE_<LANG>_ARCHIVE_APPEND
- CMAKE_<LANG>_ARCHIVE_CREATE - CMAKE_<LANG>_ARCHIVE_CREATE
- CMAKE_<LANG>_ARCHIVE_FINISH - CMAKE_<LANG>_ARCHIVE_FINISH
- CMAKE_<LANG>_BYTE_ORDER # Since 3.20
- CMAKE_<LANG>_COMPILER - CMAKE_<LANG>_COMPILER
- CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN - CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN
- CMAKE_<LANG>_COMPILER_ID - CMAKE_<LANG>_COMPILER_ID
@@ -1173,6 +1192,7 @@ variables:
# Variables for CPack # Variables for CPack
- CPACK_ABSOLUTE_DESTINATION_FILES - CPACK_ABSOLUTE_DESTINATION_FILES
- CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY - CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
- CPACK_CUSTOM_INSTALL_VARIABLES # Since 3.21
- CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION - CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
- CPACK_INCLUDE_TOPLEVEL_DIRECTORY - CPACK_INCLUDE_TOPLEVEL_DIRECTORY
- CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS # Since 3.11 - CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS # Since 3.11
@@ -1182,32 +1202,57 @@ variables:
- CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION - CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
# Variables for `find_package()` # Variables for `find_package()`
- PACKAGE_FIND_NAME - PACKAGE_FIND_NAME
- PACKAGE_FIND_VERSION # NOTE <SMTH>_VERSION and components already defined above, so skipped here
- PACKAGE_FIND_VERSION_MAJOR
- PACKAGE_FIND_VERSION_MINOR
- PACKAGE_FIND_VERSION_PATCH
- PACKAGE_FIND_VERSION_TWEAK
- PACKAGE_FIND_VERSION_COUNT - PACKAGE_FIND_VERSION_COUNT
- PACKAGE_FIND_VERSION_RANGE
- PACKAGE_FIND_VERSION_RANGE_MIN
- PACKAGE_FIND_VERSION_RANGE_MAX
- PACKAGE_FIND_VERSION_MIN
- PACKAGE_FIND_VERSION_MIN_MAJOR
- PACKAGE_FIND_VERSION_MIN_MINOR
- PACKAGE_FIND_VERSION_MIN_PATCH
- PACKAGE_FIND_VERSION_MIN_TWEAK
- PACKAGE_FIND_VERSION_MIN_COUNT
- PACKAGE_FIND_VERSION_MAX
- PACKAGE_FIND_VERSION_MAX_MAJOR
- PACKAGE_FIND_VERSION_MAX_MINOR
- PACKAGE_FIND_VERSION_MAX_PATCH
- PACKAGE_FIND_VERSION_MAX_TWEAK
- PACKAGE_FIND_VERSION_MAX_COUNT
- PACKAGE_FIND_VERSION_COMPLETE
- PACKAGE_VERSION - PACKAGE_VERSION
- PACKAGE_VERSION_EXACT - PACKAGE_VERSION_EXACT
- PACKAGE_VERSION_COMPATIBLE - PACKAGE_VERSION_COMPATIBLE
- PACKAGE_VERSION_UNSUITABLE - PACKAGE_VERSION_UNSUITABLE
# NOTE <SMTH>_VERSION and components already defined above, so skipped here # Package File Interface Variables
- <package>_FOUND - <package>_FOUND
- <package>_VERSION_COUNT
- <package>_FIND_REQUIRED - <package>_FIND_REQUIRED
- <package>_FIND_QUIETLY - <package>_FIND_QUIETLY
- <package>_FIND_VERSION - <package>_VERSION_COUNT
- <package>_FIND_VERSION_MAJOR # NOTE <SMTH>_VERSION and components already defined above, so skipped here
- <package>_FIND_VERSION_MINOR - <PackageName>_FIND_VERSION_COUNT
- <package>_FIND_VERSION_PATCH - <PackageName>_FIND_VERSION_EXACT
- <package>_FIND_VERSION_TWEAK - <PackageName>_FIND_COMPONENTS
- <package>_FIND_VERSION_COUNT - <PackageName>_FIND_REQUIRED_<c>
- <package>_FIND_VERSION_EXACT - <PackageName>_FIND_VERSION_RANGE
- <package>_FIND_COMPONENTS - <PackageName>_FIND_VERSION_RANGE_MIN
- <package>_FIND_REQUIRED_<c> - <PackageName>_FIND_VERSION_RANGE_MAX
- <package>_CONSIDERED_CONFIGS - <PackageName>_FIND_VERSION_MIN
- <package>_CONSIDERED_VERSIONS - <PackageName>_FIND_VERSION_MIN_MAJOR
- <PackageName>_FIND_VERSION_MIN_MINOR
- <PackageName>_FIND_VERSION_MIN_PATCH
- <PackageName>_FIND_VERSION_MIN_TWEAK
- <PackageName>_FIND_VERSION_MIN_COUNT
- <PackageName>_FIND_VERSION_MAX
- <PackageName>_FIND_VERSION_MAX_MAJOR
- <PackageName>_FIND_VERSION_MAX_MINOR
- <PackageName>_FIND_VERSION_MAX_PATCH
- <PackageName>_FIND_VERSION_MAX_TWEAK
- <PackageName>_FIND_VERSION_MAX_COUNT
- <PackageName>_FIND_VERSION_COMPLETE
- <PackageName>_CONFIG
- <PackageName>_CONSIDERED_CONFIGS
- <PackageName>_CONSIDERED_VERSIONS
- <PackageName>_ROOT # Since 3.12 - <PackageName>_ROOT # Since 3.12
# Other standard variables/patterns # Other standard variables/patterns
# - `try_run` # - `try_run`
@@ -1220,6 +1265,10 @@ variables:
# - `cmake_parse_arguments` # - `cmake_parse_arguments`
- <pfx>_UNPARSED_ARGUMENTS - <pfx>_UNPARSED_ARGUMENTS
- <pfx>_KEYWORDS_MISSING_VALUES - <pfx>_KEYWORDS_MISSING_VALUES
# Variables that control `file(GET_RUNTIME_DEPENDENCIES)` behavior
- CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
- CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
- CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
# Well known CMake's official module's variables # Well known CMake's official module's variables
# - CheckCompilerFlag # - CheckCompilerFlag
# - CheckCCompilerFlag # - CheckCCompilerFlag
@@ -1327,6 +1376,7 @@ variables:
- CPACK_DEBIAN_PACKAGE_HOMEPAGE - CPACK_DEBIAN_PACKAGE_HOMEPAGE
- CPACK_DEBIAN_PACKAGE_SHLIBDEPS - CPACK_DEBIAN_PACKAGE_SHLIBDEPS
- CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS - CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS
- CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS # Since 3.20
- CPACK_DEBIAN_PACKAGE_DEBUG - CPACK_DEBIAN_PACKAGE_DEBUG
- CPACK_DEBIAN_PACKAGE_PREDEPENDS - CPACK_DEBIAN_PACKAGE_PREDEPENDS
- CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS - CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS
@@ -1364,6 +1414,7 @@ variables:
- CPACK_DMG_SLA_DIR - CPACK_DMG_SLA_DIR
- CPACK_DMG_SLA_LANGUAGES - CPACK_DMG_SLA_LANGUAGES
- CPACK_DMG_<component>_FILE_NAME # Since 3.17 - CPACK_DMG_<component>_FILE_NAME # Since 3.17
- CPACK_DMG_FILESYSTEM # Since 3.21
- CPACK_COMMAND_HDIUTIL - CPACK_COMMAND_HDIUTIL
- CPACK_COMMAND_SETFILE - CPACK_COMMAND_SETFILE
- CPACK_COMMAND_REZ - CPACK_COMMAND_REZ
@@ -1389,6 +1440,7 @@ variables:
- CPACK_IFW_PACKAGE_STYLE_SHEET # Since 3.15 - CPACK_IFW_PACKAGE_STYLE_SHEET # Since 3.15
- CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH - CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH
- CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT - CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT
- CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST # Since 3.20
- CPACK_IFW_PACKAGE_TITLE_COLOR - CPACK_IFW_PACKAGE_TITLE_COLOR
- CPACK_IFW_PACKAGE_START_MENU_DIRECTORY - CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
- CPACK_IFW_TARGET_DIRECTORY - CPACK_IFW_TARGET_DIRECTORY
@@ -1443,6 +1495,9 @@ variables:
- CPACK_NSIS_FINISH_TITLE_3LINES # Since 3.17 - CPACK_NSIS_FINISH_TITLE_3LINES # Since 3.17
- CPACK_NSIS_MUI_HEADERIMAGE # Since 3.17 - CPACK_NSIS_MUI_HEADERIMAGE # Since 3.17
- CPACK_NSIS_MANIFEST_DPI_AWARE # Since 3.18 - CPACK_NSIS_MANIFEST_DPI_AWARE # Since 3.18
- CPACK_NSIS_BRANDING_TEXT # Since 3.20
- CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION # Since 3.20
- CPACK_NSIS_EXECUTABLE # Since 3.21
# - CPackNuGet (since 3.12) # - CPackNuGet (since 3.12)
- CPACK_NUGET_COMPONENT_INSTALL - CPACK_NUGET_COMPONENT_INSTALL
- CPACK_NUGET_PACKAGE_NAME - CPACK_NUGET_PACKAGE_NAME
@@ -1461,14 +1516,22 @@ variables:
- CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL - CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
- CPACK_NUGET_PACKAGE_LICENSEURL - CPACK_NUGET_PACKAGE_LICENSEURL
- CPACK_NUGET_<compName>_PACKAGE_LICENSEURL - CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
- CPACK_NUGET_PACKAGE_LICENSE_EXPRESSION # Since 3.20
- CPACK_NUGET_<compName>_PACKAGE_LICENSE_EXPRESSION # Since 3.20
- CPACK_NUGET_PACKAGE_LICENSE_FILE_NAME # Since 3.20
- CPACK_NUGET_<compName>_PACKAGE_LICENSE_FILE_NAME # Since 3.20
- CPACK_NUGET_PACKAGE_ICONURL - CPACK_NUGET_PACKAGE_ICONURL
- CPACK_NUGET_<compName>_PACKAGE_ICONURL - CPACK_NUGET_<compName>_PACKAGE_ICONURL
- CPACK_NUGET_PACKAGE_ICON # Since 3.20
- CPACK_NUGET_<compName>_PACKAGE_ICON # Since 3.20
- CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY - CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY
- CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY - CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY
- CPACK_NUGET_PACKAGE_RELEASE_NOTES - CPACK_NUGET_PACKAGE_RELEASE_NOTES
- CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES - CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES
- CPACK_NUGET_PACKAGE_COPYRIGHT - CPACK_NUGET_PACKAGE_COPYRIGHT
- CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT - CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT
- CPACK_NUGET_PACKAGE_LANGUAGE # Since 3.20
- CPACK_NUGET_<compName>_PACKAGE_LANGUAGE # Since 3.20
- CPACK_NUGET_PACKAGE_TAGS - CPACK_NUGET_PACKAGE_TAGS
- CPACK_NUGET_<compName>_PACKAGE_TAGS - CPACK_NUGET_<compName>_PACKAGE_TAGS
- CPACK_NUGET_PACKAGE_DEPENDENCIES - CPACK_NUGET_PACKAGE_DEPENDENCIES
@@ -1617,6 +1680,7 @@ variables:
- CPACK_PACKAGE_EXECUTABLES - CPACK_PACKAGE_EXECUTABLES
- CPACK_STRIP_FILES - CPACK_STRIP_FILES
- CPACK_VERBATIM_VARIABLES - CPACK_VERBATIM_VARIABLES
- CPACK_THREADS # Since 3.20
- CPACK_SOURCE_PACKAGE_FILE_NAME - CPACK_SOURCE_PACKAGE_FILE_NAME
- CPACK_SOURCE_STRIP_FILES - CPACK_SOURCE_STRIP_FILES
- CPACK_SOURCE_GENERATOR - CPACK_SOURCE_GENERATOR
@@ -1754,12 +1818,19 @@ variables:
- CMAKE_NO_ANSI_STRING_STREAM - CMAKE_NO_ANSI_STRING_STREAM
# - TestForSTDNamespace # - TestForSTDNamespace
- CMAKE_NO_STD_NAMESPACE - CMAKE_NO_STD_NAMESPACE
# - UseJava
- CMAKE_JAVA_COMPILE_FLAGS
- CMAKE_JAVA_INCLUDE_PATH
- CMAKE_JNI_TARGET
- CMAKE_JAR_CLASSES_PREFIX
# - UseSWIG # - UseSWIG
- UseSWIG_MODULE_VERSION # Since 3.12
- CMAKE_SWIG_FLAGS - CMAKE_SWIG_FLAGS
- CMAKE_SWIG_OUTDIR - CMAKE_SWIG_OUTDIR
- SWIG_OUTFILE_DIR - SWIG_OUTFILE_DIR
- SWIG_MODULE_<name>_EXTRA_DEPS - SWIG_MODULE_<name>_EXTRA_DEPS
- SWIG_SOURCE_FILE_EXTENSIONS # Since 3.14 - SWIG_SOURCE_FILE_EXTENSIONS # Since 3.14
- SWIG_USE_SWIG_DEPENDENCIES # Since 3.20
deprecated-or-internal-variables: deprecated-or-internal-variables:
- CMAKE_HOME_DIRECTORY - CMAKE_HOME_DIRECTORY
@@ -1784,6 +1855,10 @@ deprecated-or-internal-variables:
- CPACK_TEMPORARY_DIRECTORY - CPACK_TEMPORARY_DIRECTORY
- CPACK_TOPLEVEL_DIRECTORY - CPACK_TOPLEVEL_DIRECTORY
- CPACK_INSTALL_PREFIX - CPACK_INSTALL_PREFIX
# Mentioned in `file(GET_RUNTIME_DEPENDENCIES)` docs
- CMAKE_OBJDUMP
# Mentioned in "Deprecated and Removed Features" of release notes 3.21
- CMAKE_SYSTEM_ARCH
# https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html # https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html
# NOTE Added to syntax file version 14 at 3.15.0 version of CMake # NOTE Added to syntax file version 14 at 3.15.0 version of CMake
@@ -1801,6 +1876,7 @@ environment-variables:
- CMAKE_MSVCIDE_RUN_PATH - CMAKE_MSVCIDE_RUN_PATH
- CMAKE_NO_VERBOSE - CMAKE_NO_VERBOSE
- CMAKE_OSX_ARCHITECTURES - CMAKE_OSX_ARCHITECTURES
- CMAKE_TOOLCHAIN_FILE # Since 3.21
- DESTDIR - DESTDIR
- LDFLAGS - LDFLAGS
- MACOSX_DEPLOYMENT_TARGET - MACOSX_DEPLOYMENT_TARGET
@@ -1812,6 +1888,7 @@ environment-variables:
- CC - CC
- CFLAGS - CFLAGS
- CSFLAGS - CSFLAGS
- CUDAARCHS # Since 3.20
- CUDACXX - CUDACXX
- CUDAFLAGS - CUDAFLAGS
- CUDAHOSTCXX - CUDAHOSTCXX
@@ -1896,6 +1973,55 @@ scripting-commands:
- -
name: cmake_parse_arguments name: cmake_parse_arguments
named-args: [PARSE_ARGV] named-args: [PARSE_ARGV]
-
name: cmake_path # Since 3.20
named-args: [
# Decomposition
GET
, ROOT_NAME
, ROOT_DIRECTORY
, ROOT_PATH
, FILENAME
, EXTENSION
, LAST_ONLY
, STEM
, RELATIVE_PART
, PARENT_PATH
# Query
, HAS_ROOT_NAME
, HAS_ROOT_DIRECTORY
, HAS_ROOT_PATH
, HAS_FILENAME
, HAS_EXTENSION
, HAS_STEM
, HAS_RELATIVE_PART
, HAS_PARENT_PATH
, IS_ABSOLUTE
, IS_RELATIVE
, IS_PREFIX
, NORMALIZE
# Modification
, SET
, APPEND
, OUTPUT_VARIABLE
, APPEND_STRING
, REMOVE_FILENAME
, REPLACE_FILENAME
, REMOVE_EXTENSION
, REPLACE_EXTENSION
# Generation
, NORMAL_PATH
, RELATIVE_PATH
, BASE_DIRECTORY
, ABSOLUTE_PATH
# Native Conversion
, NATIVE_PATH
, CONVERT
, TO_CMAKE_PATH_LIST
, TO_NATIVE_PATH_LIST
# Hashing
, HASH
]
- -
name: cmake_policy name: cmake_policy
named-args: [GET, SET, PUSH, POP, VERSION] named-args: [GET, SET, PUSH, POP, VERSION]
@@ -1908,6 +2034,8 @@ scripting-commands:
, NO_SOURCE_PERMISSIONS # Since 3.19 , NO_SOURCE_PERMISSIONS # Since 3.19
, "@ONLY" , "@ONLY"
, NEWLINE_STYLE , NEWLINE_STYLE
, USE_SOURCE_PERMISSIONS # Since 3.20
, FILE_PERMISSIONS # Since 3.20
] ]
special-args: [UNIX, DOS, WIN32, LF, CRLF] special-args: [UNIX, DOS, WIN32, LF, CRLF]
- -
@@ -2098,6 +2226,19 @@ scripting-commands:
, SIZE , SIZE
# New sub-options since 3.16 # New sub-options since 3.16
, GET_RUNTIME_DEPENDENCIES , GET_RUNTIME_DEPENDENCIES
, RESOLVED_DEPENDENCIES_VAR
, UNRESOLVED_DEPENDENCIES_VAR
, EXECUTABLES
, LIBRARIES
, MODULES
, DIRECTORIES
, BUNDLE_EXECUTABLE
, PRE_INCLUDE_REGEXES
, PRE_EXCLUDE_REGEXES
, POST_INCLUDE_REGEXES
, POST_EXCLUDE_REGEXES
, POST_INCLUDE_FILES # Since 3.21
, POST_EXCLUDE_FILES # Since 3.21
# New sub-options since 3.18 # New sub-options since 3.18
, ARCHIVE_CREATE , ARCHIVE_CREATE
, FILES , FILES
@@ -2112,10 +2253,17 @@ scripting-commands:
, ESCAPE_QUOTES , ESCAPE_QUOTES
, "@ONLY" , "@ONLY"
, NEWLINE_STYLE , NEWLINE_STYLE
, CHMOD # Since 3.19 # New sub-options since 3.19
, CHMOD_RECURSE # Since 3.19 , CHMOD
, REAL_PATH # Since 3.19 , CHMOD_RECURSE
, BASE_DIRECTORY # Since 3.19 , REAL_PATH
, BASE_DIRECTORY
# New sub-options since 3.21
, COPY_FILE
, RESULT
, ONLY_IF_DIFFERENT
, EXPAND_TILDE
, NO_REPLACE
] ]
special-args: [ special-args: [
UTF-8 UTF-8
@@ -2169,6 +2317,7 @@ scripting-commands:
, PATHS , PATHS
, PATH_SUFFIXES , PATH_SUFFIXES
, DOC , DOC
, NO_CACHE # Since 3.21
, REQUIRED # Since 3.18 , REQUIRED # Since 3.18
, NO_DEFAULT_PATH , NO_DEFAULT_PATH
, NO_PACKAGE_ROOT_PATH , NO_PACKAGE_ROOT_PATH
@@ -2189,6 +2338,7 @@ scripting-commands:
, PATHS , PATHS
, PATH_SUFFIXES , PATH_SUFFIXES
, DOC , DOC
, NO_CACHE # Since 3.21
, REQUIRED # Since 3.18 , REQUIRED # Since 3.18
, NO_DEFAULT_PATH , NO_DEFAULT_PATH
, NO_PACKAGE_ROOT_PATH , NO_PACKAGE_ROOT_PATH
@@ -2595,7 +2745,11 @@ project-commands:
name: aux_source_directory name: aux_source_directory
- -
name: build_command name: build_command
named-args: [CONFIGURATION, TARGET] named-args: [
CONFIGURATION
, PARALLEL_LEVEL # Since 3.21
, TARGET
]
- -
name: create_test_sourcelist name: create_test_sourcelist
named-args: [EXTRA_INCLUDE, FUNCTION] named-args: [EXTRA_INCLUDE, FUNCTION]
@@ -2615,6 +2769,7 @@ project-commands:
, CSharp , CSharp
, CXX , CXX
, CUDA , CUDA
, HIP # Since 3.21
, ISPC # Since 3.19 , ISPC # Since 3.19
, Java , Java
, OBJC # Since 3.16 , OBJC # Since 3.16
@@ -2664,6 +2819,7 @@ project-commands:
, EXCLUDE_FROM_ALL , EXCLUDE_FROM_ALL
, RENAME , RENAME
, OPTIONAL , OPTIONAL
, TYPE # Since 3.20
# Installing Targets # Installing Targets
, TARGETS , TARGETS
, EXPORT , EXPORT
@@ -2679,6 +2835,7 @@ project-commands:
, INCLUDES , INCLUDES
, NAMELINK_ONLY , NAMELINK_ONLY
, NAMELINK_SKIP , NAMELINK_SKIP
, RUNTIME_DEPENDENCIES # Since 3.21
# Installing Files # Installing Files
, FILES , FILES
, PROGRAMS , PROGRAMS
@@ -2700,6 +2857,17 @@ project-commands:
, FILE , FILE
, EXPORT_ANDROID_MK , EXPORT_ANDROID_MK
, EXPORT_LINK_INTERFACE_LIBRARIES , EXPORT_LINK_INTERFACE_LIBRARIES
# Installing Imported Runtime Artifacts (since 3.21)
, IMPORTED_RUNTIME_ARTIFACTS
, RUNTIME_DEPENDENCY_SET
# Installing Runtime Dependencies (since 3.21)
, PRE_INCLUDE_REGEXES
, PRE_EXCLUDE_REGEXES
, POST_INCLUDE_REGEXES
, POST_EXCLUDE_REGEXES
, POST_INCLUDE_FILES
, POST_EXCLUDE_FILES
, DIRECTORIES
] ]
special-args: &valid_permissions [ special-args: &valid_permissions [
OWNER_READ OWNER_READ
@@ -2740,6 +2908,7 @@ project-commands:
, CSharp , CSharp
, CXX , CXX
, CUDA , CUDA
, HIP # Since 3.21
, ISPC # Since 3.19 , ISPC # Since 3.19
, Java , Java
, OBJC # Since 3.16 , OBJC # Since 3.16
@@ -2787,6 +2956,7 @@ project-commands:
, cxx_std_14 , cxx_std_14
, cxx_std_17 , cxx_std_17
, cxx_std_20 # Since 3.12 , cxx_std_20 # Since 3.12
, cxx_std_23 # Since 3.20
, cxx_aggregate_default_initializers , cxx_aggregate_default_initializers
, cxx_alias_templates , cxx_alias_templates
, cxx_alignas , cxx_alignas
@@ -2848,6 +3018,8 @@ project-commands:
, c_std_90 , c_std_90
, c_std_99 , c_std_99
, c_std_11 , c_std_11
, c_std_17 # Since 3.21
, c_std_23 # Since 3.21
, c_function_prototypes , c_function_prototypes
, c_restrict , c_restrict
, c_static_assert , c_static_assert
@@ -2858,13 +3030,21 @@ project-commands:
, cuda_std_14 , cuda_std_14
, cuda_std_17 , cuda_std_17
, cuda_std_20 , cuda_std_20
, cuda_std_23 # Since 3.21
] ]
- -
name: target_compile_options name: target_compile_options
named-args: &target_compile_options [BEFORE, INTERFACE, PUBLIC, PRIVATE] named-args: &target_compile_options [BEFORE, INTERFACE, PUBLIC, PRIVATE]
- -
name: target_include_directories name: target_include_directories
named-args: [BEFORE, SYSTEM, INTERFACE, PUBLIC, PRIVATE] named-args: [
AFTER # Since 3.20
, BEFORE
, SYSTEM
, INTERFACE
, PUBLIC
, PRIVATE
]
- -
# Since 3.13 # Since 3.13
name: target_link_directories name: target_link_directories
@@ -2910,6 +3090,7 @@ project-commands:
, COMPILE_OUTPUT_VARIABLE , COMPILE_OUTPUT_VARIABLE
, RUN_OUTPUT_VARIABLE , RUN_OUTPUT_VARIABLE
, OUTPUT_VARIABLE , OUTPUT_VARIABLE
, WORKING_DIRECTORY # Since 3.20
, ARGS , ARGS
] ]

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env perl
# SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
# SPDX-License-Identifier: MIT
my $file = "";
open(my $input, '<:encoding(UTF-8)', $ARGV[0])
or die "Could not open file '$ARGV[0]': $!";
open(my $output, '>:encoding(UTF-8)', $ARGV[1])
or die "Could not open file '$ARGV[1]': $!";
while (<$input>)
{
$file .= $_;
}
$warning = "\n\n<!-- ***** THIS FILE WAS GENERATED BY A SCRIPT - DO NOT EDIT ***** -->\n";
$first_context = " <context attribute=\"Normal Text\" lineEndContext=\"#stay\" name=\"Normal\">
<RegExpr attribute=\"Comment\" context=\"LineComment\" String=\"--(?:!|(?:-(?=[^-]|\$)))\"/>
<RegExpr attribute=\"Region\" context=\"#stay\" String=\"--\\s*\@\\{\\s*\$\" beginRegion=\"MemberGroup\" />
<RegExpr attribute=\"Region\" context=\"#stay\" String=\"--\\s*\@\\}\\s*\$\" endRegion=\"MemberGroup\" />
</context>";
$file =~ s/\n\s*<context [^\n]*?(?:name="ML_|name="BlockComment").*?<\/context>//gs;
$file =~ s/\n\s*<context [^\n]*?name="Normal".*?<\/context>/\n$first_context/s;
$file =~ s/\n[^\n]*?(?: ml_word|LineContinue)[^\n]+//gs;
$file =~ s/\/\/\//---/gs;
$file =~ s/\/\/!/--!/gs;
$language = $file =~ s/.*?(<language[^>]+?>).*/$1/sr;
$language =~ s/ name="[^"]+/ name="DoxygenLua/s;
$language =~ s/ extensions="[^"]+/ extensions="/s;
$language =~ s/ mimetype="[^"]+/ mimetype="/s;
$language =~ s/ priority="[^"]+"//s;
$version = $language =~ s/.*? version="([^"]+).*/$1/sr;
$version = $version+2;
$language =~ s/ version="[^"]+/ version="$version/s;
$file =~ s/<language[^>]+?>/$warning\n$language/s;
print $output $file;
print $output $warning;

View File

@@ -45,6 +45,7 @@ if ($root == 1)
$file =~ s/<language([^>]+)section="[^"]*"/<language$1section="Scripts"/s; $file =~ s/<language([^>]+)section="[^"]*"/<language$1section="Scripts"/s;
$file =~ s/<language([^>]+)extensions="[^"]*"/<language$1extensions="*.php;*.php3;*.wml;*.phtml;*.phtm;*.inc;*.ctp"/s; $file =~ s/<language([^>]+)extensions="[^"]*"/<language$1extensions="*.php;*.php3;*.wml;*.phtml;*.phtm;*.inc;*.ctp"/s;
$file =~ s/<language([^>]+)mimetype="[^"]*"/<language$1mimetype="text\/x-php4-src;text\/x-php3-src;text\/vnd.wap.wml;application\/x-php"/s; $file =~ s/<language([^>]+)mimetype="[^"]*"/<language$1mimetype="text\/x-php4-src;text\/x-php3-src;text\/vnd.wap.wml;application\/x-php"/s;
$file =~ s/<language([^>]+)*/<language$1 indenter="cstyle"/s;
} }
else else
{ {

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Generate SPDX-Comments syntax file
#
# SPDX-FileCopyrightText: 2020 Alex Turbov <i.zaufi@gmail.com>
# SPDX-License-Identifier: MIT
#
# To install prerequisites:
#
# $ pip install --user click jinja2
#
# To use:
#
# $ ./generate-spdx-syntax.py > ../syntax/spdx-comments.xml
#
import json
import pathlib
import urllib.request
import click
import jinja2
def get_json(url):
with urllib.request.urlopen(url=url) as body:
return json.load(body)
@click.command()
@click.argument('template', type=click.File('r'), default='./spdx-comments.xml.tpl')
def cli(template):
data = {
'licenses': [
*filter(
lambda l: not l['licenseId'].endswith('+')
, get_json(url='https://spdx.org/licenses/licenses.json')['licenses']
)
]
, 'exceptions': [
*filter(
lambda l: not l['licenseExceptionId'].endswith('+')
, get_json(url='https://spdx.org/licenses/exceptions.json')['exceptions']
)
]
}
env = jinja2.Environment(
keep_trailing_newline=True
)
env.block_start_string = '<!--['
env.block_end_string = ']-->'
env.variable_start_string = '<!--{'
env.variable_end_string = '}-->'
env.comment_start_string = '<!--#'
env.comment_end_string = '#-->'
tpl = env.from_string(template.read())
result = tpl.render(data)
print(result.strip(), end=None)
if __name__ == '__main__':
cli()
# TODO Handle execptions and show errors

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<language
version="4"
kateversion="3.1"
name="SPDX-Comments"
section="Other"
extensions=""
mimetype=""
author="Alex Turbov (i.zaufi@gmail.com)"
license="MIT"
hidden="true"
>
<highlighting>
<list name="tags">
<item>SPDX-License-Identifier:</item>
<item>SPDX-FileContributor:</item>
<item>SPDX-FileCopyrightText:</item>
<item>SPDX-LicenseInfoInFile:</item>
</list>
<list name="operators">
<item>AND</item>
<item>OR</item>
<item>WITH</item>
</list>
<list name="licenses">
<!--[- for license in licenses if not license.isDeprecatedLicenseId ]-->
<item><!--{ license.licenseId }--></item>
<!--[- endfor ]-->
</list>
<list name="deprecated-licenses">
<!--[- for license in licenses if license.isDeprecatedLicenseId ]-->
<item><!--{ license.licenseId }--></item>
<!--[- endfor ]-->
</list>
<list name="exceptions">
<!--[- for exception in exceptions if not exception.isDeprecatedLicenseId ]-->
<item><!--{ exception.licenseExceptionId }--></item>
<!--[- endfor ]-->
</list>
<list name="deprecated-exceptions">
<!--[- for exception in exceptions if exception.isDeprecatedLicenseId ]-->
<item><!--{ exception.licenseExceptionId }--></item>
<!--[- endfor ]-->
</list>
<contexts>
<context name="Normal" attribute="SPDX Tag" lineEndContext="#pop">
<WordDetect String="SPDX-License-Identifier:" attribute="SPDX Tag" context="license-expression" />
<keyword String="tags" attribute="SPDX Tag" />
</context>
<context name="license-expression" attribute="SPDX Value" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<DetectSpaces/>
<DetectChar char="(" context="#stay" attribute="SPDX License Expression Operator" />
<DetectChar char=")" context="#stay" attribute="SPDX License Expression Operator" />
<DetectChar char="+" context="#stay" attribute="SPDX License Expression Operator" />
<keyword String="licenses" context="#stay" attribute="SPDX License" />
<keyword String="deprecated-licenses" context="#stay" attribute="SPDX Deprecated License" />
<keyword String="exceptions" context="#stay" attribute="SPDX License Exception" />
<keyword String="deprecated-exceptions" context="#stay" attribute="SPDX Deprecated License Exception" />
<keyword String="operators" context="#stay" attribute="SPDX License Expression Operator" />
<RegExpr attribute="SPDX License" context="#stay" String="\bLicenseRef-[^\s]+" />
</context>
</contexts>
<itemDatas>
<itemData name="SPDX Tag" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX Value" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX License" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX License Exception" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX Deprecated License" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX Deprecated License Exception" defStyleNum="dsAnnotation" italic="true" spellChecking="false" />
<itemData name="SPDX License Expression Operator" defStyleNum="dsOperator" italic="true" spellChecking="false" />
</itemDatas>
</highlighting>
<general>
<keywords casesensitive="1" weakDeliminator=":-." />
</general>
</language>
<!-- kate: indent-width 2; -->

View File

@@ -5,7 +5,7 @@
<!ENTITY funcname "([^&_fragpathseps;}=#$]|[+!@](?!\())([^&_fragpathseps;}=$]*+([+!@](?!\())?+)*+"> <!ENTITY funcname "([^&_fragpathseps;}=#$]|[+!@](?!\())([^&_fragpathseps;}=$]*+([+!@](?!\())?+)*+">
<!ENTITY varname "[A-Za-z_][A-Za-z0-9_]*"> <!ENTITY varname "[A-Za-z_][A-Za-z0-9_]*">
<!ENTITY eos "(?=$|[ &tab;])"> <!-- eol or space following --> <!ENTITY eos "(?=$|[ &tab;])"> <!-- eol or space following -->
<!ENTITY eoexpr "(?=$|[ &tab;&lt;>|&amp;;])"> <!ENTITY eoexpr "(?=$|[ &tab;&lt;>|&amp;;)])">
<!ENTITY substseps "${'&quot;`\\"> <!ENTITY substseps "${'&quot;`\\">
<!ENTITY symbolseps "&lt;>|&amp;;()"> <!-- see man bash --> <!ENTITY symbolseps "&lt;>|&amp;;()"> <!-- see man bash -->
@@ -18,6 +18,13 @@
<!ENTITY opt "(?:[^&_fragpathseps;=/]*+&_fragpathnosep;)*+"> <!ENTITY opt "(?:[^&_fragpathseps;=/]*+&_fragpathnosep;)*+">
<!ENTITY pathpart "(?:~|\.\.?|&fragpath;)(?:/&path;|(?=[*?]|[+!@]\(|&fragpath;(?:[/*?]|[+!@]\()))|(?:~|\.\.?)(?=[&wordseps;]|$)"> <!ENTITY pathpart "(?:~|\.\.?|&fragpath;)(?:/&path;|(?=[*?]|[+!@]\(|&fragpath;(?:[/*?]|[+!@]\()))|(?:~|\.\.?)(?=[&wordseps;]|$)">
<!ENTITY _fragpathseps_alt "*?+!@&substseps;}">
<!ENTITY _fragpathnosep_alt "(?:[+!@](?!\()|\\.)?+">
<!ENTITY path_alt "(?:[^&_fragpathseps_alt;]*+&_fragpathnosep_alt;)*+">
<!ENTITY fragpath_alt "(?:[^&_fragpathseps_alt;/]*+&_fragpathnosep_alt;)*+">
<!ENTITY opt_alt "(?:[^&_fragpathseps_alt;=/]*+&_fragpathnosep_alt;)*+">
<!ENTITY pathpart_alt "(?:~|\.\.?|&fragpath_alt;)(?:/&path_alt;|(?=[*?]|[+!@]\(|&fragpath_alt;(?:[/*?]|[+!@]\()))|(?:~|\.\.?)(?=\}|$)">
<!ENTITY _braceexpansion_spe " &tab;&lt;>|&amp;;{}\\`'&quot;$"> <!ENTITY _braceexpansion_spe " &tab;&lt;>|&amp;;{}\\`'&quot;$">
<!ENTITY _brace_noexpansion "\{[^&_braceexpansion_spe;,]*+\}"> <!ENTITY _brace_noexpansion "\{[^&_braceexpansion_spe;,]*+\}">
<!ENTITY _braceexpansion_var "\$(?:\{[^\[\]&_braceexpansion_spe;]*+(?:\[[*@a-zA-Z0-9]\])\})?"> <!ENTITY _braceexpansion_var "\$(?:\{[^\[\]&_braceexpansion_spe;]*+(?:\[[*@a-zA-Z0-9]\])\})?">
@@ -28,9 +35,11 @@
<!ENTITY braceexpansion "{&_braceexpansion;"> <!ENTITY braceexpansion "{&_braceexpansion;">
<!ENTITY heredocq "(?|&quot;([^&quot;]+)&quot;|'([^']+)'|\\(.[^&wordseps;&substseps;]*))"> <!ENTITY heredocq "(?|&quot;([^&quot;]+)&quot;|'([^']+)'|\\(.[^&wordseps;&substseps;]*))">
<!ENTITY arithmetic_as_subshell "\(((?:[^`'&quot;()$]++|\$\{[^`'&quot;(){}$]+\}|\$(?=[^{`'&quot;()])|`[^`]*+`|\((?1)(?:[)]|(?=['&quot;])))++)(?:[)](?=$|[^)])|[&quot;'])">
]> ]>
<language name="Bash" version="27" kateversion="5.79" section="Scripts" extensions="*.sh;*.bash;*.ebuild;*.eclass;*.nix;.bashrc;.bash_profile;.bash_login;.profile;PKGBUILD;APKBUILD" mimetype="application/x-shellscript" casesensitive="1" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL"> <language name="Bash" version="30" kateversion="5.79" section="Scripts" extensions="*.sh;*.bash;*.ebuild;*.eclass;*.nix;.bashrc;.bash_profile;.bash_login;.profile;PKGBUILD;APKBUILD" mimetype="application/x-shellscript" casesensitive="1" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL">
<!-- (c) 2004 by Wilbert Berendsen (wilbert@kde.nl) <!-- (c) 2004 by Wilbert Berendsen (wilbert@kde.nl)
Changes by Matthew Woehlke (mw_triad@users.sourceforge.net) Changes by Matthew Woehlke (mw_triad@users.sourceforge.net)
@@ -40,6 +49,7 @@
<highlighting> <highlighting>
<list name="keywords"> <list name="keywords">
<item>break</item>
<item>case</item> <item>case</item>
<item>continue</item> <item>continue</item>
<item>do</item> <item>do</item>
@@ -66,7 +76,6 @@
<item>alias</item> <item>alias</item>
<item>bg</item> <item>bg</item>
<item>bind</item> <item>bind</item>
<item>break</item>
<item>builtin</item> <item>builtin</item>
<item>cd</item> <item>cd</item>
<item>caller</item> <item>caller</item>
@@ -458,7 +467,7 @@
<DetectSpaces attribute="Normal Text" context="#stay"/> <DetectSpaces attribute="Normal Text" context="#stay"/>
<DetectChar attribute="Comment" context="Comment" char="#"/> <DetectChar attribute="Comment" context="Comment" char="#"/>
<!-- start expression in double parentheses --> <!-- start expression in double parentheses -->
<Detect2Chars attribute="Keyword" context="ExprDblParen" char="(" char1="(" beginRegion="expression"/> <Detect2Chars context="ExprDblParenOrSubShell" char="(" char1="(" lookAhead="1"/>
<!-- start a subshell --> <!-- start a subshell -->
<DetectChar attribute="Keyword" context="SubShell" char="(" beginRegion="subshell"/> <DetectChar attribute="Keyword" context="SubShell" char="(" beginRegion="subshell"/>
<!-- start expression in single/double brackets --> <!-- start expression in single/double brackets -->
@@ -554,8 +563,8 @@
</context> </context>
<context attribute="Command" lineEndContext="#pop#pop" name="DispatchSubstVariables"> <context attribute="Command" lineEndContext="#pop#pop" name="DispatchSubstVariables">
<Detect2Chars attribute="Parameter Expansion" context="#pop!VarBraceStart" char="$" char1="{"/> <Detect2Chars attribute="Parameter Expansion" context="#pop!VarBraceStart" char="$" char1="{"/>
<StringDetect attribute="Parameter Expansion" context="#pop!ExprDblParenSubst" String="$((" beginRegion="expression"/> <StringDetect context="#pop!ExprDblParenSubstOrSubstCommand" String="$((" lookAhead="1"/>
<Detect2Chars attribute="Parameter Expansion" context="#pop!SubstCommand" char="$" char1="("/> <Detect2Chars attribute="Parameter Expansion" context="#pop!SubstCommand" char="$" char1="(" beginRegion="subshell"/>
</context> </context>
<context attribute="Command" lineEndContext="#pop#pop" name="DispatchStringVariables"> <context attribute="Command" lineEndContext="#pop#pop" name="DispatchStringVariables">
<Detect2Chars attribute="String SingleQ" context="#pop!StringEsc" char="$" char1="'"/> <Detect2Chars attribute="String SingleQ" context="#pop!StringEsc" char="$" char1="'"/>
@@ -695,27 +704,30 @@
</context> </context>
<context attribute="Path" lineEndContext="#stay" name="ExtGlobAndPop"> <context attribute="Path" lineEndContext="#stay" name="ExtGlobAndPop">
<DetectChar attribute="Glob" context="#pop!PathThenPop" char=")"/> <DetectChar attribute="Glob" context="#pop!PathThenPop" char=")"/>
<IncludeRules context="FindWord"/>
<IncludeRules context="IncExtGlob"/> <IncludeRules context="IncExtGlob"/>
</context> </context>
<context attribute="Path" lineEndContext="#stay" name="RecursiveExtGlob"> <context attribute="Path" lineEndContext="#stay" name="FindExtGlob">
<DetectChar attribute="Glob" context="#pop" char=")"/>
<IncludeRules context="IncExtGlob"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="IncExtGlob">
<Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="?" char1="("/> <Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="?" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="*" char1="("/> <Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="*" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="+" char1="("/> <Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="+" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="@" char1="("/> <Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="@" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="!" char1="("/> <Detect2Chars attribute="Glob" context="RecursiveExtGlob" char="!" char1="("/>
<AnyChar attribute="Glob" context="#stay" String="|?*"/> <AnyChar attribute="Glob" context="#stay" String="|?*"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="RecursiveExtGlob">
<DetectChar attribute="Glob" context="#pop" char=")"/>
<IncludeRules context="FindWord"/> <IncludeRules context="FindWord"/>
<IncludeRules context="IncExtGlob"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="IncExtGlob">
<IncludeRules context="FindExtGlob"/>
<DetectChar context="PathMaybeBraceExpansion" char="{" lookAhead="1"/> <DetectChar context="PathMaybeBraceExpansion" char="{" lookAhead="1"/>
</context> </context>
<context attribute="Path" lineEndContext="#pop#pop" name="PathThenPop"> <context attribute="Path" lineEndContext="#pop#pop" name="PathThenPop">
<AnyChar context="#pop#pop" String="&wordseps;`" lookAhead="1"/> <AnyChar context="#pop#pop" String="&wordseps;`" lookAhead="1"/>
<IncludeRules context="FindWord"/> <IncludeRules context="FindWord"/>
<IncludeRules context="FindExtGlobAndPop"/> <IncludeRules context="FindExtGlob"/>
<AnyChar attribute="Glob" context="#stay" String="?*"/>
<DetectChar context="PathMaybeBraceExpansion" char="{" lookAhead="1"/> <DetectChar context="PathMaybeBraceExpansion" char="{" lookAhead="1"/>
<RegExpr attribute="Path" context="#stay" String="&path;"/> <RegExpr attribute="Path" context="#stay" String="&path;"/>
</context> </context>
@@ -724,6 +736,47 @@
<DetectChar attribute="Path" context="#pop" char="{"/> <DetectChar attribute="Path" context="#pop" char="{"/>
</context> </context>
<!-- FindPathThenPopInAlternateValue consumes path in ${xx:here}-->
<context attribute="Normal Text" lineEndContext="#pop" name="FindPathThenPopInAlternateValue">
<IncludeRules context="FindExtGlobAndPopInAlternateValue"/>
<AnyChar attribute="Glob" context="PathThenPopInAlternateValue" String="?*"/>
<RegExpr attribute="Path" context="PathThenPopInAlternateValue" String="&pathpart_alt;"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="FindExtGlobAndPopInAlternateValue">
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="?" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="*" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="+" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="@" char1="("/>
<Detect2Chars attribute="Glob" context="ExtGlobAndPopInAlternateValue" char="!" char1="("/>
</context>
<context attribute="Path" lineEndContext="#stay" name="FindExtGlobInAlternateValue">
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="?" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="*" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="+" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="@" char1="("/>
<Detect2Chars attribute="Glob" context="RecursiveExtGlobInAlternateValue" char="!" char1="("/>
<AnyChar attribute="Glob" context="#stay" String="|?*"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="RecursiveExtGlobInAlternateValue">
<DetectChar attribute="Glob" context="#pop" char=")"/>
<DetectChar context="#pop" char="}" lookAhead="1"/>
<IncludeRules context="FindWord"/>
<IncludeRules context="FindExtGlobInAlternateValue"/>
</context>
<context attribute="Path" lineEndContext="#stay" name="ExtGlobAndPopInAlternateValue">
<DetectChar attribute="Glob" context="#pop!PathThenPopInAlternateValue" char=")"/>
<DetectChar attribute="Error" context="#pop#pop" char="}"/>
<IncludeRules context="FindWord"/>
<IncludeRules context="FindExtGlobInAlternateValue"/>
</context>
<context attribute="Path" lineEndContext="#pop#pop" name="PathThenPopInAlternateValue">
<DetectChar attribute="Parameter Expansion" context="#pop#pop" char="}"/>
<IncludeRules context="FindWord"/>
<IncludeRules context="FindExtGlobAndPopInAlternateValue"/>
<AnyChar attribute="Glob" context="#stay" String="?*"/>
<RegExpr attribute="Path" context="#stay" String="&path_alt;"/>
</context>
<context attribute="Pattern" lineEndContext="#stay" name="FindPattern"> <context attribute="Pattern" lineEndContext="#stay" name="FindPattern">
<Detect2Chars attribute="Glob" context="ExtPattern" char="?" char1="("/> <Detect2Chars attribute="Glob" context="ExtPattern" char="?" char1="("/>
<Detect2Chars attribute="Glob" context="ExtPattern" char="*" char1="("/> <Detect2Chars attribute="Glob" context="ExtPattern" char="*" char1="("/>
@@ -1038,7 +1091,7 @@
<!-- SubstCommand is called after a $( is encountered --> <!-- SubstCommand is called after a $( is encountered -->
<context attribute="Normal Text" lineEndContext="#stay" name="SubstCommand" fallthroughContext="Command"> <context attribute="Normal Text" lineEndContext="#stay" name="SubstCommand" fallthroughContext="Command">
<DetectChar attribute="Parameter Expansion" context="#pop" char=")"/> <DetectChar attribute="Parameter Expansion" context="#pop" char=")" endRegion="subshell"/>
<IncludeRules context="Start"/> <IncludeRules context="Start"/>
</context> </context>
@@ -1084,7 +1137,7 @@
<Detect2Chars attribute="Parameter Expansion Operator" context="#pop!AlternatePatternValue" char="," char1=","/> <Detect2Chars attribute="Parameter Expansion Operator" context="#pop!AlternatePatternValue" char="," char1=","/>
<DetectChar attribute="Parameter Expansion Operator" context="#pop!VarSub" char=":"/> <DetectChar attribute="Parameter Expansion Operator" context="#pop!VarSub" char=":"/>
<DetectChar attribute="Parameter Expansion Operator" context="#pop!VarSubst" char="/"/> <DetectChar attribute="Parameter Expansion Operator" context="#pop!VarSubst" char="/"/>
<AnyChar attribute="Parameter Expansion Operator" context="#pop!AlternateValue" String="%#"/> <AnyChar attribute="Parameter Expansion Operator" context="#pop!AlternateValue" String="-+=?#%"/>
<AnyChar attribute="Parameter Expansion Operator" context="#pop!AlternatePatternValue" String="^,"/> <AnyChar attribute="Parameter Expansion Operator" context="#pop!AlternatePatternValue" String="^,"/>
<DetectChar attribute="Parameter Expansion Operator" context="#pop!VarTransformation" char="@"/> <DetectChar attribute="Parameter Expansion Operator" context="#pop!VarTransformation" char="@"/>
</context> </context>
@@ -1109,7 +1162,7 @@
<context attribute="Normal Text" lineEndContext="#stay" name="AlternateValue"> <context attribute="Normal Text" lineEndContext="#stay" name="AlternateValue">
<DetectChar attribute="Parameter Expansion" context="#pop" char="}"/> <DetectChar attribute="Parameter Expansion" context="#pop" char="}"/>
<IncludeRules context="FindWord"/> <IncludeRules context="FindWord"/>
<IncludeRules context="FindPattern"/> <IncludeRules context="FindPathThenPopInAlternateValue"/>
</context> </context>
<!-- called as soon as ${xxx^ are ${xxx, are encoutered --> <!-- called as soon as ${xxx^ are ${xxx, are encoutered -->
@@ -1125,7 +1178,7 @@
</context> </context>
<context attribute="Pattern" lineEndContext="#stay" name="VarSubstPat"> <context attribute="Pattern" lineEndContext="#stay" name="VarSubstPat">
<DetectChar attribute="Parameter Expansion Operator" context="#pop!AlternateValue" char="/"/> <DetectChar attribute="Parameter Expansion Operator" context="#pop!AlternateValue" char="/"/>
<IncludeRules context="AlternateValue"/> <IncludeRules context="AlternatePatternValue"/>
</context> </context>
<!-- called as soon as ${xxx@ is encoutered --> <!-- called as soon as ${xxx@ is encoutered -->
@@ -1164,19 +1217,26 @@
<!-- ====== These are the contexts that can be branched to ======= --> <!-- ====== These are the contexts that can be branched to ======= -->
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParenOrSubShell">
<RegExpr attribute="Keyword" context="#pop!SubShell" String="\((?=&arithmetic_as_subshell;)|" beginRegion="subshell"/>
<Detect2Chars attribute="Keyword" context="#pop!ExprDblParen" char="(" char1="(" beginRegion="expression"/>
</context>
<!-- ExprDblParen consumes an expression started in command mode till )) --> <!-- ExprDblParen consumes an expression started in command mode till )) -->
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParen"> <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParen">
<DetectSpaces attribute="Normal Text" context="#stay"/> <DetectSpaces attribute="Normal Text" context="#stay"/>
<Detect2Chars attribute="Keyword" context="#pop" char=")" char1=")" endRegion="expression"/> <Detect2Chars attribute="Keyword" context="#pop" char=")" char1=")" endRegion="expression"/>
<IncludeRules context="FindExprDblParen"/> <IncludeRules context="FindExprDblParen"/>
<!-- ((cmd
) # jump to SubShell context -->
<DetectChar attribute="Keyword" context="#pop!SubShell" char=")" endRegion="expression" beginRegion="subshell"/>
</context> </context>
<context attribute="Normal Text" lineEndContext="#stay" name="FindExprDblParen"> <context attribute="Normal Text" lineEndContext="#stay" name="FindExprDblParen">
<Detect2Chars attribute="Control" context="#stay" char="&amp;" char1="&amp;"/> <Detect2Chars attribute="Control" context="#stay" char="&amp;" char1="&amp;"/>
<Detect2Chars attribute="Control" context="#stay" char="|" char1="|"/> <Detect2Chars attribute="Control" context="#stay" char="|" char1="|"/>
<AnyChar attribute="Operator" context="#stay" String="+-!~*/%&lt;>=&amp;^|?:"/> <AnyChar attribute="Operator" context="#stay" String="+-!~*/%&lt;>=&amp;^|?:"/>
<AnyChar context="Number" String="0123456789" lookAhead="1"/>
<DetectChar attribute="Control" context="#stay" char=","/> <DetectChar attribute="Control" context="#stay" char=","/>
<DetectChar attribute="Normal Text" context="ExprSubDblParen" char="("/> <DetectChar attribute="Normal Text" context="ExprSubDblParen" char="("/>
<AnyChar context="Number" String="0123456789" lookAhead="1"/>
<DetectChar attribute="Parameter Expansion Operator" context="Subscript" char="["/> <DetectChar attribute="Parameter Expansion Operator" context="Subscript" char="["/>
<IncludeRules context="FindWord"/> <IncludeRules context="FindWord"/>
<DetectChar attribute="Error" context="#stay" char="#"/> <DetectChar attribute="Error" context="#stay" char="#"/>
@@ -1184,8 +1244,9 @@
<DetectIdentifier attribute="Variable" context="#stay"/> <DetectIdentifier attribute="Variable" context="#stay"/>
</context> </context>
<context attribute="Normal Text" lineEndContext="#stay" name="ExprSubDblParen"> <context attribute="Normal Text" lineEndContext="#stay" name="ExprSubDblParen">
<DetectSpaces attribute="Normal Text" context="#stay"/>
<DetectChar attribute="Normal Text" context="#pop" char=")"/> <DetectChar attribute="Normal Text" context="#pop" char=")"/>
<IncludeRules context="ExprDblParen"/> <IncludeRules context="FindExprDblParen"/>
</context> </context>
<context attribute="Normal Text" lineEndContext="#pop" name="MaybeArithmeticBrace"> <context attribute="Normal Text" lineEndContext="#pop" name="MaybeArithmeticBrace">
<IncludeRules context="DispatchBraceExpansion"/> <IncludeRules context="DispatchBraceExpansion"/>
@@ -1216,11 +1277,18 @@
<AnyChar attribute="Error" context="#stay" String="8901234567"/> <AnyChar attribute="Error" context="#stay" String="8901234567"/>
</context> </context>
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParenSubstOrSubstCommand">
<RegExpr attribute="Parameter Expansion" context="#pop!SubstCommand" String="\$\((?=&arithmetic_as_subshell;)|" beginRegion="subshell"/>
<StringDetect attribute="Parameter Expansion" context="#pop!ExprDblParenSubst" String="$((" beginRegion="expression"/>
</context>
<!-- ExprDblParenSubst like ExprDblParen but matches )) as Variable --> <!-- ExprDblParenSubst like ExprDblParen but matches )) as Variable -->
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParenSubst"> <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblParenSubst">
<DetectSpaces attribute="Normal Text" context="#stay"/> <DetectSpaces attribute="Normal Text" context="#stay"/>
<Detect2Chars attribute="Variable" context="#pop" char=")" char1=")" endRegion="expression"/> <Detect2Chars attribute="Variable" context="#pop" char=")" char1=")" endRegion="expression"/>
<IncludeRules context="FindExprDblParen"/> <IncludeRules context="FindExprDblParen"/>
<!-- $((cmd
) # jump to SubstCommand context -->
<DetectChar attribute="Parameter Expansion" context="#pop!SubstCommand" char=")" endRegion="expression" beginRegion="subshell"/>
</context> </context>
<!-- ExprBracket consumes an expression till ] --> <!-- ExprBracket consumes an expression till ] -->
@@ -1305,7 +1373,7 @@
</context> </context>
<context attribute="Normal Text" lineEndContext="#pop" name="ExprDblBracketValue"> <context attribute="Normal Text" lineEndContext="#pop" name="ExprDblBracketValue">
<Detect2Chars attribute="Keyword" context="ExprDblParen" char="(" char1="(" beginRegion="expression"/> <Detect2Chars context="ExprDblBracketDblParentOrSubValue" char="(" char1="(" lookAhead="1"/>
<DetectChar context="ExprDblBracketSubValue" char="(" lookAhead="1"/> <DetectChar context="ExprDblBracketSubValue" char="(" lookAhead="1"/>
<DetectChar attribute="Operator" context="#pop#pop" char=")"/> <DetectChar attribute="Operator" context="#pop#pop" char=")"/>
<Detect2Chars attribute="Control" context="#pop#pop!ExprDblBracket" char="&amp;" char1="&amp;"/> <Detect2Chars attribute="Control" context="#pop#pop!ExprDblBracket" char="&amp;" char1="&amp;"/>
@@ -1321,6 +1389,18 @@
<DetectChar attribute="Operator" context="ExprDblBracketNot" char="("/> <DetectChar attribute="Operator" context="ExprDblBracketNot" char="("/>
<Detect2Chars context="#pop#pop" char="]" char1="]" lookAhead="1"/> <Detect2Chars context="#pop#pop" char="]" char1="]" lookAhead="1"/>
</context> </context>
<context attribute="Normal Text" lineEndContext="#pop" name="ExprDblBracketDblParentOrSubValue">
<RegExpr context="#pop!ExprDblBracketSubValue" String="\((?=&arithmetic_as_subshell;)|" lookAhead="1"/>
<Detect2Chars attribute="Keyword" context="#pop!ExprDblBracketExprDblParen" char="(" char1="(" beginRegion="expression"/>
</context>
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketExprDblParen">
<DetectSpaces attribute="Normal Text" context="#stay"/>
<Detect2Chars attribute="Keyword" context="#pop" char=")" char1=")" endRegion="expression"/>
<IncludeRules context="FindExprDblParen"/>
<!-- ((cmd
) # jump to ExprDblBracketValue context -->
<DetectChar attribute="Operator" context="ExprDblBracketValue" char=")" endRegion="expression" beginRegion="subshell"/>
</context>
<context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketParam2" fallthroughContext="ExprDblBracketValue"> <context attribute="Normal Text" lineEndContext="#stay" name="ExprDblBracketParam2" fallthroughContext="ExprDblBracketValue">
<DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketParam3"/> <DetectSpaces attribute="Normal Text" context="#pop!ExprDblBracketParam3"/>

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd" <!DOCTYPE language SYSTEM "language.dtd"
[ [
<!ENTITY wordsep "(?:[][,?;()]|\.$|\.?\s)"> <!-- things that end a TagWord --> <!ENTITY wordsep "(?:[][,?;()]|\.$|\.?\s|$)"> <!-- things that end a TagWord -->
<!ENTITY sl_word ".*?(?=&wordsep;)"> <!ENTITY sl_word ".*?(?=&wordsep;)">
<!ENTITY ml_word ".*?(?=&wordsep;|\*/)"> <!ENTITY ml_word ".*?(?=&wordsep;|\*/)">
]> ]>
<language name="Doxygen" <language name="Doxygen"
version="13" version="14"
kateversion="5.0" kateversion="5.0"
section="Markup" section="Markup"
extensions="*.dox;*.doxygen" extensions="*.dox;*.doxygen"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd"> <!DOCTYPE language SYSTEM "language.dtd">
<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc" mimetype="" version="8" kateversion="5.0" author="Jan Janssen (medhefgo@web.de)" license="LGPL"> <language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc" mimetype="" version="10" kateversion="5.0" author="Jan Janssen (medhefgo@web.de)" license="LGPL">
<highlighting> <highlighting>
<list name="keywords"> <list name="keywords">
@@ -37,12 +37,23 @@
<RangeDetect attribute="Section" context="#stay" char="[" char1="]" beginRegion="Section" endRegion="Section" /> <RangeDetect attribute="Section" context="#stay" char="[" char1="]" beginRegion="Section" endRegion="Section" />
<DetectChar attribute="Assignment" context="Value" char="=" /> <DetectChar attribute="Assignment" context="Value" char="=" />
<AnyChar String=";#" attribute="Comment" context="Comment" firstNonSpace="true" /> <AnyChar String=";#" attribute="Comment" context="Comment" firstNonSpace="true" />
<DetectIdentifier />
<DetectSpaces />
</context> </context>
<context name="Value" attribute="Value" lineEndContext="#pop" > <context name="Value" attribute="Value" lineEndContext="#pop" fallthrough="1" fallthroughContext="#pop!NormalValue">
<RegExpr context="#pop!SpecialValue" String="\s*((-?(\d+(\.\d*)?|\.d+)(e\d+)?|On|Off|Defaults?|Localhost|Null|True|False|Yes|No|Normal)\s*$|~?(E_ALL|E_ERROR|E_WARNING|E_PARSE|E_NOTICE|E_STRICT|E_CORE_ERROR|E_CORE_WARNING|E_COMPILE_ERROR|E_COMPILE_WARNING|E_USER_ERROR|E_USER_WARNING|E_USER_NOTICE)\b)" lookAhead="1" insensitive="1"/>
</context>
<context name="SpecialValue" attribute="Value" lineEndContext="#pop">
<Float attribute="Float" /> <Float attribute="Float" />
<Int attribute="Int" /> <Int attribute="Int" />
<keyword attribute="Keyword" String="keywords"/> <keyword attribute="Keyword" String="keywords"/>
<DetectChar attribute="Int" char="-" />
<DetectSpaces />
</context>
<context name="NormalValue" attribute="Value" lineEndContext="#pop">
</context> </context>
<context name="Comment" attribute="Comment" lineEndContext="#pop"> <context name="Comment" attribute="Comment" lineEndContext="#pop">

View File

@@ -7,7 +7,7 @@
<!ENTITY float "(\b&int;(\.((&int;&exp;?+|&exp;)[fFdD]?\b|[fFdD]\b)?|&exp;[fFdD]?\b|[fFdD]\b)|\.&int;&exp;?[fFdD]?\b)"> <!ENTITY float "(\b&int;(\.((&int;&exp;?+|&exp;)[fFdD]?\b|[fFdD]\b)?|&exp;[fFdD]?\b|[fFdD]\b)|\.&int;&exp;?[fFdD]?\b)">
<!ENTITY hexfloat "\b0[xX](&hex;\.?+&hex;?+|\.&hex;?)[pP][-+]?&int;[fFdD]?\b"> <!ENTITY hexfloat "\b0[xX](&hex;\.?+&hex;?+|\.&hex;?)[pP][-+]?&int;[fFdD]?\b">
]> ]>
<language name="Java" version="9" kateversion="5.62" section="Sources" extensions="*.java" mimetype="text/x-java" license="LGPL" author="Alfredo Luiz Foltran Fialho (alfoltran@ig.com.br)"> <language name="Java" version="10" kateversion="5.62" section="Sources" extensions="*.java" mimetype="text/x-java" license="LGPL" author="Alfredo Luiz Foltran Fialho (alfoltran@ig.com.br)">
<highlighting> <highlighting>
<list name="java15"> <list name="java15">
<item>ACTIVE</item> <item>ACTIVE</item>
@@ -3732,6 +3732,7 @@
<item>volatile</item> <item>volatile</item>
</list> </list>
<list name="control flow"> <list name="control flow">
<item>assert</item>
<item>break</item> <item>break</item>
<item>case</item> <item>case</item>
<item>catch</item> <item>catch</item>
@@ -3760,6 +3761,7 @@
<item>long</item> <item>long</item>
<item>short</item> <item>short</item>
<item>static</item> <item>static</item>
<item>var</item>
<item>void</item> <item>void</item>
</list> </list>
<contexts> <contexts>

View File

@@ -90,7 +90,7 @@
<!ENTITY checkbox "\[[ x]\](?=\s)"> <!ENTITY checkbox "\[[ x]\](?=\s)">
]> ]>
<language name="Markdown" version="17" kateversion="5.79" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD"> <language name="Markdown" version="19" kateversion="5.79" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD">
<highlighting> <highlighting>
<contexts> <contexts>
<!-- Start of the Markdown document: find metadata or code block --> <!-- Start of the Markdown document: find metadata or code block -->
@@ -149,14 +149,33 @@
</context> </context>
<context name="find-header" attribute="Normal Text" lineEndContext="#pop"> <context name="find-header" attribute="Normal Text" lineEndContext="#pop">
<RegExpr attribute="Header H1" context="#pop" String="^#\s.*[#]?$" column="0"/> <!-- TODO: Replace "(?=.$)" in the regexes with just "$" when close-H#-region are removed -->
<RegExpr attribute="Header H2" context="#pop" String="^##\s.*[#]?$" column="0"/> <RegExpr attribute="Header H1" context="#pop!close-H2-region" String="^#\s.*[#]?(?=.$)" column="0" endRegion="H1" beginRegion="H1"/>
<RegExpr attribute="Header H3" context="#pop" String="^###\s.*[#]?$" column="0"/> <RegExpr attribute="Header H2" context="#pop!close-H3-region" String="^##\s.*[#]?(?=.$)" column="0" endRegion="H2" beginRegion="H2"/>
<RegExpr attribute="Header H4" context="#pop" String="^####\s.*[#]?$" column="0"/> <RegExpr attribute="Header H3" context="#pop!close-H4-region" String="^###\s.*[#]?(?=.$)" column="0" endRegion="H3" beginRegion="H3"/>
<RegExpr attribute="Header H5" context="#pop" String="^#####\s.*[#]?$" column="0"/> <RegExpr attribute="Header H4" context="#pop!close-H5-region" String="^####\s.*[#]?(?=.$)" column="0" endRegion="H4" beginRegion="H4"/>
<RegExpr attribute="Header H6" context="#pop" String="^######\s.*[#]?$" column="0"/> <RegExpr attribute="Header H5" context="#pop!close-H6-region" String="^#####\s.*[#]?(?=.$)" column="0" endRegion="H5" beginRegion="H5"/>
<RegExpr attribute="Header H6" context="#pop" String="^######\s.*[#]?$" column="0" endRegion="H6" beginRegion="H6"/>
<DetectChar attribute="Normal Text" context="#pop" char="#"/> <DetectChar attribute="Normal Text" context="#pop" char="#"/>
</context> </context>
<!-- BUG: 441278 sub-headers should be closed when their parent header is closed (e.g. in h1 h2 h3 h1, h1-h3 should all be closed at the 2nd h1) -->
<!-- TODO: Port to a less hacky version (maybe a new attribute for declaring multiple endRegions) -->
<context name="close-H2-region" attribute="Header H2" lineEndContext="#pop!close-H3-region" fallthroughContext="#pop!close-H3-region">
<RegExpr attribute="Header H2" context="#pop!close-H3-region" String="." lookAhead="true" endRegion="H2"/>
</context>
<context name="close-H3-region" attribute="Header H3" lineEndContext="#pop!close-H4-region" fallthroughContext="#pop!close-H4-region">
<RegExpr attribute="Header H3" context="#pop!close-H4-region" String="." lookAhead="true" endRegion="H3"/>
</context>
<context name="close-H4-region" attribute="Header H4" lineEndContext="#pop!close-H5-region" fallthroughContext="#pop!close-H5-region">
<RegExpr attribute="Header H4" context="#pop!close-H5-region" String="." lookAhead="true" endRegion="H4"/>
</context>
<context name="close-H5-region" attribute="Header H5" lineEndContext="#pop!close-H6-region" fallthroughContext="#pop!close-H6-region">
<RegExpr attribute="Header H5" context="#pop!close-H6-region" String="." lookAhead="true" endRegion="H5"/>
</context>
<context name="close-H6-region" attribute="Header H6" lineEndContext="#pop" fallthroughContext="#pop">
<RegExpr attribute="Header H6" context="#pop" String="." endRegion="H6"/>
</context>
<context name="find-strong-normal" attribute="Normal Text" lineEndContext="#pop"> <context name="find-strong-normal" attribute="Normal Text" lineEndContext="#pop">
<RegExpr attribute="Strong-Emphasis Text" context="#pop" minimal="true" String="&strongemphasisregex_ast_und;|&strongemphasisregex_ast_und2;"/> <RegExpr attribute="Strong-Emphasis Text" context="#pop" minimal="true" String="&strongemphasisregex_ast_und;|&strongemphasisregex_ast_und2;"/>
<RegExpr attribute="Strong Text" context="#pop" minimal="true" String="&strongregex_ast;"/> <RegExpr attribute="Strong Text" context="#pop" minimal="true" String="&strongregex_ast;"/>

View File

@@ -39,7 +39,7 @@
Enhance tr/// and y/// support. Enhance tr/// and y/// support.
--> -->
<language name="Perl" version="17" kateversion="5.0" section="Scripts" extensions="*.pl;*.PL;*.pm" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2"> <language name="Perl" version="18" kateversion="5.0" section="Scripts" extensions="*.pl;*.PL;*.pm" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2">
<highlighting> <highlighting>
<list name="keywords"> <list name="keywords">
<item>if</item> <item>if</item>
@@ -420,7 +420,8 @@
<DetectChar attribute="Operator" context="quote_word_paren" char="(" beginRegion="Wordlist" /> <DetectChar attribute="Operator" context="quote_word_paren" char="(" beginRegion="Wordlist" />
<DetectChar attribute="Operator" context="quote_word_brace" char="{" beginRegion="Wordlist" /> <DetectChar attribute="Operator" context="quote_word_brace" char="{" beginRegion="Wordlist" />
<DetectChar attribute="Operator" context="quote_word_bracket" char="[" beginRegion="Wordlist" /> <DetectChar attribute="Operator" context="quote_word_bracket" char="[" beginRegion="Wordlist" />
<RegExpr attribute="Operator" context="quote_word" String="([^a-zA-Z0-9_\s[\]{}()])" beginRegion="Wordlist" /> <DetectChar attribute="Operator" context="quote_word_angular" char="&lt;" beginRegion="Wordlist" />
<RegExpr attribute="Operator" context="quote_word" String="([^a-zA-Z0-9_\s[\]{}()\&lt;&gt;])" beginRegion="Wordlist" />
<RegExpr attribute="Comment" context="#stay" String="\s+#.*" /><!-- q[qwx] # == comment, look for the delim on the next line --> <RegExpr attribute="Comment" context="#stay" String="\s+#.*" /><!-- q[qwx] # == comment, look for the delim on the next line -->
</context> </context>
@@ -756,6 +757,12 @@
<Detect2Chars attribute="Normal Text" context="#stay" char="\" char1="]" /> <Detect2Chars attribute="Normal Text" context="#stay" char="\" char1="]" />
<DetectChar attribute="Operator" context="#pop#pop#pop" char="]" endRegion="Wordlist" /> <DetectChar attribute="Operator" context="#pop#pop#pop" char="]" endRegion="Wordlist" />
</context> </context>
<context name="quote_word_angular" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces />
<DetectIdentifier />
<Detect2Chars attribute="Normal Text" context="#stay" char="\" char1="&gt;" />
<DetectChar attribute="Operator" context="#pop#pop#pop" char="&gt;" endRegion="Wordlist" />
</context>
<!-- ====== Here Documents ====== --> <!-- ====== Here Documents ====== -->
<context name="find_here_document" attribute="Normal Text" lineEndContext="#pop" > <context name="find_here_document" attribute="Normal Text" lineEndContext="#pop" >

View File

@@ -33,6 +33,10 @@
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
--> -->
<!ENTITY strsubstitution_py3 "\{(?:(?:[a-zA-Z0-9_]+|[0-9]+)(?:\.[a-zA-Z0-9_]+|\[[^ \]]+\])*)?(?:![rs])?(?::(?:[^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(?:\.[0-9]+)?[bcdeEfFgGnosxX&#37;]?)?\}"> <!ENTITY strsubstitution_py3 "\{(?:(?:[a-zA-Z0-9_]+|[0-9]+)(?:\.[a-zA-Z0-9_]+|\[[^ \]]+\])*)?(?:![rs])?(?::(?:[^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(?:\.[0-9]+)?[bcdeEfFgGnosxX&#37;]?)?\}">
<!ENTITY rawString "(?:ru|u?r|)(?:'(?:[^']++|\\')*+'|&quot;(?:[^&quot;]++|\\&quot;)*+&quot;)">
<!ENTITY formatString "(?:r?f|fr?)(?:'(?:[^'{]++|\\'|\{\{|\{[^}]++\})*+'|&quot;(?:[^&quot;]++|\\&quot;|\{\{|\{[^}]*+\})*+&quot;)">
<!ENTITY string "&rawString;|&formatString;">
]> ]>
<!-- Python syntax highlightning v0.9 by Per Wigren --> <!-- Python syntax highlightning v0.9 by Per Wigren -->
<!-- Python syntax highlighting v1.9 by Michael Bueker (improved keyword differentiation) --> <!-- Python syntax highlighting v1.9 by Michael Bueker (improved keyword differentiation) -->
@@ -48,7 +52,7 @@
<!-- v2.07 add support for %prog and co, see bug 142832 --> <!-- v2.07 add support for %prog and co, see bug 142832 -->
<!-- v2.08 add missing overloaders, new Python 3 statements, builtins, and keywords --> <!-- v2.08 add missing overloaders, new Python 3 statements, builtins, and keywords -->
<!-- v2.29 recognize escape sequenzes correctly --> <!-- v2.29 recognize escape sequenzes correctly -->
<language name="Python" version="14" style="python" indenter="python" kateversion="5.0" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript;*.FCMacro" mimetype="application/x-python;text/x-python;text/x-python3" casesensitive="1" author="Michael Bueker" license=""> <language name="Python" version="22" style="python" indenter="python" kateversion="5.0" section="Scripts" extensions="*.py;*.pyw;SConstruct;SConscript;*.FCMacro" mimetype="application/x-python;text/x-python;text/x-python3" casesensitive="1" author="Michael Bueker" license="">
<highlighting> <highlighting>
<list name="import"> <list name="import">
<item>import</item> <item>import</item>
@@ -86,10 +90,21 @@
<item>try</item> <item>try</item>
<item>while</item> <item>while</item>
<item>with</item> <item>with</item>
<item>yield</item>
<item>async</item> <item>async</item>
<item>await</item> <item>await</item>
</list> </list>
<list name="flow_yield">
<item>yield</item>
<!--
"yield from" added here as a keyword for autocompletion. The actual handling
is in context="yield" so that we won't need to add space as a weakDeliminator.
-->
<item>yield from</item>
</list>
<list name="patternmatching">
<item>match</item>
<item>case</item>
</list>
<list name="builtinfuncs"> <list name="builtinfuncs">
<item>__import__</item> <item>__import__</item>
<item>abs</item> <item>abs</item>
@@ -366,89 +381,137 @@
</list> </list>
<contexts> <contexts>
<context name="Normal" attribute="Normal Text" lineEndContext="#stay"> <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces attribute="Normal Text"/>
<keyword attribute="Import" String="import" context="#stay"/> <keyword attribute="Import" String="import" context="#stay"/>
<keyword attribute="Definition Keyword" String="defs" context="#stay"/> <keyword attribute="Definition Keyword" String="defs" context="#stay"/>
<keyword attribute="Operator Keyword" String="operators" context="#stay"/> <keyword attribute="Operator Keyword" String="operators" context="#stay"/>
<keyword attribute="Flow Control Keyword" String="flow" context="#stay"/> <keyword attribute="Flow Control Keyword" String="flow" context="#stay"/>
<keyword attribute="Flow Control Keyword" String="flow_yield" context="yield"/>
<keyword attribute="Flow Control Keyword" String="patternmatching" context="Pattern Matching" lookAhead="1" firstNonSpace="1"/>
<keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/> <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
<keyword attribute="Special Variable" String="specialvars" context="#stay"/> <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
<keyword attribute="Extensions" String="bindings" context="#stay"/> <keyword attribute="Extensions" String="bindings" context="#stay"/>
<keyword attribute="Exceptions" String="exceptions" context="#stay"/> <keyword attribute="Exceptions" String="exceptions" context="#stay"/>
<keyword attribute="Overloaders" String="overloaders" context="#stay"/> <keyword attribute="Overloaders" String="overloaders" context="#stay"/>
<RegExpr attribute="Normal Text" String="[a-zA-Z_][a-zA-Z_0-9]{2,}" context="#stay"/>
<!-- Complex: 1j ; 1.1j ; 1.j ; .1j ; 1e3j ; 1.1e3j ; 1.e3j ; .1e3j -->
<RegExpr attribute="Complex" String="(?:&beforeDigit;&digitPart;(?:\.(?:&digitPart;)?)?|&beforePointFloat;\.&digitPart;)(?:[eE][\+\-]?&digitPart;)?[jJ]\b" context="#stay"/>
<!-- Hexadecimal: 0xA1, Binary: 0b01, Octal: 0o71 -->
<RegExpr attribute="Hex" String="&beforeDigit;0[xX](?:_?[\da-fA-F])+\b" context="#stay"/>
<RegExpr attribute="Binary" String="&beforeDigit;0[bB](?:_?[01])+\b" context="#stay"/>
<RegExpr attribute="Octal" String="&beforeDigit;0[oO](?:_?[0-7])+\b" context="#stay"/>
<!-- Float: 1.1 ; 1. ; .1 ; 1e3 ; 1.1e3 ; 1.e3 ; .1e3 -->
<RegExpr attribute="Float" String="(?:&beforeDigit;&digitPart;(?:\.(?:&digitPart;)?)?|&beforePointFloat;\.&digitPart;)[eE][\+\-]?&digitPart;\b|(?:&beforeDigit;&digitPart;\.(?:&digitPart;\b)?|&beforePointFloat;\.&digitPart;\b)" context="#stay"/>
<!-- Decimal: 123 ; 000 -->
<RegExpr attribute="Int" String="&beforeDigit;(?:[1-9](?:_?\d)*|0(?:_?0)*)[lL]?\b" context="#stay"/>
<DetectChar attribute="Normal Text" char="{" context="Dictionary" beginRegion="Dictionary"/> <DetectChar attribute="Normal Text" char="{" context="Dictionary" beginRegion="Dictionary"/>
<DetectChar attribute="Normal Text" char="[" context="List" beginRegion="List"/> <DetectChar attribute="Normal Text" char="[" context="List" beginRegion="List"/>
<DetectChar attribute="Normal Text" char="(" context="Tuple" beginRegion="Tuple"/> <DetectChar attribute="Normal Text" char="(" context="Tuple" beginRegion="Tuple"/>
<IncludeRules context="CommentVariants" />
<DetectChar attribute="Comment" char="#" context="Hash comment"/> <DetectChar attribute="Comment" char="#" context="Hash comment"/>
<IncludeRules context="Number" />
<IncludeRules context="CommentVariants" />
<IncludeRules context="StringVariants" /> <IncludeRules context="StringVariants" />
<DetectIdentifier attribute="Normal Text"/>
<RegExpr attribute="Decorator" String="@[_a-zA-Z[:^ascii:]][\._a-zA-Z0-9[:^ascii:]]*" firstNonSpace="true"/> <RegExpr attribute="Decorator" String="@[_a-zA-Z[:^ascii:]][\._a-zA-Z0-9[:^ascii:]]*" firstNonSpace="true"/>
<AnyChar attribute="Operator" String="+*/%\|=;\!&lt;&gt;!^&amp;~-@" context="#stay"/> <AnyChar attribute="Operator" String="+*/%\|=;&lt;&gt;!^&amp;~-@" context="#stay"/>
<Int attribute="Error"/>
</context>
<!-- https://docs.python.org/2/reference/lexical_analysis.html#integer-and-long-integer-literals -->
<!-- https://docs.python.org/3/reference/lexical_analysis.html#integer-literals -->
<context name="Number" attribute="Normal Text" lineEndContext="#pop">
<!-- fast path -->
<RegExpr String="&beforeDigit;[0-9]|&beforePointFloat;\.[0-9]" context="AssumeNumber" lookAhead="1"/>
</context>
<context name="AssumeNumber" attribute="Normal Text" lineEndContext="#pop">
<!-- Complex: 1j ; 1.1j ; 1.j ; .1j ; 1e3j ; 1.1e3j ; 1.e3j ; .1e3j -->
<RegExpr attribute="Complex" String="(?:&digitPart;(?:\.(?:&digitPart;)?)?|&beforePointFloat;\.&digitPart;)(?:[eE][\+\-]?&digitPart;)?[jJ]" context="CheckSuffixError"/>
<!-- Hexadecimal: 0xA1, Binary: 0b01, Octal: 0o71 -->
<RegExpr attribute="Hex" String="0[xX](?:_?[0-9a-fA-F])+" context="CheckSuffixError"/>
<RegExpr attribute="Binary" String="0[bB](?:_?[01])+" context="CheckSuffixError"/>
<RegExpr attribute="Octal" String="0[oO](?:_?[0-7])+" context="CheckSuffixError"/>
<!-- Float: 1.1 ; 1. ; .1 ; 1e3 ; 1.1e3 ; 1.e3 ; .1e3 -->
<RegExpr attribute="Float" String="(?:&digitPart;(?:\.(?:&digitPart;)?)?|\.&digitPart;)[eE][\+\-]?&digitPart;|&digitPart;\.(?:&digitPart;)?|\.&digitPart;" context="CheckSuffixError"/>
<!-- Decimal: 123 ; 000 -->
<!-- l and L are python2 suffixes -->
<RegExpr attribute="Int" String="(?:[1-9](?:_?\d)*|0(?:_?0)*)[lL]?" context="CheckSuffixError"/>
</context>
<context name="CheckSuffixError" attribute="Normal Text" lineEndContext="#pop#pop" fallthrough="1" fallthroughContext="#pop#pop">
<RegExpr attribute="Error" String="[\w\d]+" context="#pop#pop"/>
</context>
<context name="yield" attribute="Flow Control Keyword" lineEndContext="#pop" fallthrough="1" fallthroughContext="#pop">
<DetectSpaces attribute="Normal Text" context="#stay"/>
<WordDetect attribute="Flow Control Keyword" context="#pop" String="from"/>
</context>
<context name="Pattern Matching" attribute="Flow Control Keyword" lineEndContext="#pop">
<!--
Python 3.10: https://docs.python.org/3.10/reference/compound_stmts.html#the-match-statement
( 'match' | 'case' ) expression ':'
exclude:
( 'match' | 'case' ) ( 'if' | 'for' | '.' | ':' | '=' | ',' | ']' | ')' ) ...
-->
<RegExpr attribute="Flow Control Keyword" String="\w++(?=\s+(?!(?:if|for)\b)[\w'&quot;~]|\s*+(?![.:=\]),]|(?:if|for)\b)((?:&string;|[^#;(){}]|\(\)|\((?1)\)|\{\}|\{(\s*+(?:(?:&string;|[a-zA-Z0-9.]++)\s*+:\s*+(?:&string;|[^#;(){},]|\(\)|\((?1)\)|\{\}|\{(?2)\})++,?)*+)\})+?):)|" context="#pop"/>
<DetectIdentifier attribute="Normal Text" context="#pop"/>
</context> </context>
<context name="#CheckForString" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop"> <context name="#CheckForString" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
<DetectSpaces/> <DetectSpaces/>
<LineContinue attribute="Normal Text" context="CheckForStringNext"/> <LineContinue attribute="Normal Text" context="#pop!CheckForStringNext"/>
</context> </context>
<context name="CheckForStringNext" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop"> <context name="CheckForStringNext" attribute="Normal Text" lineEndContext="#pop#pop" fallthrough="true" fallthroughContext="#pop#pop">
<DetectSpaces/> <DetectSpaces/>
<LineContinue attribute="Normal Text" context="CheckForStringNext"/> <LineContinue attribute="Normal Text" context="#stay"/>
<IncludeRules context="StringVariants"/> <IncludeRules context="StringVariants"/>
</context> </context>
<!-- https://docs.python.org/2/reference/lexical_analysis.html#string-literals -->
<!-- https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals -->
<context name="StringVariants" attribute="Normal Text" lineEndContext="#stay"> <context name="StringVariants" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces/> <!-- fast path -->
<RegExpr String="(?:u|r|b|f|ur|fr|rf|br|rb)?['&quot;]" insensitive="true" context="AssumeStringVariants" lookAhead="1"/>
</context>
<context name="AssumeStringVariants" attribute="Normal Text" lineEndContext="#stay">
<RegExpr attribute="String" String="u?'''" insensitive="true" context="#pop!Triple A-string" beginRegion="Triple A-region"/>
<RegExpr attribute="String" String="u?&quot;&quot;&quot;" insensitive="true" context="#pop!Triple Q-string" beginRegion="Triple Q-region"/>
<RegExpr attribute="String" String="u?'" insensitive="true" context="#pop!Single A-string"/>
<RegExpr attribute="String" String="u?&quot;" insensitive="true" context="#pop!Single Q-string"/>
<RegExpr attribute="String" String="u?'''" insensitive="true" context="Triple A-string" beginRegion="Triple A-region"/> <RegExpr attribute="Raw String" String="u?r'''" insensitive="true" context="#pop!Raw Triple A-string" beginRegion="Triple A-region"/>
<RegExpr attribute="String" String="u?&quot;&quot;&quot;" insensitive="true" context="Triple Q-string" beginRegion="Triple Q-region"/> <RegExpr attribute="Raw String" String="u?r&quot;&quot;&quot;" insensitive="true" context="#pop!Raw Triple Q-string" beginRegion="Triple Q-region"/>
<RegExpr attribute="String" String="u?'" insensitive="true" context="Single A-string"/> <RegExpr attribute="Raw String" String="u?r'" insensitive="true" context="#pop!Raw A-string"/>
<RegExpr attribute="String" String="u?&quot;" insensitive="true" context="Single Q-string"/> <RegExpr attribute="Raw String" String="u?r&quot;" insensitive="true" context="#pop!Raw Q-string"/>
<RegExpr attribute="Raw String" String="(?:u?r|ru)'''" insensitive="true" context="Raw Triple A-string" beginRegion="Triple A-region"/> <StringDetect attribute="F-String" String="f'''" insensitive="true" context="#pop!Triple A-F-String" beginRegion="Triple A-region"/>
<RegExpr attribute="Raw String" String="(?:u?r|ru)&quot;&quot;&quot;" insensitive="true" context="Raw Triple Q-string" beginRegion="Triple Q-region"/> <StringDetect attribute="F-String" String="f&quot;&quot;&quot;" insensitive="true" context="#pop!Triple Q-F-String" beginRegion="Triple Q-region"/>
<RegExpr attribute="Raw String" String="(?:u?r|ru)'" insensitive="true" context="Raw A-string"/> <StringDetect attribute="F-String" String="f'" insensitive="true" context="#pop!Single A-F-String"/>
<RegExpr attribute="Raw String" String="(?:u?r|ru)&quot;" insensitive="true" context="Raw Q-string"/> <StringDetect attribute="F-String" String="f&quot;" insensitive="true" context="#pop!Single Q-F-String"/>
<StringDetect attribute="F-String" String="f'''" insensitive="true" context="Triple A-F-String" beginRegion="Triple A-region"/> <RegExpr attribute="Raw F-String" String="(?:fr|rf)'''" insensitive="true" context="#pop!Raw Triple A-F-String" beginRegion="Triple A-region"/>
<StringDetect attribute="F-String" String="f&quot;&quot;&quot;" insensitive="true" context="Triple Q-F-String" beginRegion="Triple Q-region"/> <RegExpr attribute="Raw F-String" String="(?:fr|rf)&quot;&quot;&quot;" insensitive="true" context="#pop!Raw Triple Q-F-String" beginRegion="Triple Q-region"/>
<StringDetect attribute="F-String" String="f'" insensitive="true" context="Single A-F-String"/> <RegExpr attribute="Raw F-String" String="(?:fr|rf)'" insensitive="true" context="#pop!Raw A-F-String"/>
<StringDetect attribute="F-String" String="f&quot;" insensitive="true" context="Single Q-F-String"/> <RegExpr attribute="Raw F-String" String="(?:fr|rf)&quot;" insensitive="true" context="#pop!Raw Q-F-String"/>
<RegExpr attribute="Raw F-String" String="(?:fr|rf)'''" insensitive="true" context="Raw Triple A-F-String" beginRegion="Triple A-region"/> <StringDetect attribute="B-String" String="b'''" insensitive="true" context="#pop!Triple A-B-String" beginRegion="Triple A-region"/>
<RegExpr attribute="Raw F-String" String="(?:fr|rf)&quot;&quot;&quot;" insensitive="true" context="Raw Triple Q-F-String" beginRegion="Triple Q-region"/> <StringDetect attribute="B-String" String="b&quot;&quot;&quot;" insensitive="true" context="#pop!Triple Q-B-String" beginRegion="Triple Q-region"/>
<RegExpr attribute="Raw F-String" String="(?:fr|rf)'" insensitive="true" context="Raw A-F-String"/> <StringDetect attribute="B-String" String="b'" insensitive="true" context="#pop!Single A-B-String"/>
<RegExpr attribute="Raw F-String" String="(?:fr|rf)&quot;" insensitive="true" context="Raw Q-F-String"/> <StringDetect attribute="B-String" String="b&quot;" insensitive="true" context="#pop!Single Q-B-String"/>
<RegExpr attribute="Raw B-String" String="(?:br|rb)'''" insensitive="true" context="#pop!Raw Triple A-B-String" beginRegion="Triple A-region"/>
<RegExpr attribute="Raw B-String" String="(?:br|rb)&quot;&quot;&quot;" insensitive="true" context="#pop!Raw Triple Q-B-String" beginRegion="Triple Q-region"/>
<RegExpr attribute="Raw B-String" String="(?:br|rb)'" insensitive="true" context="#pop!Raw A-B-String"/>
<RegExpr attribute="Raw B-String" String="(?:br|rb)&quot;" insensitive="true" context="#pop!Raw Q-B-String"/>
</context> </context>
<!-- https://docs.python.org/2/reference/lexical_analysis.html#string-literals -->
<!-- https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals -->
<context name="CommentVariants" attribute="Normal Text" lineEndContext="#stay"> <context name="CommentVariants" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces/> <!-- fast path -->
<RegExpr String="(?:u|r|ur)?['&quot;]" insensitive="true" firstNonSpace="true" context="AssumeCommentVariants" lookAhead="1"/>
<RegExpr attribute="Comment" String="u?'''" insensitive="true" firstNonSpace="true" context="Triple A-comment" beginRegion="Triple A-region"/> </context>
<RegExpr attribute="Comment" String="u?&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Triple Q-comment" beginRegion="Triple Q-region"/> <context name="AssumeCommentVariants" attribute="Normal Text" lineEndContext="#stay">
<RegExpr attribute="Comment" String="u?'" insensitive="true" firstNonSpace="true" context="Single A-comment"/> <RegExpr attribute="Comment" String="(?:u?r?)'''" insensitive="true" context="#pop!Triple A-comment" beginRegion="Triple A-region"/>
<RegExpr attribute="Comment" String="u?&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/> <RegExpr attribute="Comment" String="(?:u?r?)&quot;&quot;&quot;" insensitive="true" context="#pop!Triple Q-comment" beginRegion="Triple Q-region"/>
<RegExpr attribute="Comment" String="(?:u?r?)'" insensitive="true" context="#pop!Single A-comment"/>
<RegExpr attribute="Comment" String="(?:u?r|ru)'''" insensitive="true" firstNonSpace="true" context="Triple A-comment" beginRegion="Triple A-region"/> <RegExpr attribute="Comment" String="(?:u?r?)&quot;" insensitive="true" context="#pop!Single Q-comment"/>
<RegExpr attribute="Comment" String="(?:u?r|ru)&quot;&quot;&quot;" insensitive="true" firstNonSpace="true" context="Triple Q-comment" beginRegion="Triple Q-region"/>
<RegExpr attribute="Comment" String="(?:u?r|ru)'" insensitive="true" firstNonSpace="true" context="Single A-comment"/>
<RegExpr attribute="Comment" String="(?:u?r|ru)&quot;" insensitive="true" firstNonSpace="true" context="Single Q-comment"/>
</context> </context>
<context name="Dictionary" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Dictionary" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="true">
@@ -472,35 +535,53 @@
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="UnfinishedStringError" attribute="Error" lineEndContext="#stay" noIndentationBasedFolding="true">
<!-- A single string/comment reached the end of the line without a \ line escape -->
<!-- We set ALL succeeding lines to the "Error" attribute so that this error is easier to spot -->
</context>
<!-- Comments --> <!-- Comments -->
<context name="Hash comment" attribute="Comment" lineEndContext="#pop"> <context name="Hash comment" attribute="Comment" lineEndContext="#pop">
<DetectSpaces /> <DetectSpaces />
<IncludeRules context="##Comments" /> <IncludeRules context="##Comments" />
<DetectIdentifier/>
</context> </context>
<context name="Triple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/> <DetectSpaces/>
<StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Triple A-region"/> <StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Triple A-region"/>
<IncludeRules context="##Comments" /> <IncludeRules context="##Comments" />
<DetectIdentifier/>
<IncludeRules context="stringescape"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Triple Q-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple Q-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="true">
<IncludeRules context="stringescape"/> <DetectSpaces/>
<StringDetect attribute="Comment" String="&quot;&quot;&quot;" context="#pop" endRegion="Triple Q-region"/> <StringDetect attribute="Comment" String="&quot;&quot;&quot;" context="#pop" endRegion="Triple Q-region"/>
<IncludeRules context="##Comments" /> <IncludeRules context="##Comments" />
<DetectIdentifier/>
<IncludeRules context="stringescape"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Single A-comment" attribute="Comment" lineEndContext="#stay"> <context name="Single A-comment" attribute="Comment" lineEndContext="#pop!UnfinishedStringError">
<IncludeRules context="stringescape"/> <DetectSpaces/>
<DetectChar attribute="Comment" char="'" context="#pop"/> <DetectChar attribute="Comment" char="'" context="#pop"/>
<IncludeRules context="##Comments" /> <IncludeRules context="##Comments" />
<DetectIdentifier/>
<IncludeRules context="stringescape"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Single Q-comment" attribute="Comment" lineEndContext="#stay"> <context name="Single Q-comment" attribute="Comment" lineEndContext="#pop!UnfinishedStringError">
<IncludeRules context="stringescape"/> <DetectSpaces/>
<DetectChar attribute="Comment" char="&quot;" context="#pop"/> <DetectChar attribute="Comment" char="&quot;" context="#pop"/>
<IncludeRules context="##Comments" /> <IncludeRules context="##Comments" />
<DetectIdentifier/>
<IncludeRules context="stringescape"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<!-- Strings --> <!-- Strings -->
@@ -520,14 +601,25 @@
<RegExpr attribute="String Char" String="\\[\\'&quot;abfnrtv]|\\[0-7]{1,3}|\\x[0-9A-Fa-f]{2}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8}|\\N\{[a-zA-Z0-9\- ]+\}" context="#stay"/> <RegExpr attribute="String Char" String="\\[\\'&quot;abfnrtv]|\\[0-7]{1,3}|\\x[0-9A-Fa-f]{2}|\\u[0-9A-Fa-f]{4}|\\U[0-9A-Fa-f]{8}|\\N\{[a-zA-Z0-9\- ]+\}" context="#stay"/>
</context> </context>
<!-- escape characters -->
<context name="bytesescape" attribute="String Char" lineEndContext="#stay">
<!-- As this highlighting style is for both, Python 2 and 3,
we do not know if a normal string is “unicode” or not. So we
-->
<RegExpr attribute="String Char" String="\\[\\'&quot;abfnrtv]|\\[0-7]{1,3}|\\x[0-9A-Fa-f]{2}" context="#stay"/>
</context>
<!-- f-literals --> <!-- f-literals -->
<context name="stringinterpolation" attribute="F-String" lineEndContext="#stay"> <context name="stringinterpolation" attribute="F-String" lineEndContext="#stay">
<Detect2Chars attribute="String Char" char="{" char1="{" context="#stay"/> <Detect2Chars attribute="String Char" char="{" char1="{" context="#stay"/>
<DetectChar attribute="String Substitution" char="{" context="String Interpolation"/> <DetectChar attribute="String Substitution" char="{" context="String Interpolation"/>
<Detect2Chars attribute="String Char" char="}" char1="}" context="#stay"/>
<DetectChar attribute="Error" char="}" context="#stay"/>
</context> </context>
<context name="String Interpolation" attribute="String Substitution" lineEndContext="#stay"> <context name="String Interpolation" attribute="String Substitution" lineEndContext="#stay">
<DetectChar attribute="Error" char="\" context="#pop"/> <DetectChar attribute="Error" char="\" context="#pop"/>
<RegExpr attribute="String Substitution" String="(?:![rs])?(?::(?:[^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(?:\.[0-9]+)?[bcdeEfFgGnosxX%]?)?\}" context="#pop"/> <!-- format specifiers: [[fill]align][sign][#][0][minimumwidth][.precision][type] -->
<RegExpr attribute="String Substitution" String="(?:![rsa])?(?::(?:[^}]?[&lt;&gt;=^])?[ +-]?#?0?[0-9]*(?:\.[0-9]+)?[bcdeEfFgGnosxX%]?)?\}" context="#pop"/>
<IncludeRules context="Normal"/> <!-- TODO: create expression context instead --> <IncludeRules context="Normal"/> <!-- TODO: create expression context instead -->
</context> </context>
@@ -542,107 +634,218 @@
Adding byte literals wouldnt make the current 2⁴ into 2⁵ contexts, as there are no byte f-literals Adding byte literals wouldnt make the current 2⁴ into 2⁵ contexts, as there are no byte f-literals
--> -->
<!-- Triple-quoted A-strings --> <!-- Triple-quoted A-strings -->
<context name="Triple A-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple A-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces attribute="String"/>
<DetectIdentifier attribute="String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/> <StringDetect attribute="String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Triple A-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Raw Triple A-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw String" context="#stay"/> <DetectSpaces attribute="Raw String"/>
<DetectIdentifier attribute="Raw String"/>
<Detect2Chars attribute="Raw String" char="\" char1="'"/>
<Detect2Chars attribute="Raw String" char="\" char1="\"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<StringDetect attribute="Raw String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/> <StringDetect attribute="Raw String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
</context> </context>
<context name="Triple A-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple A-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces attribute="F-String"/>
<DetectIdentifier attribute="F-String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<StringDetect attribute="F-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/> <StringDetect attribute="F-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Triple A-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Raw Triple A-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw F-String" context="#stay"/> <DetectSpaces attribute="Raw F-String"/>
<DetectIdentifier attribute="Raw F-String"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="'"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="\"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<StringDetect attribute="Raw F-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/> <StringDetect attribute="Raw F-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
</context> </context>
<context name="Triple A-B-String" attribute="B-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<RegExpr attribute="B-String" String="([\x20-\x26\x28-\x5B\x5D-\x7E]++|\\(?=[^\\'&quot;abfnrtvx0-7])|\\x(?![0-9a-fA-F]{2})|'(?!''))++"/>
<IncludeRules context="bytesescape"/>
<StringDetect attribute="B-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
<LineContinue attribute="String Char" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context>
<context name="Raw Triple A-B-String" attribute="Raw B-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<RegExpr attribute="Raw B-String" String="([\x20-\x26\x28-\x5B\x5D-\x7E]++|\\.?|'(?!''))++"/>
<StringDetect attribute="Raw B-String" String="'''" context="#pop!#CheckForString" endRegion="Triple A-region"/>
<RegExpr attribute="Error" String="."/>
</context>
<!-- Triple-quoted Q-strings --> <!-- Triple-quoted Q-strings -->
<context name="Triple Q-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple Q-string" attribute="String" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces attribute="String"/>
<DetectIdentifier attribute="String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/> <StringDetect attribute="String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Triple Q-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Raw Triple Q-string" attribute="Raw String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw String" context="#stay"/> <DetectSpaces attribute="Raw String"/>
<DetectIdentifier attribute="Raw String"/>
<Detect2Chars attribute="Raw String" char="\" char1="&quot;"/>
<Detect2Chars attribute="Raw String" char="\" char1="\"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<StringDetect attribute="Raw String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/> <StringDetect attribute="Raw String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
</context> </context>
<context name="Triple Q-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Triple Q-F-String" attribute="F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<DetectSpaces attribute="F-String"/>
<DetectIdentifier attribute="F-String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<StringDetect attribute="F-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/> <StringDetect attribute="F-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Triple Q-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true"> <context name="Raw Triple Q-F-String" attribute="Raw F-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<HlCStringChar attribute="Raw F-String" context="#stay"/> <DetectSpaces attribute="Raw F-String"/>
<DetectIdentifier attribute="Raw F-String"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="&quot;"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="\"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<StringDetect attribute="Raw F-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/> <StringDetect attribute="Raw F-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
</context> </context>
<context name="Triple Q-B-String" attribute="B-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<RegExpr attribute="B-String" String="([\x20\x21\x23-\x5B\x5D-\x7E]++|\\(?=[^\\'&quot;abfnrtvx0-7])|\\x(?![0-9a-fA-F]{2})|&quot;(?!&quot;&quot;))++"/>
<IncludeRules context="bytesescape"/>
<StringDetect attribute="B-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
<LineContinue attribute="String Char" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context>
<context name="Raw Triple Q-B-String" attribute="Raw B-String" lineEndContext="#stay" noIndentationBasedFolding="true">
<RegExpr attribute="Raw B-String" String="([\x20\x21\x23-\x5B\x5D-\x7E]++|\\.?|&quot;(?!&quot;&quot;))++"/>
<StringDetect attribute="Raw B-String" String="&quot;&quot;&quot;" context="#pop!#CheckForString" endRegion="Triple Q-region"/>
<RegExpr attribute="Error" String="."/>
</context>
<!-- Single-quoted A-strings --> <!-- Single-quoted A-strings -->
<context name="Single A-string" attribute="String" lineEndContext="#stay"> <context name="Single A-string" attribute="String" lineEndContext="#pop!UnfinishedStringError">
<DetectSpaces attribute="String"/>
<DetectIdentifier attribute="String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<DetectChar attribute="String" char="'" context="#pop!#CheckForString"/> <DetectChar attribute="String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw A-string" attribute="Raw String" lineEndContext="#stay"> <context name="Raw A-string" attribute="Raw String" lineEndContext="#pop!UnfinishedStringError">
<HlCStringChar attribute="Raw String" context="#stay"/> <DetectSpaces attribute="Raw String"/>
<DetectIdentifier attribute="Raw String"/>
<Detect2Chars attribute="Raw String" char="\" char1="'"/>
<Detect2Chars attribute="Raw String" char="\" char1="\"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<DetectChar attribute="Raw String" char="'" context="#pop!#CheckForString"/> <DetectChar attribute="Raw String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="Raw String" context="#stay"/>
</context> </context>
<context name="Single A-F-String" attribute="F-String" lineEndContext="#stay"> <context name="Single A-F-String" attribute="F-String" lineEndContext="#pop!UnfinishedStringError">
<DetectSpaces attribute="F-String"/>
<DetectIdentifier attribute="F-String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<DetectChar attribute="F-String" char="'" context="#pop!#CheckForString"/> <DetectChar attribute="F-String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw A-F-String" attribute="Raw F-String" lineEndContext="#stay"> <context name="Raw A-F-String" attribute="Raw F-String" lineEndContext="#pop!UnfinishedStringError">
<HlCStringChar attribute="Raw F-String" context="#stay"/> <DetectSpaces attribute="Raw F-String"/>
<DetectIdentifier attribute="Raw F-String"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="'"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="\"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<DetectChar attribute="Raw F-String" char="'" context="#pop!#CheckForString"/> <DetectChar attribute="Raw F-String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="Raw F-String" context="#stay"/>
</context>
<context name="Single A-B-String" attribute="B-String" lineEndContext="#pop!UnfinishedStringError">
<RegExpr attribute="B-String" String="([\x20-\x26\x28-\x5B\x5D-\x7E]++|\\(?=[^\\'&quot;abfnrtvx0-7])|\\x(?![0-9a-fA-F]{2}))++"/>
<IncludeRules context="bytesescape"/>
<DetectChar attribute="B-String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context>
<context name="Raw A-B-String" attribute="Raw B-String" lineEndContext="#pop!UnfinishedStringError">
<RegExpr attribute="Raw B-String" String="([\x20-\x26\x28-\x5B\x5D-\x7E]++|\\.)++"/>
<DetectChar attribute="Raw B-String" char="'" context="#pop!#CheckForString"/>
<LineContinue attribute="Raw B-String" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context> </context>
<!-- Single-quoted Q-strings --> <!-- Single-quoted Q-strings -->
<context name="Single Q-string" attribute="String" lineEndContext="#stay"> <context name="Single Q-string" attribute="String" lineEndContext="#pop!UnfinishedStringError">
<DetectSpaces attribute="String"/>
<DetectIdentifier attribute="String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<DetectChar attribute="String" char="&quot;" context="#pop!#CheckForString"/> <DetectChar attribute="String" char="&quot;" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Q-string" attribute="Raw String" lineEndContext="#stay"> <context name="Raw Q-string" attribute="Raw String" lineEndContext="#pop!UnfinishedStringError">
<HlCStringChar attribute="Raw String" context="#stay"/> <DetectSpaces attribute="Raw String"/>
<DetectIdentifier attribute="Raw String"/>
<Detect2Chars attribute="Raw String" char="\" char1="&quot;"/>
<Detect2Chars attribute="Raw String" char="\" char1="\"/>
<IncludeRules context="stringformat"/> <IncludeRules context="stringformat"/>
<DetectChar attribute="Raw String" char="&quot;" context="#pop!#CheckForString"/> <DetectChar attribute="Raw String" char="&quot;" context="#pop!#CheckForString"/>
<LineContinue attribute="Raw String" context="#stay"/>
</context> </context>
<context name="Single Q-F-String" attribute="F-String" lineEndContext="#stay"> <context name="Single Q-F-String" attribute="F-String" lineEndContext="#pop!UnfinishedStringError">
<DetectSpaces attribute="F-String"/>
<DetectIdentifier attribute="F-String"/>
<IncludeRules context="stringescape"/> <IncludeRules context="stringescape"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<DetectChar attribute="F-String" char="&quot;" context="#pop!#CheckForString"/> <DetectChar attribute="F-String" char="&quot;" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
</context> </context>
<context name="Raw Q-F-String" attribute="Raw F-String" lineEndContext="#stay"> <context name="Raw Q-F-String" attribute="Raw F-String" lineEndContext="#pop!UnfinishedStringError">
<HlCStringChar attribute="Raw F-String" context="#stay"/> <DetectSpaces attribute="Raw F-String"/>
<DetectIdentifier attribute="Raw F-String"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="&quot;"/>
<Detect2Chars attribute="Raw F-String" char="\" char1="\"/>
<IncludeRules context="stringinterpolation"/> <IncludeRules context="stringinterpolation"/>
<DetectChar attribute="Raw F-String" char="&quot;" context="#pop!#CheckForString"/> <DetectChar attribute="Raw F-String" char="&quot;" context="#pop!#CheckForString"/>
<LineContinue attribute="Raw F-String" context="#stay"/>
</context> </context>
<context name="Single Q-B-String" attribute="B-String" lineEndContext="#pop!UnfinishedStringError">
<RegExpr attribute="B-String" String="([\x20\x21\x23-\x5B\x5D-\x7E]++|\\(?=[^\\'&quot;abfnrtvx0-7])|\\x(?![0-9a-fA-F]{2}))++"/>
<IncludeRules context="bytesescape"/>
<DetectChar attribute="B-String" char="&quot;" context="#pop!#CheckForString"/>
<LineContinue attribute="String Char" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context>
<context name="Raw Q-B-String" attribute="Raw B-String" lineEndContext="#pop!UnfinishedStringError">
<RegExpr attribute="Raw B-String" String="([\x20\x21\x23-\x5B\x5D-\x7E]++|\\.)++"/>
<DetectChar attribute="Raw B-String" char="&quot;" context="#pop!#CheckForString"/>
<Detect2Chars attribute="Raw B-String" char="\" char1="\"/>
<LineContinue attribute="Raw B-String" context="#stay"/>
<RegExpr attribute="Error" String="."/>
</context>
</contexts> </contexts>
<itemDatas> <itemDatas>
@@ -668,6 +871,8 @@
<itemData name="Raw String" defStyleNum="dsVerbatimString"/> <itemData name="Raw String" defStyleNum="dsVerbatimString"/>
<itemData name="F-String" defStyleNum="dsSpecialString"/> <itemData name="F-String" defStyleNum="dsSpecialString"/>
<itemData name="Raw F-String" defStyleNum="dsVerbatimString"/> <itemData name="Raw F-String" defStyleNum="dsVerbatimString"/>
<itemData name="B-String" defStyleNum="dsString" spellChecking="false"/>
<itemData name="Raw B-String" defStyleNum="dsVerbatimString" spellChecking="false"/>
<itemData name="String Char" defStyleNum="dsChar" spellChecking="false"/> <itemData name="String Char" defStyleNum="dsChar" spellChecking="false"/>
<itemData name="String Substitution" defStyleNum="dsSpecialChar" spellChecking="false"/> <itemData name="String Substitution" defStyleNum="dsSpecialChar" spellChecking="false"/>
<itemData name="Decorator" defStyleNum="dsAttribute" spellChecking="false"/> <itemData name="Decorator" defStyleNum="dsAttribute" spellChecking="false"/>

View File

@@ -6,7 +6,7 @@
<!ENTITY name "(?![0-9])[\w_:][\w.:_-]*"> <!ENTITY name "(?![0-9])[\w_:][\w.:_-]*">
<!ENTITY entref "&amp;(?:#[0-9]+|#[xX][0-9A-Fa-f]+|&name;);"> <!ENTITY entref "&amp;(?:#[0-9]+|#[xX][0-9A-Fa-f]+|&name;);">
]> ]>
<language name="XML" version="12" kateversion="5.0" section="Markup" extensions="*.docbook;*.xml;*.rc;*.daml;*.rdf;*.rss;*.xspf;*.xsd;*.svg;*.ui;*.kcfg;*.qrc;*.wsdl;*.scxml;*.xbel;*.dae;*.sch;*.brd" mimetype="text/xml;text/book;text/daml;text/rdf;application/rss+xml;application/xspf+xml;image/svg+xml;application/x-designer;application/x-xbel;application/xml;application/scxml+xml" casesensitive="1" indenter="xml" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL"> <language name="XML" version="14" kateversion="5.0" section="Markup" extensions="*.docbook;*.xml;*.rc;*.daml;*.rdf;*.rss;*.xspf;*.xsd;*.svg;*.ui;*.kcfg;*.qrc;*.wsdl;*.scxml;*.xbel;*.dae;*.sch;*.brd" mimetype="text/xml;text/book;text/daml;text/rdf;application/rss+xml;application/xspf+xml;image/svg+xml;application/x-designer;application/x-xbel;application/xml;application/scxml+xml" casesensitive="1" indenter="xml" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL">
<highlighting> <highlighting>
<contexts> <contexts>
@@ -16,13 +16,13 @@
<context name="FindXML" attribute="Normal Text" lineEndContext="#stay"> <context name="FindXML" attribute="Normal Text" lineEndContext="#stay">
<DetectSpaces /> <DetectSpaces />
<DetectIdentifier />
<RegExpr attribute="Element Symbols" context="ElementTagName" String="&lt;(?=(&name;))" beginRegion="element" />
<StringDetect attribute="Comment" context="Comment" String="&lt;!--" beginRegion="comment" /> <StringDetect attribute="Comment" context="Comment" String="&lt;!--" beginRegion="comment" />
<StringDetect attribute="CDATA" context="CDATAStart" String="&lt;![CDATA[" lookAhead="true" /> <StringDetect attribute="CDATA" context="CDATAStart" String="&lt;![CDATA[" lookAhead="true" />
<RegExpr attribute="Doctype Symbols" context="DoctypeTagName" String="&lt;!(?=DOCTYPE\s+)" beginRegion="doctype" /> <RegExpr attribute="Doctype Symbols" context="DoctypeTagName" String="&lt;!(?=DOCTYPE(\s|$))" beginRegion="doctype" />
<IncludeRules context="FindProcessingInstruction" /> <IncludeRules context="FindProcessingInstruction" />
<RegExpr attribute="Element Symbols" context="ElementTagName" String="&lt;(?=(&name;))" beginRegion="element" />
<IncludeRules context="FindEntityRefs" /> <IncludeRules context="FindEntityRefs" />
<DetectIdentifier />
</context> </context>
<context name="FindEntityRefs" attribute="Other Text" lineEndContext="#stay"> <context name="FindEntityRefs" attribute="Other Text" lineEndContext="#stay">
@@ -70,13 +70,13 @@
<context name="PI-XML" attribute="Other Text" lineEndContext="#stay"> <context name="PI-XML" attribute="Other Text" lineEndContext="#stay">
<IncludeRules context="PI" /> <IncludeRules context="PI" />
<RegExpr attribute="Attribute" context="#stay" String="(?:^|\s+)&name;" /> <RegExpr attribute="Attribute" context="#stay" String="(?:^|\s+)&name;" />
<DetectChar attribute="Attribute" context="Value" char="=" /> <DetectChar attribute="Attribute Separator" context="Value" char="=" />
</context> </context>
<context name="DoctypeTagName" attribute="Other Text" lineEndContext="#pop"> <context name="DoctypeTagName" attribute="Other Text" lineEndContext="#pop">
<StringDetect attribute="Doctype" context="#pop!DoctypeVariableName" String="DOCTYPE" /> <StringDetect attribute="Doctype" context="#pop!DoctypeVariableName" String="DOCTYPE" />
</context> </context>
<context name="DoctypeVariableName" attribute="Other Text" lineEndContext="#pop!Doctype" fallthrough="true" fallthroughContext="#pop!Doctype"> <context name="DoctypeVariableName" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop!Doctype">
<DetectSpaces /> <DetectSpaces />
<RegExpr attribute="Doctype Name" context="#pop!Doctype" String="&name;" /> <RegExpr attribute="Doctype Name" context="#pop!Doctype" String="&name;" />
</context> </context>
@@ -116,7 +116,7 @@
<IncludeRules context="FindPEntityRefs" /> <IncludeRules context="FindPEntityRefs" />
</context> </context>
<context name="ElementTagName" attribute="Other Text" lineEndContext="#pop!Element" fallthrough="true" fallthroughContext="#pop!Element"> <context name="ElementTagName" attribute="Other Text" lineEndContext="#pop!Element">
<StringDetect attribute="Element" context="#pop!Element" String="%1" dynamic="true" /> <StringDetect attribute="Element" context="#pop!Element" String="%1" dynamic="true" />
</context> </context>
<context name="Element" attribute="Other Text" lineEndContext="#stay"> <context name="Element" attribute="Other Text" lineEndContext="#stay">
@@ -131,7 +131,7 @@
<IncludeRules context="FindXML" /> <IncludeRules context="FindXML" />
</context> </context>
<context name="El End TagName" attribute="Other Text" lineEndContext="#pop!El End" fallthrough="true" fallthroughContext="#pop!El End"> <context name="El End TagName" attribute="Other Text" lineEndContext="#pop!El End">
<StringDetect attribute="Element" context="#pop!El End" String="%1" dynamic="true" /> <StringDetect attribute="Element" context="#pop!El End" String="%1" dynamic="true" />
</context> </context>
<context name="El End" attribute="Other Text" lineEndContext="#stay"> <context name="El End" attribute="Other Text" lineEndContext="#stay">
@@ -140,7 +140,7 @@
</context> </context>
<context name="Attribute" attribute="Other Text" lineEndContext="#stay"> <context name="Attribute" attribute="Other Text" lineEndContext="#stay">
<DetectChar attribute="Attribute" context="#pop!Value" char="=" /> <DetectChar attribute="Attribute Separator" context="#pop!Value" char="=" />
<RegExpr attribute="Error" context="#stay" String="\S" /> <RegExpr attribute="Error" context="#stay" String="\S" />
</context> </context>
@@ -175,6 +175,7 @@
<itemData name="Element" defStyleNum="dsKeyword" spellChecking="false" /> <itemData name="Element" defStyleNum="dsKeyword" spellChecking="false" />
<itemData name="Element Symbols" defStyleNum="dsNormal" spellChecking="false" /> <itemData name="Element Symbols" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Attribute" defStyleNum="dsOthers" spellChecking="false" /> <itemData name="Attribute" defStyleNum="dsOthers" spellChecking="false" />
<itemData name="Attribute Separator" defStyleNum="dsOthers" spellChecking="false" />
<itemData name="Value" defStyleNum="dsString" spellChecking="false" /> <itemData name="Value" defStyleNum="dsString" spellChecking="false" />
<itemData name="EntityRef" defStyleNum="dsDecVal" spellChecking="false" /> <itemData name="EntityRef" defStyleNum="dsDecVal" spellChecking="false" />
<itemData name="PEntityRef" defStyleNum="dsDecVal" spellChecking="false" /> <itemData name="PEntityRef" defStyleNum="dsDecVal" spellChecking="false" />

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Feb 22, 2021 (revision 3)", "Last update: Jul 28, 2021 (revision 4)",
"This file has been converted from: https://github.com/dempfi/ayu", "This file has been converted from: https://github.com/dempfi/ayu",
"Also see: https://github.com/ayu-theme" "Also see: https://github.com/ayu-theme"
], ],
@@ -11,7 +11,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "ayu Dark", "name": "ayu Dark",
"revision": 3 "revision": 4
}, },
"editor-colors": { "editor-colors": {
"BackgroundColor": "#0a0e14", "BackgroundColor": "#0a0e14",
@@ -169,8 +169,8 @@
"text-color": "#39bae6" "text-color": "#39bae6"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#c2d94c", "selected-text-color": "#99ca44",
"text-color": "#c2d94c" "text-color": "#99ca44"
}, },
"Warning": { "Warning": {
"selected-text-color": "#f07178", "selected-text-color": "#f07178",

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Sep 21, 2020 (revision 2)", "Last update: Jul 28, 2021 (revision 3)",
"This file has been converted from: https://github.com/dempfi/ayu", "This file has been converted from: https://github.com/dempfi/ayu",
"Also see: https://github.com/ayu-theme" "Also see: https://github.com/ayu-theme"
], ],
@@ -11,7 +11,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "ayu Light", "name": "ayu Light",
"revision": 2 "revision": 3
}, },
"editor-colors": { "editor-colors": {
"BackgroundColor": "#fafafa", "BackgroundColor": "#fafafa",
@@ -169,8 +169,8 @@
"text-color": "#55b4d4" "text-color": "#55b4d4"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#86b300", "selected-text-color": "#729800",
"text-color": "#86b300" "text-color": "#729800"
}, },
"Warning": { "Warning": {
"selected-text-color": "#f07171", "selected-text-color": "#f07171",

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Feb 22, 2021 (revision 3)", "Last update: Jul 28, 2021 (revision 4)",
"This file has been converted from: https://github.com/dempfi/ayu", "This file has been converted from: https://github.com/dempfi/ayu",
"Also see: https://github.com/ayu-theme" "Also see: https://github.com/ayu-theme"
], ],
@@ -11,7 +11,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "ayu Mirage", "name": "ayu Mirage",
"revision": 3 "revision": 4
}, },
"editor-colors": { "editor-colors": {
"BackgroundColor": "#1f2430", "BackgroundColor": "#1f2430",
@@ -169,8 +169,8 @@
"text-color": "#5ccfe6" "text-color": "#5ccfe6"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#bae67e", "selected-text-color": "#82e26a",
"text-color": "#bae67e" "text-color": "#82e26a"
}, },
"Warning": { "Warning": {
"selected-text-color": "#f28779", "selected-text-color": "#f28779",

View File

@@ -5,7 +5,7 @@
"SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>" "SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 6, "revision" : 7,
"name" : "Breeze Dark" "name" : "Breeze Dark"
}, },
"text-styles": { "text-styles": {
@@ -149,7 +149,7 @@
"editor-colors": { "editor-colors": {
"BackgroundColor" : "#232629", "BackgroundColor" : "#232629",
"CodeFolding" : "#224e65", "CodeFolding" : "#224e65",
"BracketMatching" : "#323030", "BracketMatching" : "#8e44ad",
"CurrentLine" : "#2A2E32", "CurrentLine" : "#2A2E32",
"IconBorder" : "#31363b", "IconBorder" : "#31363b",
"IndentationLine" : "#3a3f44", "IndentationLine" : "#3a3f44",

View File

@@ -5,7 +5,7 @@
"SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>" "SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 8, "revision" : 9,
"name" : "Breeze Light" "name" : "Breeze Light"
}, },
"text-styles": { "text-styles": {
@@ -70,7 +70,7 @@
"selected-text-color" : "#9c0e0e" "selected-text-color" : "#9c0e0e"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#bf0303", "text-color" : "#e31616",
"selected-text-color" : "#9c0e0e" "selected-text-color" : "#9c0e0e"
}, },
"SpecialString" : { "SpecialString" : {

View File

@@ -570,7 +570,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "Dracula", "name": "Dracula",
"revision": 7 "revision": 8
}, },
"text-styles": { "text-styles": {
"Alert": { "Alert": {
@@ -694,8 +694,8 @@
"text-color": "#8be9fd" "text-color": "#8be9fd"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#f1fa8c", "selected-text-color": "#d7e60a",
"text-color": "#f1fa8c" "text-color": "#d7e60a"
}, },
"Warning": { "Warning": {
"selected-text-color": "#ff5555", "selected-text-color": "#ff5555",

View File

@@ -0,0 +1,184 @@
{
"_comments": [
"A theme focused on ergonomics, using the 3 digit Tango color palette"
],
"metadata": {
"name": "Falcon",
"revision": 4,
"license": "SPDX-License-Identifier: MIT",
"copyright": [ "SPDX-FileCopyrightText: 2021 Alberto Salvia Novella <https://es20490446e.wordpress.com>" ]
},
"custom-styles": {
"Bash": {
"Normal Text": {
"text-color": "#bbbbbb"
}
}
},
"editor-colors": {
"BackgroundColor": "#223333",
"BracketMatching": "#555555",
"CodeFolding": "#224488",
"CurrentLine": "#555555",
"CurrentLineNumber": "#bbbbbb",
"IconBorder": "#223333",
"IndentationLine": "#888888",
"LineNumbers": "#888888",
"MarkBookmark": "#7799cc",
"MarkBreakpointActive": "#ffaa33",
"MarkBreakpointDisabled": "#aa77aa",
"MarkBreakpointReached": "#449900",
"MarkError": "#ef2929",
"MarkExecution": "#888888",
"MarkWarning": "#aa77aa",
"ModifiedLines": "#aa0000",
"ReplaceHighlight": "#224488",
"SavedLines": "#449900",
"SearchHighlight": "#224488",
"Separator": "#555753",
"SpellChecking": "#ef2929",
"TabMarker": "#555555",
"TemplateBackground": "#223333",
"TemplateFocusedPlaceholder": "#23321a",
"TemplatePlaceholder": "#23321a",
"TemplateReadOnlyPlaceholder": "#451e1a",
"TextSelection": "#3366aa",
"WordWrapMarker": "#555753"
},
"text-styles": {
"Alert": {
"background-color": "#320000",
"bold": true,
"selected-text-color": "#ffaa33",
"text-color": "#ee2222"
},
"Annotation": {
"selected-text-color": "#ddddcc",
"text-color": "#aa77aa"
},
"Attribute": {
"selected-text-color": "#ddddcc",
"text-color": "#aa77aa"
},
"BaseN": {
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"BuiltIn": {
"selected-text-color": "#ddddcc",
"text-color": "#7799cc"
},
"Char": {
"selected-text-color": "#ffaa33",
"text-color": "#ffaa33"
},
"Comment": {
"selected-text-color": "#eeeeec",
"text-color": "#888888"
},
"CommentVar": {
"selected-text-color": "#ddddcc",
"text-color": "#aa77aa"
},
"Constant": {
"bold": true,
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"ControlFlow": {
"bold": true,
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"DataType": {
"selected-text-color": "#ddddcc",
"text-color": "#7799cc"
},
"DecVal": {
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"Documentation": {
"selected-text-color": "#eeeeee",
"text-color": "#d3d7cf"
},
"Error": {
"selected-text-color": "#ffaa33",
"text-color": "#ee2222",
"underline": true
},
"Extension": {
"bold": true,
"selected-text-color": "#ddddcc",
"text-color": "#7799cc"
},
"Float": {
"selected-text-color": "#ffaa33",
"text-color": "#ffaa33"
},
"Function": {
"bold": true,
"selected-text-color": "#ddddcc",
"text-color": "#7799cc"
},
"Import": {
"selected-text-color": "#88ee33",
"text-color": "#88ee33"
},
"Information": {
"selected-text-color": "#eeeeee",
"text-color": "#ddddcc"
},
"Keyword": {
"bold": true,
"selected-text-color": "#ddddcc",
"text-color": "#aa77aa"
},
"Normal": {
"selected-text-color": "#eeeeee",
"text-color": "#ddddcc"
},
"Operator": {
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"Others": {
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
},
"Preprocessor": {
"selected-text-color": "#ddddcc",
"text-color": "#aa77aa"
},
"RegionMarker": {
"background-color": "#0d1932",
"selected-text-color": "#ddddcc",
"text-color": "#7799cc"
},
"SpecialChar": {
"selected-text-color": "#ffaa33",
"text-color": "#ffaa33"
},
"SpecialString": {
"selected-text-color": "#eeeeee",
"text-color": "#ddddcc"
},
"String": {
"selected-text-color": "#eeeeee",
"text-color": "#ddddcc"
},
"Variable": {
"bold": true,
"selected-text-color": "#ffaa33",
"text-color": "#ffaa33"
},
"VerbatimString": {
"selected-text-color": "#ffaa33",
"text-color": "#ffaa33"
},
"Warning": {
"selected-text-color": "#ffee44",
"text-color": "#eedd00"
}
}
}

View File

@@ -82,7 +82,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "GitHub Dark", "name": "GitHub Dark",
"revision": 2 "revision": 3
}, },
"text-styles": { "text-styles": {
"Alert": { "Alert": {
@@ -205,8 +205,8 @@
"text-color": "#ffab70" "text-color": "#ffab70"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#9ecbff", "selected-text-color": "#41a0ff",
"text-color": "#9ecbff" "text-color": "#41a0ff"
}, },
"Warning": { "Warning": {
"selected-text-color": "#ff5555", "selected-text-color": "#ff5555",

View File

@@ -82,7 +82,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "GitHub Light", "name": "GitHub Light",
"revision": 2 "revision": 3
}, },
"text-styles": { "text-styles": {
"Alert": { "Alert": {
@@ -205,8 +205,8 @@
"text-color": "#e36209" "text-color": "#e36209"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#032f62", "selected-text-color": "#034c95",
"text-color": "#032f62" "text-color": "#034c95"
}, },
"Warning": { "Warning": {
"selected-text-color": "#ff5555", "selected-text-color": "#ff5555",

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Sep 17, 2020 (revision 2)", "Last update: Jul 28, 2021 (revision 3)",
"This file has been converted from: https://github.com/morhetz/gruvbox" "This file has been converted from: https://github.com/morhetz/gruvbox"
], ],
"metadata" : { "metadata" : {
@@ -10,7 +10,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name" : "gruvbox Dark", "name" : "gruvbox Dark",
"revision" : 2 "revision" : 3
}, },
"text-styles": { "text-styles": {
"Normal" : { "Normal" : {
@@ -73,7 +73,7 @@
"selected-text-color" : "#b8bb26" "selected-text-color" : "#b8bb26"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#98971a", "text-color" : "#848216",
"selected-text-color" : "#b8bb26" "selected-text-color" : "#b8bb26"
}, },
"SpecialString" : { "SpecialString" : {

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Sep 17, 2020 (revision 2)", "Last update: Jul 28, 2021 (revision 3)",
"This file has been converted from: https://github.com/morhetz/gruvbox" "This file has been converted from: https://github.com/morhetz/gruvbox"
], ],
"metadata" : { "metadata" : {
@@ -10,7 +10,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name" : "gruvbox Light", "name" : "gruvbox Light",
"revision" : 2 "revision" : 3
}, },
"text-styles": { "text-styles": {
"Normal" : { "Normal" : {
@@ -73,7 +73,7 @@
"selected-text-color" : "#79740e" "selected-text-color" : "#79740e"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#98971a", "text-color" : "#848216",
"selected-text-color" : "#79740e" "selected-text-color" : "#79740e"
}, },
"SpecialString" : { "SpecialString" : {

View File

@@ -259,7 +259,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "Monokai", "name": "Monokai",
"revision": 5 "revision": 6
}, },
"text-styles": { "text-styles": {
"Alert": { "Alert": {
@@ -383,8 +383,8 @@
"text-color": "#f8f8f2" "text-color": "#f8f8f2"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#e6db74", "selected-text-color": "#d8c72c",
"text-color": "#e6db74" "text-color": "#d8c72c"
}, },
"Warning": { "Warning": {
"selected-text-color": "#ff5555", "selected-text-color": "#ff5555",

View File

@@ -1,6 +1,6 @@
{ {
"_comments": [ "_comments": [
"Last update: Sep 21, 2020 (revision 2)", "Last update: Jul 28, 2020 (revision 3)",
"This theme has been adapted from: https://www.nordtheme.com" "This theme has been adapted from: https://www.nordtheme.com"
], ],
"metadata": { "metadata": {
@@ -11,7 +11,7 @@
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"name": "Nord", "name": "Nord",
"revision": 2 "revision": 3
}, },
"editor-colors": { "editor-colors": {
"BackgroundColor": "#2e3440", "BackgroundColor": "#2e3440",
@@ -170,8 +170,8 @@
"text-color": "#5e81ac" "text-color": "#5e81ac"
}, },
"VerbatimString": { "VerbatimString": {
"selected-text-color": "#a3be8c", "selected-text-color": "#8dae70",
"text-color": "#a3be8c" "text-color": "#8dae70"
}, },
"Warning": { "Warning": {
"selected-text-color": "#bf616a", "selected-text-color": "#bf616a",

View File

@@ -5,7 +5,7 @@
"SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>" "SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 4, "revision" : 5,
"name" : "Printing" "name" : "Printing"
}, },
"text-styles": { "text-styles": {
@@ -69,7 +69,7 @@
"selected-text-color" : "#9c0e0e" "selected-text-color" : "#9c0e0e"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#bf0303", "text-color" : "#ea0404",
"selected-text-color" : "#9c0e0e" "selected-text-color" : "#9c0e0e"
}, },
"SpecialString" : { "SpecialString" : {

View File

@@ -9,7 +9,7 @@
"SPDX-FileCopyrightText: 2018 Andrew Crouthamel <andrew.crouthamel@kdemail.net>" "SPDX-FileCopyrightText: 2018 Andrew Crouthamel <andrew.crouthamel@kdemail.net>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 5, "revision" : 6,
"name" : "Solarized Dark" "name" : "Solarized Dark"
}, },
"text-styles": { "text-styles": {
@@ -70,8 +70,8 @@
"selected-text-color" : "#2aa198" "selected-text-color" : "#2aa198"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#2aa198", "text-color" : "#23877e",
"selected-text-color" : "#2aa198" "selected-text-color" : "#23877e"
}, },
"SpecialString" : { "SpecialString" : {
"text-color" : "#dc322f", "text-color" : "#dc322f",

View File

@@ -9,7 +9,7 @@
"SPDX-FileCopyrightText: 2018 Andrew Crouthamel <andrew.crouthamel@kdemail.net>" "SPDX-FileCopyrightText: 2018 Andrew Crouthamel <andrew.crouthamel@kdemail.net>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 4, "revision" : 5,
"name" : "Solarized Light" "name" : "Solarized Light"
}, },
"text-styles": { "text-styles": {
@@ -73,8 +73,8 @@
"selected-text-color" : "#2aa198" "selected-text-color" : "#2aa198"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#2aa198", "text-color" : "#23837a",
"selected-text-color" : "#2aa198" "selected-text-color" : "#23837a"
}, },
"SpecialString" : { "SpecialString" : {
"text-color" : "#dc322f", "text-color" : "#dc322f",

View File

@@ -9,6 +9,7 @@
<file>ayu-light.theme</file> <file>ayu-light.theme</file>
<file>ayu-mirage.theme</file> <file>ayu-mirage.theme</file>
<file>dracula.theme</file> <file>dracula.theme</file>
<file>falcon.theme</file>
<file>github-dark.theme</file> <file>github-dark.theme</file>
<file>github-light.theme</file> <file>github-light.theme</file>
<file>gruvbox-dark.theme</file> <file>gruvbox-dark.theme</file>

View File

@@ -5,7 +5,7 @@
"SPDX-FileCopyrightText: 2020 Nibaldo González <nibgonz@gmail.com>" "SPDX-FileCopyrightText: 2020 Nibaldo González <nibgonz@gmail.com>"
], ],
"license": "SPDX-License-Identifier: MIT", "license": "SPDX-License-Identifier: MIT",
"revision" : 3, "revision" : 4,
"name" : "Vim Dark" "name" : "Vim Dark"
}, },
"text-styles": { "text-styles": {
@@ -70,8 +70,8 @@
"selected-text-color" : "#ff54ff" "selected-text-color" : "#ff54ff"
}, },
"VerbatimString" : { "VerbatimString" : {
"text-color" : "#ff54ff", "text-color" : "#f000f0",
"selected-text-color" : "#ff54ff" "selected-text-color" : "#f000f0"
}, },
"SpecialString" : { "SpecialString" : {
"text-color" : "#ff5500", "text-color" : "#ff5500",

View File

@@ -6,7 +6,7 @@ platforms:
- name: Linux - name: Linux
- name: FreeBSD - name: FreeBSD
- name: Windows - name: Windows
- name: MacOSX - name: macOS
- name: Android - name: Android
portingAid: false portingAid: false
deprecated: false deprecated: false

View File

@@ -30,10 +30,11 @@ static void applyHighlighter(Highlighter &highlighter,
const QCommandLineOption &outputName, const QCommandLineOption &outputName,
const Ts &...highlightParams) const Ts &...highlightParams)
{ {
if (parser.isSet(outputName)) if (parser.isSet(outputName)) {
highlighter.setOutputFile(parser.value(outputName)); highlighter.setOutputFile(parser.value(outputName));
else } else {
highlighter.setOutputFile(stdout); highlighter.setOutputFile(stdout);
}
if (fromFileName) { if (fromFileName) {
highlighter.highlightFile(inFileName, highlightParams...); highlighter.highlightFile(inFileName, highlightParams...);
@@ -126,8 +127,9 @@ int main(int argc, char **argv)
} }
if (parser.isSet(listThemes)) { if (parser.isSet(listThemes)) {
for (const auto &theme : repo.themes()) for (const auto &theme : repo.themes()) {
std::cout << qPrintable(theme.name()) << std::endl; std::cout << qPrintable(theme.name()) << std::endl;
}
return 0; return 0;
} }
@@ -158,11 +160,12 @@ int main(int argc, char **argv)
if (!def.isValid()) { if (!def.isValid()) {
/* see if it's a extension instead */ /* see if it's a extension instead */
def = repo.definitionForFileName(QLatin1String("f.") + syntax); def = repo.definitionForFileName(QLatin1String("f.") + syntax);
if (!def.isValid()) if (!def.isValid()) {
/* see if it's a filename instead */ /* see if it's a filename instead */
def = repo.definitionForFileName(syntax); def = repo.definitionForFileName(syntax);
} }
} }
}
} else if (fromFileName) { } else if (fromFileName) {
def = repo.definitionForFileName(inFileName); def = repo.definitionForFileName(inFileName);
} else { } else {
@@ -177,8 +180,9 @@ int main(int argc, char **argv)
QString outputFormat = parser.value(outputFormatOption); QString outputFormat = parser.value(outputFormatOption);
if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) { if (0 == outputFormat.compare(QLatin1String("html"), Qt::CaseInsensitive)) {
QString title; QString title;
if (parser.isSet(titleOption)) if (parser.isSet(titleOption)) {
title = parser.value(titleOption); title = parser.value(titleOption);
}
HtmlHighlighter highlighter; HtmlHighlighter highlighter;
highlighter.setDefinition(def); highlighter.setDefinition(def);

View File

@@ -28,7 +28,8 @@ elseif(CMAKE_CROSSCOMPILING)
else() else()
# host build # host build
add_executable(katehighlightingindexer katehighlightingindexer.cpp ../lib/worddelimiters.cpp) add_executable(katehighlightingindexer katehighlightingindexer.cpp ../lib/worddelimiters.cpp)
if(Qt5XmlPatterns_FOUND) ecm_mark_nongui_executable(katehighlightingindexer)
if(Qt5XmlPatterns_FOUND AND NOT ECM_ENABLE_SANITIZERS)
target_link_libraries(katehighlightingindexer Qt5::XmlPatterns) target_link_libraries(katehighlightingindexer Qt5::XmlPatterns)
else() else()
target_link_libraries(katehighlightingindexer Qt5::Core) target_link_libraries(katehighlightingindexer Qt5::Core)

View File

@@ -31,7 +31,8 @@ using KSyntaxHighlighting::Xml::attrToBool;
class HlFilesChecker class HlFilesChecker
{ {
public: public:
void setDefinition(const QStringRef &verStr, const QString &filename, const QString &name) template<typename T>
void setDefinition(const T &verStr, const QString &filename, const QString &name)
{ {
m_currentDefinition = &*m_definitions.insert(name, Definition{}); m_currentDefinition = &*m_definitions.insert(name, Definition{});
m_currentDefinition->languageName = name; m_currentDefinition->languageName = name;
@@ -93,6 +94,12 @@ public:
continue; continue;
} }
auto markAsUsedContext = [](ContextName &ContextName) {
if (!ContextName.stay && ContextName.context) {
ContextName.context->isOnlyIncluded = false;
}
};
QMutableMapIterator<QString, Context> contextIt(contexts); QMutableMapIterator<QString, Context> contextIt(contexts);
while (contextIt.hasNext()) { while (contextIt.hasNext()) {
contextIt.next(); contextIt.next();
@@ -100,12 +107,21 @@ public:
resolveContextName(definition, context, context.lineEndContext, context.line); resolveContextName(definition, context, context.lineEndContext, context.line);
resolveContextName(definition, context, context.lineEmptyContext, context.line); resolveContextName(definition, context, context.lineEmptyContext, context.line);
resolveContextName(definition, context, context.fallthroughContext, context.line); resolveContextName(definition, context, context.fallthroughContext, context.line);
markAsUsedContext(context.lineEndContext);
markAsUsedContext(context.lineEmptyContext);
markAsUsedContext(context.fallthroughContext);
for (auto &rule : context.rules) { for (auto &rule : context.rules) {
rule.parentContext = &context;
resolveContextName(definition, context, rule.context, rule.line); resolveContextName(definition, context, rule.context, rule.line);
if (rule.type != Context::Rule::Type::IncludeRules) {
markAsUsedContext(rule.context);
}
} }
} }
definition.firstContext = &*definition.contexts.find(definition.firstContextName); auto *firstContext = &*definition.contexts.find(definition.firstContextName);
firstContext->isOnlyIncluded = false;
definition.firstContext = firstContext;
} }
resolveIncludeRules(); resolveIncludeRules();
@@ -118,6 +134,7 @@ public:
const auto usedContexts = extractUsedContexts(); const auto usedContexts = extractUsedContexts();
QMap<const Definition *, const Definition *> maxVersionByDefinitions; QMap<const Definition *, const Definition *> maxVersionByDefinitions;
QMap<const Context::Rule *, IncludedRuleUnreachableBy> unreachableIncludedRules;
QMapIterator<QString, Definition> def(m_definitions); QMapIterator<QString, Definition> def(m_definitions);
while (def.hasNext()) { while (def.hasNext()) {
@@ -135,14 +152,7 @@ public:
QSet<const Keywords *> referencedKeywords; QSet<const Keywords *> referencedKeywords;
QSet<ItemDatas::Style> usedAttributeNames; QSet<ItemDatas::Style> usedAttributeNames;
success = checkKeywordsList(definition, referencedKeywords) && success; success = checkKeywordsList(definition, referencedKeywords) && success;
success = checkContexts(definition, referencedKeywords, usedAttributeNames, usedContexts) && success; success = checkContexts(definition, referencedKeywords, usedAttributeNames, usedContexts, unreachableIncludedRules) && success;
// search for non-existing or unreferenced keyword lists.
for (const auto &keywords : definition.keywordsList) {
if (!referencedKeywords.contains(&keywords)) {
qWarning() << filename << "line" << keywords.line << "unused keyword:" << keywords.name;
}
}
// search for non-existing itemDatas. // search for non-existing itemDatas.
const auto invalidNames = usedAttributeNames - definition.itemDatas.styleNames; const auto invalidNames = usedAttributeNames - definition.itemDatas.styleNames;
@@ -159,6 +169,56 @@ public:
} }
} }
QMutableMapIterator<const Context::Rule *, IncludedRuleUnreachableBy> unreachableIncludedRuleIt(unreachableIncludedRules);
while (unreachableIncludedRuleIt.hasNext()) {
unreachableIncludedRuleIt.next();
IncludedRuleUnreachableBy &unreachableRulesBy = unreachableIncludedRuleIt.value();
if (unreachableRulesBy.alwaysUnreachable) {
auto *rule = unreachableIncludedRuleIt.key();
if (!rule->parentContext->isOnlyIncluded) {
continue;
}
// remove duplicates rules
QSet<const Context::Rule *> rules;
auto &unreachableBy = unreachableRulesBy.unreachableBy;
unreachableBy.erase(std::remove_if(unreachableBy.begin(),
unreachableBy.end(),
[&](const RuleAndInclude &ruleAndInclude) {
if (rules.contains(ruleAndInclude.rule)) {
return true;
}
rules.insert(ruleAndInclude.rule);
return false;
}),
unreachableBy.end());
QString message;
message.reserve(128);
for (auto &ruleAndInclude : std::as_const(unreachableBy)) {
message += QStringLiteral("line ");
message += QString::number(ruleAndInclude.rule->line);
message += QStringLiteral(" [");
message += ruleAndInclude.rule->parentContext->name;
if (rule->filename != ruleAndInclude.rule->filename) {
message += QStringLiteral(" (");
message += ruleAndInclude.rule->filename;
message += QLatin1Char(')');
}
if (ruleAndInclude.includeRules) {
message += QStringLiteral(" via line ");
message += QString::number(ruleAndInclude.includeRules->line);
}
message += QStringLiteral("], ");
}
message.chop(2);
qWarning() << rule->filename << "line" << rule->line << "no IncludeRule can reach this rule, hidden by" << message;
success = false;
}
}
return success; return success;
} }
@@ -176,7 +236,7 @@ private:
int popCount = 0; int popCount = 0;
bool stay = false; bool stay = false;
const Context *context = nullptr; Context *context = nullptr;
}; };
struct Parser { struct Parser {
@@ -185,12 +245,13 @@ private:
QXmlStreamAttribute &attr; QXmlStreamAttribute &attr;
bool success; bool success;
//! Read a string type attribute, \c sucess = \c false when \p str is not empty //! Read a string type attribute, \c success = \c false when \p str is not empty
//! \return \c true when attr.name() == attrName, otherwise false //! \return \c true when attr.name() == attrName, otherwise false
bool extractString(QString &str, const QString &attrName) bool extractString(QString &str, const QString &attrName)
{ {
if (attr.name() != attrName) if (attr.name() != attrName) {
return false; return false;
}
str = attr.value().toString(); str = attr.value().toString();
if (str.isEmpty()) { if (str.isEmpty()) {
@@ -201,24 +262,26 @@ private:
return true; return true;
} }
//! Read a bool type attribute, \c sucess = \c false when \p xmlBool is not \c XmlBool::Unspecified. //! Read a bool type attribute, \c success = \c false when \p xmlBool is not \c XmlBool::Unspecified.
//! \return \c true when attr.name() == attrName, otherwise false //! \return \c true when attr.name() == attrName, otherwise false
bool extractXmlBool(XmlBool &xmlBool, const QString &attrName) bool extractXmlBool(XmlBool &xmlBool, const QString &attrName)
{ {
if (attr.name() != attrName) if (attr.name() != attrName) {
return false; return false;
}
xmlBool = attr.value().isNull() ? XmlBool::Unspecified : attrToBool(attr.value()) ? XmlBool::True : XmlBool::False; xmlBool = attr.value().isNull() ? XmlBool::Unspecified : attrToBool(attr.value()) ? XmlBool::True : XmlBool::False;
return true; return true;
} }
//! Read a positive integer type attribute, \c sucess = \c false when \p positive is already greater than or equal to 0 //! Read a positive integer type attribute, \c success = \c false when \p positive is already greater than or equal to 0
//! \return \c true when attr.name() == attrName, otherwise false //! \return \c true when attr.name() == attrName, otherwise false
bool extractPositive(int &positive, const QString &attrName) bool extractPositive(int &positive, const QString &attrName)
{ {
if (attr.name() != attrName) if (attr.name() != attrName) {
return false; return false;
}
bool ok = true; bool ok = true;
positive = attr.value().toInt(&ok); positive = attr.value().toInt(&ok);
@@ -231,12 +294,13 @@ private:
return true; return true;
} }
//! Read a color, \c sucess = \c false when \p color is already greater than or equal to 0 //! Read a color, \c success = \c false when \p color is already greater than or equal to 0
//! \return \c true when attr.name() == attrName, otherwise false //! \return \c true when attr.name() == attrName, otherwise false
bool checkColor(const QString &attrName) bool checkColor(const QString &attrName)
{ {
if (attr.name() != attrName) if (attr.name() != attrName) {
return false; return false;
}
const auto value = attr.value().toString(); const auto value = attr.value().toString();
if (value.isEmpty() /*|| QColor(value).isValid()*/) { if (value.isEmpty() /*|| QColor(value).isValid()*/) {
@@ -247,16 +311,17 @@ private:
return true; return true;
} }
//! Read a QChar, \c sucess = \c false when \p c is not \c '\0' or does not have one char //! Read a QChar, \c success = \c false when \p c is not \c '\0' or does not have one char
//! \return \c true when attr.name() == attrName, otherwise false //! \return \c true when attr.name() == attrName, otherwise false
bool extractChar(QChar &c, const QString &attrName) bool extractChar(QChar &c, const QString &attrName)
{ {
if (attr.name() != attrName) if (attr.name() != attrName) {
return false; return false;
}
if (attr.value().size() == 1) if (attr.value().size() == 1) {
c = attr.value()[0]; c = attr.value()[0];
else { } else {
c = QLatin1Char('_'); c = QLatin1Char('_');
qWarning() << filename << "line" << xml.lineNumber() << attrName << "must contain exactly one char:" << attr.value(); qWarning() << filename << "line" << xml.lineNumber() << attrName << "must contain exactly one char:" << attr.value();
success = false; success = false;
@@ -268,8 +333,9 @@ private:
//! \return parsing status when \p isExtracted is \c true, otherwise \c false //! \return parsing status when \p isExtracted is \c true, otherwise \c false
bool checkIfExtracted(bool isExtracted) bool checkIfExtracted(bool isExtracted)
{ {
if (isExtracted) if (isExtracted) {
return success; return success;
}
qWarning() << filename << "line" << xml.lineNumber() << "unknown attribute:" << attr.name(); qWarning() << filename << "line" << xml.lineNumber() << "unknown attribute:" << attr.name();
return false; return false;
@@ -400,18 +466,19 @@ private:
QString additionalDeliminator; QString additionalDeliminator;
QString weakDeliminator; QString weakDeliminator;
// rules included by IncludeRules // rules included by IncludeRules (without IncludeRule)
QVector<const Rule *> includedRules; QVector<const Rule *> includedRules;
// IncludeRules included by IncludeRules // IncludeRules included by IncludeRules
QSet<const Rule *> includedIncludeRules; QSet<const Rule *> includedIncludeRules;
Context const *parentContext = nullptr;
QString filename; QString filename;
bool parseElement(const QString &filename, QXmlStreamReader &xml) bool parseElement(const QString &filename, QXmlStreamReader &xml)
{ {
this->filename = filename; this->filename = filename;
line = xml.lineNumber(); line = xml.lineNumber();
using Pair = QPair<QString, Type>; using Pair = QPair<QString, Type>;
@@ -579,6 +646,8 @@ private:
}; };
int line; int line;
// becomes false when a context refers to it
bool isOnlyIncluded = true;
QString name; QString name;
QString attribute; QString attribute;
ContextName lineEndContext; ContextName lineEndContext;
@@ -723,8 +792,9 @@ private:
{ {
Context context; Context context;
m_success = context.parseElement(m_currentDefinition->filename, xml) && m_success; m_success = context.parseElement(m_currentDefinition->filename, xml) && m_success;
if (m_currentDefinition->firstContextName.isEmpty()) if (m_currentDefinition->firstContextName.isEmpty()) {
m_currentDefinition->firstContextName = context.name; m_currentDefinition->firstContextName = context.name;
}
if (m_currentDefinition->contexts.contains(context.name)) { if (m_currentDefinition->contexts.contains(context.name)) {
qWarning() << m_currentDefinition->filename << "line" << xml.lineNumber() << "duplicate context:" << context.name; qWarning() << m_currentDefinition->filename << "line" << xml.lineNumber() << "duplicate context:" << context.name;
m_success = false; m_success = false;
@@ -784,6 +854,7 @@ private:
m_success = false; m_success = false;
continue; continue;
} }
if (rule.context.popCount) { if (rule.context.popCount) {
qWarning() << definition.filename << "line" << rule.line << "IncludeRules with #pop prefix"; qWarning() << definition.filename << "line" << rule.line << "IncludeRules with #pop prefix";
m_success = false; m_success = false;
@@ -794,6 +865,8 @@ private:
continue; continue;
} }
// resolve includedRules and includedIncludeRules
usedContexts.clear(); usedContexts.clear();
usedContexts.insert(rule.context.context); usedContexts.insert(rule.context.context);
contexts.clear(); contexts.clear();
@@ -866,11 +939,27 @@ private:
return usedContexts; return usedContexts;
} }
struct RuleAndInclude {
const Context::Rule *rule;
const Context::Rule *includeRules;
explicit operator bool() const
{
return rule;
}
};
struct IncludedRuleUnreachableBy {
QVector<RuleAndInclude> unreachableBy;
bool alwaysUnreachable = true;
};
//! Check contexts and rules //! Check contexts and rules
bool checkContexts(const Definition &definition, bool checkContexts(const Definition &definition,
QSet<const Keywords *> &referencedKeywords, QSet<const Keywords *> &referencedKeywords,
QSet<ItemDatas::Style> &usedAttributeNames, QSet<ItemDatas::Style> &usedAttributeNames,
const QSet<const Context *> &usedContexts) const const QSet<const Context *> &usedContexts,
QMap<const Context::Rule *, IncludedRuleUnreachableBy> &unreachableIncludedRules) const
{ {
bool success = true; bool success = true;
@@ -892,16 +981,18 @@ private:
success = false; success = false;
} }
if (!context.attribute.isEmpty()) if (!context.attribute.isEmpty()) {
usedAttributeNames.insert({context.attribute, context.line}); usedAttributeNames.insert({context.attribute, context.line});
}
success = checkfallthrough(definition, context) && success; success = checkfallthrough(definition, context) && success;
success = checkUreachableRules(definition.filename, context) && success; success = checkUreachableRules(definition.filename, context, unreachableIncludedRules) && success;
success = suggestRuleMerger(definition.filename, context) && success; success = suggestRuleMerger(definition.filename, context) && success;
for (const auto &rule : context.rules) { for (const auto &rule : context.rules) {
if (!rule.attribute.isEmpty()) if (!rule.attribute.isEmpty()) {
usedAttributeNames.insert({rule.attribute, rule.line}); usedAttributeNames.insert({rule.attribute, rule.line});
}
success = checkLookAhead(rule) && success; success = checkLookAhead(rule) && success;
success = checkStringDetect(rule) && success; success = checkStringDetect(rule) && success;
success = checkAnyChar(rule) && success; success = checkAnyChar(rule) && success;
@@ -954,9 +1045,14 @@ private:
return false; return false;
} }
#define REG_ESCAPE_CHAR R"(\\(?:[^0BDPSWbdpswoux]|x[0-9a-fA-F]{2}|x\{[0-9a-fA-F]+\}|0\d\d|o\{[0-7]+\}|u[0-9a-fA-F]{4}))"
#define REG_CHAR "(?:" REG_ESCAPE_CHAR "|\\[(?:" REG_ESCAPE_CHAR "|.)\\]|[^[.^])"
// is RangeDetect // is RangeDetect
static const QRegularExpression isRange(QStringLiteral( static const QRegularExpression isRange(QStringLiteral("^\\^?" REG_CHAR "(?:"
R"(^(\\(?:[^0BDPSWbdpswoux]|x[0-9a-fA-F]{2}|x\{[0-9a-fA-F]+\}|0\d\d|o\{[0-7]+\}|u[0-9a-fA-F]{4})|[^[.]|\[[^].\\]\])(?:\.|\[^\1\])\*[?*]?\1$)")); "\\.\\*[?*]?" REG_CHAR "|"
"\\[\\^(" REG_ESCAPE_CHAR "|.)\\]\\*[?*]?\\1"
")$"));
if (( rule.lookAhead == XmlBool::True if (( rule.lookAhead == XmlBool::True
|| rule.minimal == XmlBool::True || rule.minimal == XmlBool::True
|| rule.string.contains(QStringLiteral(".*?")) || rule.string.contains(QStringLiteral(".*?"))
@@ -967,11 +1063,21 @@ private:
return false; return false;
} }
// is LineContinue
static const QRegularExpression isLineContinue(QStringLiteral("^\\^?" REG_CHAR "\\$$"));
if (reg.contains(isLineContinue)) {
auto extra = (reg[0] == QLatin1Char('^')) ? "with column=\"0\"" : "";
qWarning() << filename << "line" << rule.line << "RegExpr should be replaced by LineContinue:" << rule.string << extra;
return false;
}
// replace \c, \xhhh, \x{hhh...}, \0dd, \o{ddd}, \uhhhh, with _ // replace \c, \xhhh, \x{hhh...}, \0dd, \o{ddd}, \uhhhh, with _
static const QRegularExpression sanitize1( static const QRegularExpression sanitize1(QStringLiteral(REG_ESCAPE_CHAR));
QStringLiteral(R"(\\(?:[^0BDPSWbdpswoux]|x[0-9a-fA-F]{2}|x\{[0-9a-fA-F]+\}|0\d\d|o\{[0-7]+\}|u[0-9a-fA-F]{4}))"));
reg.replace(sanitize1, QStringLiteral("_")); reg.replace(sanitize1, QStringLiteral("_"));
#undef REG_CHAR
#undef REG_ESCAPE_CHAR
// use minimal or lazy operator // use minimal or lazy operator
static const QRegularExpression isMinimal(QStringLiteral( static const QRegularExpression isMinimal(QStringLiteral(
R"([.][*+][^][?+*()|$]*$)")); R"([.][*+][^][?+*()|$]*$)"));
@@ -1008,8 +1114,9 @@ private:
char const *extraMsg = rule.string.contains(QLatin1Char('^')) ? "+ column=\"0\" or firstNonSpace=\"1\"" : ""; char const *extraMsg = rule.string.contains(QLatin1Char('^')) ? "+ column=\"0\" or firstNonSpace=\"1\"" : "";
qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by StringDetect / Detect2Chars / DetectChar" << extraMsg qWarning() << rule.filename << "line" << rule.line << "RegExpr should be replaced by StringDetect / Detect2Chars / DetectChar" << extraMsg
<< ":" << rule.string; << ":" << rule.string;
if (len != reg.size()) if (len != reg.size()) {
qWarning() << rule.filename << "line" << rule.line << "insensitive=\"1\" missing:" << rule.string; qWarning() << rule.filename << "line" << rule.line << "insensitive=\"1\" missing:" << rule.string;
}
return false; return false;
} }
@@ -1019,8 +1126,8 @@ private:
// (^sas*) -> ok // (^sas*) -> ok
// (^sa|s*) -> ko // (^sa|s*) -> ko
// (^(sa|s*)) -> ok // (^(sa|s*)) -> ok
auto first = qAsConst(reg).begin(); auto first = std::as_const(reg).begin();
auto last = qAsConst(reg).end(); auto last = std::as_const(reg).end();
int depth = 0; int depth = 0;
while (QLatin1Char('(') == *first) { while (QLatin1Char('(') == *first) {
@@ -1066,8 +1173,8 @@ private:
// add ^ with column=0 // add ^ with column=0
if (rule.column == 0 && !rule.isDotRegex) { if (rule.column == 0 && !rule.isDotRegex) {
bool hasStartOfLine = false; bool hasStartOfLine = false;
auto first = qAsConst(reg).begin(); auto first = std::as_const(reg).begin();
auto last = qAsConst(reg).end(); auto last = std::as_const(reg).end();
for (; first != last; ++first) { for (; first != last; ++first) {
if (*first == QLatin1Char('^')) { if (*first == QLatin1Char('^')) {
hasStartOfLine = true; hasStartOfLine = true;
@@ -1306,8 +1413,9 @@ private:
//! Search for additionalDeliminator/weakDeliminator which has no effect. //! Search for additionalDeliminator/weakDeliminator which has no effect.
bool checkDelimiters(const Definition &definition, const Context::Rule &rule) const bool checkDelimiters(const Definition &definition, const Context::Rule &rule) const
{ {
if (rule.additionalDeliminator.isEmpty() && rule.weakDeliminator.isEmpty()) if (rule.additionalDeliminator.isEmpty() && rule.weakDeliminator.isEmpty()) {
return true; return true;
}
bool success = true; bool success = true;
@@ -1472,16 +1580,39 @@ private:
//! - StringDetect, WordDetect, RegExpr with as prefix Detect2Chars or other strings //! - StringDetect, WordDetect, RegExpr with as prefix Detect2Chars or other strings
//! - duplicate rule (Int, Float, keyword with same String, etc) //! - duplicate rule (Int, Float, keyword with same String, etc)
//! - Rule hidden by a dot regex //! - Rule hidden by a dot regex
bool checkUreachableRules(const QString &filename, const Context &context) const bool checkUreachableRules(const QString &filename,
const Context &context,
QMap<const Context::Rule *, IncludedRuleUnreachableBy> &unreachableIncludedRules) const
{ {
struct RuleAndInclude { if (context.isOnlyIncluded) {
const Context::Rule *rule; return true;
const Context::Rule *includeRules;
explicit operator bool() const
{
return rule;
} }
struct Rule4 {
RuleAndInclude setRule(const Context::Rule &rule, const Context::Rule *includeRules = nullptr)
{
auto set = [&](RuleAndInclude &ruleAndInclude) {
auto old = ruleAndInclude;
ruleAndInclude = {&rule, includeRules};
return old;
};
if (rule.firstNonSpace == XmlBool::True) {
return set(firstNonSpace);
} else if (rule.column == 0) {
return set(column0);
} else if (rule.column > 0) {
return set(columnGreaterThan0[rule.column]);
} else {
return set(normal);
}
}
private:
RuleAndInclude normal;
RuleAndInclude column0;
QMap<int, RuleAndInclude> columnGreaterThan0;
RuleAndInclude firstNonSpace;
}; };
// Associate QChar with RuleAndInclude // Associate QChar with RuleAndInclude
@@ -1489,8 +1620,9 @@ private:
/// Search RuleAndInclude associated with @p c. /// Search RuleAndInclude associated with @p c.
RuleAndInclude find(QChar c) const RuleAndInclude find(QChar c) const
{ {
if (c.unicode() < 128) if (c.unicode() < 128) {
return m_asciiMap[c.unicode()]; return m_asciiMap[c.unicode()];
}
auto it = m_utf8Map.find(c); auto it = m_utf8Map.find(c);
return it == m_utf8Map.end() ? RuleAndInclude{nullptr, nullptr} : it.value(); return it == m_utf8Map.end() ? RuleAndInclude{nullptr, nullptr} : it.value();
} }
@@ -1517,11 +1649,12 @@ private:
/// Associates @p c with a rule. /// Associates @p c with a rule.
void append(QChar c, const Context::Rule &rule, const Context::Rule *includeRule = nullptr) void append(QChar c, const Context::Rule &rule, const Context::Rule *includeRule = nullptr)
{ {
if (c.unicode() < 128) if (c.unicode() < 128) {
m_asciiMap[c.unicode()] = {&rule, includeRule}; m_asciiMap[c.unicode()] = {&rule, includeRule};
else } else {
m_utf8Map[c] = {&rule, includeRule}; m_utf8Map[c] = {&rule, includeRule};
} }
}
/// Associates each character of @p s with a rule. /// Associates each character of @p s with a rule.
void append(QStringView s, const Context::Rule &rule, const Context::Rule *includeRule = nullptr) void append(QStringView s, const Context::Rule &rule, const Context::Rule *includeRule = nullptr)
@@ -1549,13 +1682,15 @@ private:
// Char4Tables::char is always added. // Char4Tables::char is always added.
CharTableArray(Char4Tables &tables, const Context::Rule &rule) CharTableArray(Char4Tables &tables, const Context::Rule &rule)
{ {
if (rule.firstNonSpace == XmlBool::True) if (rule.firstNonSpace == XmlBool::True) {
appendTable(tables.charsFirstNonSpace); appendTable(tables.charsFirstNonSpace);
}
if (rule.column == 0) if (rule.column == 0) {
appendTable(tables.charsColumn0); appendTable(tables.charsColumn0);
else if (rule.column > 0) } else if (rule.column > 0) {
appendTable(tables.charsColumnGreaterThan0[rule.column]); appendTable(tables.charsColumnGreaterThan0[rule.column]);
}
appendTable(tables.chars); appendTable(tables.chars);
} }
@@ -1572,9 +1707,10 @@ private:
RuleAndInclude find(QChar c) const RuleAndInclude find(QChar c) const
{ {
for (int i = 0; i < m_size; ++i) { for (int i = 0; i < m_size; ++i) {
if (auto ruleAndInclude = m_charTables[i]->find(c)) if (auto ruleAndInclude = m_charTables[i]->find(c)) {
return ruleAndInclude; return ruleAndInclude;
} }
}
return RuleAndInclude{nullptr, nullptr}; return RuleAndInclude{nullptr, nullptr};
} }
@@ -1621,9 +1757,19 @@ private:
int m_size = 0; int m_size = 0;
}; };
struct ObservableRule {
const Context::Rule *rule;
const Context::Rule *includeRules;
bool hasResolvedIncludeRules() const
{
return rule == includeRules;
}
};
// Iterates over all the rules, including those in includedRules // Iterates over all the rules, including those in includedRules
struct RuleIterator { struct RuleIterator {
RuleIterator(const QVector<Context::Rule> &rules, const Context::Rule &endRule) RuleIterator(const QVector<ObservableRule> &rules, const ObservableRule &endRule)
: m_end(&endRule - rules.data()) : m_end(&endRule - rules.data())
, m_rules(rules) , m_rules(rules)
{ {
@@ -1635,7 +1781,7 @@ private:
// if in includedRules // if in includedRules
if (m_includedRules) { if (m_includedRules) {
++m_i2; ++m_i2;
if (m_i2 != m_rules[m_i].includedRules.size()) { if (m_i2 != m_includedRules->size()) {
return (*m_includedRules)[m_i2]; return (*m_includedRules)[m_i2];
} }
++m_i; ++m_i;
@@ -1643,10 +1789,10 @@ private:
} }
// if is a includedRules // if is a includedRules
while (m_i < m_end && m_rules[m_i].type == Context::Rule::Type::IncludeRules) { while (m_i < m_end && m_rules[m_i].rule->type == Context::Rule::Type::IncludeRules) {
if (m_rules[m_i].includedRules.size()) { if (!m_rules[m_i].includeRules && m_rules[m_i].rule->includedRules.size()) {
m_i2 = 0; m_i2 = 0;
m_includedRules = &m_rules[m_i].includedRules; m_includedRules = &m_rules[m_i].rule->includedRules;
return (*m_includedRules)[m_i2]; return (*m_includedRules)[m_i2];
} }
++m_i; ++m_i;
@@ -1654,7 +1800,7 @@ private:
if (m_i < m_end) { if (m_i < m_end) {
++m_i; ++m_i;
return &m_rules[m_i - 1]; return m_rules[m_i - 1].rule;
} }
return nullptr; return nullptr;
@@ -1663,14 +1809,14 @@ private:
/// \return current IncludeRules or nullptr /// \return current IncludeRules or nullptr
const Context::Rule *currentIncludeRules() const const Context::Rule *currentIncludeRules() const
{ {
return m_includedRules ? &m_rules[m_i] : nullptr; return m_includedRules ? m_rules[m_i].rule : m_rules[m_i].includeRules;
} }
private: private:
int m_i = 0; int m_i = 0;
int m_i2; int m_i2;
int m_end; int m_end;
const QVector<Context::Rule> &m_rules; const QVector<ObservableRule> &m_rules;
const QVector<const Context::Rule *> *m_includedRules = nullptr; const QVector<const Context::Rule *> *m_includedRules = nullptr;
}; };
@@ -1680,20 +1826,24 @@ private:
void append(const Context::Rule &rule, const Context::Rule *includedRule) void append(const Context::Rule &rule, const Context::Rule *includedRule)
{ {
auto array = extractDotRegexes(rule); auto array = extractDotRegexes(rule);
if (array[0]) if (array[0]) {
*array[0] = {&rule, includedRule}; *array[0] = {&rule, includedRule};
if (array[1]) }
if (array[1]) {
*array[1] = {&rule, includedRule}; *array[1] = {&rule, includedRule};
} }
}
/// Search dot regex which hides @p rule /// Search dot regex which hides @p rule
RuleAndInclude find(const Context::Rule &rule) RuleAndInclude find(const Context::Rule &rule)
{ {
auto array = extractDotRegexes(rule); auto array = extractDotRegexes(rule);
if (array[0]) if (array[0]) {
return *array[0]; return *array[0];
if (array[1]) }
if (array[1]) {
return *array[1]; return *array[1];
}
return RuleAndInclude{}; return RuleAndInclude{};
} }
@@ -1707,14 +1857,16 @@ private:
if (rule.firstNonSpace != XmlBool::True && rule.column == -1) { if (rule.firstNonSpace != XmlBool::True && rule.column == -1) {
ret[0] = &dotRegex; ret[0] = &dotRegex;
} else { } else {
if (rule.firstNonSpace == XmlBool::True) if (rule.firstNonSpace == XmlBool::True) {
ret[0] = &dotRegexFirstNonSpace; ret[0] = &dotRegexFirstNonSpace;
}
if (rule.column == 0) if (rule.column == 0) {
ret[1] = &dotRegexColumn0; ret[1] = &dotRegexColumn0;
else if (rule.column > 0) } else if (rule.column > 0) {
ret[1] = &dotRegexColumnGreaterThan0[rule.column]; ret[1] = &dotRegexColumnGreaterThan0[rule.column];
} }
}
return ret; return ret;
} }
@@ -1734,23 +1886,44 @@ private:
// characters of LineContinue // characters of LineContinue
Char4Tables lineContinueChars; Char4Tables lineContinueChars;
RuleAndInclude intRule{}; Rule4 intRule{};
RuleAndInclude floatRule{}; Rule4 floatRule{};
RuleAndInclude hlCCharRule{}; Rule4 hlCCharRule{};
RuleAndInclude hlCOctRule{}; Rule4 hlCOctRule{};
RuleAndInclude hlCHexRule{}; Rule4 hlCHexRule{};
RuleAndInclude hlCStringCharRule{}; Rule4 hlCStringCharRule{};
Rule4 detectIdentifierRule{};
// Contains includedRules and included includedRules // Contains includedRules and included includedRules
QMap<Context const*, RuleAndInclude> includeContexts; QMap<Context const*, RuleAndInclude> includeContexts;
DotRegex dotRegex; DotRegex dotRegex;
QVector<ObservableRule> observedRules;
observedRules.reserve(context.rules.size());
for (const Context::Rule &rule : context.rules) { for (const Context::Rule &rule : context.rules) {
const Context::Rule *includeRule = nullptr;
if (rule.type == Context::Rule::Type::IncludeRules) {
auto *context = rule.context.context;
if (context && context->isOnlyIncluded) {
includeRule = &rule;
}
}
observedRules.push_back({&rule, includeRule});
if (includeRule) {
for (const Context::Rule *rule2 : rule.includedRules) {
observedRules.push_back({rule2, includeRule});
}
}
}
for (auto &observedRule : observedRules) {
const Context::Rule &rule = *observedRule.rule;
bool isUnreachable = false; bool isUnreachable = false;
QVector<RuleAndInclude> unreachableBy; QVector<RuleAndInclude> unreachableBy;
// declare rule as unreacheable if ruleAndInclude is not empty // declare rule as unreachable if ruleAndInclude is not empty
auto updateUnreachable1 = [&](RuleAndInclude ruleAndInclude) { auto updateUnreachable1 = [&](RuleAndInclude ruleAndInclude) {
if (ruleAndInclude) { if (ruleAndInclude) {
isUnreachable = true; isUnreachable = true;
@@ -1758,7 +1931,7 @@ private:
} }
}; };
// declare rule as unreacheable if ruleAndIncludes is not empty // declare rule as unreachable if ruleAndIncludes is not empty
auto updateUnreachable2 = [&](const QVector<RuleAndInclude> &ruleAndIncludes) { auto updateUnreachable2 = [&](const QVector<RuleAndInclude> &ruleAndIncludes) {
if (!ruleAndIncludes.isEmpty()) { if (!ruleAndIncludes.isEmpty()) {
isUnreachable = true; isUnreachable = true;
@@ -1810,43 +1983,42 @@ private:
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::HlCChar: case Context::Rule::Type::HlCChar:
updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('\''))); updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('\'')));
updateUnreachable1(hlCCharRule); updateUnreachable1(hlCCharRule.setRule(rule));
hlCCharRule = {&rule, nullptr};
break; break;
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::HlCHex: case Context::Rule::Type::HlCHex:
updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('0'))); updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('0')));
updateUnreachable1(hlCHexRule); updateUnreachable1(hlCHexRule.setRule(rule));
hlCHexRule = {&rule, nullptr};
break; break;
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::HlCOct: case Context::Rule::Type::HlCOct:
updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('0'))); updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('0')));
updateUnreachable1(hlCOctRule); updateUnreachable1(hlCOctRule.setRule(rule));
hlCOctRule = {&rule, nullptr};
break; break;
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::HlCStringChar: case Context::Rule::Type::HlCStringChar:
updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('\\'))); updateUnreachable1(CharTableArray(detectChars, rule).find(QLatin1Char('\\')));
updateUnreachable1(hlCStringCharRule); updateUnreachable1(hlCStringCharRule.setRule(rule));
hlCStringCharRule = {&rule, nullptr};
break; break;
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::Int: case Context::Rule::Type::Int:
updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789"))); updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789")));
updateUnreachable1(intRule); updateUnreachable1(intRule.setRule(rule));
intRule = {&rule, nullptr};
break; break;
// check if hidden by DetectChar/AnyChar // check if hidden by DetectChar/AnyChar
case Context::Rule::Type::Float: case Context::Rule::Type::Float:
updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789."))); updateUnreachable2(CharTableArray(detectChars, rule).find(QStringLiteral("0123456789.")));
updateUnreachable1(floatRule); updateUnreachable1(floatRule.setRule(rule));
floatRule = {&rule, nullptr}; break;
// check if hidden by another DetectIdentifier rule
case Context::Rule::Type::DetectIdentifier:
updateUnreachable1(detectIdentifierRule.setRule(rule));
break; break;
// check if hidden by DetectChar/AnyChar or another LineContinue // check if hidden by DetectChar/AnyChar or another LineContinue
@@ -1865,10 +2037,11 @@ private:
case Context::Rule::Type::RangeDetect: case Context::Rule::Type::RangeDetect:
updateUnreachable1(CharTableArray(detectChars, rule).find(rule.char0)); updateUnreachable1(CharTableArray(detectChars, rule).find(rule.char0));
if (!isUnreachable) { if (!isUnreachable) {
RuleIterator ruleIterator(context.rules, rule); RuleIterator ruleIterator(observedRules, observedRule);
while (const auto *rulePtr = ruleIterator.next()) { while (const auto *rulePtr = ruleIterator.next()) {
if (isUnreachable) if (isUnreachable) {
break; break;
}
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
if (rule2.type == rule.type && isCompatible(rule2) && rule.char0 == rule2.char0 && rule.char1 == rule2.char1) { if (rule2.type == rule.type && isCompatible(rule2) && rule.char0 == rule2.char0 && rule.char1 == rule2.char1) {
updateUnreachable1({&rule2, ruleIterator.currentIncludeRules()}); updateUnreachable1({&rule2, ruleIterator.currentIncludeRules()});
@@ -1884,10 +2057,11 @@ private:
} }
// check that `rule` does not have another RegExpr as a prefix // check that `rule` does not have another RegExpr as a prefix
RuleIterator ruleIterator(context.rules, rule); RuleIterator ruleIterator(observedRules, observedRule);
while (const auto *rulePtr = ruleIterator.next()) { while (const auto *rulePtr = ruleIterator.next()) {
if (isUnreachable) if (isUnreachable) {
break; break;
}
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
if (rule2.type == Context::Rule::Type::RegExpr && isCompatible(rule2) && rule.insensitive == rule2.insensitive if (rule2.type == Context::Rule::Type::RegExpr && isCompatible(rule2) && rule.insensitive == rule2.insensitive
&& rule.dynamic == rule2.dynamic && rule.string.startsWith(rule2.string)) { && rule.dynamic == rule2.dynamic && rule.string.startsWith(rule2.string)) {
@@ -1902,10 +2076,11 @@ private:
case Context::Rule::Type::StringDetect: { case Context::Rule::Type::StringDetect: {
// check that dynamic `rule` does not have another dynamic StringDetect as a prefix // check that dynamic `rule` does not have another dynamic StringDetect as a prefix
if (rule.type == Context::Rule::Type::StringDetect && rule.dynamic == XmlBool::True) { if (rule.type == Context::Rule::Type::StringDetect && rule.dynamic == XmlBool::True) {
RuleIterator ruleIterator(context.rules, rule); RuleIterator ruleIterator(observedRules, observedRule);
while (const auto *rulePtr = ruleIterator.next()) { while (const auto *rulePtr = ruleIterator.next()) {
if (isUnreachable) if (isUnreachable) {
break; break;
}
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
if (rule2.type != Context::Rule::Type::StringDetect || rule2.dynamic != XmlBool::True || !isCompatible(rule2)) { if (rule2.type != Context::Rule::Type::StringDetect || rule2.dynamic != XmlBool::True || !isCompatible(rule2)) {
@@ -1963,10 +2138,11 @@ private:
// combination of uppercase and lowercase // combination of uppercase and lowercase
RuleAndInclude detect2CharsInsensitives[]{{}, {}, {}, {}}; RuleAndInclude detect2CharsInsensitives[]{{}, {}, {}, {}};
RuleIterator ruleIterator(context.rules, rule); RuleIterator ruleIterator(observedRules, observedRule);
while (const auto *rulePtr = ruleIterator.next()) { while (const auto *rulePtr = ruleIterator.next()) {
if (isUnreachable) if (isUnreachable) {
break; break;
}
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
const bool isSensitive = (rule2.insensitive == XmlBool::True); const bool isSensitive = (rule2.insensitive == XmlBool::True);
const auto caseSensitivity = isSensitive ? Qt::CaseInsensitive : Qt::CaseSensitive; const auto caseSensitivity = isSensitive ? Qt::CaseInsensitive : Qt::CaseSensitive;
@@ -2030,10 +2206,11 @@ private:
// check if hidden by another keyword rule // check if hidden by another keyword rule
case Context::Rule::Type::keyword: { case Context::Rule::Type::keyword: {
RuleIterator ruleIterator(context.rules, rule); RuleIterator ruleIterator(observedRules, observedRule);
while (const auto *rulePtr = ruleIterator.next()) { while (const auto *rulePtr = ruleIterator.next()) {
if (isUnreachable) if (isUnreachable) {
break; break;
}
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
if (rule2.type == Context::Rule::Type::keyword && isCompatible(rule2) && rule.string == rule2.string) { if (rule2.type == Context::Rule::Type::keyword && isCompatible(rule2) && rule.string == rule2.string) {
updateUnreachable1({&rule2, ruleIterator.currentIncludeRules()}); updateUnreachable1({&rule2, ruleIterator.currentIncludeRules()});
@@ -2049,6 +2226,10 @@ private:
// <includedRules .../> <- reference a <DetectChar char="{" /> who will be added // <includedRules .../> <- reference a <DetectChar char="{" /> who will be added
// <DetectChar char="{" /> <- hidden by previous rule // <DetectChar char="{" /> <- hidden by previous rule
case Context::Rule::Type::IncludeRules: case Context::Rule::Type::IncludeRules:
if (observedRule.includeRules && !observedRule.hasResolvedIncludeRules()) {
break;
}
if (auto &ruleAndInclude = includeContexts[rule.context.context]) { if (auto &ruleAndInclude = includeContexts[rule.context.context]) {
updateUnreachable1(ruleAndInclude); updateUnreachable1(ruleAndInclude);
} }
@@ -2060,6 +2241,10 @@ private:
includeContexts.insert(rulePtr->context.context, RuleAndInclude{rulePtr, &rule}); includeContexts.insert(rulePtr->context.context, RuleAndInclude{rulePtr, &rule});
} }
if (observedRule.includeRules) {
break;
}
for (const auto *rulePtr : rule.includedRules) { for (const auto *rulePtr : rule.includedRules) {
const auto &rule2 = *rulePtr; const auto &rule2 = *rulePtr;
switch (rule2.type) { switch (rule2.type) {
@@ -2087,27 +2272,27 @@ private:
} }
case Context::Rule::Type::HlCChar: case Context::Rule::Type::HlCChar:
hlCCharRule = {&rule2, &rule}; hlCCharRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::HlCHex: case Context::Rule::Type::HlCHex:
hlCHexRule = {&rule2, &rule}; hlCHexRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::HlCOct: case Context::Rule::Type::HlCOct:
hlCOctRule = {&rule2, &rule}; hlCOctRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::HlCStringChar: case Context::Rule::Type::HlCStringChar:
hlCStringCharRule = {&rule2, &rule}; hlCStringCharRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::Int: case Context::Rule::Type::Int:
intRule = {&rule2, &rule}; intRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::Float: case Context::Rule::Type::Float:
floatRule = {&rule2, &rule}; floatRule.setRule(rule2, &rule);
break; break;
case Context::Rule::Type::LineContinue: { case Context::Rule::Type::LineContinue: {
@@ -2136,12 +2321,18 @@ private:
} }
break; break;
case Context::Rule::Type::DetectIdentifier:
case Context::Rule::Type::Unknown: case Context::Rule::Type::Unknown:
break; break;
} }
if (isUnreachable) { if (observedRule.includeRules && !observedRule.hasResolvedIncludeRules()) {
auto &unreachableIncludedRule = unreachableIncludedRules[&rule];
if (isUnreachable && unreachableIncludedRule.alwaysUnreachable) {
unreachableIncludedRule.unreachableBy.append(unreachableBy);
} else {
unreachableIncludedRule.alwaysUnreachable = false;
}
} else if (isUnreachable) {
success = false; success = false;
QString message; QString message;
message.reserve(128); message.reserve(128);
@@ -2165,7 +2356,7 @@ private:
message += QStringLiteral(", "); message += QStringLiteral(", ");
} }
message.chop(2); message.chop(2);
qWarning() << filename << "line" << rule.line << "unreachable element by" << message; qWarning() << filename << "line" << rule.line << "unreachable rule by" << message;
} }
} }
@@ -2179,8 +2370,9 @@ private:
{ {
bool success = true; bool success = true;
if (context.rules.isEmpty()) if (context.rules.isEmpty()) {
return success; return success;
}
auto it = context.rules.begin(); auto it = context.rules.begin();
const auto end = context.rules.end() - 1; const auto end = context.rules.end() - 1;
@@ -2249,7 +2441,7 @@ private:
//! - "#pop!Comment" -> "Comment" //! - "#pop!Comment" -> "Comment"
//! - "##ISO C++" -> "" //! - "##ISO C++" -> ""
//! - "Comment##ISO C++"-> "Comment" in ISO C++ //! - "Comment##ISO C++"-> "Comment" in ISO C++
void resolveContextName(Definition &definition, const Context &context, ContextName &contextName, int line) void resolveContextName(Definition &definition, Context &context, ContextName &contextName, int line)
{ {
QString name = contextName.name; QString name = contextName.name;
if (name.isEmpty()) { if (name.isEmpty()) {
@@ -2281,8 +2473,9 @@ private:
const int idx = name.indexOf(QStringLiteral("##")); const int idx = name.indexOf(QStringLiteral("##"));
if (idx == -1) { if (idx == -1) {
auto it = definition.contexts.find(name); auto it = definition.contexts.find(name);
if (it != definition.contexts.end()) if (it != definition.contexts.end()) {
contextName.context = &*it; contextName.context = &*it;
}
} else { } else {
auto defName = name.mid(idx + 2); auto defName = name.mid(idx + 2);
auto listName = name.left(idx); auto listName = name.left(idx);
@@ -2392,14 +2585,16 @@ int main(int argc, char *argv[])
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
// ensure enough arguments are passed // ensure enough arguments are passed
if (app.arguments().size() < 3) if (app.arguments().size() < 3) {
return 1; return 1;
}
#ifdef QT_XMLPATTERNS_LIB #ifdef QT_XMLPATTERNS_LIB
// open schema // open schema
QXmlSchema schema; QXmlSchema schema;
if (!schema.load(QUrl::fromLocalFile(app.arguments().at(2)))) if (!schema.load(QUrl::fromLocalFile(app.arguments().at(2)))) {
return 2; return 2;
}
#endif #endif
const QString hlFilenamesListing = app.arguments().value(3); const QString hlFilenamesListing = app.arguments().value(3);
@@ -2422,7 +2617,7 @@ int main(int argc, char *argv[])
HlFilesChecker filesChecker; HlFilesChecker filesChecker;
QVariantMap hls; QVariantMap hls;
int anyError = 0; int anyError = 0;
for (const QString &hlFilename : qAsConst(hlFilenames)) { for (const QString &hlFilename : std::as_const(hlFilenames)) {
QFile hlFile(hlFilename); QFile hlFile(hlFilename);
if (!hlFile.open(QIODevice::ReadOnly)) { if (!hlFile.open(QIODevice::ReadOnly)) {
qWarning("Failed to open %s", qPrintable(hlFilename)); qWarning("Failed to open %s", qPrintable(hlFilename));
@@ -2456,7 +2651,7 @@ int main(int argc, char *argv[])
QVariantMap hl; QVariantMap hl;
// transfer text attributes // transfer text attributes
for (const QString &attribute : qAsConst(textAttributes)) { for (const QString &attribute : std::as_const(textAttributes)) {
hl[attribute] = xml.attributes().value(attribute).toString(); hl[attribute] = xml.attributes().value(attribute).toString();
} }
@@ -2489,17 +2684,20 @@ int main(int argc, char *argv[])
filesChecker.resolveContexts(); filesChecker.resolveContexts();
if (!filesChecker.check()) if (!filesChecker.check()) {
anyError = 7; anyError = 7;
}
// bail out if any problem was seen // bail out if any problem was seen
if (anyError) if (anyError) {
return anyError; return anyError;
}
// create outfile, after all has worked! // create outfile, after all has worked!
QFile outFile(app.arguments().at(1)); QFile outFile(app.arguments().at(1));
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return 9; return 9;
}
// write out json // write out json
outFile.write(QCborValue::fromVariant(QVariant(hls)).toCbor()); outFile.write(QCborValue::fromVariant(QVariant(hls)).toCbor());

View File

@@ -1,6 +1,8 @@
add_library(KF5SyntaxHighlighting)
ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting5_qt) ecm_create_qm_loader(syntax_highlighting_QM_LOADER syntaxhighlighting5_qt)
set(syntax_highlighting_srcs target_sources(KF5SyntaxHighlighting PRIVATE
abstracthighlighter.cpp abstracthighlighter.cpp
context.cpp context.cpp
contextswitch.cpp contextswitch.cpp
@@ -20,8 +22,9 @@ set(syntax_highlighting_srcs
themedata.cpp themedata.cpp
worddelimiters.cpp worddelimiters.cpp
${syntax_highlighting_QM_LOADER} ${syntax_highlighting_QM_LOADER}
$<TARGET_OBJECTS:SyntaxHighlightingData>
) )
ecm_qt_declare_logging_category(syntax_highlighting_srcs ecm_qt_declare_logging_category(KF5SyntaxHighlighting
HEADER ksyntaxhighlighting_logging.h HEADER ksyntaxhighlighting_logging.h
IDENTIFIER KSyntaxHighlighting::Log IDENTIFIER KSyntaxHighlighting::Log
CATEGORY_NAME kf.syntaxhighlighting CATEGORY_NAME kf.syntaxhighlighting
@@ -30,16 +33,27 @@ ecm_qt_declare_logging_category(syntax_highlighting_srcs
EXPORT KSYNTAXHIGHLIGHTING EXPORT KSYNTAXHIGHLIGHTING
) )
add_library(KF5SyntaxHighlighting ${syntax_highlighting_srcs} $<TARGET_OBJECTS:SyntaxHighlightingData>) ecm_generate_export_header(KF5SyntaxHighlighting
generate_export_header(KF5SyntaxHighlighting BASE_NAME KSyntaxHighlighting) BASE_NAME KSyntaxHighlighting
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
DEPRECATED_BASE_VERSION 0
DEPRECATION_VERSIONS 5.87
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
set_target_properties(KF5SyntaxHighlighting PROPERTIES set_target_properties(KF5SyntaxHighlighting PROPERTIES
VERSION ${SyntaxHighlighting_VERSION_STRING} VERSION ${SyntaxHighlighting_VERSION}
SOVERSION ${SyntaxHighlighting_SOVERSION} SOVERSION ${SyntaxHighlighting_SOVERSION}
EXPORT_NAME SyntaxHighlighting EXPORT_NAME SyntaxHighlighting
) )
target_include_directories(KF5SyntaxHighlighting INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KSyntaxHighlighting;${KDE_INSTALL_INCLUDEDIR_KF5}>") target_include_directories(KF5SyntaxHighlighting INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KSyntaxHighlighting;${KDE_INSTALL_INCLUDEDIR_KF5}>")
target_include_directories(KF5SyntaxHighlighting PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};>") target_include_directories(KF5SyntaxHighlighting PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR};>")
target_link_libraries(KF5SyntaxHighlighting LINK_PUBLIC Qt5::Gui LINK_PRIVATE Qt5::Network) target_link_libraries(KF5SyntaxHighlighting
PUBLIC
Qt5::Gui
PRIVATE
Qt5::Network
)
ecm_generate_headers(SyntaxHighlighting_HEADERS ecm_generate_headers(SyntaxHighlighting_HEADERS
HEADER_NAMES HEADER_NAMES
@@ -52,6 +66,7 @@ ecm_generate_headers(SyntaxHighlighting_HEADERS
State State
SyntaxHighlighter SyntaxHighlighter
Theme Theme
WildcardMatcher
REQUIRED_HEADERS SyntaxHighlighting_HEADERS REQUIRED_HEADERS SyntaxHighlighting_HEADERS
) )

View File

@@ -36,12 +36,14 @@ void AbstractHighlighterPrivate::ensureDefinitionLoaded()
defData = DefinitionData::get(m_definition); defData = DefinitionData::get(m_definition);
} }
if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty())) if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty())) {
qCCritical(Log) << "Repository got deleted while a highlighter is still active!"; qCCritical(Log) << "Repository got deleted while a highlighter is still active!";
}
if (m_definition.isValid()) if (m_definition.isValid()) {
defData->load(); defData->load();
} }
}
AbstractHighlighter::AbstractHighlighter() AbstractHighlighter::AbstractHighlighter()
: d_ptr(new AbstractHighlighterPrivate) : d_ptr(new AbstractHighlighterPrivate)
@@ -85,7 +87,7 @@ void AbstractHighlighter::setTheme(const Theme &theme)
* Returns the index of the first non-space character. If the line is empty, * Returns the index of the first non-space character. If the line is empty,
* or only contains white spaces, text.size() is returned. * or only contains white spaces, text.size() is returned.
*/ */
static inline int firstNonSpaceChar(const QString &text) static inline int firstNonSpaceChar(QStringView text)
{ {
for (int i = 0; i < text.length(); ++i) { for (int i = 0; i < text.length(); ++i) {
if (!text[i].isSpace()) { if (!text[i].isSpace()) {
@@ -95,7 +97,14 @@ static inline int firstNonSpaceChar(const QString &text)
return text.size(); return text.size();
} }
#if KSYNTAXHIGHLIGHTING_BUILD_DEPRECATED_SINCE(5, 87)
State AbstractHighlighter::highlightLine(const QString &text, const State &state) State AbstractHighlighter::highlightLine(const QString &text, const State &state)
{
return highlightLine(QStringView(text), state);
}
#endif
State AbstractHighlighter::highlightLine(QStringView text, const State &state)
{ {
Q_D(AbstractHighlighter); Q_D(AbstractHighlighter);
@@ -145,8 +154,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
* skipping empty lines after a line continuation character (see bug 405903) * skipping empty lines after a line continuation character (see bug 405903)
*/ */
} else if (!stateData->topContext()->lineEndContext().isStay() } else if (!stateData->topContext()->lineEndContext().isStay()
&& !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) && !d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) {
break; break;
}
// guard against endless loops // guard against endless loops
++endlessLoopingCounter; ++endlessLoopingCounter;
@@ -160,7 +170,8 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
return newState; return newState;
} }
int offset = 0, beginOffset = 0; int offset = 0;
int beginOffset = 0;
bool lineContinuation = false; bool lineContinuation = false;
/** /**
@@ -247,8 +258,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
skipOffsets.clear(); skipOffsets.clear();
} }
const auto currentSkipOffset = skipOffsets.value(rule.get()); const auto currentSkipOffset = skipOffsets.value(rule.get());
if (currentSkipOffset < 0 || currentSkipOffset > offset) if (currentSkipOffset < 0 || currentSkipOffset > offset) {
continue; continue;
}
const auto newResult = rule->doMatch(text, offset, stateData->topCaptures()); const auto newResult = rule->doMatch(text, offset, stateData->topCaptures());
newOffset = newResult.offset(); newOffset = newResult.offset();
@@ -265,8 +277,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
} }
} }
if (newOffset <= offset) if (newOffset <= offset) {
continue; continue;
}
/** /**
* apply folding. * apply folding.
@@ -274,12 +287,14 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
* - rule with endRegion + beginRegion: in endRegion, the length is 0 * - rule with endRegion + beginRegion: in endRegion, the length is 0
* - rule with lookAhead: length is 0 * - rule with lookAhead: length is 0
*/ */
if (rule->endRegion().isValid() && rule->beginRegion().isValid()) if (rule->endRegion().isValid() && rule->beginRegion().isValid()) {
applyFolding(offset, 0, rule->endRegion()); applyFolding(offset, 0, rule->endRegion());
else if (rule->endRegion().isValid()) } else if (rule->endRegion().isValid()) {
applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion()); applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion());
if (rule->beginRegion().isValid()) }
if (rule->beginRegion().isValid()) {
applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion()); applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion());
}
if (rule->isLookAhead()) { if (rule->isLookAhead()) {
Q_ASSERT(!rule->context().isStay()); Q_ASSERT(!rule->context().isStay());
@@ -290,12 +305,14 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
d->switchContext(stateData, rule->context(), newResult.captures()); d->switchContext(stateData, rule->context(), newResult.captures());
newFormat = rule->attributeFormat().isValid() ? &rule->attributeFormat() : &stateData->topContext()->attributeFormat(); newFormat = rule->attributeFormat().isValid() ? &rule->attributeFormat() : &stateData->topContext()->attributeFormat();
if (newOffset == text.size() && std::dynamic_pointer_cast<LineContinue>(rule)) if (newOffset == text.size() && std::dynamic_pointer_cast<LineContinue>(rule)) {
lineContinuation = true; lineContinuation = true;
}
break; break;
} }
if (isLookAhead) if (isLookAhead) {
continue; continue;
}
if (newOffset <= offset) { // no matching rule if (newOffset <= offset) { // no matching rule
if (stateData->topContext()->fallthrough()) { if (stateData->topContext()->fallthrough()) {
@@ -316,8 +333,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
* on format change, apply the last one and switch to new one * on format change, apply the last one and switch to new one
*/ */
if (newFormat != currentFormat && newFormat->id() != currentFormat->id()) { if (newFormat != currentFormat && newFormat->id() != currentFormat->id()) {
if (offset > 0) if (offset > 0) {
applyFormat(beginOffset, offset - beginOffset, *currentFormat); applyFormat(beginOffset, offset - beginOffset, *currentFormat);
}
beginOffset = offset; beginOffset = offset;
currentFormat = newFormat; currentFormat = newFormat;
} }
@@ -333,8 +351,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
/** /**
* apply format for remaining text, if any * apply format for remaining text, if any
*/ */
if (beginOffset < offset) if (beginOffset < offset) {
applyFormat(beginOffset, text.size() - beginOffset, *currentFormat); applyFormat(beginOffset, text.size() - beginOffset, *currentFormat);
}
/** /**
* handle line end context switches * handle line end context switches
@@ -344,8 +363,9 @@ State AbstractHighlighter::highlightLine(const QString &text, const State &state
{ {
int endlessLoopingCounter = 0; int endlessLoopingCounter = 0;
while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) { while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) {
if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList())) {
break; break;
}
// guard against endless loops // guard against endless loops
++endlessLoopingCounter; ++endlessLoopingCounter;

View File

@@ -108,6 +108,15 @@ protected:
AbstractHighlighter(); AbstractHighlighter();
AbstractHighlighter(AbstractHighlighterPrivate *dd); AbstractHighlighter(AbstractHighlighterPrivate *dd);
#if KSYNTAXHIGHLIGHTING_ENABLE_DEPRECATED_SINCE(5, 87)
/**
* @copydoc highlightLine(QStringView,const State&)
* @deprecated since 5.87, use highlightLine(QStringView, const State&) instead.
*/
// no deprecation warning, as removal of this will automatically "port" the using code
State highlightLine(const QString &text, const State &state);
#endif
// TODO KF6: add an optional void* context argument that is passed through // TODO KF6: add an optional void* context argument that is passed through
// to the applyX() calls, so highlighters dealing with some form of line object // to the applyX() calls, so highlighters dealing with some form of line object
// (such as QSyntaxHighlighter or KTextEditor) can avoid some ugly hacks to have // (such as QSyntaxHighlighter or KTextEditor) can avoid some ugly hacks to have
@@ -120,14 +129,14 @@ protected:
* @param state The highlighting state handle returned by the call * @param state The highlighting state handle returned by the call
* to highlightLine() for the previous line. For the very first line, * to highlightLine() for the previous line. For the very first line,
* just pass a default constructed State(). * just pass a default constructed State().
* @returns The state of the highlighing engine after processing the * @returns The state of the highlighting engine after processing the
* given line. This needs to passed into highlightLine() for the * given line. This needs to passed into highlightLine() for the
* next line. You can store the state for efficient partial * next line. You can store the state for efficient partial
* re-highlighting for example during editing. * re-highlighting for example during editing.
* *
* @see applyFormat(), applyFolding() * @see applyFormat(), applyFolding()
*/ */
State highlightLine(const QString &text, const State &state); State highlightLine(QStringView text, const State &state);
/** /**
* Reimplement this to apply formats to your output. The provided @p format * Reimplement this to apply formats to your output. The provided @p format

View File

@@ -33,10 +33,6 @@ struct CieLab {
double b; double b;
}; };
#ifndef M_PI
constexpr double M_PI = 3.14159265358979323846;
#endif
// clang-format off // clang-format off
// xterm color reference // xterm color reference
// constexpr Rgb888 xterm256Colors[] { // constexpr Rgb888 xterm256Colors[] {
@@ -388,10 +384,11 @@ CieLab rgbToLab(QRgb rgb)
// Perform the inverse gamma companding for a sRGB color // Perform the inverse gamma companding for a sRGB color
// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html // http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
auto inverseGammaCompanding = [](int c) { auto inverseGammaCompanding = [](int c) {
if (c <= 10) if (c <= 10) {
return c / (255.0 * 12.92); return c / (255.0 * 12.92);
else } else {
return std::pow((c / 255.0 + 0.055) / 1.055, 2.4); return std::pow((c / 255.0 + 0.055) / 1.055, 2.4);
}
}; };
const double r = inverseGammaCompanding(qRed(rgb)); const double r = inverseGammaCompanding(qRed(rgb));
@@ -404,10 +401,11 @@ CieLab rgbToLab(QRgb rgb)
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
auto f = [](double t) { auto f = [](double t) {
if (t > 216.0 / 24389.0) if (t > 216.0 / 24389.0) {
return std::cbrt(t); return std::cbrt(t);
else } else {
return t * (24389.0 / (27.0 * 116.0)) + 4.0 / 29.0; return t * (24389.0 / (27.0 * 116.0)) + 4.0 / 29.0;
}
}; };
const double f_x = f(x / illuminant_D65[0]); const double f_x = f(x / illuminant_D65[0]);
@@ -440,8 +438,9 @@ inline double pow2(double x)
inline double computeHPrime(double a_prime, double b) inline double computeHPrime(double a_prime, double b)
{ {
if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) {
return 0.0; return 0.0;
}
const double value = std::atan2(b, a_prime) * 180.0 / M_PI; const double value = std::atan2(b, a_prime) * 180.0 / M_PI;
return (value < 0.0) ? value + 360.0 : value; return (value < 0.0) ? value + 360.0 : value;
@@ -449,35 +448,39 @@ inline double computeHPrime(double a_prime, double b)
inline double computeDeltaHPrime(double C1_prime, double C2_prime, double h1_prime, double h2_prime) inline double computeDeltaHPrime(double C1_prime, double C2_prime, double h1_prime, double h2_prime)
{ {
if (C1_prime * C2_prime < epsilon) if (C1_prime * C2_prime < epsilon) {
return 0.0; return 0.0;
}
const double diff = h2_prime - h1_prime; const double diff = h2_prime - h1_prime;
if (std::abs(diff) <= 180.0) if (std::abs(diff) <= 180.0) {
return diff; return diff;
else if (diff > 180.0) } else if (diff > 180.0) {
return diff - 360.0; return diff - 360.0;
else } else {
return diff + 360.0; return diff + 360.0;
} }
}
inline double computeHPrimeBar(double C1_prime, double C2_prime, double h1_prime, double h2_prime) inline double computeHPrimeBar(double C1_prime, double C2_prime, double h1_prime, double h2_prime)
{ {
const double sum = h1_prime + h2_prime; const double sum = h1_prime + h2_prime;
if (C1_prime * C2_prime < epsilon) if (C1_prime * C2_prime < epsilon) {
return sum; return sum;
}
const double dist = std::abs(h1_prime - h2_prime); const double dist = std::abs(h1_prime - h2_prime);
if (dist <= 180.0) if (dist <= 180.0) {
return 0.5 * sum; return 0.5 * sum;
else if (sum < 360.0) } else if (sum < 360.0) {
return 0.5 * (sum + 360.0); return 0.5 * (sum + 360.0);
else } else {
return 0.5 * (sum - 360.0); return 0.5 * (sum - 360.0);
} }
}
/// Calculate the perceptual color difference based on CIEDE2000. /// Calculate the perceptual color difference based on CIEDE2000.
/// https://en.wikipedia.org/wiki/Color_difference#CIEDE2000 /// https://en.wikipedia.org/wiki/Color_difference#CIEDE2000
@@ -702,7 +705,7 @@ struct GraphLine {
const int n2 = offset - labelLineLength; const int n2 = offset - labelLineLength;
labelLineLength += n2 + 1; labelLineLength += n2 + 1;
fillLine(labelLine, n2); fillLine(labelLine, n2);
labelLine += graphLine.rightRef(graphLine.size() - ps1); labelLine += QStringView(graphLine).right(graphLine.size() - ps1);
} }
} }
@@ -781,8 +784,9 @@ public:
state = highlightLine(currentLine, state); state = highlightLine(currentLine, state);
if (hasSeparator) { if (hasSeparator) {
if (!firstLine) if (!firstLine) {
out << QStringLiteral("\x1b[0m────────────────────────────────────────────────────\x1b[K\n"); out << QStringLiteral("\x1b[0m────────────────────────────────────────────────────\x1b[K\n");
}
firstLine = false; firstLine = false;
} }
@@ -793,14 +797,15 @@ public:
for (const auto &fragment : m_highlightedFragments) { for (const auto &fragment : m_highlightedFragments) {
auto const &ansiStyle = ansiStyles[fragment.formatId]; auto const &ansiStyle = ansiStyles[fragment.formatId];
out << ansiStyle.first << currentLine.midRef(fragment.offset, fragment.length) << ansiStyle.second; out << ansiStyle.first << QStringView(currentLine).mid(fragment.offset, fragment.length) << ansiStyle.second;
} }
out << QStringLiteral("\x1b[K\n"); out << QStringLiteral("\x1b[K\n");
if (hasFormatOrContextTrace && !m_highlightedFragments.empty()) { if (hasFormatOrContextTrace && !m_highlightedFragments.empty()) {
if (m_hasContextTrace || m_hasStackSizeTrace) if (m_hasContextTrace || m_hasStackSizeTrace) {
appendContextNames(oldState, currentLine); appendContextNames(oldState, currentLine);
}
printFormats(out, infoStyle, ansiStyles); printFormats(out, infoStyle, ansiStyles);
out << resetBgColor; out << resetBgColor;
@@ -817,8 +822,9 @@ public:
void applyFolding(int offset, int /*length*/, FoldingRegion region) override void applyFolding(int offset, int /*length*/, FoldingRegion region) override
{ {
if (!m_hasRegionTrace) if (!m_hasRegionTrace) {
return; return;
}
const auto id = region.id(); const auto id = region.id();
@@ -829,10 +835,11 @@ public:
auto &previousRegion = m_regions[m_regions.size() - 2]; auto &previousRegion = m_regions[m_regions.size() - 2];
if (previousRegion.state == Region::State::Close && previousRegion.offset == offset) { if (previousRegion.state == Region::State::Close && previousRegion.offset == offset) {
std::swap(previousRegion, m_regions.back()); std::swap(previousRegion, m_regions.back());
if (previousRegion.bindIndex != -1) if (previousRegion.bindIndex != -1) {
m_regions[previousRegion.bindIndex].bindIndex = m_regions.size() - 1; m_regions[previousRegion.bindIndex].bindIndex = m_regions.size() - 1;
} }
} }
}
++m_regionDepth; ++m_regionDepth;
} else { } else {
// find open region // find open region
@@ -840,12 +847,13 @@ public:
auto eit = m_regions.rend(); auto eit = m_regions.rend();
for (int depth = 0; it != eit; ++it) { for (int depth = 0; it != eit; ++it) {
if (it->regionId == id && it->bindIndex < 0) { if (it->regionId == id && it->bindIndex < 0) {
if (it->state == Region::State::Close) if (it->state == Region::State::Close) {
++depth; ++depth;
else if (--depth < 0) } else if (--depth < 0) {
break; break;
} }
} }
}
if (it != eit) { if (it != eit) {
it->bindIndex = int(m_regions.size()); it->bindIndex = int(m_regions.size());
@@ -868,8 +876,9 @@ private:
void initRegionStyles(const std::vector<QPair<QString, QString>> &ansiStyles) void initRegionStyles(const std::vector<QPair<QString, QString>> &ansiStyles)
{ {
m_regionStyles.resize(ansiStyles.size()); m_regionStyles.resize(ansiStyles.size());
for (std::size_t i = 0; i < m_regionStyles.size(); ++i) for (std::size_t i = 0; i < m_regionStyles.size(); ++i) {
m_regionStyles[i] = ansiStyles[i].first; m_regionStyles[i] = ansiStyles[i].first;
}
std::sort(m_regionStyles.begin(), m_regionStyles.end()); std::sort(m_regionStyles.begin(), m_regionStyles.end());
m_regionStyles.erase(std::unique(m_regionStyles.begin(), m_regionStyles.end()), m_regionStyles.end()); m_regionStyles.erase(std::unique(m_regionStyles.begin(), m_regionStyles.end()), m_regionStyles.end());
@@ -1216,7 +1225,7 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
} }
// initialize ansiStyles // initialize ansiStyles
for (auto &&definition : qAsConst(definitions)) { for (auto &&definition : std::as_const(definitions)) {
const auto formats = definition.formats(); const auto formats = definition.formats();
for (auto &&format : formats) { for (auto &&format : formats) {
const auto id = format.id(); const auto id = format.id();
@@ -1236,20 +1245,26 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
const bool hasUnderline = format.isUnderline(theme); const bool hasUnderline = format.isUnderline(theme);
const bool hasStrikeThrough = format.isStrikeThrough(theme); const bool hasStrikeThrough = format.isStrikeThrough(theme);
if (hasFg) if (hasFg) {
buffer.appendForeground(format.textColor(theme).rgb(), is256Colors, colorCache); buffer.appendForeground(format.textColor(theme).rgb(), is256Colors, colorCache);
else } else {
buffer.append(foregroundDefaultColor); buffer.append(foregroundDefaultColor);
if (hasBg) }
if (hasBg) {
buffer.appendBackground(format.backgroundColor(theme).rgb(), is256Colors, colorCache); buffer.appendBackground(format.backgroundColor(theme).rgb(), is256Colors, colorCache);
if (hasBold) }
if (hasBold) {
buffer.append(QLatin1String("1;")); buffer.append(QLatin1String("1;"));
if (hasItalic) }
if (hasItalic) {
buffer.append(QLatin1String("3;")); buffer.append(QLatin1String("3;"));
if (hasUnderline) }
if (hasUnderline) {
buffer.append(QLatin1String("4;")); buffer.append(QLatin1String("4;"));
if (hasStrikeThrough) }
if (hasStrikeThrough) {
buffer.append(QLatin1String("9;")); buffer.append(QLatin1String("9;"));
}
// if there is ANSI style // if there is ANSI style
if (buffer.latin1().size() > 2) { if (buffer.latin1().size() > 2) {
@@ -1266,14 +1281,18 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
d->ansiStyles[id].second = buffer.latin1(); d->ansiStyles[id].second = buffer.latin1();
} else if (hasEffect) { } else if (hasEffect) {
buffer.append(QLatin1String("\x1b[")); buffer.append(QLatin1String("\x1b["));
if (hasBold) if (hasBold) {
buffer.append(QLatin1String("21;")); buffer.append(QLatin1String("21;"));
if (hasItalic) }
if (hasItalic) {
buffer.append(QLatin1String("23;")); buffer.append(QLatin1String("23;"));
if (hasUnderline) }
if (hasUnderline) {
buffer.append(QLatin1String("24;")); buffer.append(QLatin1String("24;"));
if (hasStrikeThrough) }
if (hasStrikeThrough) {
buffer.append(QLatin1String("29;")); buffer.append(QLatin1String("29;"));
}
buffer.setFinalStyle(); buffer.setFinalStyle();
d->ansiStyles[id].second = buffer.latin1(); d->ansiStyles[id].second = buffer.latin1();
} }
@@ -1301,11 +1320,12 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
d->currentLine = in.readLine(); d->currentLine = in.readLine();
state = highlightLine(d->currentLine, state); state = highlightLine(d->currentLine, state);
if (useEditorBackground) if (useEditorBackground) {
d->out << QStringLiteral("\x1b[K\n"); d->out << QStringLiteral("\x1b[K\n");
else } else {
d->out << QLatin1Char('\n'); d->out << QLatin1Char('\n');
} }
}
} else { } else {
AnsiBuffer buffer; AnsiBuffer buffer;
buffer.append(QLatin1String("\x1b[0;")); buffer.append(QLatin1String("\x1b[0;"));
@@ -1328,5 +1348,5 @@ void AnsiHighlighter::highlightData(QIODevice *dev, AnsiFormat format, bool useE
void AnsiHighlighter::applyFormat(int offset, int length, const Format &format) void AnsiHighlighter::applyFormat(int offset, int length, const Format &format)
{ {
auto const &ansiStyle = d->ansiStyles[format.id()]; auto const &ansiStyle = d->ansiStyles[format.id()];
d->out << ansiStyle.first << d->currentLine.midRef(offset, length) << ansiStyle.second; d->out << ansiStyle.first << QStringView(d->currentLine).mid(offset, length) << ansiStyle.second;
} }

View File

@@ -30,8 +30,9 @@ void Context::setDefinition(const DefinitionRef &def)
bool Context::indentationBasedFoldingEnabled() const bool Context::indentationBasedFoldingEnabled() const
{ {
if (m_noIndentationBasedFolding) if (m_noIndentationBasedFolding) {
return false; return false;
}
return m_def.definition().indentationBasedFoldingEnabled(); return m_def.definition().indentationBasedFoldingEnabled();
} }
@@ -56,8 +57,9 @@ void Context::load(QXmlStreamReader &reader)
auto rule = Rule::create(reader.name()); auto rule = Rule::create(reader.name());
if (rule) { if (rule) {
rule->setDefinition(m_def.definition()); rule->setDefinition(m_def.definition());
if (rule->load(reader)) if (rule->load(reader)) {
m_rules.push_back(std::move(rule)); m_rules.push_back(std::move(rule));
}
} else { } else {
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
@@ -79,9 +81,10 @@ void Context::resolveContexts()
m_lineEndContext.resolve(def); m_lineEndContext.resolve(def);
m_lineEmptyContext.resolve(def); m_lineEmptyContext.resolve(def);
m_fallthroughContext.resolve(def); m_fallthroughContext.resolve(def);
for (const auto &rule : m_rules) for (const auto &rule : m_rules) {
rule->resolveContext(); rule->resolveContext();
} }
}
Context::ResolveState Context::resolveState() Context::ResolveState Context::resolveState()
{ {
@@ -100,8 +103,9 @@ Context::ResolveState Context::resolveState()
void Context::resolveIncludes() void Context::resolveIncludes()
{ {
if (resolveState() == Resolved) if (resolveState() == Resolved) {
return; return;
}
if (resolveState() == Resolving) { if (resolveState() == Resolving) {
qCWarning(Log) << "Cyclic dependency!"; qCWarning(Log) << "Cyclic dependency!";
return; return;
@@ -129,11 +133,12 @@ void Context::resolveIncludes()
} }
auto defData = DefinitionData::get(def); auto defData = DefinitionData::get(def);
defData->load(); defData->load();
if (inc->contextName().isEmpty()) if (inc->contextName().isEmpty()) {
context = defData->initialContext(); context = defData->initialContext();
else } else {
context = defData->contextByName(inc->contextName()); context = defData->contextByName(inc->contextName());
} }
}
if (!context) { if (!context) {
qCWarning(Log) << "Unable to resolve include rule for definition" << inc->contextName() << "##" << inc->definitionName() << "in" qCWarning(Log) << "Unable to resolve include rule for definition" << inc->contextName() << "##" << inc->definitionName() << "in"
<< m_def.definition().name(); << m_def.definition().name();

View File

@@ -29,8 +29,9 @@ Context *ContextSwitch::context() const
void ContextSwitch::parse(QStringView contextInstr) void ContextSwitch::parse(QStringView contextInstr)
{ {
if (contextInstr.isEmpty() || contextInstr == QLatin1String("#stay")) if (contextInstr.isEmpty() || contextInstr == QLatin1String("#stay")) {
return; return;
}
if (contextInstr.startsWith(QLatin1String("#pop!"))) { if (contextInstr.startsWith(QLatin1String("#pop!"))) {
++m_popCount; ++m_popCount;
@@ -60,13 +61,15 @@ void ContextSwitch::resolve(const Definition &def)
d = DefinitionData::get(def)->repo->definitionForName(m_defName); d = DefinitionData::get(def)->repo->definitionForName(m_defName);
auto data = DefinitionData::get(d); auto data = DefinitionData::get(d);
data->load(); data->load();
if (m_contextName.isEmpty()) if (m_contextName.isEmpty()) {
m_context = data->initialContext(); m_context = data->initialContext();
} }
}
if (!m_contextName.isEmpty()) { if (!m_contextName.isEmpty()) {
m_context = DefinitionData::get(d)->contextByName(m_contextName); m_context = DefinitionData::get(d)->contextByName(m_contextName);
if (!m_context) if (!m_context) {
qCWarning(Log) << "cannot find context" << m_contextName << "in" << def.name(); qCWarning(Log) << "cannot find context" << m_contextName << "in" << def.name();
} }
} }
}

View File

@@ -51,30 +51,21 @@ DefinitionData *DefinitionData::get(const Definition &def)
Definition::Definition() Definition::Definition()
: d(new DefinitionData) : d(new DefinitionData)
{
}
Definition::Definition(const Definition &other)
: d(other.d)
{ {
d->q = *this; d->q = *this;
} }
Definition::Definition(Definition &&other) noexcept = default;
Definition::Definition(const Definition &) = default;
Definition::~Definition() = default;
Definition &Definition::operator=(Definition &&other) noexcept = default;
Definition &Definition::operator=(const Definition &) = default;
Definition::Definition(std::shared_ptr<DefinitionData> &&dd) Definition::Definition(std::shared_ptr<DefinitionData> &&dd)
: d(std::move(dd)) : d(std::move(dd))
{ {
} }
Definition::~Definition()
{
}
Definition &Definition::operator=(const Definition &rhs)
{
d = rhs.d;
return *this;
}
bool Definition::operator==(const Definition &other) const bool Definition::operator==(const Definition &other) const
{ {
return d->fileName == other.d->fileName; return d->fileName == other.d->fileName;
@@ -223,9 +214,10 @@ bool Definition::setKeywordList(const QString &name, const QStringList &content)
if (list) { if (list) {
list->setKeywordList(content); list->setKeywordList(content);
return true; return true;
} else } else {
return false; return false;
} }
}
QVector<Format> Definition::formats() const QVector<Format> Definition::formats() const
{ {
@@ -251,7 +243,7 @@ QVector<Definition> Definition::includedDefinitions() const
// Iterate all context rules to find associated Definitions. This will // Iterate all context rules to find associated Definitions. This will
// automatically catch other Definitions referenced with IncludeRuldes or ContextSwitch. // automatically catch other Definitions referenced with IncludeRuldes or ContextSwitch.
const auto definition = queue.takeLast(); const auto definition = queue.takeLast();
for (const auto &context : qAsConst(definition.d->contexts)) { for (const auto &context : std::as_const(definition.d->contexts)) {
// handle context switch attributes of this context itself // handle context switch attributes of this context itself
for (const auto switchContext : for (const auto switchContext :
{context->lineEndContext().context(), context->lineEmptyContext().context(), context->fallthroughContext().context()}) { {context->lineEndContext().context(), context->lineEmptyContext().context(), context->fallthroughContext().context()}) {
@@ -321,9 +313,10 @@ Context *DefinitionData::initialContext() const
Context *DefinitionData::contextByName(const QString &wantedName) const Context *DefinitionData::contextByName(const QString &wantedName) const
{ {
for (const auto context : contexts) { for (const auto context : contexts) {
if (context->name() == wantedName) if (context->name() == wantedName) {
return context; return context;
} }
}
return nullptr; return nullptr;
} }
@@ -336,8 +329,9 @@ KeywordList *DefinitionData::keywordList(const QString &wantedName)
Format DefinitionData::formatByName(const QString &wantedName) const Format DefinitionData::formatByName(const QString &wantedName) const
{ {
const auto it = formats.constFind(wantedName); const auto it = formats.constFind(wantedName);
if (it != formats.constEnd()) if (it != formats.constEnd()) {
return it.value(); return it.value();
}
return Format(); return Format();
} }
@@ -349,24 +343,29 @@ bool DefinitionData::isLoaded() const
bool DefinitionData::load(OnlyKeywords onlyKeywords) bool DefinitionData::load(OnlyKeywords onlyKeywords)
{ {
if (fileName.isEmpty()) if (fileName.isEmpty()) {
return false; return false;
}
if (isLoaded()) if (isLoaded()) {
return true; return true;
}
if (bool(onlyKeywords) && keywordIsLoaded) if (bool(onlyKeywords) && keywordIsLoaded) {
return true; return true;
}
QFile file(fileName); QFile file(fileName);
if (!file.open(QFile::ReadOnly)) if (!file.open(QFile::ReadOnly)) {
return false; return false;
}
QXmlStreamReader reader(&file); QXmlStreamReader reader(&file);
while (!reader.atEnd()) { while (!reader.atEnd()) {
const auto token = reader.readNext(); const auto token = reader.readNext();
if (token != QXmlStreamReader::StartElement) if (token != QXmlStreamReader::StartElement) {
continue; continue;
}
if (reader.name() == QLatin1String("highlighting")) { if (reader.name() == QLatin1String("highlighting")) {
loadHighlighting(reader, onlyKeywords); loadHighlighting(reader, onlyKeywords);
@@ -375,21 +374,22 @@ bool DefinitionData::load(OnlyKeywords onlyKeywords)
} }
} }
else if (reader.name() == QLatin1String("general")) else if (reader.name() == QLatin1String("general")) {
loadGeneral(reader); loadGeneral(reader);
} }
}
for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) { for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
it->setCaseSensitivity(caseSensitive); it->setCaseSensitivity(caseSensitive);
} }
for (const auto context : qAsConst(contexts)) { for (const auto context : std::as_const(contexts)) {
context->resolveContexts(); context->resolveContexts();
context->resolveIncludes(); context->resolveIncludes();
context->resolveAttributeFormat(); context->resolveAttributeFormat();
} }
for (const auto context : qAsConst(contexts)) { for (const auto context : std::as_const(contexts)) {
for (const auto &rule : context->rules()) { for (const auto &rule : context->rules()) {
rule->resolvePostProcessing(); rule->resolvePostProcessing();
} }
@@ -427,14 +427,16 @@ bool DefinitionData::loadMetaData(const QString &definitionFileName)
fileName = definitionFileName; fileName = definitionFileName;
QFile file(definitionFileName); QFile file(definitionFileName);
if (!file.open(QFile::ReadOnly)) if (!file.open(QFile::ReadOnly)) {
return false; return false;
}
QXmlStreamReader reader(&file); QXmlStreamReader reader(&file);
while (!reader.atEnd()) { while (!reader.atEnd()) {
const auto token = reader.readNext(); const auto token = reader.readNext();
if (token != QXmlStreamReader::StartElement) if (token != QXmlStreamReader::StartElement) {
continue; continue;
}
if (reader.name() == QLatin1String("language")) { if (reader.name() == QLatin1String("language")) {
return loadLanguage(reader); return loadLanguage(reader);
} }
@@ -457,11 +459,13 @@ bool DefinitionData::loadMetaData(const QString &file, const QCborMap &obj)
fileName = file; fileName = file;
const auto exts = obj.value(QLatin1String("extensions")).toString(); const auto exts = obj.value(QLatin1String("extensions")).toString();
for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
extensions.push_back(ext); extensions.push_back(ext);
}
const auto mts = obj.value(QLatin1String("mimetype")).toString(); const auto mts = obj.value(QLatin1String("mimetype")).toString();
for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
mimetypes.push_back(mt); mimetypes.push_back(mt);
}
return true; return true;
} }
@@ -471,8 +475,9 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
Q_ASSERT(reader.name() == QLatin1String("language")); Q_ASSERT(reader.name() == QLatin1String("language"));
Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
if (!checkKateVersion(reader.attributes().value(QLatin1String("kateversion")))) if (!checkKateVersion(reader.attributes().value(QLatin1String("kateversion")))) {
return false; return false;
}
name = reader.attributes().value(QLatin1String("name")).toString(); name = reader.attributes().value(QLatin1String("name")).toString();
section = reader.attributes().value(QLatin1String("section")).toString(); section = reader.attributes().value(QLatin1String("section")).toString();
@@ -485,13 +490,16 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
author = reader.attributes().value(QLatin1String("author")).toString(); author = reader.attributes().value(QLatin1String("author")).toString();
license = reader.attributes().value(QLatin1String("license")).toString(); license = reader.attributes().value(QLatin1String("license")).toString();
const auto exts = reader.attributes().value(QLatin1String("extensions")).toString(); const auto exts = reader.attributes().value(QLatin1String("extensions")).toString();
for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) for (const auto &ext : exts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
extensions.push_back(ext); extensions.push_back(ext);
}
const auto mts = reader.attributes().value(QLatin1String("mimetype")).toString(); const auto mts = reader.attributes().value(QLatin1String("mimetype")).toString();
for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) for (const auto &mt : mts.split(QLatin1Char(';'), Qt::SkipEmptyParts)) {
mimetypes.push_back(mt); mimetypes.push_back(mt);
if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) }
if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) {
caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive; caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
}
return true; return true;
} }
@@ -618,8 +626,9 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader)
++elementRefCounter; ++elementRefCounter;
if (reader.name() == QLatin1String("keywords")) { if (reader.name() == QLatin1String("keywords")) {
if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) if (reader.attributes().hasAttribute(QLatin1String("casesensitive"))) {
caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive; caseSensitive = Xml::attrToBool(reader.attributes().value(QLatin1String("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
}
// adapt wordDelimiters // adapt wordDelimiters
wordDelimiters.append(reader.attributes().value(QLatin1String("additionalDeliminator"))); wordDelimiters.append(reader.attributes().value(QLatin1String("additionalDeliminator")));
@@ -628,14 +637,15 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader)
// adapt WordWrapDelimiters // adapt WordWrapDelimiters
auto wordWrapDeliminatorAttr = reader.attributes().value( auto wordWrapDeliminatorAttr = reader.attributes().value(
QLatin1String("wordWrapDeliminator")); QLatin1String("wordWrapDeliminator"));
if (wordWrapDeliminatorAttr.isEmpty()) if (wordWrapDeliminatorAttr.isEmpty()) {
wordWrapDelimiters = wordDelimiters; wordWrapDelimiters = wordDelimiters;
else { } else {
wordWrapDelimiters.append(wordWrapDeliminatorAttr); wordWrapDelimiters.append(wordWrapDeliminatorAttr);
} }
} else if (reader.name() == QLatin1String("folding")) { } else if (reader.name() == QLatin1String("folding")) {
if (reader.attributes().hasAttribute(QLatin1String("indentationsensitive"))) if (reader.attributes().hasAttribute(QLatin1String("indentationsensitive"))) {
indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("indentationsensitive"))); indentationBasedFolding = Xml::attrToBool(reader.attributes().value(QLatin1String("indentationsensitive")));
}
} else if (reader.name() == QLatin1String("emptyLines")) { } else if (reader.name() == QLatin1String("emptyLines")) {
loadFoldingIgnoreList(reader); loadFoldingIgnoreList(reader);
} else if (reader.name() == QLatin1String("comments")) { } else if (reader.name() == QLatin1String("comments")) {
@@ -649,8 +659,9 @@ void DefinitionData::loadGeneral(QXmlStreamReader &reader)
break; break;
case QXmlStreamReader::EndElement: case QXmlStreamReader::EndElement:
--elementRefCounter; --elementRefCounter;
if (elementRefCounter == 0) if (elementRefCounter == 0) {
return; return;
}
reader.readNext(); reader.readNext();
break; break;
default: default:
@@ -688,8 +699,9 @@ void DefinitionData::loadComments(QXmlStreamReader &reader)
break; break;
case QXmlStreamReader::EndElement: case QXmlStreamReader::EndElement:
--elementRefCounter; --elementRefCounter;
if (elementRefCounter == 0) if (elementRefCounter == 0) {
return; return;
}
reader.readNext(); reader.readNext();
break; break;
default: default:
@@ -719,8 +731,9 @@ void DefinitionData::loadFoldingIgnoreList(QXmlStreamReader &reader)
break; break;
case QXmlStreamReader::EndElement: case QXmlStreamReader::EndElement:
--elementRefCounter; --elementRefCounter;
if (elementRefCounter == 0) if (elementRefCounter == 0) {
return; return;
}
reader.readNext(); reader.readNext();
break; break;
default: default:
@@ -754,8 +767,9 @@ void DefinitionData::loadSpellchecking(QXmlStreamReader &reader)
break; break;
case QXmlStreamReader::EndElement: case QXmlStreamReader::EndElement:
--elementRefCounter; --elementRefCounter;
if (elementRefCounter == 0) if (elementRefCounter == 0) {
return; return;
}
reader.readNext(); reader.readNext();
break; break;
default: default:
@@ -798,10 +812,6 @@ DefinitionRef::DefinitionRef(const Definition &def)
{ {
} }
DefinitionRef::~DefinitionRef()
{
}
DefinitionRef &DefinitionRef::operator=(const Definition &def) DefinitionRef &DefinitionRef::operator=(const Definition &def)
{ {
d = def.d; d = def.d;
@@ -810,8 +820,9 @@ DefinitionRef &DefinitionRef::operator=(const Definition &def)
Definition DefinitionRef::definition() const Definition DefinitionRef::definition() const
{ {
if (!d.expired()) if (!d.expired()) {
return Definition(d.lock()); return Definition(d.lock());
}
return Definition(); return Definition();
} }

View File

@@ -13,6 +13,7 @@
#include <QPair> #include <QPair>
#include <QVector> #include <QVector>
#include <memory> #include <memory>
#include <qobjectdefs.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QChar; class QChar;
@@ -74,7 +75,7 @@ enum class CommentPosition {
* singleLineCommentMarker() and multiLineCommentMarker() provide comment * singleLineCommentMarker() and multiLineCommentMarker() provide comment
* markers that can be used for commenting/uncommenting code. Similarly, * markers that can be used for commenting/uncommenting code. Similarly,
* formats() returns a list of Format items defined by this Definition (which * formats() returns a list of Format items defined by this Definition (which
* equal the itemDatas of a highlighing definition file). includedDefinitions() * equal the itemDatas of a highlighting definition file). includedDefinitions()
* returns a list of all included Definition%s referenced by this Definition via * returns a list of all included Definition%s referenced by this Definition via
* the rule IncludeRules, which is useful for displaying all Format items for * the rule IncludeRules, which is useful for displaying all Format items for
* color configuration in the user interface. * color configuration in the user interface.
@@ -84,6 +85,13 @@ enum class CommentPosition {
*/ */
class KSYNTAXHIGHLIGHTING_EXPORT Definition class KSYNTAXHIGHLIGHTING_EXPORT Definition
{ {
Q_GADGET
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString translatedName READ translatedName)
Q_PROPERTY(QString section READ section)
Q_PROPERTY(QString translatedSection READ translatedSection)
Q_PROPERTY(QString author READ author)
Q_PROPERTY(QString license READ license)
public: public:
/** /**
* Default constructor, creating an empty (invalid) Definition instance. * Default constructor, creating an empty (invalid) Definition instance.
@@ -93,6 +101,14 @@ public:
*/ */
Definition(); Definition();
/**
* Move constructor.
* This definition takes the Definition data from @p other.
* @note @p other may only be assigned to or destroyed afterwards.
* @since 5.86
*/
Definition(Definition &&other) noexcept;
/** /**
* Copy constructor. * Copy constructor.
* Both this definition as well as @p other share the Definition data. * Both this definition as well as @p other share the Definition data.
@@ -105,7 +121,15 @@ public:
~Definition(); ~Definition();
/** /**
* Assignment operator. * Move assignment operator.
* This definition takes the Definition data from @p other.
* @note @p other may only be assigned to or destroyed afterwards.
* @since 5.86
*/
Definition &operator=(Definition &&other) noexcept;
/**
* Copy assignment operator.
* Both this definition as well as @p rhs share the Definition data. * Both this definition as well as @p rhs share the Definition data.
*/ */
Definition &operator=(const Definition &rhs); Definition &operator=(const Definition &rhs);

View File

@@ -51,24 +51,27 @@ void DefinitionDownloaderPrivate::definitionListDownloadFinished(QNetworkReply *
while (!parser.atEnd()) { while (!parser.atEnd()) {
switch (parser.readNext()) { switch (parser.readNext()) {
case QXmlStreamReader::StartElement: case QXmlStreamReader::StartElement:
if (parser.name() == QLatin1String("Definition")) if (parser.name() == QLatin1String("Definition")) {
updateDefinition(parser); updateDefinition(parser);
}
break; break;
default: default:
break; break;
} }
} }
if (pendingDownloads == 0) if (pendingDownloads == 0) {
Q_EMIT q->informationMessage(QObject::tr("All syntax definitions are up-to-date.")); Q_EMIT q->informationMessage(QObject::tr("All syntax definitions are up-to-date."));
}
checkDone(); checkDone();
} }
void DefinitionDownloaderPrivate::updateDefinition(QXmlStreamReader &parser) void DefinitionDownloaderPrivate::updateDefinition(QXmlStreamReader &parser)
{ {
const auto name = parser.attributes().value(QLatin1String("name")); const auto name = parser.attributes().value(QLatin1String("name"));
if (name.isEmpty()) if (name.isEmpty()) {
return; return;
}
auto localDef = repo->definitionForName(name.toString()); auto localDef = repo->definitionForName(name.toString());
if (!localDef.isValid()) { if (!localDef.isValid()) {
@@ -86,11 +89,13 @@ void DefinitionDownloaderPrivate::updateDefinition(QXmlStreamReader &parser)
void DefinitionDownloaderPrivate::downloadDefinition(const QUrl &downloadUrl) void DefinitionDownloaderPrivate::downloadDefinition(const QUrl &downloadUrl)
{ {
if (!downloadUrl.isValid()) if (!downloadUrl.isValid()) {
return; return;
}
auto url = downloadUrl; auto url = downloadUrl;
if (url.scheme() == QLatin1String("http")) if (url.scheme() == QLatin1String("http")) {
url.setScheme(QStringLiteral("https")); url.setScheme(QStringLiteral("https"));
}
QNetworkRequest req(url); QNetworkRequest req(url);
auto reply = nam->get(req); auto reply = nam->get(req);
@@ -133,8 +138,9 @@ void DefinitionDownloaderPrivate::downloadDefinitionFinished(QNetworkReply *repl
void DefinitionDownloaderPrivate::checkDone() void DefinitionDownloaderPrivate::checkDone()
{ {
if (pendingDownloads == 0) { if (pendingDownloads == 0) {
if (needsReload) if (needsReload) {
repo->reload(); repo->reload();
}
Q_EMIT QTimer::singleShot(0, q, &DefinitionDownloader::done); Q_EMIT QTimer::singleShot(0, q, &DefinitionDownloader::done);
} }

View File

@@ -13,7 +13,6 @@ namespace KSyntaxHighlighting
{ {
class Definition; class Definition;
class DefinitionData; class DefinitionData;
class DefinitionPrivate;
/** Weak reference for Definition instances. /** Weak reference for Definition instances.
* *
@@ -21,6 +20,8 @@ class DefinitionPrivate;
* in objects hold directly or indirectly by Definition * in objects hold directly or indirectly by Definition
* to avoid reference count loops and thus memory leaks. * to avoid reference count loops and thus memory leaks.
* *
* This class follows the rule of zero. It is implicitly movable and copyable.
*
* @internal * @internal
*/ */
class DefinitionRef class DefinitionRef
@@ -28,7 +29,6 @@ class DefinitionRef
public: public:
DefinitionRef(); DefinitionRef();
explicit DefinitionRef(const Definition &def); explicit DefinitionRef(const Definition &def);
~DefinitionRef();
DefinitionRef &operator=(const Definition &def); DefinitionRef &operator=(const Definition &def);
Definition definition() const; Definition definition() const;

View File

@@ -21,8 +21,9 @@ using namespace KSyntaxHighlighting;
static Theme::TextStyle stringToDefaultFormat(QStringView str) static Theme::TextStyle stringToDefaultFormat(QStringView str)
{ {
if (!str.startsWith(QLatin1String("ds"))) if (!str.startsWith(QLatin1String("ds"))) {
return Theme::Normal; return Theme::Normal;
}
static const auto idx = Theme::staticMetaObject.indexOfEnumerator("TextStyle"); static const auto idx = Theme::staticMetaObject.indexOfEnumerator("TextStyle");
Q_ASSERT(idx >= 0); Q_ASSERT(idx >= 0);
@@ -30,8 +31,9 @@ static Theme::TextStyle stringToDefaultFormat(QStringView str)
bool ok = false; bool ok = false;
const auto value = metaEnum.keyToValue(str.mid(2).toLatin1().constData(), &ok); const auto value = metaEnum.keyToValue(str.mid(2).toLatin1().constData(), &ok);
if (!ok || value < 0) if (!ok || value < 0) {
return Theme::Normal; return Theme::Normal;
}
return static_cast<Theme::TextStyle>(value); return static_cast<Theme::TextStyle>(value);
} }
@@ -44,8 +46,9 @@ FormatPrivate *FormatPrivate::detachAndGet(Format &format)
TextStyleData FormatPrivate::styleOverride(const Theme &theme) const TextStyleData FormatPrivate::styleOverride(const Theme &theme) const
{ {
const auto themeData = ThemeData::get(theme); const auto themeData = ThemeData::get(theme);
if (themeData) if (themeData) {
return themeData->textStyleOverride(definition.definition().name(), name); return themeData->textStyleOverride(definition.definition().name(), name);
}
return TextStyleData(); return TextStyleData();
} }
@@ -113,16 +116,18 @@ bool Format::hasTextColor(const Theme &theme) const
QColor Format::textColor(const Theme &theme) const QColor Format::textColor(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.textColor) if (overrideStyle.textColor) {
return overrideStyle.textColor; return overrideStyle.textColor;
}
return d->style.textColor ? QColor::fromRgba(d->style.textColor) : QColor::fromRgba(theme.textColor(d->defaultStyle)); return d->style.textColor ? QColor::fromRgba(d->style.textColor) : QColor::fromRgba(theme.textColor(d->defaultStyle));
} }
QColor Format::selectedTextColor(const Theme &theme) const QColor Format::selectedTextColor(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.selectedTextColor) if (overrideStyle.selectedTextColor) {
return overrideStyle.selectedTextColor; return overrideStyle.selectedTextColor;
}
return d->style.selectedTextColor ? QColor::fromRgba(d->style.selectedTextColor) : QColor::fromRgba(theme.selectedTextColor(d->defaultStyle)); return d->style.selectedTextColor ? QColor::fromRgba(d->style.selectedTextColor) : QColor::fromRgba(theme.selectedTextColor(d->defaultStyle));
} }
@@ -136,8 +141,9 @@ bool Format::hasBackgroundColor(const Theme &theme) const
QColor Format::backgroundColor(const Theme &theme) const QColor Format::backgroundColor(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.backgroundColor) if (overrideStyle.backgroundColor) {
return overrideStyle.backgroundColor; return overrideStyle.backgroundColor;
}
// use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black!
return d->style.backgroundColor ? QColor::fromRgba(d->style.backgroundColor) : QColor::fromRgba(theme.backgroundColor(d->defaultStyle)); return d->style.backgroundColor ? QColor::fromRgba(d->style.backgroundColor) : QColor::fromRgba(theme.backgroundColor(d->defaultStyle));
@@ -146,8 +152,9 @@ QColor Format::backgroundColor(const Theme &theme) const
QColor Format::selectedBackgroundColor(const Theme &theme) const QColor Format::selectedBackgroundColor(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.selectedBackgroundColor) if (overrideStyle.selectedBackgroundColor) {
return overrideStyle.selectedBackgroundColor; return overrideStyle.selectedBackgroundColor;
}
// use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black!
return d->style.selectedBackgroundColor ? QColor::fromRgba(d->style.selectedBackgroundColor) return d->style.selectedBackgroundColor ? QColor::fromRgba(d->style.selectedBackgroundColor)
@@ -157,32 +164,36 @@ QColor Format::selectedBackgroundColor(const Theme &theme) const
bool Format::isBold(const Theme &theme) const bool Format::isBold(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.hasBold) if (overrideStyle.hasBold) {
return overrideStyle.bold; return overrideStyle.bold;
}
return d->style.hasBold ? d->style.bold : theme.isBold(d->defaultStyle); return d->style.hasBold ? d->style.bold : theme.isBold(d->defaultStyle);
} }
bool Format::isItalic(const Theme &theme) const bool Format::isItalic(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.hasItalic) if (overrideStyle.hasItalic) {
return overrideStyle.italic; return overrideStyle.italic;
}
return d->style.hasItalic ? d->style.italic : theme.isItalic(d->defaultStyle); return d->style.hasItalic ? d->style.italic : theme.isItalic(d->defaultStyle);
} }
bool Format::isUnderline(const Theme &theme) const bool Format::isUnderline(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.hasUnderline) if (overrideStyle.hasUnderline) {
return overrideStyle.underline; return overrideStyle.underline;
}
return d->style.hasUnderline ? d->style.underline : theme.isUnderline(d->defaultStyle); return d->style.hasUnderline ? d->style.underline : theme.isUnderline(d->defaultStyle);
} }
bool Format::isStrikeThrough(const Theme &theme) const bool Format::isStrikeThrough(const Theme &theme) const
{ {
const auto overrideStyle = d->styleOverride(theme); const auto overrideStyle = d->styleOverride(theme);
if (overrideStyle.hasStrikeThrough) if (overrideStyle.hasStrikeThrough) {
return overrideStyle.strikeThrough; return overrideStyle.strikeThrough;
}
return d->style.hasStrikeThrough ? d->style.strikeThrough : theme.isStrikeThrough(d->defaultStyle); return d->style.hasStrikeThrough ? d->style.strikeThrough : theme.isStrikeThrough(d->defaultStyle);
} }

View File

@@ -70,11 +70,12 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl
return; return;
} }
if (title.isEmpty()) if (title.isEmpty()) {
highlightData(&f, fi.fileName()); highlightData(&f, fi.fileName());
else } else {
highlightData(&f, title); highlightData(&f, title);
} }
}
/** /**
* @brief toHtmlRgba * @brief toHtmlRgba
@@ -87,8 +88,9 @@ void HtmlHighlighter::highlightFile(const QString &fileName, const QString &titl
*/ */
static QString toHtmlRgbaString(const QColor &color) static QString toHtmlRgbaString(const QColor &color)
{ {
if (color.alpha() == 0xFF) if (color.alpha() == 0xFF) {
return color.name(); return color.name();
}
QString rgba = QStringLiteral("rgba("); QString rgba = QStringLiteral("rgba(");
rgba.append(QString::number(color.red())); rgba.append(QString::number(color.red()));
@@ -111,10 +113,11 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title)
} }
QString htmlTitle; QString htmlTitle;
if (title.isEmpty()) if (title.isEmpty()) {
htmlTitle = QStringLiteral("Kate Syntax Highlighter"); htmlTitle = QStringLiteral("Kate Syntax Highlighter");
else } else {
htmlTitle = title.toHtmlEscaped(); htmlTitle = title.toHtmlEscaped();
}
State state; State state;
*d->out << "<!DOCTYPE html>\n"; *d->out << "<!DOCTYPE html>\n";
@@ -125,8 +128,9 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title)
<< ")\"/>\n"; << ")\"/>\n";
*d->out << "</head><body"; *d->out << "</head><body";
*d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme().editorColor(Theme::BackgroundColor))); *d->out << " style=\"background-color:" << toHtmlRgbaString(QColor::fromRgba(theme().editorColor(Theme::BackgroundColor)));
if (theme().textColor(Theme::Normal)) if (theme().textColor(Theme::Normal)) {
*d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme().textColor(Theme::Normal))); *d->out << ";color:" << toHtmlRgbaString(QColor::fromRgba(theme().textColor(Theme::Normal)));
}
*d->out << "\"><pre>\n"; *d->out << "\"><pre>\n";
QTextStream in(dev); QTextStream in(dev);
@@ -148,27 +152,34 @@ void HtmlHighlighter::highlightData(QIODevice *dev, const QString &title)
void HtmlHighlighter::applyFormat(int offset, int length, const Format &format) void HtmlHighlighter::applyFormat(int offset, int length, const Format &format)
{ {
if (length == 0) if (length == 0) {
return; return;
}
// collect potential output, cheaper than thinking about "is there any?" // collect potential output, cheaper than thinking about "is there any?"
QVarLengthArray<QString, 16> formatOutput; QVarLengthArray<QString, 16> formatOutput;
if (format.hasTextColor(theme())) if (format.hasTextColor(theme())) {
formatOutput << QStringLiteral("color:") << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";"); formatOutput << QStringLiteral("color:") << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";");
if (format.hasBackgroundColor(theme())) }
if (format.hasBackgroundColor(theme())) {
formatOutput << QStringLiteral("background-color:") << toHtmlRgbaString(format.backgroundColor(theme())) << QStringLiteral(";"); formatOutput << QStringLiteral("background-color:") << toHtmlRgbaString(format.backgroundColor(theme())) << QStringLiteral(";");
if (format.isBold(theme())) }
if (format.isBold(theme())) {
formatOutput << QStringLiteral("font-weight:bold;"); formatOutput << QStringLiteral("font-weight:bold;");
if (format.isItalic(theme())) }
if (format.isItalic(theme())) {
formatOutput << QStringLiteral("font-style:italic;"); formatOutput << QStringLiteral("font-style:italic;");
if (format.isUnderline(theme())) }
if (format.isUnderline(theme())) {
formatOutput << QStringLiteral("text-decoration:underline;"); formatOutput << QStringLiteral("text-decoration:underline;");
if (format.isStrikeThrough(theme())) }
if (format.isStrikeThrough(theme())) {
formatOutput << QStringLiteral("text-decoration:line-through;"); formatOutput << QStringLiteral("text-decoration:line-through;");
}
if (!formatOutput.isEmpty()) { if (!formatOutput.isEmpty()) {
*d->out << "<span style=\""; *d->out << "<span style=\"";
for (const auto &out : qAsConst(formatOutput)) { for (const auto &out : std::as_const(formatOutput)) {
*d->out << out; *d->out << out;
} }
*d->out << "\">"; *d->out << "\">";

View File

@@ -16,6 +16,27 @@
using namespace KSyntaxHighlighting; using namespace KSyntaxHighlighting;
namespace
{
struct KeywordComparator {
Qt::CaseSensitivity caseSensitive;
bool operator()(QStringView a, QStringView b) const
{
if (a.size() < b.size()) {
return true;
}
if (a.size() > b.size()) {
return false;
}
return a.compare(b, caseSensitive) < 0;
}
};
}
bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) const bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) const
{ {
/** /**
@@ -26,9 +47,7 @@ bool KeywordList::contains(QStringView str, Qt::CaseSensitivity caseSensitive) c
/** /**
* search with right predicate * search with right predicate
*/ */
return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), [caseSensitive](QStringView a, QStringView b) { return std::binary_search(vectorToSearch.begin(), vectorToSearch.end(), QStringView(str), KeywordComparator{caseSensitive});
return a.compare(b, caseSensitive) < 0;
});
} }
void KeywordList::load(QXmlStreamReader &reader) void KeywordList::load(QXmlStreamReader &reader)
@@ -85,16 +104,14 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive
* fill vector with refs to keywords * fill vector with refs to keywords
*/ */
vectorToSort.reserve(m_keywords.size()); vectorToSort.reserve(m_keywords.size());
for (const auto &keyword : qAsConst(m_keywords)) { for (const auto &keyword : std::as_const(m_keywords)) {
vectorToSort.push_back(keyword); vectorToSort.push_back(keyword);
} }
/** /**
* sort with right predicate * sort with right predicate
*/ */
std::sort(vectorToSort.begin(), vectorToSort.end(), [caseSensitive](QStringView a, QStringView b) { std::sort(vectorToSort.begin(), vectorToSort.end(), KeywordComparator{caseSensitive});
return a.compare(b, caseSensitive) < 0;
});
} }
void KeywordList::resolveIncludeKeywords(DefinitionData &def) void KeywordList::resolveIncludeKeywords(DefinitionData &def)

View File

@@ -1,34 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QtGlobal>
#if defined(KSYNTAXHIGHLIGHTING_LIBRARY)
# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_EXPORT
#else
# define KSYNTAXHIGHLIGHTING_EXPORT Q_DECL_IMPORT
#endif

View File

@@ -11,7 +11,7 @@
#include "repository_p.h" #include "repository_p.h"
#include "theme.h" #include "theme.h"
#include "themedata_p.h" #include "themedata_p.h"
#include "wildcardmatcher_p.h" #include "wildcardmatcher.h"
#include <QCborMap> #include <QCborMap>
#include <QCborValue> #include <QCborValue>
@@ -19,15 +19,75 @@
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QPalette> #include <QPalette>
#include <QString>
#include <QStringView>
#ifndef NO_STANDARD_PATHS #ifndef NO_STANDARD_PATHS
#include <QStandardPaths> #include <QStandardPaths>
#endif #endif
#include <algorithm>
#include <iterator>
#include <limits> #include <limits>
using namespace KSyntaxHighlighting; using namespace KSyntaxHighlighting;
namespace
{
QString fileNameFromFilePath(const QString &filePath)
{
return QFileInfo{filePath}.fileName();
}
auto anyWildcardMatches(QStringView str)
{
return [str](const Definition &def) {
const auto strings = def.extensions();
return std::any_of(strings.cbegin(), strings.cend(), [str](QStringView wildcard) {
return WildcardMatcher::exactMatch(str, wildcard);
});
};
}
auto anyMimeTypeEquals(QStringView mimeTypeName)
{
return [mimeTypeName](const Definition &def) {
const auto strings = def.mimeTypes();
return std::any_of(strings.cbegin(), strings.cend(), [mimeTypeName](QStringView name) {
return mimeTypeName == name;
});
};
}
// The two function templates below take defs - a map sorted by highlighting name - to be deterministic and independent of translations.
template<typename UnaryPredicate>
Definition findHighestPriorityDefinitionIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate)
{
const Definition *match = nullptr;
auto matchPriority = std::numeric_limits<int>::lowest();
for (const Definition &def : defs) {
const auto defPriority = def.priority();
if (defPriority > matchPriority && predicate(def)) {
match = &def;
matchPriority = defPriority;
}
}
return match == nullptr ? Definition{} : *match;
}
template<typename UnaryPredicate>
QVector<Definition> findDefinitionsIf(const QMap<QString, Definition> &defs, UnaryPredicate predicate)
{
QVector<Definition> matches;
std::copy_if(defs.cbegin(), defs.cend(), std::back_inserter(matches), predicate);
std::stable_sort(matches.begin(), matches.end(), [](const Definition &lhs, const Definition &rhs) {
return lhs.priority() > rhs.priority();
});
return matches;
}
} // unnamed namespace
static void initResource() static void initResource()
{ {
#ifdef HAS_SYNTAX_RESOURCE #ifdef HAS_SYNTAX_RESOURCE
@@ -52,67 +112,34 @@ Repository::~Repository()
{ {
// reset repo so we can detect in still alive definition instances // reset repo so we can detect in still alive definition instances
// that the repo was deleted // that the repo was deleted
for (const auto &def : qAsConst(d->m_sortedDefs)) for (const auto &def : std::as_const(d->m_sortedDefs)) {
DefinitionData::get(def)->repo = nullptr; DefinitionData::get(def)->repo = nullptr;
} }
}
Definition Repository::definitionForName(const QString &defName) const Definition Repository::definitionForName(const QString &defName) const
{ {
return d->m_defs.value(defName); return d->m_defs.value(defName);
} }
static void sortDefinitions(QVector<Definition> &definitions)
{
std::stable_sort(definitions.begin(), definitions.end(), [](const Definition &lhs, const Definition &rhs) {
return lhs.priority() > rhs.priority();
});
}
Definition Repository::definitionForFileName(const QString &fileName) const Definition Repository::definitionForFileName(const QString &fileName) const
{ {
return definitionsForFileName(fileName).value(0); return findHighestPriorityDefinitionIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
} }
QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const
{ {
QFileInfo fi(fileName); return findDefinitionsIf(d->m_defs, anyWildcardMatches(fileNameFromFilePath(fileName)));
const auto name = fi.fileName();
// use d->m_defs, sorted map by highlighting name, to be deterministic and independent of translations
QVector<Definition> candidates;
for (const Definition &def : qAsConst(d->m_defs)) {
for (const auto &pattern : def.extensions()) {
if (WildcardMatcher::exactMatch(name, pattern)) {
candidates.push_back(def);
break;
}
}
}
sortDefinitions(candidates);
return candidates;
} }
Definition Repository::definitionForMimeType(const QString &mimeType) const Definition Repository::definitionForMimeType(const QString &mimeType) const
{ {
return definitionsForMimeType(mimeType).value(0); return findHighestPriorityDefinitionIf(d->m_defs, anyMimeTypeEquals(mimeType));
} }
QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
{ {
// use d->m_defs, sorted map by highlighting name, to be deterministic and independent of translations return findDefinitionsIf(d->m_defs, anyMimeTypeEquals(mimeType));
QVector<Definition> candidates;
for (const Definition &def : qAsConst(d->m_defs)) {
for (const auto &matchType : def.mimeTypes()) {
if (mimeType == matchType) {
candidates.push_back(def);
break;
}
}
}
sortDefinitions(candidates);
return candidates;
} }
QVector<Definition> Repository::definitions() const QVector<Definition> Repository::definitions() const
@@ -127,7 +154,7 @@ QVector<Theme> Repository::themes() const
Theme Repository::theme(const QString &themeName) const Theme Repository::theme(const QString &themeName) const
{ {
for (const auto &theme : qAsConst(d->m_themes)) { for (const auto &theme : std::as_const(d->m_themes)) {
if (theme.name() == themeName) { if (theme.name() == themeName) {
return theme; return theme;
} }
@@ -138,14 +165,15 @@ Theme Repository::theme(const QString &themeName) const
Theme Repository::defaultTheme(Repository::DefaultTheme t) const Theme Repository::defaultTheme(Repository::DefaultTheme t) const
{ {
if (t == DarkTheme) if (t == DarkTheme) {
return theme(QLatin1String("Breeze Dark")); return theme(QLatin1String("Breeze Dark"));
}
return theme(QLatin1String("Breeze Light")); return theme(QLatin1String("Breeze Light"));
} }
Theme Repository::defaultTheme(Repository::DefaultTheme t) Theme Repository::defaultTheme(Repository::DefaultTheme t)
{ {
return qAsConst(*this).defaultTheme(t); return std::as_const(*this).defaultTheme(t);
} }
Theme Repository::themeForPalette(const QPalette &palette) const Theme Repository::themeForPalette(const QPalette &palette) const
@@ -164,7 +192,7 @@ Theme Repository::themeForPalette(const QPalette &palette) const
if (!matchingThemes.empty()) { if (!matchingThemes.empty()) {
// if there's multiple, search for one with a matching highlight color // if there's multiple, search for one with a matching highlight color
const auto highlight = palette.color(QPalette::Highlight); const auto highlight = palette.color(QPalette::Highlight);
for (const auto &theme : qAsConst(matchingThemes)) { for (const auto &theme : std::as_const(matchingThemes)) {
auto selection = theme.editorColor(KSyntaxHighlighting::Theme::EditorColorRole::TextSelection); auto selection = theme.editorColor(KSyntaxHighlighting::Theme::EditorColorRole::TextSelection);
if (selection == highlight.rgb()) { if (selection == highlight.rgb()) {
return theme; return theme;
@@ -179,7 +207,7 @@ Theme Repository::themeForPalette(const QPalette &palette) const
Theme Repository::themeForPalette(const QPalette &palette) Theme Repository::themeForPalette(const QPalette &palette)
{ {
return qAsConst(*this).themeForPalette(palette); return std::as_const(*this).themeForPalette(palette);
} }
void RepositoryPrivate::load(Repository *repo) void RepositoryPrivate::load(Repository *repo)
@@ -189,29 +217,39 @@ void RepositoryPrivate::load(Repository *repo)
// do lookup in standard paths, if not disabled // do lookup in standard paths, if not disabled
#ifndef NO_STANDARD_PATHS #ifndef NO_STANDARD_PATHS
for (const auto &dir : for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory)) QStringLiteral("org.kde.syntax-highlighting/syntax"),
QStandardPaths::LocateDirectory)) {
loadSyntaxFolder(repo, dir); loadSyntaxFolder(repo, dir);
}
// backward compatibility with Kate // backward compatibility with Kate
for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) for (const auto &dir :
QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("katepart5/syntax"), QStandardPaths::LocateDirectory)) {
loadSyntaxFolder(repo, dir); loadSyntaxFolder(repo, dir);
}
#endif #endif
// default resources are always used // default resources are always used, this is the one location that has a index cbor file
loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax")); loadSyntaxFolderFromIndex(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax"));
// extra resources provided by 3rdparty libraries/applications
loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax-addons"));
// user given extra paths // user given extra paths
for (const auto &path : qAsConst(m_customSearchPaths)) for (const auto &path : std::as_const(m_customSearchPaths)) {
loadSyntaxFolder(repo, path + QStringLiteral("/syntax")); loadSyntaxFolder(repo, path + QStringLiteral("/syntax"));
}
m_sortedDefs.reserve(m_defs.size()); m_sortedDefs.reserve(m_defs.size());
for (auto it = m_defs.constBegin(); it != m_defs.constEnd(); ++it) for (auto it = m_defs.constBegin(); it != m_defs.constEnd(); ++it) {
m_sortedDefs.push_back(it.value()); m_sortedDefs.push_back(it.value());
}
std::sort(m_sortedDefs.begin(), m_sortedDefs.end(), [](const Definition &left, const Definition &right) { std::sort(m_sortedDefs.begin(), m_sortedDefs.end(), [](const Definition &left, const Definition &right) {
auto comparison = left.translatedSection().compare(right.translatedSection(), Qt::CaseInsensitive); auto comparison = left.translatedSection().compare(right.translatedSection(), Qt::CaseInsensitive);
if (comparison == 0) if (comparison == 0) {
comparison = left.translatedName().compare(right.translatedName(), Qt::CaseInsensitive); comparison = left.translatedName().compare(right.translatedName(), Qt::CaseInsensitive);
}
return comparison < 0; return comparison < 0;
}); });
@@ -219,54 +257,60 @@ void RepositoryPrivate::load(Repository *repo)
// do lookup in standard paths, if not disabled // do lookup in standard paths, if not disabled
#ifndef NO_STANDARD_PATHS #ifndef NO_STANDARD_PATHS
for (const auto &dir : for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory)) QStringLiteral("org.kde.syntax-highlighting/themes"),
QStandardPaths::LocateDirectory)) {
loadThemeFolder(dir); loadThemeFolder(dir);
}
#endif #endif
// default resources are always used // default resources are always used
loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes")); loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes"));
// extra resources provided by 3rdparty libraries/applications
loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes-addons"));
// user given extra paths // user given extra paths
for (const auto &path : qAsConst(m_customSearchPaths)) for (const auto &path : std::as_const(m_customSearchPaths)) {
loadThemeFolder(path + QStringLiteral("/themes")); loadThemeFolder(path + QStringLiteral("/themes"));
} }
}
void RepositoryPrivate::loadSyntaxFolder(Repository *repo, const QString &path) void RepositoryPrivate::loadSyntaxFolder(Repository *repo, const QString &path)
{ {
if (loadSyntaxFolderFromIndex(repo, path))
return;
QDirIterator it(path, QStringList() << QLatin1String("*.xml"), QDir::Files); QDirIterator it(path, QStringList() << QLatin1String("*.xml"), QDir::Files);
while (it.hasNext()) { while (it.hasNext()) {
Definition def; Definition def;
auto defData = DefinitionData::get(def); auto defData = DefinitionData::get(def);
defData->repo = repo; defData->repo = repo;
if (defData->loadMetaData(it.next())) if (defData->loadMetaData(it.next())) {
addDefinition(def); addDefinition(def);
} }
} }
}
bool RepositoryPrivate::loadSyntaxFolderFromIndex(Repository *repo, const QString &path) void RepositoryPrivate::loadSyntaxFolderFromIndex(Repository *repo, const QString &path)
{ {
QFile indexFile(path + QLatin1String("/index.katesyntax")); QFile indexFile(path + QLatin1String("/index.katesyntax"));
if (!indexFile.open(QFile::ReadOnly)) if (!indexFile.open(QFile::ReadOnly)) {
return false; return;
}
const auto indexDoc(QCborValue::fromCbor(indexFile.readAll())); const auto indexDoc(QCborValue::fromCbor(indexFile.readAll()));
const auto index = indexDoc.toMap(); const auto index = indexDoc.toMap();
for (auto it = index.begin(); it != index.end(); ++it) { for (auto it = index.begin(); it != index.end(); ++it) {
if (!it.value().isMap()) if (!it.value().isMap()) {
continue; continue;
}
const auto fileName = QString(path + QLatin1Char('/') + it.key().toString()); const auto fileName = QString(path + QLatin1Char('/') + it.key().toString());
const auto defMap = it.value().toMap(); const auto defMap = it.value().toMap();
Definition def; Definition def;
auto defData = DefinitionData::get(def); auto defData = DefinitionData::get(def);
defData->repo = repo; defData->repo = repo;
if (defData->loadMetaData(fileName, defMap)) if (defData->loadMetaData(fileName, defMap)) {
addDefinition(def); addDefinition(def);
} }
return true; }
} }
void RepositoryPrivate::addDefinition(const Definition &def) void RepositoryPrivate::addDefinition(const Definition &def)
@@ -277,8 +321,9 @@ void RepositoryPrivate::addDefinition(const Definition &def)
return; return;
} }
if (it.value().version() >= def.version()) if (it.value().version() >= def.version()) {
return; return;
}
m_defs.insert(def.name(), def); m_defs.insert(def.name(), def);
} }
@@ -287,10 +332,11 @@ void RepositoryPrivate::loadThemeFolder(const QString &path)
QDirIterator it(path, QStringList() << QLatin1String("*.theme"), QDir::Files); QDirIterator it(path, QStringList() << QLatin1String("*.theme"), QDir::Files);
while (it.hasNext()) { while (it.hasNext()) {
auto themeData = std::unique_ptr<ThemeData>(new ThemeData); auto themeData = std::unique_ptr<ThemeData>(new ThemeData);
if (themeData->load(it.next())) if (themeData->load(it.next())) {
addTheme(Theme(themeData.release())); addTheme(Theme(themeData.release()));
} }
} }
}
static int themeRevision(const Theme &theme) static int themeRevision(const Theme &theme)
{ {
@@ -307,15 +353,17 @@ void RepositoryPrivate::addTheme(const Theme &theme)
m_themes.insert(it, theme); m_themes.insert(it, theme);
return; return;
} }
if (themeRevision(*it) < themeRevision(theme)) if (themeRevision(*it) < themeRevision(theme)) {
*it = theme; *it = theme;
} }
}
quint16 RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName) quint16 RepositoryPrivate::foldingRegionId(const QString &defName, const QString &foldName)
{ {
const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName)); const auto it = m_foldingRegionIds.constFind(qMakePair(defName, foldName));
if (it != m_foldingRegionIds.constEnd()) if (it != m_foldingRegionIds.constEnd()) {
return it.value(); return it.value();
}
m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId); m_foldingRegionIds.insert(qMakePair(defName, foldName), ++m_foldingRegionId);
return m_foldingRegionId; return m_foldingRegionId;
} }
@@ -329,8 +377,9 @@ quint16 RepositoryPrivate::nextFormatId()
void Repository::reload() void Repository::reload()
{ {
qCDebug(Log) << "Reloading syntax definitions!"; qCDebug(Log) << "Reloading syntax definitions!";
for (const auto &def : qAsConst(d->m_sortedDefs)) for (const auto &def : std::as_const(d->m_sortedDefs)) {
DefinitionData::get(def)->clear(); DefinitionData::get(def)->clear();
}
d->m_defs.clear(); d->m_defs.clear();
d->m_sortedDefs.clear(); d->m_sortedDefs.clear();

View File

@@ -86,6 +86,11 @@ class Theme;
* The internal resource path is ":/org.kde.syntax-highlighting/syntax". * The internal resource path is ":/org.kde.syntax-highlighting/syntax".
* This path should never be touched by other applications. * This path should never be touched by other applications.
* *
* -# Then, all custom files compiled into resources are loaded.
* The resource path is ":/org.kde.syntax-highlighting/syntax-addons".
* This path can be used by other libraries/applications to bundle specialized definitions.
* Per default this path isn't used by the framework itself.
*
* -# Finally, the search path can be extended by calling addCustomSearchPath(). * -# Finally, the search path can be extended by calling addCustomSearchPath().
* A custom search path can either be a path on disk or again a path to * A custom search path can either be a path on disk or again a path to
* a Qt resource. * a Qt resource.
@@ -102,6 +107,11 @@ class Theme;
* The internal resource path is ":/org.kde.syntax-highlighting/themes". * The internal resource path is ":/org.kde.syntax-highlighting/themes".
* This path should never be touched by other applications. * This path should never be touched by other applications.
* *
* -# Then, all custom files compiled into resources are loaded.
* The resource path is ":/org.kde.syntax-highlighting/themes-addons".
* This path can be used by other libraries/applications to bundle specialized themes.
* Per default this path isn't used by the framework itself.
*
* -# Finally, all Theme%s located in the paths added addCustomSearchPath() * -# Finally, all Theme%s located in the paths added addCustomSearchPath()
* are loaded. * are loaded.
* *

View File

@@ -29,7 +29,7 @@ public:
void load(Repository *repo); void load(Repository *repo);
void loadSyntaxFolder(Repository *repo, const QString &path); void loadSyntaxFolder(Repository *repo, const QString &path);
bool loadSyntaxFolderFromIndex(Repository *repo, const QString &path); void loadSyntaxFolderFromIndex(Repository *repo, const QString &path);
void addDefinition(const Definition &def); void addDefinition(const Definition &def);

View File

@@ -34,10 +34,11 @@ static bool isHexChar(QChar c)
return isDigit(c) || (c <= QLatin1Char('f') && QLatin1Char('a') <= c) || (c <= QLatin1Char('F') && QLatin1Char('A') <= c); return isDigit(c) || (c <= QLatin1Char('f') && QLatin1Char('a') <= c) || (c <= QLatin1Char('F') && QLatin1Char('A') <= c);
} }
static int matchEscapedChar(const QString &text, int offset) static int matchEscapedChar(QStringView text, int offset)
{ {
if (text.at(offset) != QLatin1Char('\\') || text.size() < offset + 2) if (text.at(offset) != QLatin1Char('\\') || text.size() < offset + 2) {
return offset; return offset;
}
const auto c = text.at(offset + 1); const auto c = text.at(offset + 1);
switch (c.unicode()) { switch (c.unicode()) {
@@ -59,8 +60,9 @@ static int matchEscapedChar(const QString &text, int offset)
// hex encoded character // hex encoded character
case 'x': case 'x':
if (offset + 2 < text.size() && isHexChar(text.at(offset + 2))) { if (offset + 2 < text.size() && isHexChar(text.at(offset + 2))) {
if (offset + 3 < text.size() && isHexChar(text.at(offset + 3))) if (offset + 3 < text.size() && isHexChar(text.at(offset + 3))) {
return offset + 4; return offset + 4;
}
return offset + 3; return offset + 3;
} }
return offset; return offset;
@@ -75,8 +77,9 @@ static int matchEscapedChar(const QString &text, int offset)
case '6': case '6':
case '7': case '7':
if (offset + 2 < text.size() && isOctalChar(text.at(offset + 2))) { if (offset + 2 < text.size() && isOctalChar(text.at(offset + 2))) {
if (offset + 3 < text.size() && isOctalChar(text.at(offset + 3))) if (offset + 3 < text.size() && isOctalChar(text.at(offset + 3))) {
return offset + 4; return offset + 4;
}
return offset + 3; return offset + 3;
} }
return offset + 2; return offset + 2;
@@ -116,26 +119,31 @@ bool Rule::load(QXmlStreamReader &reader)
Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement); Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
m_attribute = reader.attributes().value(QLatin1String("attribute")).toString(); m_attribute = reader.attributes().value(QLatin1String("attribute")).toString();
if (reader.name() != QLatin1String("IncludeRules")) // IncludeRules uses this with a different semantic if (reader.name() != QLatin1String("IncludeRules")) { // IncludeRules uses this with a different semantic
m_context.parse(reader.attributes().value(QLatin1String("context"))); m_context.parse(reader.attributes().value(QLatin1String("context")));
}
m_firstNonSpace = Xml::attrToBool(reader.attributes().value(QLatin1String("firstNonSpace"))); m_firstNonSpace = Xml::attrToBool(reader.attributes().value(QLatin1String("firstNonSpace")));
m_lookAhead = Xml::attrToBool(reader.attributes().value(QLatin1String("lookAhead"))); m_lookAhead = Xml::attrToBool(reader.attributes().value(QLatin1String("lookAhead")));
bool colOk = false; bool colOk = false;
m_column = reader.attributes().value(QLatin1String("column")).toInt(&colOk); m_column = reader.attributes().value(QLatin1String("column")).toInt(&colOk);
if (!colOk) if (!colOk) {
m_column = -1; m_column = -1;
}
auto regionName = reader.attributes().value(QLatin1String("beginRegion")); auto regionName = reader.attributes().value(QLatin1String("beginRegion"));
if (!regionName.isEmpty()) if (!regionName.isEmpty()) {
m_beginRegion = FoldingRegion(FoldingRegion::Begin, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString())); m_beginRegion = FoldingRegion(FoldingRegion::Begin, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString()));
}
regionName = reader.attributes().value(QLatin1String("endRegion")); regionName = reader.attributes().value(QLatin1String("endRegion"));
if (!regionName.isEmpty()) if (!regionName.isEmpty()) {
m_endRegion = FoldingRegion(FoldingRegion::End, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString())); m_endRegion = FoldingRegion(FoldingRegion::End, DefinitionData::get(m_def.definition())->foldingRegionId(regionName.toString()));
}
auto result = doLoad(reader); auto result = doLoad(reader);
if (m_lookAhead && m_context.isStay()) if (m_lookAhead && m_context.isStay()) {
result = false; result = false;
}
// be done with this rule, skip all subelements, e.g. no longer supported sub-rules // be done with this rule, skip all subelements, e.g. no longer supported sub-rules
reader.skipCurrentElement(); reader.skipCurrentElement();
@@ -184,42 +192,60 @@ void Rule::loadAdditionalWordDelimiters(QXmlStreamReader &reader)
Rule::Ptr Rule::create(QStringView name) Rule::Ptr Rule::create(QStringView name)
{ {
if (name == QLatin1String("AnyChar")) if (name == QLatin1String("AnyChar")) {
return std::make_shared<AnyChar>(); return std::make_shared<AnyChar>();
if (name == QLatin1String("DetectChar")) }
if (name == QLatin1String("DetectChar")) {
return std::make_shared<DetectChar>(); return std::make_shared<DetectChar>();
if (name == QLatin1String("Detect2Chars")) }
if (name == QLatin1String("Detect2Chars")) {
return std::make_shared<Detect2Char>(); return std::make_shared<Detect2Char>();
if (name == QLatin1String("DetectIdentifier")) }
if (name == QLatin1String("DetectIdentifier")) {
return std::make_shared<DetectIdentifier>(); return std::make_shared<DetectIdentifier>();
if (name == QLatin1String("DetectSpaces")) }
if (name == QLatin1String("DetectSpaces")) {
return std::make_shared<DetectSpaces>(); return std::make_shared<DetectSpaces>();
if (name == QLatin1String("Float")) }
if (name == QLatin1String("Float")) {
return std::make_shared<Float>(); return std::make_shared<Float>();
if (name == QLatin1String("Int")) }
if (name == QLatin1String("Int")) {
return std::make_shared<Int>(); return std::make_shared<Int>();
if (name == QLatin1String("HlCChar")) }
if (name == QLatin1String("HlCChar")) {
return std::make_shared<HlCChar>(); return std::make_shared<HlCChar>();
if (name == QLatin1String("HlCHex")) }
if (name == QLatin1String("HlCHex")) {
return std::make_shared<HlCHex>(); return std::make_shared<HlCHex>();
if (name == QLatin1String("HlCOct")) }
if (name == QLatin1String("HlCOct")) {
return std::make_shared<HlCOct>(); return std::make_shared<HlCOct>();
if (name == QLatin1String("HlCStringChar")) }
if (name == QLatin1String("HlCStringChar")) {
return std::make_shared<HlCStringChar>(); return std::make_shared<HlCStringChar>();
if (name == QLatin1String("IncludeRules")) }
if (name == QLatin1String("IncludeRules")) {
return std::make_shared<IncludeRules>(); return std::make_shared<IncludeRules>();
if (name == QLatin1String("keyword")) }
if (name == QLatin1String("keyword")) {
return std::make_shared<KeywordListRule>(); return std::make_shared<KeywordListRule>();
if (name == QLatin1String("LineContinue")) }
if (name == QLatin1String("LineContinue")) {
return std::make_shared<LineContinue>(); return std::make_shared<LineContinue>();
if (name == QLatin1String("RangeDetect")) }
if (name == QLatin1String("RangeDetect")) {
return std::make_shared<RangeDetect>(); return std::make_shared<RangeDetect>();
if (name == QLatin1String("RegExpr")) }
if (name == QLatin1String("RegExpr")) {
return std::make_shared<RegExpr>(); return std::make_shared<RegExpr>();
if (name == QLatin1String("StringDetect")) }
if (name == QLatin1String("StringDetect")) {
return std::make_shared<StringDetect>(); return std::make_shared<StringDetect>();
if (name == QLatin1String("WordDetect")) }
if (name == QLatin1String("WordDetect")) {
return std::make_shared<WordDetect>(); return std::make_shared<WordDetect>();
}
qCWarning(Log) << "Unknown rule type:" << name; qCWarning(Log) << "Unknown rule type:" << name;
return Ptr(nullptr); return Ptr(nullptr);
@@ -233,23 +259,26 @@ bool Rule::isWordDelimiter(QChar c) const
bool AnyChar::doLoad(QXmlStreamReader &reader) bool AnyChar::doLoad(QXmlStreamReader &reader)
{ {
m_chars = reader.attributes().value(QLatin1String("String")).toString(); m_chars = reader.attributes().value(QLatin1String("String")).toString();
if (m_chars.size() == 1) if (m_chars.size() == 1) {
qCDebug(Log) << "AnyChar rule with just one char: use DetectChar instead."; qCDebug(Log) << "AnyChar rule with just one char: use DetectChar instead.";
}
return !m_chars.isEmpty(); return !m_chars.isEmpty();
} }
MatchResult AnyChar::doMatch(const QString &text, int offset, const QStringList &) const MatchResult AnyChar::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (m_chars.contains(text.at(offset))) if (m_chars.contains(text.at(offset))) {
return offset + 1; return offset + 1;
}
return offset; return offset;
} }
bool DetectChar::doLoad(QXmlStreamReader &reader) bool DetectChar::doLoad(QXmlStreamReader &reader)
{ {
const auto s = reader.attributes().value(QLatin1String("char")); const auto s = reader.attributes().value(QLatin1String("char"));
if (s.isEmpty()) if (s.isEmpty()) {
return false; return false;
}
m_char = s.at(0); m_char = s.at(0);
m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic"))); m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic")));
if (m_dynamic) { if (m_dynamic) {
@@ -258,18 +287,21 @@ bool DetectChar::doLoad(QXmlStreamReader &reader)
return true; return true;
} }
MatchResult DetectChar::doMatch(const QString &text, int offset, const QStringList &captures) const MatchResult DetectChar::doMatch(QStringView text, int offset, const QStringList &captures) const
{ {
if (m_dynamic) { if (m_dynamic) {
if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) if (m_captureIndex == 0 || captures.size() <= m_captureIndex || captures.at(m_captureIndex).isEmpty()) {
return offset; return offset;
if (text.at(offset) == captures.at(m_captureIndex).at(0)) }
if (text.at(offset) == captures.at(m_captureIndex).at(0)) {
return offset + 1; return offset + 1;
}
return offset; return offset;
} }
if (text.at(offset) == m_char) if (text.at(offset) == m_char) {
return offset + 1; return offset + 1;
}
return offset; return offset;
} }
@@ -277,40 +309,46 @@ bool Detect2Char::doLoad(QXmlStreamReader &reader)
{ {
const auto s1 = reader.attributes().value(QLatin1String("char")); const auto s1 = reader.attributes().value(QLatin1String("char"));
const auto s2 = reader.attributes().value(QLatin1String("char1")); const auto s2 = reader.attributes().value(QLatin1String("char1"));
if (s1.isEmpty() || s2.isEmpty()) if (s1.isEmpty() || s2.isEmpty()) {
return false; return false;
}
m_char1 = s1.at(0); m_char1 = s1.at(0);
m_char2 = s2.at(0); m_char2 = s2.at(0);
return true; return true;
} }
MatchResult Detect2Char::doMatch(const QString &text, int offset, const QStringList &) const MatchResult Detect2Char::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (text.size() - offset < 2) if (text.size() - offset < 2) {
return offset; return offset;
if (text.at(offset) == m_char1 && text.at(offset + 1) == m_char2) }
if (text.at(offset) == m_char1 && text.at(offset + 1) == m_char2) {
return offset + 2; return offset + 2;
}
return offset; return offset;
} }
MatchResult DetectIdentifier::doMatch(const QString &text, int offset, const QStringList &) const MatchResult DetectIdentifier::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) if (!text.at(offset).isLetter() && text.at(offset) != QLatin1Char('_')) {
return offset; return offset;
}
for (int i = offset + 1; i < text.size(); ++i) { for (int i = offset + 1; i < text.size(); ++i) {
const auto c = text.at(i); const auto c = text.at(i);
if (!c.isLetterOrNumber() && c != QLatin1Char('_')) if (!c.isLetterOrNumber() && c != QLatin1Char('_')) {
return i; return i;
} }
}
return text.size(); return text.size();
} }
MatchResult DetectSpaces::doMatch(const QString &text, int offset, const QStringList &) const MatchResult DetectSpaces::doMatch(QStringView text, int offset, const QStringList &) const
{ {
while (offset < text.size() && text.at(offset).isSpace()) while (offset < text.size() && text.at(offset).isSpace()) {
++offset; ++offset;
}
return offset; return offset;
} }
@@ -320,63 +358,76 @@ bool Float::doLoad(QXmlStreamReader &reader)
return true; return true;
} }
MatchResult Float::doMatch(const QString &text, int offset, const QStringList &) const MatchResult Float::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) {
return offset; return offset;
}
auto newOffset = offset; auto newOffset = offset;
while (newOffset < text.size() && isDigit(text.at(newOffset))) while (newOffset < text.size() && isDigit(text.at(newOffset))) {
++newOffset; ++newOffset;
}
if (newOffset >= text.size() || text.at(newOffset) != QLatin1Char('.')) if (newOffset >= text.size() || text.at(newOffset) != QLatin1Char('.')) {
return offset; return offset;
}
++newOffset; ++newOffset;
while (newOffset < text.size() && isDigit(text.at(newOffset))) while (newOffset < text.size() && isDigit(text.at(newOffset))) {
++newOffset; ++newOffset;
}
if (newOffset == offset + 1) // we only found a decimal point if (newOffset == offset + 1) { // we only found a decimal point
return offset; return offset;
}
auto expOffset = newOffset; auto expOffset = newOffset;
if (expOffset >= text.size() || (text.at(expOffset) != QLatin1Char('e') && text.at(expOffset) != QLatin1Char('E'))) if (expOffset >= text.size() || (text.at(expOffset) != QLatin1Char('e') && text.at(expOffset) != QLatin1Char('E'))) {
return newOffset; return newOffset;
}
++expOffset; ++expOffset;
if (expOffset < text.size() && (text.at(expOffset) == QLatin1Char('+') || text.at(expOffset) == QLatin1Char('-'))) if (expOffset < text.size() && (text.at(expOffset) == QLatin1Char('+') || text.at(expOffset) == QLatin1Char('-'))) {
++expOffset; ++expOffset;
}
bool foundExpDigit = false; bool foundExpDigit = false;
while (expOffset < text.size() && isDigit(text.at(expOffset))) { while (expOffset < text.size() && isDigit(text.at(expOffset))) {
++expOffset; ++expOffset;
foundExpDigit = true; foundExpDigit = true;
} }
if (!foundExpDigit) if (!foundExpDigit) {
return newOffset; return newOffset;
}
return expOffset; return expOffset;
} }
MatchResult HlCChar::doMatch(const QString &text, int offset, const QStringList &) const MatchResult HlCChar::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (text.size() < offset + 3) if (text.size() < offset + 3) {
return offset; return offset;
}
if (text.at(offset) != QLatin1Char('\'') || text.at(offset + 1) == QLatin1Char('\'')) if (text.at(offset) != QLatin1Char('\'') || text.at(offset + 1) == QLatin1Char('\'')) {
return offset; return offset;
}
auto newOffset = matchEscapedChar(text, offset + 1); auto newOffset = matchEscapedChar(text, offset + 1);
if (newOffset == offset + 1) { if (newOffset == offset + 1) {
if (text.at(newOffset) == QLatin1Char('\\')) if (text.at(newOffset) == QLatin1Char('\\')) {
return offset; return offset;
else } else {
++newOffset; ++newOffset;
} }
if (newOffset >= text.size()) }
if (newOffset >= text.size()) {
return offset; return offset;
}
if (text.at(newOffset) == QLatin1Char('\'')) if (text.at(newOffset) == QLatin1Char('\'')) {
return newOffset + 1; return newOffset + 1;
}
return offset; return offset;
} }
@@ -387,23 +438,28 @@ bool HlCHex::doLoad(QXmlStreamReader &reader)
return true; return true;
} }
MatchResult HlCHex::doMatch(const QString &text, int offset, const QStringList &) const MatchResult HlCHex::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) {
return offset; return offset;
}
if (text.size() < offset + 3) if (text.size() < offset + 3) {
return offset; return offset;
}
if (text.at(offset) != QLatin1Char('0') || (text.at(offset + 1) != QLatin1Char('x') && text.at(offset + 1) != QLatin1Char('X'))) if (text.at(offset) != QLatin1Char('0') || (text.at(offset + 1) != QLatin1Char('x') && text.at(offset + 1) != QLatin1Char('X'))) {
return offset; return offset;
}
if (!isHexChar(text.at(offset + 2))) if (!isHexChar(text.at(offset + 2))) {
return offset; return offset;
}
offset += 3; offset += 3;
while (offset < text.size() && isHexChar(text.at(offset))) while (offset < text.size() && isHexChar(text.at(offset))) {
++offset; ++offset;
}
// TODO Kate matches U/L suffix, QtC does not? // TODO Kate matches U/L suffix, QtC does not?
@@ -416,28 +472,33 @@ bool HlCOct::doLoad(QXmlStreamReader &reader)
return true; return true;
} }
MatchResult HlCOct::doMatch(const QString &text, int offset, const QStringList &) const MatchResult HlCOct::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) {
return offset; return offset;
}
if (text.size() < offset + 2) if (text.size() < offset + 2) {
return offset; return offset;
}
if (text.at(offset) != QLatin1Char('0')) if (text.at(offset) != QLatin1Char('0')) {
return offset; return offset;
}
if (!isOctalChar(text.at(offset + 1))) if (!isOctalChar(text.at(offset + 1))) {
return offset; return offset;
}
offset += 2; offset += 2;
while (offset < text.size() && isOctalChar(text.at(offset))) while (offset < text.size() && isOctalChar(text.at(offset))) {
++offset; ++offset;
}
return offset; return offset;
} }
MatchResult HlCStringChar::doMatch(const QString &text, int offset, const QStringList &) const MatchResult HlCStringChar::doMatch(QStringView text, int offset, const QStringList &) const
{ {
return matchEscapedChar(text, offset); return matchEscapedChar(text, offset);
} }
@@ -461,17 +522,19 @@ bool IncludeRules::doLoad(QXmlStreamReader &reader)
{ {
const auto s = reader.attributes().value(QLatin1String("context")); const auto s = reader.attributes().value(QLatin1String("context"));
const auto split = s.split(QString::fromLatin1("##"), Qt::KeepEmptyParts); const auto split = s.split(QString::fromLatin1("##"), Qt::KeepEmptyParts);
if (split.isEmpty()) if (split.isEmpty()) {
return false; return false;
}
m_contextName = split.at(0).toString(); m_contextName = split.at(0).toString();
if (split.size() > 1) if (split.size() > 1) {
m_defName = split.at(1).toString(); m_defName = split.at(1).toString();
}
m_includeAttribute = Xml::attrToBool(reader.attributes().value(QLatin1String("includeAttrib"))); m_includeAttribute = Xml::attrToBool(reader.attributes().value(QLatin1String("includeAttrib")));
return !m_contextName.isEmpty() || !m_defName.isEmpty(); return !m_contextName.isEmpty() || !m_defName.isEmpty();
} }
MatchResult IncludeRules::doMatch(const QString &text, int offset, const QStringList &) const MatchResult IncludeRules::doMatch(QStringView text, int offset, const QStringList &) const
{ {
Q_UNUSED(text); Q_UNUSED(text);
qCWarning(Log) << "Unresolved include rule for" << m_contextName << "##" << m_defName; qCWarning(Log) << "Unresolved include rule for" << m_contextName << "##" << m_defName;
@@ -484,13 +547,15 @@ bool Int::doLoad(QXmlStreamReader &reader)
return true; return true;
} }
MatchResult Int::doMatch(const QString &text, int offset, const QStringList &) const MatchResult Int::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) if (offset > 0 && !isWordDelimiter(text.at(offset - 1))) {
return offset; return offset;
}
while (offset < text.size() && isDigit(text.at(offset))) while (offset < text.size() && isDigit(text.at(offset))) {
++offset; ++offset;
}
return offset; return offset;
} }
@@ -522,22 +587,25 @@ bool KeywordListRule::doLoad(QXmlStreamReader &reader)
return !m_keywordList->isEmpty(); return !m_keywordList->isEmpty();
} }
MatchResult KeywordListRule::doMatch(const QString &text, int offset, const QStringList &) const MatchResult KeywordListRule::doMatch(QStringView text, int offset, const QStringList &) const
{ {
auto newOffset = offset; auto newOffset = offset;
while (text.size() > newOffset && !isWordDelimiter(text.at(newOffset))) while (text.size() > newOffset && !isWordDelimiter(text.at(newOffset))) {
++newOffset; ++newOffset;
if (newOffset == offset) }
if (newOffset == offset) {
return offset; return offset;
}
if (m_hasCaseSensitivityOverride) { if (m_hasCaseSensitivityOverride) {
if (m_keywordList->contains(QStringView(text).mid(offset, newOffset - offset), if (m_keywordList->contains(text.mid(offset, newOffset - offset), m_caseSensitivityOverride)) {
m_caseSensitivityOverride))
return newOffset; return newOffset;
}
} else { } else {
if (m_keywordList->contains(QStringView(text).mid(offset, newOffset - offset))) if (m_keywordList->contains(text.mid(offset, newOffset - offset))) {
return newOffset; return newOffset;
} }
}
// we don't match, but we can skip until newOffset as we can't start a keyword in-between // we don't match, but we can skip until newOffset as we can't start a keyword in-between
return MatchResult(offset, newOffset); return MatchResult(offset, newOffset);
@@ -546,17 +614,19 @@ MatchResult KeywordListRule::doMatch(const QString &text, int offset, const QStr
bool LineContinue::doLoad(QXmlStreamReader &reader) bool LineContinue::doLoad(QXmlStreamReader &reader)
{ {
const auto s = reader.attributes().value(QLatin1String("char")); const auto s = reader.attributes().value(QLatin1String("char"));
if (s.isEmpty()) if (s.isEmpty()) {
m_char = QLatin1Char('\\'); m_char = QLatin1Char('\\');
else } else {
m_char = s.at(0); m_char = s.at(0);
}
return true; return true;
} }
MatchResult LineContinue::doMatch(const QString &text, int offset, const QStringList &) const MatchResult LineContinue::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (offset == text.size() - 1 && text.at(offset) == m_char) if (offset == text.size() - 1 && text.at(offset) == m_char) {
return offset + 1; return offset + 1;
}
return offset; return offset;
} }
@@ -564,24 +634,28 @@ bool RangeDetect::doLoad(QXmlStreamReader &reader)
{ {
const auto s1 = reader.attributes().value(QLatin1String("char")); const auto s1 = reader.attributes().value(QLatin1String("char"));
const auto s2 = reader.attributes().value(QLatin1String("char1")); const auto s2 = reader.attributes().value(QLatin1String("char1"));
if (s1.isEmpty() || s2.isEmpty()) if (s1.isEmpty() || s2.isEmpty()) {
return false; return false;
}
m_begin = s1.at(0); m_begin = s1.at(0);
m_end = s2.at(0); m_end = s2.at(0);
return true; return true;
} }
MatchResult RangeDetect::doMatch(const QString &text, int offset, const QStringList &) const MatchResult RangeDetect::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (text.size() - offset < 2) if (text.size() - offset < 2) {
return offset; return offset;
if (text.at(offset) != m_begin) }
if (text.at(offset) != m_begin) {
return offset; return offset;
}
auto newOffset = offset + 1; auto newOffset = offset + 1;
while (newOffset < text.size()) { while (newOffset < text.size()) {
if (text.at(newOffset) == m_end) if (text.at(newOffset) == m_end) {
return newOffset + 1; return newOffset + 1;
}
++newOffset; ++newOffset;
} }
return offset; return offset;
@@ -596,7 +670,9 @@ bool RegExpr::doLoad(QXmlStreamReader &reader)
m_regexp.setPatternOptions((isMinimal ? QRegularExpression::InvertedGreedinessOption : QRegularExpression::NoPatternOption) m_regexp.setPatternOptions((isMinimal ? QRegularExpression::InvertedGreedinessOption : QRegularExpression::NoPatternOption)
| (isCaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption) | (isCaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption)
// DontCaptureOption is removed by resolvePostProcessing() when necessary // DontCaptureOption is removed by resolvePostProcessing() when necessary
| QRegularExpression::DontCaptureOption); | QRegularExpression::DontCaptureOption
// ensure Unicode support is enabled
| QRegularExpression::UseUnicodePropertiesOption);
m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic"))); m_dynamic = Xml::attrToBool(reader.attributes().value(QLatin1String("dynamic")));
@@ -605,8 +681,9 @@ bool RegExpr::doLoad(QXmlStreamReader &reader)
void KSyntaxHighlighting::RegExpr::resolvePostProcessing() void KSyntaxHighlighting::RegExpr::resolvePostProcessing()
{ {
if (m_isResolved) if (m_isResolved) {
return; return;
}
m_isResolved = true; m_isResolved = true;
bool hasCapture = false; bool hasCapture = false;
@@ -641,7 +718,7 @@ void KSyntaxHighlighting::RegExpr::resolvePostProcessing()
} }
} }
MatchResult RegExpr::doMatch(const QString &text, int offset, const QStringList &captures) const MatchResult RegExpr::doMatch(QStringView text, int offset, const QStringList &captures) const
{ {
/** /**
* for dynamic case: create new pattern with right instantiation * for dynamic case: create new pattern with right instantiation
@@ -683,16 +760,16 @@ bool StringDetect::doLoad(QXmlStreamReader &reader)
return !m_string.isEmpty(); return !m_string.isEmpty();
} }
MatchResult StringDetect::doMatch(const QString &text, int offset, const QStringList &captures) const MatchResult StringDetect::doMatch(QStringView text, int offset, const QStringList &captures) const
{ {
/** /**
* for dynamic case: create new pattern with right instantiation * for dynamic case: create new pattern with right instantiation
*/ */
const auto &pattern = m_dynamic ? replaceCaptures(m_string, captures, false) : m_string; const auto &pattern = m_dynamic ? replaceCaptures(m_string, captures, false) : m_string;
if (offset + pattern.size() <= text.size() if (offset + pattern.size() <= text.size() && text.mid(offset, pattern.size()).compare(pattern, m_caseSensitivity) == 0) {
&& QStringView(text).mid(offset, pattern.size()).compare(pattern, m_caseSensitivity) == 0)
return offset + pattern.size(); return offset + pattern.size();
}
return offset; return offset;
} }
@@ -704,23 +781,27 @@ bool WordDetect::doLoad(QXmlStreamReader &reader)
return !m_word.isEmpty(); return !m_word.isEmpty();
} }
MatchResult WordDetect::doMatch(const QString &text, int offset, const QStringList &) const MatchResult WordDetect::doMatch(QStringView text, int offset, const QStringList &) const
{ {
if (text.size() - offset < m_word.size()) if (text.size() - offset < m_word.size()) {
return offset; return offset;
}
/** /**
* detect delimiter characters on the inner and outer boundaries of the string * detect delimiter characters on the inner and outer boundaries of the string
* NOTE: m_word isn't empty * NOTE: m_word isn't empty
*/ */
if (offset > 0 && !isWordDelimiter(text.at(offset - 1)) && !isWordDelimiter(text.at(offset))) if (offset > 0 && !isWordDelimiter(text.at(offset - 1)) && !isWordDelimiter(text.at(offset))) {
return offset; return offset;
}
if (QStringView(text).mid(offset, m_word.size()).compare(m_word, m_caseSensitivity) != 0) if (text.mid(offset, m_word.size()).compare(m_word, m_caseSensitivity) != 0) {
return offset; return offset;
}
if (text.size() == offset + m_word.size() || isWordDelimiter(text.at(offset + m_word.size())) || isWordDelimiter(text.at(offset + m_word.size() - 1))) if (text.size() == offset + m_word.size() || isWordDelimiter(text.at(offset + m_word.size())) || isWordDelimiter(text.at(offset + m_word.size() - 1))) {
return offset + m_word.size(); return offset + m_word.size();
}
return offset; return offset;
} }

View File

@@ -87,7 +87,7 @@ public:
{ {
} }
virtual MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const = 0; virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const = 0;
static Rule::Ptr create(QStringView name); static Rule::Ptr create(QStringView name);
@@ -121,58 +121,58 @@ protected:
bool m_dynamic = false; bool m_dynamic = false;
}; };
class AnyChar : public Rule class AnyChar final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
private: private:
QString m_chars; QString m_chars;
}; };
class DetectChar : public Rule class DetectChar final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
private: private:
QChar m_char; QChar m_char;
int m_captureIndex = 0; int m_captureIndex = 0;
}; };
class Detect2Char : public Rule class Detect2Char final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
private: private:
QChar m_char1; QChar m_char1;
QChar m_char2; QChar m_char2;
}; };
class DetectIdentifier : public Rule class DetectIdentifier final : public Rule
{ {
protected: protected:
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class DetectSpaces : public Rule class DetectSpaces final : public Rule
{ {
protected: protected:
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class Float : public Rule class Float final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class IncludeRules : public Rule class IncludeRules final : public Rule
{ {
public: public:
QString contextName() const; QString contextName() const;
@@ -181,7 +181,7 @@ public:
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
private: private:
QString m_contextName; QString m_contextName;
@@ -189,44 +189,44 @@ private:
bool m_includeAttribute; bool m_includeAttribute;
}; };
class Int : public Rule class Int final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
}; };
class HlCChar : public Rule class HlCChar final : public Rule
{ {
protected: protected:
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class HlCHex : public Rule class HlCHex final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class HlCOct : public Rule class HlCOct final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class HlCStringChar : public Rule class HlCStringChar final : public Rule
{ {
protected: protected:
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
}; };
class KeywordListRule : public Rule class KeywordListRule final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
private: private:
KeywordList *m_keywordList; KeywordList *m_keywordList;
@@ -234,55 +234,55 @@ private:
Qt::CaseSensitivity m_caseSensitivityOverride; Qt::CaseSensitivity m_caseSensitivityOverride;
}; };
class LineContinue : public Rule class LineContinue final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
private: private:
QChar m_char; QChar m_char;
}; };
class RangeDetect : public Rule class RangeDetect final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &) const override;
private: private:
QChar m_begin; QChar m_begin;
QChar m_end; QChar m_end;
}; };
class RegExpr : public Rule class RegExpr final : public Rule
{ {
protected: protected:
void resolvePostProcessing() override; void resolvePostProcessing() override;
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
private: private:
QRegularExpression m_regexp; QRegularExpression m_regexp;
bool m_isResolved = false; bool m_isResolved = false;
}; };
class StringDetect : public Rule class StringDetect final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
private: private:
QString m_string; QString m_string;
Qt::CaseSensitivity m_caseSensitivity; Qt::CaseSensitivity m_caseSensitivity;
}; };
class WordDetect : public Rule class WordDetect final : public Rule
{ {
protected: protected:
bool doLoad(QXmlStreamReader &reader) override; bool doLoad(QXmlStreamReader &reader) override;
MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override; MatchResult doMatch(QStringView text, int offset, const QStringList &captures) const override;
private: private:
QString m_word; QString m_word;

View File

@@ -104,7 +104,8 @@ bool State::operator!=(const State &other) const
bool State::indentationBasedFoldingEnabled() const bool State::indentationBasedFoldingEnabled() const
{ {
if (!d || d->m_contextStack.isEmpty()) if (!d || d->m_contextStack.isEmpty()) {
return false; return false;
}
return d->m_contextStack.last().first->indentationBasedFoldingEnabled(); return d->m_contextStack.last().first->indentationBasedFoldingEnabled();
} }

View File

@@ -37,12 +37,14 @@ public:
FoldingRegion SyntaxHighlighterPrivate::foldingRegion(const QTextBlock &startBlock) FoldingRegion SyntaxHighlighterPrivate::foldingRegion(const QTextBlock &startBlock)
{ {
const auto data = dynamic_cast<TextBlockUserData *>(startBlock.userData()); const auto data = dynamic_cast<TextBlockUserData *>(startBlock.userData());
if (!data) if (!data) {
return FoldingRegion(); return FoldingRegion();
}
for (int i = data->foldingRegions.size() - 1; i >= 0; --i) { for (int i = data->foldingRegions.size() - 1; i >= 0; --i) {
if (data->foldingRegions.at(i).type() == FoldingRegion::Begin) if (data->foldingRegions.at(i).type() == FoldingRegion::Begin) {
return data->foldingRegions.at(i); return data->foldingRegions.at(i);
} }
}
return FoldingRegion(); return FoldingRegion();
} }
@@ -68,9 +70,10 @@ void SyntaxHighlighter::setDefinition(const Definition &def)
{ {
const auto needsRehighlight = definition() != def; const auto needsRehighlight = definition() != def;
AbstractHighlighter::setDefinition(def); AbstractHighlighter::setDefinition(def);
if (needsRehighlight) if (needsRehighlight) {
rehighlight(); rehighlight();
} }
}
bool SyntaxHighlighter::startsFoldingRegion(const QTextBlock &startBlock) const bool SyntaxHighlighter::startsFoldingRegion(const QTextBlock &startBlock) const
{ {
@@ -86,19 +89,23 @@ QTextBlock SyntaxHighlighter::findFoldingRegionEnd(const QTextBlock &startBlock)
while (block.isValid()) { while (block.isValid()) {
block = block.next(); block = block.next();
const auto data = dynamic_cast<TextBlockUserData *>(block.userData()); const auto data = dynamic_cast<TextBlockUserData *>(block.userData());
if (!data) if (!data) {
continue; continue;
}
for (auto it = data->foldingRegions.constBegin(); it != data->foldingRegions.constEnd(); ++it) { for (auto it = data->foldingRegions.constBegin(); it != data->foldingRegions.constEnd(); ++it) {
if ((*it).id() != region.id()) if ((*it).id() != region.id()) {
continue; continue;
if ((*it).type() == FoldingRegion::End) }
if ((*it).type() == FoldingRegion::End) {
--depth; --depth;
else if ((*it).type() == FoldingRegion::Begin) } else if ((*it).type() == FoldingRegion::Begin) {
++depth; ++depth;
if (depth == 0) }
if (depth == 0) {
return block; return block;
} }
} }
}
return QTextBlock(); return QTextBlock();
} }
@@ -111,9 +118,10 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
if (currentBlock().position() > 0) { if (currentBlock().position() > 0) {
const auto prevBlock = currentBlock().previous(); const auto prevBlock = currentBlock().previous();
const auto prevData = dynamic_cast<TextBlockUserData *>(prevBlock.userData()); const auto prevData = dynamic_cast<TextBlockUserData *>(prevBlock.userData());
if (prevData) if (prevData) {
state = prevData->state; state = prevData->state;
} }
}
d->foldingRegions.clear(); d->foldingRegions.clear();
state = highlightLine(text, state); state = highlightLine(text, state);
@@ -126,35 +134,43 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
return; return;
} }
if (data->state == state && data->foldingRegions == d->foldingRegions) // we ended up in the same state, so we are done here if (data->state == state && data->foldingRegions == d->foldingRegions) { // we ended up in the same state, so we are done here
return; return;
}
data->state = state; data->state = state;
data->foldingRegions = d->foldingRegions; data->foldingRegions = d->foldingRegions;
const auto nextBlock = currentBlock().next(); const auto nextBlock = currentBlock().next();
if (nextBlock.isValid()) if (nextBlock.isValid()) {
QMetaObject::invokeMethod(this, "rehighlightBlock", Qt::QueuedConnection, Q_ARG(QTextBlock, nextBlock)); QMetaObject::invokeMethod(this, "rehighlightBlock", Qt::QueuedConnection, Q_ARG(QTextBlock, nextBlock));
} }
}
void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format)
{ {
if (length == 0) if (length == 0) {
return; return;
}
QTextCharFormat tf; QTextCharFormat tf;
// always set the foreground color to avoid palette issues // always set the foreground color to avoid palette issues
tf.setForeground(format.textColor(theme())); tf.setForeground(format.textColor(theme()));
if (format.hasBackgroundColor(theme())) if (format.hasBackgroundColor(theme())) {
tf.setBackground(format.backgroundColor(theme())); tf.setBackground(format.backgroundColor(theme()));
if (format.isBold(theme())) }
if (format.isBold(theme())) {
tf.setFontWeight(QFont::Bold); tf.setFontWeight(QFont::Bold);
if (format.isItalic(theme())) }
if (format.isItalic(theme())) {
tf.setFontItalic(true); tf.setFontItalic(true);
if (format.isUnderline(theme())) }
if (format.isUnderline(theme())) {
tf.setFontUnderline(true); tf.setFontUnderline(true);
if (format.isStrikeThrough(theme())) }
if (format.isStrikeThrough(theme())) {
tf.setFontStrikeOut(true); tf.setFontStrikeOut(true);
}
QSyntaxHighlighter::setFormat(offset, length, tf); QSyntaxHighlighter::setFormat(offset, length, tf);
} }
@@ -165,13 +181,15 @@ void SyntaxHighlighter::applyFolding(int offset, int length, FoldingRegion regio
Q_UNUSED(length); Q_UNUSED(length);
Q_D(SyntaxHighlighter); Q_D(SyntaxHighlighter);
if (region.type() == FoldingRegion::Begin) if (region.type() == FoldingRegion::Begin) {
d->foldingRegions.push_back(region); d->foldingRegions.push_back(region);
}
if (region.type() == FoldingRegion::End) { if (region.type() == FoldingRegion::End) {
for (int i = d->foldingRegions.size() - 1; i >= 0; --i) { for (int i = d->foldingRegions.size() - 1; i >= 0; --i) {
if (d->foldingRegions.at(i).id() != region.id() || d->foldingRegions.at(i).type() != FoldingRegion::Begin) if (d->foldingRegions.at(i).id() != region.id() || d->foldingRegions.at(i).type() != FoldingRegion::Begin) {
continue; continue;
}
d->foldingRegions.remove(i); d->foldingRegions.remove(i);
return; return;
} }

View File

@@ -64,6 +64,8 @@ class RepositoryPrivate;
class KSYNTAXHIGHLIGHTING_EXPORT Theme class KSYNTAXHIGHLIGHTING_EXPORT Theme
{ {
Q_GADGET Q_GADGET
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString translatedName READ translatedName)
public: public:
// TODO KF6: // TODO KF6:
// - make TextStyle an enum class // - make TextStyle an enum class

View File

@@ -160,9 +160,10 @@ bool ThemeData::load(const QString &filePath)
for (auto it = customStyles.begin(); it != customStyles.end(); ++it) { for (auto it = customStyles.begin(); it != customStyles.end(); ++it) {
const auto obj = it.value().toObject(); const auto obj = it.value().toObject();
auto &overrideStyle = m_textStyleOverrides[it.key()]; auto &overrideStyle = m_textStyleOverrides[it.key()];
for (auto it2 = obj.begin(); it2 != obj.end(); ++it2) for (auto it2 = obj.begin(); it2 != obj.end(); ++it2) {
overrideStyle.insert(it2.key(), readThemeData(it2.value().toObject())); overrideStyle.insert(it2.key(), readThemeData(it2.value().toObject()));
} }
}
return true; return true;
} }

View File

@@ -4,14 +4,16 @@
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
*/ */
#include "wildcardmatcher_p.h" #include "wildcardmatcher.h"
using namespace KSyntaxHighlighting; using namespace KSyntaxHighlighting;
#include <QChar> #include <QChar>
#include <QString> #include <QStringView>
static bool exactMatch(const QString &candidate, const QString &wildcard, int candidatePosFromRight, int wildcardPosFromRight, bool caseSensitive = true) namespace
{
bool wildcardMatch(QStringView candidate, QStringView wildcard, int candidatePosFromRight, int wildcardPosFromRight)
{ {
for (; wildcardPosFromRight >= 0; wildcardPosFromRight--) { for (; wildcardPosFromRight >= 0; wildcardPosFromRight--) {
const auto ch = wildcard.at(wildcardPosFromRight).unicode(); const auto ch = wildcard.at(wildcardPosFromRight).unicode();
@@ -27,7 +29,7 @@ static bool exactMatch(const QString &candidate, const QString &wildcard, int ca
// Eat all we can and go back as far as we have to // Eat all we can and go back as far as we have to
for (int j = -1; j <= candidatePosFromRight; j++) { for (int j = -1; j <= candidatePosFromRight; j++) {
if (exactMatch(candidate, wildcard, j, wildcardPosFromRight - 1)) { if (wildcardMatch(candidate, wildcard, j, wildcardPosFromRight - 1)) {
return true; return true;
} }
} }
@@ -47,18 +49,19 @@ static bool exactMatch(const QString &candidate, const QString &wildcard, int ca
} }
const auto candidateCh = candidate.at(candidatePosFromRight).unicode(); const auto candidateCh = candidate.at(candidatePosFromRight).unicode();
const auto match = caseSensitive ? (candidateCh == ch) : (QChar::toLower(candidateCh) == QChar::toLower(ch)); if (candidateCh == ch) {
if (match) {
candidatePosFromRight--; candidatePosFromRight--;
} else { } else {
return false; return false;
} }
} }
} }
return true; return candidatePosFromRight == -1;
} }
bool WildcardMatcher::exactMatch(const QString &candidate, const QString &wildcard, bool caseSensitive) } // unnamed namespace
bool WildcardMatcher::exactMatch(QStringView candidate, QStringView wildcard)
{ {
return ::exactMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1, caseSensitive); return ::wildcardMatch(candidate, wildcard, candidate.length() - 1, wildcard.length() - 1);
} }

View File

@@ -0,0 +1,33 @@
/*
SPDX-FileCopyrightText: 2007 Sebastian Pipping <webmaster@hartwork.org>
SPDX-License-Identifier: MIT
*/
#ifndef KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H
#define KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H
#include "ksyntaxhighlighting_export.h"
#include <QStringView>
namespace KSyntaxHighlighting
{
namespace WildcardMatcher
{
/**
* Matches a string against a given wildcard case-sensitively.
* The wildcard supports '*' (".*" in regex) and '?' ("." in regex), not more.
*
* @param candidate Text to match
* @param wildcard Wildcard to use
* @return True for an exact match, false otherwise
*
* @since 5.86
*/
KSYNTAXHIGHLIGHTING_EXPORT bool exactMatch(QStringView candidate, QStringView wildcard);
}
}
#endif // KSYNTAXHIGHLIGHTING_WILDCARDMATCHER_H

View File

@@ -11,15 +11,17 @@ using namespace KSyntaxHighlighting;
WordDelimiters::WordDelimiters() WordDelimiters::WordDelimiters()
: asciiDelimiters{} : asciiDelimiters{}
{ {
for (const char *p = "\t !%&()*+,-./:;<=>?[\\]^{|}~"; *p; ++p) for (const char *p = "\t !%&()*+,-./:;<=>?[\\]^{|}~"; *p; ++p) {
// int(*p) fix -Wchar-subscripts // int(*p) fix -Wchar-subscripts
asciiDelimiters[int(*p)] = true; asciiDelimiters[int(*p)] = true;
} }
}
bool WordDelimiters::contains(QChar c) const bool WordDelimiters::contains(QChar c) const
{ {
if (c.unicode() < 128) if (c.unicode() < 128) {
return asciiDelimiters[c.unicode()]; return asciiDelimiters[c.unicode()];
}
// perf tells contains is MUCH faster than binary search here, very short array // perf tells contains is MUCH faster than binary search here, very short array
return notAsciiDelimiters.contains(c); return notAsciiDelimiters.contains(c);
} }

View File

@@ -12,7 +12,7 @@
namespace KSyntaxHighlighting namespace KSyntaxHighlighting
{ {
/** /**
* Repesents a list of character that separates 2 words. * Represents a list of character that separates 2 words.
* *
* Default delimiters are .():!+*,-<=>%&/;?[]^{|}~\, space (' ') and tabulator ('\t'). * Default delimiters are .():!+*,-<=>%&/;?[]^{|}~\, space (' ') and tabulator ('\t').
* *

View File

@@ -17,7 +17,7 @@ namespace Xml
/** Parse a xs:boolean attribute. */ /** Parse a xs:boolean attribute. */
inline bool attrToBool(QStringView str) inline bool attrToBool(QStringView str)
{ {
return str == QLatin1String("1") || str.compare(QString("true"), Qt::CaseInsensitive) == 0; return str == QStringLiteral("1") || str.compare(QStringLiteral("true"), Qt::CaseInsensitive) == 0;
} }
} }

View File

@@ -3,7 +3,7 @@ include(autogenerated/autogenerated.pri)
QT += network QT += network
DEFINES += KSYNTAXHIGHLIGHTING_LIBRARY DEFINES += KF5SyntaxHighlighting_EXPORTS
RESOURCES += \ RESOURCES += \
data/themes/theme-data.qrc data/themes/theme-data.qrc

View File

@@ -25,7 +25,7 @@ Project {
name: "KSyntaxHighlighting_bundled" name: "KSyntaxHighlighting_bundled"
condition: !qtc.preferSystemSyntaxHighlighting || !Qt.KSyntaxHighlighting.present condition: !qtc.preferSystemSyntaxHighlighting || !Qt.KSyntaxHighlighting.present
cpp.defines: base.concat("KSYNTAXHIGHLIGHTING_LIBRARY") cpp.defines: base.concat("KF5SyntaxHighlighting_EXPORTS")
cpp.includePaths: [ cpp.includePaths: [
product.sourceDirectory + "/src/lib/", product.sourceDirectory + "/src/lib/",
product.sourceDirectory + "/autogenerated/src/lib/", product.sourceDirectory + "/autogenerated/src/lib/",
@@ -66,7 +66,6 @@ Project {
"htmlhighlighter.h", "htmlhighlighter.h",
"keywordlist.cpp", "keywordlist.cpp",
"keywordlist_p.h", "keywordlist_p.h",
"ksyntaxhighlighting_export.h",
"matchresult_p.h", "matchresult_p.h",
"repository.cpp", "repository.cpp",
"repository.h", "repository.h",