Syntax Highlighting for CMake and CMakeCache

This commit is contained in:
全卓 2022-08-23 16:50:59 +08:00
parent 775b0d1281
commit 0f2ee9a26a
8 changed files with 386 additions and 22 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ dist
node_modules node_modules
.vscode-test/ .vscode-test/
*.vsix *.vsix
syntaxes/*.json

38
.vscode/tasks.json vendored
View File

@ -3,18 +3,28 @@
{ {
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"type": "npm", "type": "npm",
"script": "watch", "script": "watch",
"problemMatcher": "$tsc-watch", "problemMatcher": "$tsc-watch",
"isBackground": true, "isBackground": true,
"presentation": { "presentation": {
"reveal": "never" "reveal": "never"
}, },
"group": { "group": "build",
"kind": "build", "label": "npm: watch",
"isDefault": true "detail": "npm run grammar && tsc -watch -p ./"
} },
} {
] "type": "npm",
"script": "compile",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"label": "npm: compile",
"detail": "npm run grammar && tsc -p ./"
}
]
} }

View File

@ -0,0 +1,74 @@
{
"comments": {
"blockComment": [
"#[=[",
"]=]"
],
"lineComment": "#"
},
"brackets": [
[
"(",
")"
],
[
"[",
"]"
],
[
"{",
"}"
]
],
"autoClosingPairs": [
{
"open": "{",
"close": "}"
},
{
"open": "[",
"close": "]"
},
{
"open": "(",
"close": ")"
},
{
"open": "\"",
"close": "\"",
"notIn": [
"string"
]
}
],
"autoCloseBefore": ";:.,=}])>` \n\t",
"surroundingPairs": [
[
"(",
")"
],
[
"[",
"]"
],
[
"{",
"}"
],
[
"\"",
"\""
]
],
"folding": {
"markers": {
"start": "^\\s*#region\\b",
"end": "^\\s*#endregion\\b"
}
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
"indentationRules": {
"increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
"decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
}
}

3
package-lock.json generated
View File

@ -17,11 +17,12 @@
"@vscode/test-electron": "^2.1.5", "@vscode/test-electron": "^2.1.5",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"glob": "^8.0.3", "glob": "^8.0.3",
"js-yaml": "^4.1.0",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"typescript": "^4.7.4" "typescript": "^4.7.4"
}, },
"engines": { "engines": {
"vscode": "^1.70.0" "vscode": "^1.68.0"
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {

View File

@ -7,10 +7,14 @@
"vscode": "^1.68.0" "vscode": "^1.68.0"
}, },
"categories": [ "categories": [
"Other" "Programming Languages",
"Snippets",
"Formatters"
], ],
"activationEvents": [ "activationEvents": [
"onCommand:cmake-ls.helloWorld" "onCommand:cmake-ls.helloWorld",
"onLanguage:cmake",
"workspaceContains:CMakeLists.txt"
], ],
"main": "./out/extension.js", "main": "./out/extension.js",
"contributes": { "contributes": {
@ -19,27 +23,67 @@
"command": "cmake-ls.helloWorld", "command": "cmake-ls.helloWorld",
"title": "Hello World" "title": "Hello World"
} }
],
"grammars": [
{
"language": "cmake",
"scopeName": "source.cmake",
"path": "./syntaxes/cmake.tmLanguage.json"
},
{
"language": "cmakecache",
"scopeName": "source.cmakecache",
"path": "./syntaxes/cmakecache.tmLanguage.json"
}
],
"languages": [
{
"id": "cmake",
"extensions": [
".cmake"
],
"filenames": [
"CMakeLists.txt"
],
"aliases": [
"CMake"
],
"configuration": "./language-configuration.json"
},
{
"id": "cmakecache",
"filenames": [
"CMakeCache.txt"
],
"aliases": [
"CMakeCache"
]
}
] ]
}, },
"scripts": { "scripts": {
"vscode:prepublish": "npm run compile", "vscode:prepublish": "npm run compile",
"compile": "tsc -p ./", "grammar-cmake": "npx js-yaml ./syntaxes/cmake.tmLanguage.yml > ./syntaxes/cmake.tmLanguage.json",
"watch": "tsc -watch -p ./", "grammar-cmakecache": "npx js-yaml ./syntaxes/cmakecache.tmLanguage.yml > ./syntaxes/cmakecache.tmLanguage.json",
"grammar": "npm run grammar-cmake && npm run grammar-cmakecache",
"compile": "npm run grammar && tsc -p ./",
"watch": "npm run grammar && tsc -watch -p ./",
"pretest": "npm run compile && npm run lint", "pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts", "lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js" "test": "node ./out/test/runTest.js"
}, },
"devDependencies": { "devDependencies": {
"@types/vscode": "^1.70.0",
"@types/glob": "^7.2.0", "@types/glob": "^7.2.0",
"@types/mocha": "^9.1.1", "@types/mocha": "^9.1.1",
"@types/node": "16.x", "@types/node": "16.x",
"@types/vscode": "^1.68.0",
"@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0", "@typescript-eslint/parser": "^5.31.0",
"@vscode/test-electron": "^2.1.5",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"glob": "^8.0.3", "glob": "^8.0.3",
"js-yaml": "^4.1.0",
"mocha": "^10.0.0", "mocha": "^10.0.0",
"typescript": "^4.7.4", "typescript": "^4.7.4"
"@vscode/test-electron": "^2.1.5"
} }
} }

101
src/test/CMakeLists.txt Normal file
View File

@ -0,0 +1,101 @@
# This file is used to test the cmake-ls extension
cmake_minimum_required(VERSION 3.0)
project(Demo
VERSION 1.0
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
#[=[
This is bracket block comment
The second line in comment
]=]
# test bracket parameter
set(BRAKET_PARA [=[
First line in bracket parameter
Second line in bracket parameter
]=])
# numbers
set(DIGIT 100)
set(DIGIT 100.1)
# boolean constant
set(BOOL_TRUE YES)
set(BOOL_TRUE TRUE)
set(BOOL_FALSE NO)
set(BOOL_FALSE NOTFOUND)
set(BOOL_FALSE A-NOTFOUND)
# deprecated command
exec_program(dir)
install_files(dest so libc.so)
# flow control commands
if(TRUE)
message(STATUS "This message will print")
endif()
set(INDEX 1)
while(TRUE)
message(STATUS ${INDEX})
math(EXPR INDEX "${INDEX} + 1")
if (INDEX EQUAL 11)
break()
endif()
endwhile()
foreach(INDEX RANGE 10)
message(STATUS ${INDEX})
endforeach()
# operator
if(DEFINED undefined_function)
endif()
if ("gaga" STRLESS_EQUAL "haha")
endif()
if (TRUE AND FALSE)
endif()
# usr defined functions
function(print)
foreach(ARG IN LISTS ARGV)
endforeach()
endfunction()
macro(macro_print)
endmacro()
# test for cache variable
set(STR_VAR "demo string" CACHE STRING "This is docstring" FORCE)
set(BOOL_VAR "demo bool" CACHE BOOL "This is docstring" FORCE)
set(FILEPATH_VAR "demo filepath" CACHE FILEPATH "This is docstring" FORCE)
set(PATH_VAR "demo path" CACHE PATH "This is docstring" FORCE)
set(INTERNAL_VAR "demo internal" CACHE INTERNAL "This is docstring" FORCE)
# variable reference
message(STATUS $ENV{PATH})
message(STATUS $CACHE{CMAKE_BUILD_TYPE})
message(STATUS "$ENV{PATH} plain strings")
message(STATUS "$CACHE{CMAKE_BUILD_TYPE}")
message(STATUS "${PATH}")
message(STATUS "${CMAKE_BUILD_TYPE}")
# generator expression
# The $<BOOL:...> check prevents adding anything if the property is empty,
# assuming the property value cannot be one of CMake's false constants.
set(prop $<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>)
set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
add_custom_target(run_some_tool
COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
COMMAND_EXPAND_LISTS
VERBATIM
)
# string escape
set(VAR "This a \"in string")

View File

@ -0,0 +1,85 @@
fileTypes:
- cmake
- CMakeLists.txt
scopeName: source.cmake
# a dictionary (i.e. key/value pairs) of rules which can be included from other
# places in the grammar. The key is the name of the rule and the value is the actual rule.
repository:
variable-reference:
name: variable.other.cmake
begin: \$(ENV|CACHE)?{
beginCaptures:
"0": { name: punctuation.definition.variable-ref.start.cmake }
end: "}"
endCaptures:
"0": { name: punctuation.definition.variable-ref.end.cmake }
patterns:
- include: "#variable-reference"
generator-expression:
name: variable.other.cmake
begin: \$\<
beginCaptures:
"0": { name: punctuation.definition.generator-exp.start.cmake }
end: \>
endCaptures:
"0": { name: punctuation.definition.generator-exp.end.cmake }
patterns:
- include: "#generator-expression"
patterns:
# bracket comment
- name: comment.block.bracket.cmake
begin: '#\[(=*)\['
end: \]\1\]
# line comment
- name: comment.line.number-sign.cmake
match: "#(.*$)"
# string
- name: string.quoted.double.cmake
begin: '"'
end: '"'
patterns:
- include: "#variable-reference"
- include: "#generator-expression"
- name: constant.character.escape.cmake # escaped character in quoted string
match: \\.
# bracket argument
- name: meta.function.variable.parameter.cmake
begin: \s+\[(=*)\[
end: \]\1\]
# variable reference
- include: "#variable-reference"
# generator expression
- include: "#generator-expression"
# numbers
- name: constant.numeric.cmake
match: \b[0-9\.]+\b
# bool constant
- name: constant.language.bool.cmake
match: \b(?i:ON|YES|TRUE|Y|OFF|NO|FALSE|N|IGNORE|NOTFOUND|\w*-NOTFOUND)\b
# Deprecated Commands
- name: invalid.deprecated.command.cmake
match: ^\s*\b(?i:build_name|exec_program|export_library_dependencies|install_files|install_programs|install_targets|load_command|make_directory|output_required_files|qt_wrap_cpp|qt_wrap_ui|remove|subdir_depends|subdirs|use_mangled_mesa|utility_source|variable_requires|write_file)\b
# flow control commands in cmake
- name: keyword.control.cmake
match: ^\s*\b(if|elif|else|endif|while|endwhile|break|continue|foreach|endforeach|return)\b
# unary tests operators
- name: keyword.operator.unary.cmake
match: \b(EXISTS|COMMAND|DEFINED)\b
# binary tests operators
- name: keyword.operator.binary.cmake
match: \b(EQUAL|LESS|LESS_EQUAL|GREATER|GREATER_EQUAL|STREQUAL|STRLESS|STRLESS_EQUAL|STRGREATER|STRGREATER_EQUAL|VERSION_EQUAL|VERSION_LESS|VERSION_LESS_EQUAL|VERSION_GREATER|VERSION_GREATER_EQUAL|MATCHES)\b
# logical operators
- name: keyword.operator.logical.cmake
match: \b(NOT|AND|OR)\b
# CACHE variable type
- name: entity.name.type.cmake
match: \b(BOOL|FILEPATH|PATH|STRING|INTERNAL)\b
# variable declaration
- name: entity.name.function.cmake
- match: \b(?i:(set)\s*\(\s*(\w+)\s+)
captures:
"1": { name: entity.name.function.cmake }
"2": { name: variable.cmake }
# cmake builtin functions
- name: entity.name.function.cmake
match: \b(?i:cmake_host_system_information|cmake_language|cmake_minimum_required|cmake_parse_arguments|cmake_path|cmake_policy|configure_file|endfunction|endmacro|execute_process|file|find_file|find_library|find_package|find_path|find_program|function|get_cmake_property|get_directory_property|get_filename_component|get_property|include|include_guard|list|macro|mark_as_advanced|math|message|option|separate_arguments|set|set_directory_properties|set_property|site_name|string|unset|variable_watch|add_compile_definitions|add_compile_options|add_custom_command|add_custom_target|add_definitions|add_dependencies|add_executable|add_library|add_link_options|add_subdirectory|add_test|aux_source_directory|build_command|create_test_sourcelist|define_property|enable_language|enable_testing|export|fltk_wrap_ui|get_source_file_property|get_target_property|get_test_property|include_directories|include_external_msproject|include_regular_expression|install|link_directories|link_libraries|load_cache|project|remove_definitions|set_source_files_properties|set_target_properties|set_tests_properties|source_group|target_compile_definitions|target_compile_features|target_compile_options|target_include_directories|target_link_directories|target_link_libraries|target_link_options|target_precompile_headers|target_sources|try_compile|try_run|ctest_build|ctest_configure|ctest_coverage|ctest_empty_binary_directory|ctest_memcheck|ctest_read_custom_files|ctest_run_script|ctest_sleep|ctest_start|ctest_submit|ctest_test|ctest_update|ctest_upload)\b

View File

@ -0,0 +1,48 @@
fileTypes:
- cmakecache
- CMakeCache.txt
scopeName: source.cmakecache
repository:
variable-reference:
name: variable.other.cmake
begin: \$(ENV|CACHE)?{
beginCaptures:
"0": { name: punctuation.definition.variable-ref.start.cmake }
end: "}"
endCaptures:
"0": { name: punctuation.definition.variable-ref.end.cmake }
patterns:
- include: "#variable-reference"
patterns:
# comment line start with #
- name: comment.line.number-sign.cmakecache
match: "#.*$"
# comment line start with //
- name: comment.line.double-slash.cmakecache
match: //.*$
- name: asign.cmakecache
match: '\s*([\w-]+):(\w+)(=)(.+)?'
captures:
"1": { name: variable.cmakecache } # cache variable name
"2": { name: entity.name.type.cmakecache } # cache variable type
"3": { name: asign.cmakecache } # =
# right-hand side of the =
"4":
name: value.cmakecache
# https://macromates.com/manual/en/language_grammars
# The value of these keys is a dictionary with the key being the capture
# number and the value being a dictionary of attributes to assign to the
# captured text. Currently name is the only attribute supported.
# 上面的链接中的文档说 captures 目前只支持 name 属性,实际上也支持 patterns 属性
patterns:
- name: string.quoted.double.cmake
begin: '"'
end: '"'
patterns:
- include: "#variable-reference"
- name: constant.character.escape.cmake # escaped character in quoted string
match: \\.
- name: constant.numeric.cmakecache
match: \b[0-9\.]+\b
- name: constant.language.bool.cmakecache
match: \b(?i:\w*-NOTFOUND|NOTFOUND|ON|YES|TRUE|Y|OFF|NO|FALSE|N|IGNORE)$