forked from qt-creator/qt-creator
Update KSyntaxHighlighting 5.52 -> 5.59
Task-number: QTCREATORBUG-22558 Change-Id: I2eac03b54f2c2d330ee9b5d0037ee42a6640d76b Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -7,3 +7,6 @@
|
||||
CMakeLists.txt.user
|
||||
callgrind.*
|
||||
heaptrack.*
|
||||
/build*/
|
||||
*.unc-backup*
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(KF5_VERSION "5.52.0")
|
||||
set(KF5_VERSION "5.59.0")
|
||||
project(KSyntaxHighlighting VERSION ${KF5_VERSION})
|
||||
|
||||
find_package(ECM 5.51.0 REQUIRED NO_MODULE)
|
||||
find_package(ECM 5.59.0 REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
if(POLICY CMP0063)
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
@@ -22,6 +22,7 @@ include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
|
||||
include(KDECMakeSettings)
|
||||
include(ECMMarkNonGuiExecutable)
|
||||
include(ECMAddQch)
|
||||
include(ECMOptionalAddSubdirectory)
|
||||
|
||||
|
||||
ecm_setup_version(PROJECT
|
||||
@@ -33,15 +34,16 @@ ecm_setup_version(PROJECT
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
set(REQUIRED_QT_VERSION 5.8.0)
|
||||
set(REQUIRED_QT_VERSION 5.10.0)
|
||||
find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Core Network Test)
|
||||
option(KSYNTAXHIGHLIGHTING_USE_GUI "Build components depending on Qt5Gui" ON)
|
||||
if(KSYNTAXHIGHLIGHTING_USE_GUI)
|
||||
find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED COMPONENTS Gui)
|
||||
endif()
|
||||
find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS Widgets XmlPatterns)
|
||||
find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE QUIET OPTIONAL_COMPONENTS PrintSupport Widgets XmlPatterns)
|
||||
set_package_properties(Qt5 PROPERTIES URL "http://qt-project.org/")
|
||||
set_package_properties(Qt5Widgets PROPERTIES PURPOSE "Example application.")
|
||||
set_package_properties(Qt5PrintSupport PROPERTIES PURPOSE "Example application.")
|
||||
set_package_properties(Qt5XmlPatterns PROPERTIES PURPOSE "Compile-time validation of syntax definition files.")
|
||||
|
||||
find_package(Perl REQUIRED)
|
||||
@@ -81,6 +83,7 @@ endif()
|
||||
if (NO_STANDARD_PATHS)
|
||||
add_definitions(-DNO_STANDARD_PATHS)
|
||||
endif()
|
||||
add_definitions(-DQT_NO_FOREACH)
|
||||
|
||||
#
|
||||
# Actually build the stuff
|
||||
@@ -90,6 +93,9 @@ add_subdirectory(data)
|
||||
add_subdirectory(src)
|
||||
if(TARGET Qt5::Gui)
|
||||
add_subdirectory(examples)
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(autotests)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
|
||||
17
src/libs/3rdparty/syntax-highlighting/README.md
vendored
17
src/libs/3rdparty/syntax-highlighting/README.md
vendored
@@ -30,3 +30,20 @@ out of scope:
|
||||
* management of text buffers or documents
|
||||
|
||||
If you need any of this, check out [KTextEditor](https://api.kde.org/frameworks/ktexteditor/html/).
|
||||
|
||||
## Adding unit tests for a syntax definition
|
||||
|
||||
* add an input file into the autotests/input/ folder, lets call it test.<language-extension>
|
||||
|
||||
* if the file extension is not sufficient to trigger the right syntax definition, you can add an
|
||||
second file testname.<language-extension>.syntax that contains the syntax definition name
|
||||
to enforce the use of the right extension
|
||||
|
||||
* do "make && make test"
|
||||
|
||||
* inspect the outputs found in your binary directory autotests/folding.out, autotests/html.output and autotests/output
|
||||
|
||||
* if ok, run in the binary folder "./autotests/update-reference-data.sh" to copy the results to the right location
|
||||
|
||||
* add the result references after the copying to the git
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#ifndef SyntaxHighlighting_VERSION_H
|
||||
#define SyntaxHighlighting_VERSION_H
|
||||
|
||||
#define SyntaxHighlighting_VERSION_STRING "5.52.0"
|
||||
#define SyntaxHighlighting_VERSION_STRING "5.59.0"
|
||||
#define SyntaxHighlighting_VERSION_MAJOR 5
|
||||
#define SyntaxHighlighting_VERSION_MINOR 52
|
||||
#define SyntaxHighlighting_VERSION_MINOR 59
|
||||
#define SyntaxHighlighting_VERSION_PATCH 0
|
||||
#define SyntaxHighlighting_VERSION ((5<<16)|(52<<8)|(0))
|
||||
#define SyntaxHighlighting_VERSION ((5<<16)|(59<<8)|(0))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<language
|
||||
name="CMake"
|
||||
version="11"
|
||||
version="12"
|
||||
kateversion="2.4"
|
||||
section="Other"
|
||||
extensions="CMakeLists.txt;*.cmake;*.cmake.in"
|
||||
@@ -317,6 +317,7 @@
|
||||
<item>PATTERN</item>
|
||||
<item>PERMISSIONS</item>
|
||||
<item>READ</item>
|
||||
<item>READ_SYMLINK</item>
|
||||
<item>REGEX</item>
|
||||
<item>RELATIVE</item>
|
||||
<item>RELATIVE_PATH</item>
|
||||
@@ -335,6 +336,7 @@
|
||||
<item>SHA3_512</item>
|
||||
<item>SHA512</item>
|
||||
<item>SHOW_PROGRESS</item>
|
||||
<item>SIZE</item>
|
||||
<item>STATUS</item>
|
||||
<item>STRINGS</item>
|
||||
<item>TIMEOUT</item>
|
||||
@@ -484,8 +486,10 @@
|
||||
<item>CACHE</item>
|
||||
<item>DIRECTORY</item>
|
||||
<item>EXT</item>
|
||||
<item>LAST_EXT</item>
|
||||
<item>NAME</item>
|
||||
<item>NAME_WE</item>
|
||||
<item>NAME_WLE</item>
|
||||
<item>PATH</item>
|
||||
<item>PROGRAM</item>
|
||||
<item>PROGRAM_ARGS</item>
|
||||
@@ -1054,6 +1058,7 @@
|
||||
<item>COPY_FILE</item>
|
||||
<item>COPY_FILE_ERROR</item>
|
||||
<item>LINK_LIBRARIES</item>
|
||||
<item>LINK_OPTIONS</item>
|
||||
<item>OUTPUT_VARIABLE</item>
|
||||
<item>RESULT_VAR</item>
|
||||
<item>SOURCES</item>
|
||||
@@ -1065,6 +1070,7 @@
|
||||
<item>COMPILE_OUTPUT_VARIABLE</item>
|
||||
<item>COMPILE_RESULT_VAR</item>
|
||||
<item>LINK_LIBRARIES</item>
|
||||
<item>LINK_OPTIONS</item>
|
||||
<item>OUTPUT_VARIABLE</item>
|
||||
<item>RUN_OUTPUT_VARIABLE</item>
|
||||
<item>RUN_RESULT_VAR</item>
|
||||
@@ -1209,6 +1215,7 @@
|
||||
<item>CMAKE_ARCHIVE_OUTPUT_DIRECTORY</item>
|
||||
<item>CMAKE_ARGC</item>
|
||||
<item>CMAKE_ARGV0</item>
|
||||
<item>CMAKE_AUTOGEN_ORIGIN_DEPENDS</item>
|
||||
<item>CMAKE_AUTOGEN_PARALLEL</item>
|
||||
<item>CMAKE_AUTOGEN_VERBOSE</item>
|
||||
<item>CMAKE_AUTOMOC</item>
|
||||
@@ -1223,6 +1230,7 @@
|
||||
<item>CMAKE_BACKWARDS_COMPATIBILITY</item>
|
||||
<item>CMAKE_BINARY_DIR</item>
|
||||
<item>CMAKE_BUILD_RPATH</item>
|
||||
<item>CMAKE_BUILD_RPATH_USE_ORIGIN</item>
|
||||
<item>CMAKE_BUILD_TOOL</item>
|
||||
<item>CMAKE_BUILD_TYPE</item>
|
||||
<item>CMAKE_BUILD_WITH_INSTALL_NAME_DIR</item>
|
||||
@@ -1297,6 +1305,7 @@
|
||||
<item>CMAKE_FIND_PACKAGE_NAME</item>
|
||||
<item>CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY</item>
|
||||
<item>CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY</item>
|
||||
<item>CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS</item>
|
||||
<item>CMAKE_FIND_PACKAGE_SORT_DIRECTION</item>
|
||||
<item>CMAKE_FIND_PACKAGE_SORT_ORDER</item>
|
||||
<item>CMAKE_FIND_PACKAGE_WARN_NO_MODULE</item>
|
||||
@@ -1316,6 +1325,10 @@
|
||||
<item>CMAKE_GENERATOR_INSTANCE</item>
|
||||
<item>CMAKE_GENERATOR_PLATFORM</item>
|
||||
<item>CMAKE_GENERATOR_TOOLSET</item>
|
||||
<item>CMAKE_GLOBAL_AUTOGEN_TARGET</item>
|
||||
<item>CMAKE_GLOBAL_AUTOGEN_TARGET_NAME</item>
|
||||
<item>CMAKE_GLOBAL_AUTORCC_TARGET</item>
|
||||
<item>CMAKE_GLOBAL_AUTORCC_TARGET_NAME</item>
|
||||
<item>CMAKE_GNUtoMS</item>
|
||||
<item>CMAKE_HAS_ANSI_STRING_STREAM</item>
|
||||
<item>CMAKE_HOME_DIRECTORY</item>
|
||||
@@ -1412,6 +1425,7 @@
|
||||
<item>CMAKE_MAJOR_VERSION</item>
|
||||
<item>CMAKE_MAKE_PROGRAM</item>
|
||||
<item>CMAKE_MATCH_COUNT</item>
|
||||
<item>CMAKE_MAXIMUM_RECURSION_DEPTH</item>
|
||||
<item>CMAKE_MFC_FLAG</item>
|
||||
<item>CMAKE_MINIMUM_REQUIRED_VERSION</item>
|
||||
<item>CMAKE_MINOR_VERSION</item>
|
||||
@@ -1884,6 +1898,7 @@
|
||||
<item>CTEST_SCP_COMMAND</item>
|
||||
<item>CTEST_SITE</item>
|
||||
<item>CTEST_SOURCE_DIRECTORY</item>
|
||||
<item>CTEST_SUBMIT_URL</item>
|
||||
<item>CTEST_SVN_COMMAND</item>
|
||||
<item>CTEST_SVN_OPTIONS</item>
|
||||
<item>CTEST_SVN_UPDATE_OPTIONS</item>
|
||||
@@ -1964,6 +1979,8 @@
|
||||
<item>PROJECT_VERSION_PATCH</item>
|
||||
<item>PROJECT_VERSION_TWEAK</item>
|
||||
<item>QTIFWDIR</item>
|
||||
<item>SWIG_OUTFILE_DIR</item>
|
||||
<item>SWIG_SOURCE_FILE_EXTENSIONS</item>
|
||||
<item>THREADS_PREFER_PTHREAD_FLAG</item>
|
||||
<item>UNIX</item>
|
||||
<item>WIN32</item>
|
||||
@@ -1982,6 +1999,7 @@
|
||||
<item>AUTORCC_SOURCE_GROUP</item>
|
||||
<item>CMAKE_CXX_KNOWN_FEATURES</item>
|
||||
<item>CMAKE_C_KNOWN_FEATURES</item>
|
||||
<item>CMAKE_ROLE</item>
|
||||
<item>DEBUG_CONFIGURATIONS</item>
|
||||
<item>DISABLED_FEATURES</item>
|
||||
<item>ECLIPSE_EXTRA_NATURES</item>
|
||||
@@ -2067,17 +2085,24 @@
|
||||
<item>ARCHIVE_OUTPUT_DIRECTORY</item>
|
||||
<item>ARCHIVE_OUTPUT_NAME</item>
|
||||
<item>AUTOGEN_BUILD_DIR</item>
|
||||
<item>AUTOGEN_ORIGIN_DEPENDS</item>
|
||||
<item>AUTOGEN_TARGET_DEPENDS</item>
|
||||
<item>AUTOMOC</item>
|
||||
<item>AUTOMOC_COMPILER_PREDEFINES</item>
|
||||
<item>AUTOMOC_DEPEND_FILTERS</item>
|
||||
<item>AUTOMOC_EXECUTABLE</item>
|
||||
<item>AUTOMOC_MACRO_NAMES</item>
|
||||
<item>AUTOMOC_MOC_OPTIONS</item>
|
||||
<item>AUTORCC</item>
|
||||
<item>AUTORCC_EXECUTABLE</item>
|
||||
<item>AUTORCC_OPTIONS</item>
|
||||
<item>AUTOUIC</item>
|
||||
<item>AUTOUIC_EXECUTABLE</item>
|
||||
<item>AUTOUIC_OPTIONS</item>
|
||||
<item>AUTOUIC_SEARCH_PATHS</item>
|
||||
<item>BINARY_DIR</item>
|
||||
<item>BUILD_RPATH</item>
|
||||
<item>BUILD_RPATH_USE_ORIGIN</item>
|
||||
<item>BUILD_WITH_INSTALL_NAME_DIR</item>
|
||||
<item>BUILD_WITH_INSTALL_RPATH</item>
|
||||
<item>BUNDLE</item>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!ENTITY wordsep "([][,?;()]|\.$|\.?\s)"> <!-- things that end a TagWord -->
|
||||
]>
|
||||
<language name="Doxygen"
|
||||
version="5"
|
||||
version="6"
|
||||
kateversion="5.0"
|
||||
section="Markup"
|
||||
extensions="*.dox;*.doxygen"
|
||||
@@ -463,7 +463,7 @@
|
||||
<itemData name="Tags" defStyleNum="dsAnnotation" bold="1" />
|
||||
<itemData name="Custom Tags" defStyleNum="dsAnnotation" />
|
||||
<itemData name="Word" defStyleNum="dsCommentVar" bold="1" italic="0" />
|
||||
<itemData name="HTML Tag" defStyleNum="dsKeyword" color="#000000" bold="1" italic="0" />
|
||||
<itemData name="HTML Tag" defStyleNum="dsKeyword" bold="1" italic="0" />
|
||||
<itemData name="Entities" defStyleNum="dsOthers" color="#4086C0" bold="1" italic="1" />
|
||||
<itemData name="Description" defStyleNum="dsDocumentation" />
|
||||
<itemData name="Comment" defStyleNum="dsComment" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!ENTITY attributeName "[A-Za-z_:*#\(\[][\)\]\w.:_-]*">
|
||||
<!ENTITY entref "&(#[0-9]+|#[xX][0-9A-Fa-f]+|&name;);">
|
||||
]>
|
||||
<language name="HTML" version="5" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
|
||||
<language name="HTML" version="7" kateversion="3.4" section="Markup" extensions="*.htm;*.html;*.shtml;*.shtm" mimetype="text/html" author="Wilbert Berendsen (wilbert@kde.nl)" license="LGPL" priority="10">
|
||||
|
||||
<highlighting>
|
||||
<contexts>
|
||||
@@ -163,16 +163,23 @@
|
||||
</context>
|
||||
|
||||
<context name="JS" attribute="Other Text" lineEndContext="#stay">
|
||||
<Detect2Chars attribute="Element" context="#pop" char="/" char1=">" endRegion="script" />
|
||||
<RegExpr attribute="Attribute" context="Script-Type" String="(\s+|^)type(?=\=|\s|$)" insensitive="true"/>
|
||||
<DetectChar attribute="Element" context="JS content" char=">" />
|
||||
<IncludeRules context="DefaultJS" />
|
||||
</context>
|
||||
<context name="DefaultJS" attribute="Other Text" lineEndContext="#stay">
|
||||
<Detect2Chars attribute="Element" context="#pop" char="/" char1=">" endRegion="script" />
|
||||
<IncludeRules context="FindAttributes" />
|
||||
<RegExpr attribute="Error" context="#stay" String="\S" />
|
||||
</context>
|
||||
|
||||
<context name="JS content" attribute="Other Text" lineEndContext="#stay">
|
||||
<IncludeRules context="Default JS content"/>
|
||||
<IncludeRules context="Normal##JavaScript" includeAttrib="true"/>
|
||||
</context>
|
||||
<context name="Default JS content" attribute="Other Text" lineEndContext="#stay">
|
||||
<RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" />
|
||||
<RegExpr attribute="Comment" context="JS comment close" String="//(?=.*</script\b)" insensitive="true" />
|
||||
<IncludeRules context="Normal##JavaScript" includeAttrib="true"/>
|
||||
</context>
|
||||
|
||||
<context name="JS comment close" attribute="Comment" lineEndContext="#pop">
|
||||
@@ -202,6 +209,79 @@
|
||||
<IncludeRules context="FindEntityRefs" />
|
||||
</context>
|
||||
|
||||
<!-- Read content from the "type" attribute to change the language to
|
||||
highlight in the <script> tag. The default language is JavaScript. -->
|
||||
|
||||
<context name="Script-Type" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop">
|
||||
<DetectSpaces />
|
||||
<DetectChar attribute="Attribute" context="#pop!Script-Type Value" char="=" />
|
||||
</context>
|
||||
<context name="Script-Type Value" attribute="Other Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop!Value">
|
||||
<DetectSpaces />
|
||||
<!-- TypeScript -->
|
||||
<StringDetect attribute="Value" context="#pop#pop!TypeScript" String=""text/typescript""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!TypeScript" String="'text/typescript'"/>
|
||||
<!-- JSX (JavaScript React) -->
|
||||
<StringDetect attribute="Value" context="#pop#pop!JSX" String=""text/jsx""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!JSX" String="'text/jsx'"/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!JSX" String=""text/babel""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!JSX" String="'text/babel'"/>
|
||||
<!-- MustacheJS / HandlebarsJS / RactiveJS -->
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""x-tmpl-mustache""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'x-tmpl-mustache'"/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/mustache""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/mustache'"/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/x-mustache-template""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/x-mustache-template'"/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/x-handlebars-template""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/x-handlebars-template'"/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String=""text/ractive""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!MustacheJS" String="'text/ractive'"/>
|
||||
<!-- HTML templates -->
|
||||
<StringDetect attribute="Value" context="#pop#pop!Script HTML template" String=""text/html""/>
|
||||
<StringDetect attribute="Value" context="#pop#pop!Script HTML template" String="'text/html'"/>
|
||||
</context>
|
||||
|
||||
<context name="JSX" attribute="Other Text" lineEndContext="#stay">
|
||||
<DetectChar attribute="Element" context="JSX content" char=">" />
|
||||
<IncludeRules context="DefaultJS" />
|
||||
</context>
|
||||
<context name="JSX content" attribute="Other Text" lineEndContext="#stay">
|
||||
<IncludeRules context="Default JS content"/>
|
||||
<IncludeRules context="Normal##JavaScript React" includeAttrib="true"/>
|
||||
</context>
|
||||
|
||||
<context name="TypeScript" attribute="Other Text" lineEndContext="#stay">
|
||||
<DetectChar attribute="Element" context="TypeScript content" char=">" />
|
||||
<IncludeRules context="DefaultJS" />
|
||||
</context>
|
||||
<context name="TypeScript content" attribute="Other Text" lineEndContext="#stay">
|
||||
<IncludeRules context="Default JS content"/>
|
||||
<IncludeRules context="Normal##TypeScript" includeAttrib="true"/>
|
||||
</context>
|
||||
|
||||
<context name="MustacheJS" attribute="Other Text" lineEndContext="#stay">
|
||||
<DetectChar attribute="Element" context="MustacheJS content" char=">" />
|
||||
<IncludeRules context="DefaultJS" />
|
||||
</context>
|
||||
<context name="MustacheJS content" attribute="Other Text" lineEndContext="#stay">
|
||||
<RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" />
|
||||
<StringDetect attribute="Error" context="#stay" String="<script>" insensitive="true" />
|
||||
<RegExpr attribute="Error" context="#stay" String="<script\b" insensitive="true" />
|
||||
<IncludeRules context="Base##Mustache/Handlebars (HTML)" includeAttrib="true"/>
|
||||
</context>
|
||||
|
||||
<context name="Script HTML template" attribute="Other Text" lineEndContext="#stay">
|
||||
<DetectChar attribute="Element" context="Script HTML template content" char=">" />
|
||||
<IncludeRules context="DefaultJS" />
|
||||
</context>
|
||||
<context name="Script HTML template content" attribute="Other Text" lineEndContext="#stay">
|
||||
<RegExpr attribute="Element" context="El Close 2" String="</script\b" insensitive="true" endRegion="script" />
|
||||
<StringDetect attribute="Error" context="#stay" String="<script>" insensitive="true" />
|
||||
<RegExpr attribute="Error" context="#stay" String="<script\b" insensitive="true" />
|
||||
<IncludeRules context="FindHTML" />
|
||||
</context>
|
||||
|
||||
</contexts>
|
||||
<itemDatas>
|
||||
<itemData name="Normal Text" defStyleNum="dsNormal" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "language.dtd">
|
||||
<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc;*.conf" mimetype="" version="4" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL">
|
||||
<language name="INI Files" section="Configuration" extensions="*.ini;*.pls;*.kcfgc" mimetype="" version="5" kateversion="2.4" author="Jan Janssen (medhefgo@web.de)" license="LGPL">
|
||||
|
||||
<highlighting>
|
||||
<list name="keywords">
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<!ENTITY strikeoutregex "[~]{2}[^~].*[^~][~]{2}">
|
||||
<!-- pandoc style -->
|
||||
]>
|
||||
<language name="Markdown" version="3" kateversion="3.8" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD">
|
||||
<language name="Markdown" version="6" kateversion="5.0" section="Markup" extensions="*.md;*.mmd;*.markdown" priority="15" author="Darrin Yeager, Claes Holmerson" license="GPL,BSD">
|
||||
<highlighting>
|
||||
<contexts>
|
||||
<context attribute="Normal Text" lineEndContext="#stay" name="Normal Text">
|
||||
@@ -74,13 +74,57 @@
|
||||
<context attribute="comment" lineEndContext="#stay" name="comment">
|
||||
<RegExpr String="-->" attribute="comment" context="#pop" endRegion="comment"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="bash-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##Bash" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="cmake-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##CMake" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="cpp-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##C++" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="css-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##CSS" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="email-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##Email" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="haskell-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##Haskell" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="html-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##HTML" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="json-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##JSON" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="php-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="phpsource##PHP/PHP"/>
|
||||
<IncludeRules context="phpsource##PHP/PHP" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="python-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##Python"/>
|
||||
<IncludeRules context="##Python" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="qml-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##QML" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="rust-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##Rust" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="xml-code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
<IncludeRules context="##XML" includeAttrib="true"/>
|
||||
</context>
|
||||
<context attribute="code" lineEndContext="#stay" name="code">
|
||||
<WordDetect attribute="code" context="#pop" String="```"/>
|
||||
@@ -98,8 +142,19 @@
|
||||
<RegExpr attribute="mailtolink" String="&mailtolinkregex;"/>
|
||||
<RegExpr attribute="strikeout" minimal="true" String="&strikeoutregex;"/>
|
||||
<RegExpr attribute="linebreak" minimal="true" String="&linebreakregex;"/>
|
||||
<WordDetect attribute="code" context="bash-code" String="```bash"/>
|
||||
<WordDetect attribute="code" context="cmake-code" String="```cmake"/>
|
||||
<WordDetect attribute="code" context="cpp-code" String="```cpp"/>
|
||||
<WordDetect attribute="code" context="css-code" String="```css"/>
|
||||
<WordDetect attribute="code" context="email-code" String="```email"/>
|
||||
<WordDetect attribute="code" context="haskell-code" String="```haskell"/>
|
||||
<WordDetect attribute="code" context="html-code" String="```html"/>
|
||||
<WordDetect attribute="code" context="json-code" String="```json"/>
|
||||
<WordDetect attribute="code" context="php-code" String="```php"/>
|
||||
<WordDetect attribute="code" context="python-code" String="```python"/>
|
||||
<WordDetect attribute="code" context="qml-code" String="```qml"/>
|
||||
<WordDetect attribute="code" context="rust-code" String="```rust"/>
|
||||
<WordDetect attribute="code" context="xml-code" String="```xml"/>
|
||||
<StringDetect attribute="code" context="code" String="```"/>
|
||||
</context>
|
||||
</contexts>
|
||||
@@ -121,12 +176,12 @@
|
||||
<itemData name="blockquote" defStyleNum="dsDataType"/>
|
||||
<itemData name="bq-emphasis" defStyleNum="dsDataType" italic="true"/>
|
||||
<itemData name="bq-strong" defStyleNum="dsDataType" bold="true"/>
|
||||
<itemData name="bullet" defStyleNum="dsFloat"/>
|
||||
<itemData name="bl-emphasis" defStyleNum="dsFloat" italic="true"/>
|
||||
<itemData name="bl-strong" defStyleNum="dsFloat" bold="true"/>
|
||||
<itemData name="numlist" defStyleNum="dsFloat"/>
|
||||
<itemData name="nl-emphasis" defStyleNum="dsFloat" italic="true"/>
|
||||
<itemData name="nl-strong" defStyleNum="dsFloat" bold="true"/>
|
||||
<itemData name="bullet" defStyleNum="dsString"/>
|
||||
<itemData name="bl-emphasis" defStyleNum="dsString" italic="true"/>
|
||||
<itemData name="bl-strong" defStyleNum="dsString" bold="true"/>
|
||||
<itemData name="numlist" defStyleNum="dsString"/>
|
||||
<itemData name="nl-emphasis" defStyleNum="dsString" italic="true"/>
|
||||
<itemData name="nl-strong" defStyleNum="dsString" bold="true"/>
|
||||
<itemData name="comment" defStyleNum="dsComment"/>
|
||||
<itemData name="code" defStyleNum="dsBaseN"/>
|
||||
<itemData name="reflink" defStyleNum="dsOthers" underline="true"/>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
Enhance tr/// and y/// support.
|
||||
-->
|
||||
<language name="Perl" version="7" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2">
|
||||
<language name="Perl" version="8" kateversion="2.4" section="Scripts" extensions="*.pl;*.PL;*.pm;*.pl6;*.PL6;*.p6;*.pm6;" mimetype="application/x-perl;text/x-perl" priority="5" author="Anders Lund (anders@alweb.dk)" license="LGPLv2">
|
||||
<highlighting>
|
||||
<list name="keywords">
|
||||
<item>if</item>
|
||||
@@ -383,8 +383,11 @@
|
||||
|
||||
<RegExpr attribute="Operator" context="find_pattern" String="\b(?:m|qr)(?=\s*[^\w\s\]})])" />
|
||||
|
||||
<RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*/" />
|
||||
<RegExpr attribute="Normal Text" context="#stay" String="[<>"':]/" />
|
||||
<RegExpr attribute="Normal Text" context="#stay" String="[\w_]+\s*//?\=?" />
|
||||
<RegExpr attribute="Normal Text" context="#stay" String="[<>"':]//?\=?" />
|
||||
<!-- Avoid conflicts between operators / and // -->
|
||||
<StringDetect attribute="Normal Text" context="#stay" String="//=" />
|
||||
<Detect2Chars attribute="Normal Text" context="#stay" char="/" char1="/" />
|
||||
<DetectChar attribute="Operator" context="pattern_slash" char="/" beginRegion="Pattern" />
|
||||
<RegExpr attribute="Operator" context="#stay" String="-[rwxoRWXOeszfdlpSbctugkTBMAC]\b" />
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<!-- Hold the "language" opening tag on a single line, as mentioned in "language.dtd". -->
|
||||
<language name="Ruby" section="Scripts"
|
||||
version="9" kateversion="3.3"
|
||||
version="10" kateversion="3.3"
|
||||
extensions="*.rb;*.rjs;*.rxml;*.xml.erb;*.js.erb;*.rake;Rakefile;Gemfile;*.gemspec;Vagrantfile"
|
||||
mimetype="application/x-ruby"
|
||||
style="ruby" indenter="ruby"
|
||||
@@ -179,11 +179,11 @@
|
||||
<item>warn</item>
|
||||
</list>
|
||||
|
||||
<list name="mixin-methods">
|
||||
<item>extend</item>
|
||||
<item>include</item>
|
||||
<item>prepend</item>
|
||||
</list>
|
||||
<list name="mixin-methods">
|
||||
<item>extend</item>
|
||||
<item>include</item>
|
||||
<item>prepend</item>
|
||||
</list>
|
||||
|
||||
<contexts>
|
||||
<context name="Normal" attribute="Normal Text" lineEndContext="#stay">
|
||||
@@ -204,7 +204,7 @@
|
||||
<RegExpr attribute="Keyword" String="\;\s*(while|until)\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/>
|
||||
<RegExpr attribute="Keyword" String="(if|unless)\b" context="#stay" beginRegion="def block" firstNonSpace="true"/>
|
||||
<RegExpr attribute="Keyword" String="\;\s*(if|unless)\b" context="#stay" beginRegion="def block"/>
|
||||
<WordDetect attribute="Keyword" String="class" context="#stay" beginRegion="def block"/>
|
||||
<WordDetect attribute="Keyword" String="class" context="no_heredoc" beginRegion="def block"/>
|
||||
<WordDetect attribute="Keyword" String="module" context="#stay" beginRegion="def block"/>
|
||||
<WordDetect attribute="Keyword" String="begin" context="#stay" beginRegion="def block"/>
|
||||
<RegExpr attribute="Keyword" String="\bfor\b(?!.*\bdo\b)" context="#stay" beginRegion="def block"/>
|
||||
@@ -231,7 +231,7 @@
|
||||
<keyword attribute="Pseudo variable" String="pseudo-variables" context="check_div_1"/>
|
||||
<keyword attribute="Default globals" String="default-globals" context="check_div_2"/>
|
||||
<keyword attribute="Kernel methods" String="kernel-methods" context="check_div_2"/>
|
||||
<keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/>
|
||||
<keyword attribute="Module mixin methods" String="mixin-methods" context="check_div_2"/>
|
||||
|
||||
<!-- (global) vars starting with $
|
||||
Match them before $_.
|
||||
@@ -263,8 +263,8 @@
|
||||
push operator '<<' than requiring to put space between the operator
|
||||
and the string.
|
||||
-->
|
||||
<RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*<<-(?=\w+|["'])" beginRegion="HereDocument" />
|
||||
<RegExpr attribute="Operator" context="find_heredoc" String="\s*<<(?=\w+|["'])" beginRegion="HereDocument" />
|
||||
<RegExpr attribute="Operator" context="find_indented_heredoc" String="\s*<<[-~](?=\w+|["'`])" beginRegion="HereDocument" />
|
||||
<RegExpr attribute="Operator" context="find_heredoc" String="\s*<<(?=\w+|["'`])" beginRegion="HereDocument" />
|
||||
|
||||
<DetectChar attribute="Operator" char="." context="#stay"/>
|
||||
<Detect2Chars attribute="Operator" char="&" char1="&" context="#stay"/>
|
||||
@@ -280,8 +280,10 @@
|
||||
<RegExpr attribute="Symbol" String=":(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?" context="check_div_1"/>
|
||||
<RegExpr attribute="Symbol" String=":\[\]=?" context="check_div_1"/>
|
||||
|
||||
<RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="check_div_1"/>
|
||||
<RegExpr attribute="Symbol" String="\[\]=?: " context="check_div_1"/>
|
||||
<!-- Do not send to "check_div_1" context!:
|
||||
after detecting these rules (": ") there can be a regular expression (see bug: #361875) -->
|
||||
<RegExpr attribute="Symbol" String="(@{1,2}|\$)?[a-zA-Z_][a-zA-Z0-9_]*[=?!]?: " context="#stay"/>
|
||||
<RegExpr attribute="Symbol" String="\[\]=?: " context="#stay"/>
|
||||
|
||||
<DetectChar attribute="String" char=""" context="Quoted String"/>
|
||||
<DetectChar attribute="Raw String" char="'" context="Apostrophed String"/>
|
||||
@@ -436,13 +438,17 @@
|
||||
The contexts below support both normal and indented heredocs
|
||||
-->
|
||||
<!-- here we markup the heredoc markers -->
|
||||
<context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" >
|
||||
<context name="find_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
|
||||
<RegExpr attribute="Keyword" context="apostrophed_normal_heredoc" String="'(\w+)'" />
|
||||
<RegExpr attribute="Keyword" context="normal_heredoc" String=""?(\w+)"?" />
|
||||
<RegExpr attribute="Keyword" context="normal_heredoc" String="(\w+)" />
|
||||
<RegExpr attribute="Keyword" context="normal_heredoc" String=""(\w+)"" />
|
||||
<RegExpr attribute="Keyword" context="normal_heredoc" String="`(\w+)`" />
|
||||
</context>
|
||||
<context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" >
|
||||
<context name="find_indented_heredoc" attribute="Normal Text" lineEndContext="#pop" fallthrough="true" fallthroughContext="#pop">
|
||||
<RegExpr attribute="Keyword" context="apostrophed_indented_heredoc" String="'(\w+)'" />
|
||||
<RegExpr attribute="Keyword" context="indented_heredoc" String=""?(\w+)"?" />
|
||||
<RegExpr attribute="Keyword" context="indented_heredoc" String="(\w+)" />
|
||||
<RegExpr attribute="Keyword" context="indented_heredoc" String=""(\w+)"" />
|
||||
<RegExpr attribute="Keyword" context="indented_heredoc" String="`(\w+)`" />
|
||||
</context>
|
||||
<!-- these are the real heredoc contexts -->
|
||||
<context name="indented_heredoc" attribute="Here Document" lineEndContext="#stay" dynamic="true">
|
||||
@@ -467,6 +473,16 @@
|
||||
<Detect2Chars attribute="Substitution" char="#" char1="{" context="Subst"/>
|
||||
</context>
|
||||
|
||||
<!-- avoid highlighting heredoc markers, for example, in singleton class definition (see bug: #358273) -->
|
||||
<context name="no_heredoc" attribute="Normal Text" lineEndContext="#stay" fallthrough="true" fallthroughContext="#pop">
|
||||
<DetectSpaces />
|
||||
<Detect2Chars attribute="Operator" char="<" char1="<" context="#pop"/>
|
||||
<!-- comments -->
|
||||
<RegExpr attribute="Comment" String="#\s*BEGIN.*$" context="#stay" beginRegion="marker" column="0"/>
|
||||
<RegExpr attribute="Comment" String="#\s*END.*$" context="#stay" endRegion="marker" column="0"/>
|
||||
<DetectChar attribute="Comment" char="#" context="General Comment"/>
|
||||
</context>
|
||||
|
||||
<!-- General delimited input support
|
||||
The contexts below handle the various gdl formats
|
||||
-->
|
||||
@@ -892,7 +908,7 @@
|
||||
<itemData name="Constant" defStyleNum="dsDataType"/>
|
||||
<itemData name="Constant Value" defStyleNum="dsDataType" color="#bb1188"/>
|
||||
<itemData name="Kernel methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
|
||||
<itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
|
||||
<itemData name="Module mixin methods" defStyleNum="dsNormal" color="#000080" selColor="#ffffff"/> <!-- #CC0E86 -->
|
||||
<itemData name="Member" defStyleNum="dsNormal"/>
|
||||
<itemData name="Instance Variable" defStyleNum="dsOthers"/>
|
||||
<itemData name="Class Variable" defStyleNum="dsOthers"/>
|
||||
@@ -913,3 +929,5 @@
|
||||
<keywords casesensitive="1" weakDeliminator="!?"/>
|
||||
</general>
|
||||
</language>
|
||||
|
||||
<!-- kate: replace-tabs off; -->
|
||||
|
||||
@@ -32,7 +32,7 @@ This code is released under the LGPL as part of kdelibs/kate.
|
||||
|
||||
========================================================================
|
||||
-->
|
||||
<language name="Yacc/Bison" version="4" kateversion="2.4" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL">
|
||||
<language name="Yacc/Bison" version="5" kateversion="5.0" section="Sources" extensions="*.y;*.yy;*.ypp;*.y++" mimetype="text/x-yacc;text/x-bison" priority="5" author="Jan Villat (jan.villat@net2000.ch)" license="LGPL">
|
||||
|
||||
<highlighting>
|
||||
<contexts>
|
||||
@@ -200,9 +200,12 @@ This code is released under the LGPL as part of kdelibs/kate.
|
||||
</context>
|
||||
<context name="CommentStar" attribute="Comment" lineEndContext="#stay">
|
||||
<Detect2Chars attribute="Comment" context="#pop" char="*" char1="/" />
|
||||
<IncludeRules context="##Alerts" />
|
||||
<IncludeRules context="##Modelines" />
|
||||
</context>
|
||||
<context name="CommentSlash" attribute="Comment" lineEndContext="#stay">
|
||||
<RegExpr attribute="Comment" context="#pop" String="[^\\]$" />
|
||||
<context name="CommentSlash" attribute="Comment" lineEndContext="#pop">
|
||||
<IncludeRules context="##Alerts" />
|
||||
<IncludeRules context="##Modelines" />
|
||||
</context>
|
||||
|
||||
<context name="StringOrChar" attribute="Normal Text" lineEndContext="#stay">
|
||||
|
||||
@@ -92,14 +92,14 @@ int main(int argc, char **argv)
|
||||
|
||||
Repository repo;
|
||||
if (parser.isSet(listDefs)) {
|
||||
foreach (const auto &def, repo.definitions()) {
|
||||
for (const auto &def : repo.definitions()) {
|
||||
std::cout << qPrintable(def.name()) << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parser.isSet(listThemes)) {
|
||||
foreach (const auto &theme, repo.themes())
|
||||
for (const auto &theme : repo.themes())
|
||||
std::cout << qPrintable(theme.name()) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -193,6 +193,82 @@ bool checkLookAhead(const QString &hlFilename, QXmlStreamReader &xml)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to search for non-existing keyword include.
|
||||
*/
|
||||
class KeywordIncludeChecker
|
||||
{
|
||||
public:
|
||||
void processElement(const QString &hlFilename, const QString &hlName, QXmlStreamReader &xml)
|
||||
{
|
||||
if (xml.name() == QLatin1String("list")) {
|
||||
auto &keywords = m_keywordMap[hlName];
|
||||
keywords.filename = hlFilename;
|
||||
auto name = xml.attributes().value(QLatin1String("name")).toString();
|
||||
m_currentIncludes = &keywords.includes[name];
|
||||
}
|
||||
else if (xml.name() == QLatin1String("include")) {
|
||||
if (!m_currentIncludes) {
|
||||
qWarning() << hlFilename << "line" << xml.lineNumber() << "<include> tag ouside <list>";
|
||||
m_success = false;
|
||||
} else {
|
||||
m_currentIncludes->push_back({xml.lineNumber(), xml.readElementText()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check() const
|
||||
{
|
||||
bool success = m_success;
|
||||
for (auto &keywords : m_keywordMap) {
|
||||
QMapIterator<QString, QVector<Keywords::Include>> includes(keywords.includes);
|
||||
while (includes.hasNext()) {
|
||||
includes.next();
|
||||
for (auto &include : includes.value()) {
|
||||
bool containsKeywordName = true;
|
||||
int const idx = include.name.indexOf(QStringLiteral("##"));
|
||||
if (idx == -1) {
|
||||
auto &keywordName = includes.key();
|
||||
containsKeywordName = keywords.includes.contains(keywordName);
|
||||
}
|
||||
else {
|
||||
auto defName = include.name.mid(idx + 2);
|
||||
auto listName = include.name.left(idx);
|
||||
auto it = m_keywordMap.find(defName);
|
||||
if (it == m_keywordMap.end()) {
|
||||
qWarning() << keywords.filename << "line" << include.line << "unknown definition in" << include.name;
|
||||
success = false;
|
||||
} else {
|
||||
containsKeywordName = it->includes.contains(listName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!containsKeywordName) {
|
||||
qWarning() << keywords.filename << "line" << include.line << "unknown keyword name in" << include.name;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Keywords
|
||||
{
|
||||
QString filename;
|
||||
struct Include
|
||||
{
|
||||
qint64 line;
|
||||
QString name;
|
||||
};
|
||||
QMap<QString, QVector<Include>> includes;
|
||||
};
|
||||
QHash<QString, Keywords> m_keywordMap;
|
||||
QVector<Keywords::Include> *m_currentIncludes = nullptr;
|
||||
bool m_success = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to search for non-existing or unreferenced keyword lists.
|
||||
*/
|
||||
@@ -296,6 +372,7 @@ public:
|
||||
const auto unusedNames = language.existingContextNames - language.usedContextNames;
|
||||
if (!unusedNames.isEmpty()) {
|
||||
qWarning() << language.hlFilename << "Unused contexts:" << unusedNames;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,9 +534,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
// index all given highlightings
|
||||
ContextChecker contextChecker;
|
||||
KeywordIncludeChecker keywordIncludeChecker;
|
||||
QVariantMap hls;
|
||||
int anyError = 0;
|
||||
foreach (const QString &hlFilename, hlFilenames) {
|
||||
for (const QString &hlFilename : qAsConst(hlFilenames)) {
|
||||
QFile hlFile(hlFilename);
|
||||
if (!hlFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning ("Failed to open %s", qPrintable(hlFilename));
|
||||
@@ -493,7 +571,7 @@ int main(int argc, char *argv[])
|
||||
QVariantMap hl;
|
||||
|
||||
// transfer text attributes
|
||||
Q_FOREACH (const QString &attribute, textAttributes) {
|
||||
for (const QString &attribute : qAsConst(textAttributes)) {
|
||||
hl[attribute] = xml.attributes().value(attribute).toString();
|
||||
}
|
||||
|
||||
@@ -528,6 +606,9 @@ int main(int argc, char *argv[])
|
||||
// search for used/existing contexts if applicable
|
||||
contextChecker.processElement(hlFilename, hlName, xml);
|
||||
|
||||
// search for existing keyword includes
|
||||
keywordIncludeChecker.processElement(hlFilename, hlName, xml);
|
||||
|
||||
// search for used/existing attributes if applicable
|
||||
attributeChecker.processElement(xml);
|
||||
|
||||
@@ -571,6 +652,9 @@ int main(int argc, char *argv[])
|
||||
if (!contextChecker.check())
|
||||
anyError = 7;
|
||||
|
||||
if (!keywordIncludeChecker.check())
|
||||
anyError = 7;
|
||||
|
||||
|
||||
// bail out if any problem was seen
|
||||
if (anyError)
|
||||
|
||||
@@ -40,6 +40,7 @@ ecm_generate_headers(SyntaxHighlighting_HEADERS
|
||||
HEADER_NAMES
|
||||
AbstractHighlighter
|
||||
Definition
|
||||
DefinitionDownloader
|
||||
FoldingRegion
|
||||
Format
|
||||
Repository
|
||||
|
||||
@@ -53,7 +53,7 @@ void AbstractHighlighterPrivate::ensureDefinitionLoaded()
|
||||
defData = DefinitionData::get(m_definition);
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(!defData->repo && !defData->name.isEmpty()))
|
||||
if (Q_UNLIKELY(!defData->repo && !defData->fileName.isEmpty()))
|
||||
qCCritical(Log) << "Repository got deleted while a highlighter is still active!";
|
||||
|
||||
if (m_definition.isValid())
|
||||
@@ -118,13 +118,13 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
|
||||
|
||||
// verify definition, deal with no highlighting being enabled
|
||||
d->ensureDefinitionLoaded();
|
||||
if (!d->m_definition.isValid()) {
|
||||
const auto defData = DefinitionData::get(d->m_definition);
|
||||
if (!d->m_definition.isValid() || !defData->isLoaded()) {
|
||||
applyFormat(0, text.size(), Format());
|
||||
return State();
|
||||
}
|
||||
|
||||
// verify/initialize state
|
||||
auto defData = DefinitionData::get(d->m_definition);
|
||||
auto newState = state;
|
||||
auto stateData = StateData::get(newState);
|
||||
const DefinitionRef currentDefRef(d->m_definition);
|
||||
@@ -139,9 +139,37 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
|
||||
|
||||
// process empty lines
|
||||
if (text.isEmpty()) {
|
||||
while (!stateData->topContext()->lineEmptyContext().isStay()) {
|
||||
if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList()))
|
||||
/**
|
||||
* handle line empty context switches
|
||||
* guard against endless loops
|
||||
* see https://phabricator.kde.org/D18509
|
||||
*/
|
||||
int endlessLoopingCounter = 0;
|
||||
while (!stateData->topContext()->lineEmptyContext().isStay() || (stateData->topContext()->lineEmptyContext().isStay() && !stateData->topContext()->lineEndContext().isStay())) {
|
||||
/**
|
||||
* line empty context switches
|
||||
*/
|
||||
if (!stateData->topContext()->lineEmptyContext().isStay()) {
|
||||
if (!d->switchContext(stateData, stateData->topContext()->lineEmptyContext(), QStringList())) {
|
||||
/**
|
||||
* end when trying to #pop the main context
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* line end context switches only when lineEmptyContext is #stay. This avoids
|
||||
* skipping empty lines after a line continuation character (see bug 405903)
|
||||
*/
|
||||
} else if (!stateData->topContext()->lineEndContext().isStay() &&
|
||||
!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
|
||||
break;
|
||||
|
||||
// guard against endless loops
|
||||
++endlessLoopingCounter;
|
||||
if (endlessLoopingCounter > 1024) {
|
||||
qCDebug(Log) << "Endless switch context transitions for line empty context, aborting highlighting of line.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto context = stateData->topContext();
|
||||
applyFormat(0, 0, context->attributeFormat());
|
||||
@@ -238,11 +266,18 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
|
||||
if (newOffset <= offset)
|
||||
continue;
|
||||
|
||||
// apply folding
|
||||
if (rule->endRegion().isValid())
|
||||
applyFolding(offset, newOffset - offset, rule->endRegion());
|
||||
/**
|
||||
* apply folding.
|
||||
* special cases:
|
||||
* - rule with endRegion + beginRegion: in endRegion, the length is 0
|
||||
* - rule with lookAhead: length is 0
|
||||
*/
|
||||
if (rule->endRegion().isValid() && rule->beginRegion().isValid())
|
||||
applyFolding(offset, 0, rule->endRegion());
|
||||
else if (rule->endRegion().isValid())
|
||||
applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->endRegion());
|
||||
if (rule->beginRegion().isValid())
|
||||
applyFolding(offset, newOffset - offset, rule->beginRegion());
|
||||
applyFolding(offset, rule->isLookAhead() ? 0 : newOffset - offset, rule->beginRegion());
|
||||
|
||||
if (rule->isLookAhead()) {
|
||||
Q_ASSERT(!rule->context().isStay());
|
||||
@@ -293,12 +328,30 @@ State AbstractHighlighter::highlightLine(const QString& text, const State &state
|
||||
|
||||
} while (offset < text.size());
|
||||
|
||||
/**
|
||||
* apply format for remaining text, if any
|
||||
*/
|
||||
if (beginOffset < offset)
|
||||
applyFormat(beginOffset, text.size() - beginOffset, *currentFormat);
|
||||
|
||||
while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) {
|
||||
if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
|
||||
break;
|
||||
/**
|
||||
* handle line end context switches
|
||||
* guard against endless loops
|
||||
* see https://phabricator.kde.org/D18509
|
||||
*/
|
||||
{
|
||||
int endlessLoopingCounter = 0;
|
||||
while (!stateData->topContext()->lineEndContext().isStay() && !lineContinuation) {
|
||||
if (!d->switchContext(stateData, stateData->topContext()->lineEndContext(), QStringList()))
|
||||
break;
|
||||
|
||||
// guard against endless loops
|
||||
++endlessLoopingCounter;
|
||||
if (endlessLoopingCounter > 1024) {
|
||||
qCDebug(Log) << "Endless switch context transitions for line end context, aborting highlighting of line.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newState;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "context_p.h"
|
||||
#include "format.h"
|
||||
#include "format_p.h"
|
||||
#include "repository.h"
|
||||
#include "repository_p.h"
|
||||
#include "rule_p.h"
|
||||
#include "ksyntaxhighlighting_logging.h"
|
||||
@@ -222,13 +223,13 @@ QStringList Definition::foldingIgnoreList() const
|
||||
|
||||
QStringList Definition::keywordLists() const
|
||||
{
|
||||
d->load();
|
||||
d->load(DefinitionData::OnlyKeywords(true));
|
||||
return d->keywordLists.keys();
|
||||
}
|
||||
|
||||
QStringList Definition::keywordList(const QString& name) const
|
||||
{
|
||||
d->load();
|
||||
d->load(DefinitionData::OnlyKeywords(true));
|
||||
const auto list = d->keywordList(name);
|
||||
return list ? list->keywords() : QStringList();
|
||||
}
|
||||
@@ -323,18 +324,18 @@ Context* DefinitionData::initialContext() const
|
||||
return contexts.first();
|
||||
}
|
||||
|
||||
Context* DefinitionData::contextByName(const QString& name) const
|
||||
Context* DefinitionData::contextByName(const QString& wantedName) const
|
||||
{
|
||||
foreach (auto context, contexts) {
|
||||
if (context->name() == name)
|
||||
for (const auto context : contexts) {
|
||||
if (context->name() == wantedName)
|
||||
return context;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KeywordList *DefinitionData::keywordList(const QString& name)
|
||||
KeywordList *DefinitionData::keywordList(const QString& wantedName)
|
||||
{
|
||||
auto it = keywordLists.find(name);
|
||||
auto it = keywordLists.find(wantedName);
|
||||
return (it == keywordLists.end()) ? nullptr : &it.value();
|
||||
}
|
||||
|
||||
@@ -343,9 +344,9 @@ bool DefinitionData::isWordDelimiter(QChar c) const
|
||||
return std::binary_search(wordDelimiters.constBegin(), wordDelimiters.constEnd(), c);
|
||||
}
|
||||
|
||||
Format DefinitionData::formatByName(const QString& name) const
|
||||
Format DefinitionData::formatByName(const QString& wantedName) const
|
||||
{
|
||||
const auto it = formats.constFind(name);
|
||||
const auto it = formats.constFind(wantedName);
|
||||
if (it != formats.constEnd())
|
||||
return it.value();
|
||||
|
||||
@@ -357,7 +358,7 @@ bool DefinitionData::isLoaded() const
|
||||
return !contexts.isEmpty();
|
||||
}
|
||||
|
||||
bool DefinitionData::load()
|
||||
bool DefinitionData::load(OnlyKeywords onlyKeywords)
|
||||
{
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
@@ -365,6 +366,9 @@ bool DefinitionData::load()
|
||||
if (isLoaded())
|
||||
return true;
|
||||
|
||||
if (bool(onlyKeywords) && keywordIsLoaded)
|
||||
return true;
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
return false;
|
||||
@@ -375,17 +379,22 @@ bool DefinitionData::load()
|
||||
if (token != QXmlStreamReader::StartElement)
|
||||
continue;
|
||||
|
||||
if (reader.name() == QLatin1String("highlighting"))
|
||||
loadHighlighting(reader);
|
||||
if (reader.name() == QLatin1String("highlighting")) {
|
||||
loadHighlighting(reader, onlyKeywords);
|
||||
if (bool(onlyKeywords)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (reader.name() == QLatin1String("general"))
|
||||
loadGeneral(reader);
|
||||
}
|
||||
|
||||
for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it)
|
||||
(*it).setCaseSensitivity(caseSensitive);
|
||||
for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
|
||||
it->setCaseSensitivity(caseSensitive);
|
||||
}
|
||||
|
||||
foreach (auto context, contexts) {
|
||||
for (const auto context : qAsConst(contexts)) {
|
||||
context->resolveContexts();
|
||||
context->resolveIncludes();
|
||||
context->resolveAttributeFormat();
|
||||
@@ -454,10 +463,10 @@ bool DefinitionData::loadMetaData(const QString &file, const QJsonObject &obj)
|
||||
fileName = file;
|
||||
|
||||
const auto exts = obj.value(QLatin1String("extensions")).toString();
|
||||
foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
extensions.push_back(ext);
|
||||
const auto mts = obj.value(QLatin1String("mimetype")).toString();
|
||||
foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
mimetypes.push_back(mt);
|
||||
|
||||
return true;
|
||||
@@ -482,29 +491,42 @@ bool DefinitionData::loadLanguage(QXmlStreamReader &reader)
|
||||
author = reader.attributes().value(QStringLiteral("author")).toString();
|
||||
license = reader.attributes().value(QStringLiteral("license")).toString();
|
||||
const auto exts = reader.attributes().value(QStringLiteral("extensions")).toString();
|
||||
foreach (const auto &ext, exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
for (const auto &ext : exts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
extensions.push_back(ext);
|
||||
const auto mts = reader.attributes().value(QStringLiteral("mimetype")).toString();
|
||||
foreach (const auto &mt, mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
for (const auto &mt : mts.split(QLatin1Char(';'), QString::SkipEmptyParts))
|
||||
mimetypes.push_back(mt);
|
||||
if (reader.attributes().hasAttribute(QStringLiteral("casesensitive")))
|
||||
caseSensitive = Xml::attrToBool(reader.attributes().value(QStringLiteral("casesensitive"))) ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DefinitionData::loadHighlighting(QXmlStreamReader& reader)
|
||||
void DefinitionData::loadHighlighting(QXmlStreamReader& reader, OnlyKeywords onlyKeywords)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("highlighting"));
|
||||
Q_ASSERT(reader.tokenType() == QXmlStreamReader::StartElement);
|
||||
|
||||
// skip highlighting
|
||||
reader.readNext();
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
switch (reader.tokenType()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader.name() == QLatin1String("list")) {
|
||||
KeywordList keywords;
|
||||
keywords.load(reader);
|
||||
keywordLists.insert(keywords.name(), keywords);
|
||||
if (!keywordIsLoaded) {
|
||||
KeywordList keywords;
|
||||
keywords.load(reader);
|
||||
keywordLists.insert(keywords.name(), keywords);
|
||||
}
|
||||
else {
|
||||
reader.skipCurrentElement();
|
||||
reader.readNext(); // Skip </list>
|
||||
}
|
||||
} else if (bool(onlyKeywords)) {
|
||||
resolveIncludeKeywords();
|
||||
return;
|
||||
} else if (reader.name() == QLatin1String("contexts")) {
|
||||
resolveIncludeKeywords();
|
||||
loadContexts(reader);
|
||||
reader.readNext();
|
||||
} else if (reader.name() == QLatin1String("itemDatas")) {
|
||||
@@ -522,6 +544,19 @@ void DefinitionData::loadHighlighting(QXmlStreamReader& reader)
|
||||
}
|
||||
}
|
||||
|
||||
void DefinitionData::resolveIncludeKeywords()
|
||||
{
|
||||
if (keywordIsLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
keywordIsLoaded = true;
|
||||
|
||||
for (auto it = keywordLists.begin(); it != keywordLists.end(); ++it) {
|
||||
it->resolveIncludeKeywords(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void DefinitionData::loadContexts(QXmlStreamReader& reader)
|
||||
{
|
||||
Q_ASSERT(reader.name() == QLatin1String("contexts"));
|
||||
@@ -598,7 +633,7 @@ void DefinitionData::loadGeneral(QXmlStreamReader& reader)
|
||||
std::sort(wordDelimiters.begin(), wordDelimiters.end());
|
||||
auto it = std::unique(wordDelimiters.begin(), wordDelimiters.end());
|
||||
wordDelimiters.truncate(std::distance(wordDelimiters.begin(), it));
|
||||
foreach (const auto c, reader.attributes().value(QLatin1String("weakDeliminator")))
|
||||
for (const auto c : reader.attributes().value(QLatin1String("weakDeliminator")))
|
||||
wordDelimiters.remove(c);
|
||||
|
||||
// adaptWordWrapDelimiters, and sort
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
DefinitionData();
|
||||
~DefinitionData();
|
||||
|
||||
DefinitionData(const DefinitionData &) = delete;
|
||||
DefinitionData &operator=(const DefinitionData &) = delete;
|
||||
|
||||
static DefinitionData* get(const Definition &def);
|
||||
|
||||
bool isLoaded() const;
|
||||
@@ -54,9 +57,11 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
bool load();
|
||||
enum class OnlyKeywords : bool;
|
||||
|
||||
bool load(OnlyKeywords onlyKeywords = OnlyKeywords(false));
|
||||
bool loadLanguage(QXmlStreamReader &reader);
|
||||
void loadHighlighting(QXmlStreamReader &reader);
|
||||
void loadHighlighting(QXmlStreamReader &reader, OnlyKeywords onlyKeywords);
|
||||
void loadContexts(QXmlStreamReader &reader);
|
||||
void loadItemData(QXmlStreamReader &reader);
|
||||
void loadGeneral(QXmlStreamReader &reader);
|
||||
@@ -65,6 +70,8 @@ public:
|
||||
void loadSpellchecking(QXmlStreamReader &reader);
|
||||
bool checkKateVersion(const QStringRef &verStr);
|
||||
|
||||
void resolveIncludeKeywords();
|
||||
|
||||
KeywordList *keywordList(const QString &name);
|
||||
bool isWordDelimiter(QChar c) const;
|
||||
|
||||
@@ -83,6 +90,7 @@ public:
|
||||
QHash<QString, Format> formats;
|
||||
QString wordDelimiters;
|
||||
QString wordWrapDelimiters;
|
||||
bool keywordIsLoaded = false;
|
||||
bool hasFoldingRegions = false;
|
||||
bool indentationBasedFolding = false;
|
||||
QStringList foldingIgnoreList;
|
||||
|
||||
@@ -213,52 +213,52 @@ void FormatPrivate::load(QXmlStreamReader& reader)
|
||||
name = reader.attributes().value(QStringLiteral("name")).toString();
|
||||
defaultStyle = stringToDefaultFormat(reader.attributes().value(QStringLiteral("defStyleNum")));
|
||||
|
||||
QStringRef ref = reader.attributes().value(QStringLiteral("color"));
|
||||
if (!ref.isEmpty()) {
|
||||
style.textColor = QColor(ref.toString()).rgba();
|
||||
QStringRef attribute = reader.attributes().value(QStringLiteral("color"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.textColor = QColor(attribute.toString()).rgba();
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("selColor"));
|
||||
if (!ref.isEmpty()) {
|
||||
style.selectedTextColor = QColor(ref.toString()).rgba();
|
||||
attribute = reader.attributes().value(QStringLiteral("selColor"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.selectedTextColor = QColor(attribute.toString()).rgba();
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("backgroundColor"));
|
||||
if (!ref.isEmpty()) {
|
||||
style.backgroundColor = QColor(ref.toString()).rgba();
|
||||
attribute = reader.attributes().value(QStringLiteral("backgroundColor"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.backgroundColor = QColor(attribute.toString()).rgba();
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("selBackgroundColor"));
|
||||
if (!ref.isEmpty()) {
|
||||
style.selectedBackgroundColor = QColor(ref.toString()).rgba();
|
||||
attribute = reader.attributes().value(QStringLiteral("selBackgroundColor"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.selectedBackgroundColor = QColor(attribute.toString()).rgba();
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("italic"));
|
||||
if (!ref.isEmpty()) {
|
||||
attribute = reader.attributes().value(QStringLiteral("italic"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.hasItalic = true;
|
||||
style.italic = Xml::attrToBool(ref);
|
||||
style.italic = Xml::attrToBool(attribute);
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("bold"));
|
||||
if (!ref.isEmpty()) {
|
||||
attribute = reader.attributes().value(QStringLiteral("bold"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.hasBold = true;
|
||||
style.bold = Xml::attrToBool(ref);
|
||||
style.bold = Xml::attrToBool(attribute);
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("underline"));
|
||||
if (!ref.isEmpty()) {
|
||||
attribute = reader.attributes().value(QStringLiteral("underline"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.hasUnderline = true;
|
||||
style.underline = Xml::attrToBool(ref);
|
||||
style.underline = Xml::attrToBool(attribute);
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("strikeOut"));
|
||||
if (!ref.isEmpty()) {
|
||||
attribute = reader.attributes().value(QStringLiteral("strikeOut"));
|
||||
if (!attribute.isEmpty()) {
|
||||
style.hasStrikeThrough = true;
|
||||
style.strikeThrough = Xml::attrToBool(ref);
|
||||
style.strikeThrough = Xml::attrToBool(attribute);
|
||||
}
|
||||
|
||||
ref = reader.attributes().value(QStringLiteral("spellChecking"));
|
||||
if (!ref.isEmpty()) {
|
||||
spellCheck = Xml::attrToBool(ref);
|
||||
attribute = reader.attributes().value(QStringLiteral("spellChecking"));
|
||||
if (!attribute.isEmpty()) {
|
||||
spellCheck = Xml::attrToBool(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
*/
|
||||
|
||||
#include "keywordlist_p.h"
|
||||
#include "repository.h"
|
||||
#include "definition_p.h"
|
||||
#include "ksyntaxhighlighting_logging.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QXmlStreamReader>
|
||||
@@ -58,6 +61,11 @@ void KeywordList::load(QXmlStreamReader& reader)
|
||||
reader.readNextStartElement();
|
||||
break;
|
||||
}
|
||||
else if (reader.name() == QLatin1String("include")) {
|
||||
m_includes.append(reader.readElementText().trimmed());
|
||||
reader.readNextStartElement();
|
||||
break;
|
||||
}
|
||||
reader.readNext();
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
@@ -102,3 +110,40 @@ void KeywordList::initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive
|
||||
*/
|
||||
std::sort(vectorToSort.begin(), vectorToSort.end(), [caseSensitive] (const QStringRef &a, const QStringRef &b) { return a.compare(b, caseSensitive) < 0; });
|
||||
}
|
||||
|
||||
void KeywordList::resolveIncludeKeywords(DefinitionData &def)
|
||||
{
|
||||
while (!m_includes.isEmpty()) {
|
||||
const auto kw_include = std::move(m_includes.back());
|
||||
m_includes.pop_back();
|
||||
|
||||
const auto idx = kw_include.indexOf(QLatin1String("##"));
|
||||
KeywordList *keywords = nullptr;
|
||||
|
||||
if (idx >= 0) {
|
||||
auto listName = kw_include.left(idx);
|
||||
auto defName = kw_include.mid(idx + 2);
|
||||
auto includeDef = def.repo->definitionForName(defName);
|
||||
if (includeDef.isValid()) {
|
||||
auto defData = DefinitionData::get(includeDef);
|
||||
defData->load(DefinitionData::OnlyKeywords(true));
|
||||
keywords = defData->keywordList(listName);
|
||||
}
|
||||
else {
|
||||
qCWarning(Log) << "Unable to resolve external include keyword for definition" << defName << "in" << def.name;
|
||||
}
|
||||
} else {
|
||||
keywords = def.keywordList(kw_include);
|
||||
}
|
||||
|
||||
if (keywords) {
|
||||
if (this != keywords) {
|
||||
keywords->resolveIncludeKeywords(def);
|
||||
}
|
||||
m_keywords += keywords->m_keywords;
|
||||
}
|
||||
else {
|
||||
qCWarning(Log) << "Unresolved include keyword" << kw_include << "in" << def.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace KSyntaxHighlighting {
|
||||
|
||||
class Repository;
|
||||
class DefinitionData;
|
||||
|
||||
class KeywordList
|
||||
{
|
||||
public:
|
||||
@@ -69,6 +72,7 @@ public:
|
||||
void load(QXmlStreamReader &reader);
|
||||
void setCaseSensitivity(Qt::CaseSensitivity caseSensitive);
|
||||
void initLookupForCaseSensitivity(Qt::CaseSensitivity caseSensitive);
|
||||
void resolveIncludeKeywords(DefinitionData &def);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -81,6 +85,11 @@ private:
|
||||
*/
|
||||
QStringList m_keywords;
|
||||
|
||||
/**
|
||||
* raw list of include keywords, as seen in XML (but trimmed)
|
||||
*/
|
||||
QStringList m_includes;
|
||||
|
||||
/**
|
||||
* default case-sensitivity setting
|
||||
*/
|
||||
|
||||
@@ -69,7 +69,7 @@ Repository::~Repository()
|
||||
{
|
||||
// reset repo so we can detect in still alive definition instances
|
||||
// that the repo was deleted
|
||||
foreach (const auto &def, d->m_sortedDefs)
|
||||
for (const auto &def : qAsConst(d->m_sortedDefs))
|
||||
DefinitionData::get(def)->repo = nullptr;
|
||||
}
|
||||
|
||||
@@ -78,21 +78,16 @@ Definition Repository::definitionForName(const QString& defName) const
|
||||
return d->m_defs.value(defName);
|
||||
}
|
||||
|
||||
static Definition bestCandidate(QVector<Definition> &&candidates)
|
||||
static void sortDefinitions(QVector<Definition> &definitions)
|
||||
{
|
||||
if (candidates.isEmpty())
|
||||
return Definition();
|
||||
|
||||
std::partial_sort(candidates.begin(), candidates.begin() + 1, candidates.end(), [](const Definition &lhs, const Definition &rhs) {
|
||||
std::stable_sort(definitions.begin(), definitions.end(), [](const Definition &lhs, const Definition &rhs) {
|
||||
return lhs.priority() > rhs.priority();
|
||||
});
|
||||
|
||||
return candidates.at(0);
|
||||
}
|
||||
|
||||
Definition Repository::definitionForFileName(const QString& fileName) const
|
||||
{
|
||||
return bestCandidate(definitionsForFileName(fileName));
|
||||
return definitionsForFileName(fileName).value(0);
|
||||
}
|
||||
|
||||
QVector<Definition> Repository::definitionsForFileName(const QString &fileName) const
|
||||
@@ -101,9 +96,8 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName)
|
||||
const auto name = fi.fileName();
|
||||
|
||||
QVector<Definition> candidates;
|
||||
for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) {
|
||||
auto def = it.value();
|
||||
foreach (const auto &pattern, def.extensions()) {
|
||||
for (const Definition &def : qAsConst(d->m_sortedDefs)) {
|
||||
for (const auto &pattern : def.extensions()) {
|
||||
if (WildcardMatcher::exactMatch(name, pattern)) {
|
||||
candidates.push_back(def);
|
||||
break;
|
||||
@@ -111,26 +105,28 @@ QVector<Definition> Repository::definitionsForFileName(const QString &fileName)
|
||||
}
|
||||
}
|
||||
|
||||
sortDefinitions(candidates);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
Definition Repository::definitionForMimeType(const QString& mimeType) const
|
||||
{
|
||||
return bestCandidate(definitionsForMimeType(mimeType));
|
||||
return definitionsForMimeType(mimeType).value(0);
|
||||
}
|
||||
|
||||
QVector<Definition> Repository::definitionsForMimeType(const QString &mimeType) const
|
||||
{
|
||||
QVector<Definition> candidates;
|
||||
for (auto it = d->m_defs.constBegin(); it != d->m_defs.constEnd(); ++it) {
|
||||
auto def = it.value();
|
||||
foreach (const auto &matchType, def.mimeTypes()) {
|
||||
for (const Definition &def : qAsConst(d->m_sortedDefs)) {
|
||||
for (const auto &matchType : def.mimeTypes()) {
|
||||
if (mimeType == matchType) {
|
||||
candidates.push_back(def);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortDefinitions(candidates);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@@ -169,11 +165,11 @@ void RepositoryPrivate::load(Repository *repo)
|
||||
|
||||
// do lookup in standard paths, if not disabled
|
||||
#ifndef NO_STANDARD_PATHS
|
||||
foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory))
|
||||
for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/syntax"), QStandardPaths::LocateDirectory))
|
||||
loadSyntaxFolder(repo, dir);
|
||||
|
||||
// backward compatibility with Kate
|
||||
foreach (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);
|
||||
#endif
|
||||
|
||||
@@ -181,7 +177,7 @@ void RepositoryPrivate::load(Repository *repo)
|
||||
loadSyntaxFolder(repo, QStringLiteral(":/org.kde.syntax-highlighting/syntax"));
|
||||
|
||||
// user given extra paths
|
||||
foreach (const auto &path, m_customSearchPaths)
|
||||
for (const auto &path : qAsConst(m_customSearchPaths))
|
||||
loadSyntaxFolder(repo, path + QStringLiteral("/syntax"));
|
||||
|
||||
m_sortedDefs.reserve(m_defs.size());
|
||||
@@ -198,7 +194,7 @@ void RepositoryPrivate::load(Repository *repo)
|
||||
|
||||
// do lookup in standard paths, if not disabled
|
||||
#ifndef NO_STANDARD_PATHS
|
||||
foreach (const auto &dir, QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory))
|
||||
for (const auto &dir : QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("org.kde.syntax-highlighting/themes"), QStandardPaths::LocateDirectory))
|
||||
loadThemeFolder(dir);
|
||||
#endif
|
||||
|
||||
@@ -206,7 +202,7 @@ void RepositoryPrivate::load(Repository *repo)
|
||||
loadThemeFolder(QStringLiteral(":/org.kde.syntax-highlighting/themes"));
|
||||
|
||||
// user given extra paths
|
||||
foreach (const auto &path, m_customSearchPaths)
|
||||
for (const auto &path : qAsConst(m_customSearchPaths))
|
||||
loadThemeFolder(path + QStringLiteral("/themes"));
|
||||
}
|
||||
|
||||
@@ -307,7 +303,7 @@ quint16 RepositoryPrivate::nextFormatId()
|
||||
void Repository::reload()
|
||||
{
|
||||
qCDebug(Log) << "Reloading syntax definitions!";
|
||||
foreach (const auto &def, d->m_sortedDefs)
|
||||
for (const auto &def : qAsConst(d->m_sortedDefs))
|
||||
DefinitionData::get(def)->clear();
|
||||
d->m_defs.clear();
|
||||
d->m_sortedDefs.clear();
|
||||
|
||||
@@ -167,9 +167,11 @@ public:
|
||||
Definition definitionForFileName(const QString &fileName) const;
|
||||
|
||||
/**
|
||||
* Returns all Definition%s for the file named @p fileName.
|
||||
* Returns all Definition%s for the file named @p fileName sorted by priority.
|
||||
* The match is performed based on the \e extensions and @e mimetype of
|
||||
* the definition files.
|
||||
*
|
||||
* @since 5.56
|
||||
*/
|
||||
QVector<Definition> definitionsForFileName(const QString &fileName) const;
|
||||
|
||||
@@ -184,7 +186,9 @@ public:
|
||||
Definition definitionForMimeType(const QString &mimeType) const;
|
||||
|
||||
/**
|
||||
* Returns all Definition%s to the type named @p mimeType
|
||||
* Returns all Definition%s to the type named @p mimeType sorted by priority
|
||||
*
|
||||
* @since 5.56
|
||||
*/
|
||||
QVector<Definition> definitionsForMimeType(const QString &mimeType) const;
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ static int matchEscapedChar(const QString &text, int offset)
|
||||
if (controlChars.contains(c))
|
||||
return offset + 2;
|
||||
|
||||
if (c == QLatin1Char('x')) { // hex encoded character
|
||||
// hex encoded character
|
||||
if (c == QLatin1Char('x')) {
|
||||
auto newOffset = offset + 2;
|
||||
for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) {
|
||||
if (!isHexChar(text.at(newOffset)))
|
||||
@@ -70,14 +71,13 @@ static int matchEscapedChar(const QString &text, int offset)
|
||||
return newOffset;
|
||||
}
|
||||
|
||||
if (isOctalChar(c)) { // octal encoding
|
||||
// octal encoding, simple \0 is OK, too, unlike simple \x above
|
||||
if (isOctalChar(c)) {
|
||||
auto newOffset = offset + 2;
|
||||
for (int i = 0; i < 2 && newOffset + i < text.size(); ++i, ++newOffset) {
|
||||
if (!isOctalChar(text.at(newOffset)))
|
||||
break;
|
||||
}
|
||||
if (newOffset == offset + 2)
|
||||
return offset;
|
||||
return newOffset;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,15 +156,15 @@ void SyntaxHighlighter::highlightBlock(const QString& text)
|
||||
|
||||
void SyntaxHighlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format& format)
|
||||
{
|
||||
if (format.isDefaultTextStyle(theme()) || length == 0)
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
QTextCharFormat tf;
|
||||
if (format.hasTextColor(theme()))
|
||||
tf.setForeground(format.textColor(theme()));
|
||||
// always set the foreground color to avoid palette issues
|
||||
tf.setForeground(format.textColor(theme()));
|
||||
|
||||
if (format.hasBackgroundColor(theme()))
|
||||
tf.setBackground(format.backgroundColor(theme()));
|
||||
|
||||
if (format.isBold(theme()))
|
||||
tf.setFontWeight(QFont::Bold);
|
||||
if (format.isItalic(theme()))
|
||||
|
||||
Reference in New Issue
Block a user