diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-09-06 10:10:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-06 10:10:01 +0200 |
commit | 5b8d6e0b3200c5cb9d98cbdb4ed0afe2b4edd38d (patch) | |
tree | 23aac48c4aff31236341260942ceeb7b42fc90ab | |
parent | 4bf005e9fdfb57397475b2663a3651faa83886ff (diff) | |
parent | 0822896efcf0da7002e323369fdc1e4a15ad1d57 (diff) | |
download | rneovim-5b8d6e0b3200c5cb9d98cbdb4ed0afe2b4edd38d.tar.gz rneovim-5b8d6e0b3200c5cb9d98cbdb4ed0afe2b4edd38d.tar.bz2 rneovim-5b8d6e0b3200c5cb9d98cbdb4ed0afe2b4edd38d.zip |
Merge pull request #15391 from vigoux/ts-lua-builtin
feat(treesitter): highlighting for core languages, enabled for Lua
-rwxr-xr-x | .github/workflows/env.sh | 2 | ||||
-rw-r--r-- | cmake.deps/CMakeLists.txt | 6 | ||||
-rw-r--r-- | cmake.deps/cmake/BuildTreesitterParsers.cmake | 52 | ||||
-rw-r--r-- | cmake.deps/cmake/TreesitterParserCMakeLists.txt | 7 | ||||
-rw-r--r-- | runtime/CMakeLists.txt | 2 | ||||
-rw-r--r-- | runtime/doc/treesitter.txt | 67 | ||||
-rw-r--r-- | runtime/ftplugin/lua.lua | 3 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter.lua | 86 | ||||
-rw-r--r-- | runtime/queries/c/injections.scm | 3 | ||||
-rw-r--r-- | runtime/queries/lua/highlights.scm | 192 | ||||
-rw-r--r-- | runtime/queries/lua/injections.scm | 22 | ||||
-rw-r--r-- | runtime/queries/vim/highlights.scm | 245 | ||||
-rw-r--r-- | runtime/queries/vim/injections.scm | 26 | ||||
-rw-r--r-- | runtime/syntax/syntax.vim | 6 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 1 | ||||
-rw-r--r-- | test/functional/helpers.lua | 10 | ||||
-rw-r--r-- | test/functional/treesitter/highlight_spec.lua | 25 | ||||
-rw-r--r-- | test/functional/treesitter/language_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/treesitter/node_spec.lua | 5 | ||||
-rw-r--r-- | test/functional/treesitter/parser_spec.lua | 3 | ||||
-rw-r--r-- | test/functional/treesitter/utils_spec.lua | 2 |
21 files changed, 658 insertions, 119 deletions
diff --git a/.github/workflows/env.sh b/.github/workflows/env.sh index 061588da1a..da70d358a9 100755 --- a/.github/workflows/env.sh +++ b/.github/workflows/env.sh @@ -57,7 +57,7 @@ EOF functionaltest-lua) BUILD_FLAGS="$BUILD_FLAGS -DPREFER_LUA=ON" FUNCTIONALTEST=functionaltest-lua - DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUAJIT=OFF -DUSE_BUNDLED_TS_PARSERS=OFF" + DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUAJIT=OFF" ;; *) ;; diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index d2047c5b3d..2c19aa6e6b 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -208,6 +208,12 @@ set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc891 set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.2.tar.gz) set(TREESITTER_C_SHA256 af66fde03feb0df4faf03750102a0d265b007e5d957057b6b293c13116a70af2 ) +set(TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.12.tar.gz) +set(TREESITTER_LUA_SHA256 b6d7c6d04e9101a2e589d25f1d61668301e776c0b8defa6eae8dd86272e9e7c3) + +set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.1.0.tar.gz) +set(TREESITTER_VIM_SHA256 ea64fa211ccc7197669017b55911fdb56e8d4b6de96ba25c32b9586ec1c4f4c5) + set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz) set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e) diff --git a/cmake.deps/cmake/BuildTreesitterParsers.cmake b/cmake.deps/cmake/BuildTreesitterParsers.cmake index 1ff86e89b9..dd3f4eb308 100644 --- a/cmake.deps/cmake/BuildTreesitterParsers.cmake +++ b/cmake.deps/cmake/BuildTreesitterParsers.cmake @@ -1,29 +1,25 @@ -ExternalProject_Add(treesitter-c -PREFIX ${DEPS_BUILD_DIR} -URL ${TREESITTER_C_URL} -DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/treesitter-c -DOWNLOAD_COMMAND ${CMAKE_COMMAND} - -DPREFIX=${DEPS_BUILD_DIR} - -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/treesitter-c - -DURL=${TREESITTER_C_URL} - -DEXPECTED_SHA256=${TREESITTER_C_SHA256} - -DTARGET=treesitter-c - -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake -PATCH_COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterParserCMakeLists.txt - ${DEPS_BUILD_DIR}/src/treesitter-c/CMakeLists.txt -CMAKE_ARGS - -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - -DCMAKE_GENERATOR=${CMAKE_GENERATOR} - -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM} - ${BUILD_TYPE_STRING} - -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} - -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_ALT_SEP} - # Pass toolchain - -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} - -DPARSERLANG=c +function(BuildTSParser LANG TS_URL TS_SHA256 TS_CMAKE_FILE) + set(NAME treesitter-${LANG}) + ExternalProject_Add(${NAME} + PREFIX ${DEPS_BUILD_DIR} + URL ${TREESITTER_C_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${NAME} + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/${NAME} + -DURL=${TS_URL} + -DEXPECTED_SHA256=${TS_SHA256} + -DTARGET=${NAME} + -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + PATCH_COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TS_CMAKE_FILE} + ${DEPS_BUILD_DIR}/src/${NAME}/CMakeLists.txt + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR} + -DPARSERLANG=${LANG}) +endfunction() -BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} -INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE} -LIST_SEPARATOR |) +BuildTSParser(c ${TREESITTER_C_URL} ${TREESITTER_C_SHA256} TreesitterParserCMakeLists.txt) +BuildTSParser(lua ${TREESITTER_LUA_URL} ${TREESITTER_LUA_SHA256} TreesitterParserCMakeLists.txt) +BuildTSParser(vim ${TREESITTER_VIM_URL} ${TREESITTER_VIM_SHA256} TreesitterParserCMakeLists.txt) diff --git a/cmake.deps/cmake/TreesitterParserCMakeLists.txt b/cmake.deps/cmake/TreesitterParserCMakeLists.txt index 54bc35fb8a..9ec7a23864 100644 --- a/cmake.deps/cmake/TreesitterParserCMakeLists.txt +++ b/cmake.deps/cmake/TreesitterParserCMakeLists.txt @@ -1,10 +1,11 @@ cmake_minimum_required(VERSION 3.10) -# some parsers have c++ scanner, problem? -project(parser C) # CXX +project(parser C) + +file(GLOB source_files src/*.c) add_library(parser MODULE - src/parser.c + ${source_files} ) set_target_properties( parser diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e0a0b34d28..b42b1de54b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -123,7 +123,7 @@ foreach(PROG ${RUNTIME_PROGRAMS}) endforeach() globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR} - *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json) + *.vim *.lua *.scm *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json) foreach(F ${RUNTIME_FILES}) get_filename_component(BASEDIR ${F} DIRECTORY) diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 2c6c9e4ed8..8d5e494601 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -375,9 +375,9 @@ get_captures_at_position({bufnr}, {row}, {col}) Gets a list of captures for a given cursor position Parameters: ~ - {bufnr} (number) The buffer number - {row} (number) The position row - {col} (number) The position column + {bufnr} (number) Buffer number (0 for current buffer) + {row} (number) Position row + {col} (number) Position column Return: ~ (table) A table of captures @@ -398,12 +398,14 @@ get_parser({bufnr}, {lang}, {opts}) *get_parser()* callback Parameters: ~ - {bufnr} The buffer the parser should be tied to - {lang} The filetype of this parser - {opts} Options object to pass to the created language tree + {bufnr} (number|nil) Buffer the parser should be tied to: (default + current buffer) + {lang} (string) |nil Filetype of this parser (default: buffer + filetype) + {opts} (table|nil) Options to pass to the created language tree Return: ~ - The parser + (table) Parser object get_string_parser({str}, {lang}, {opts}) *get_string_parser()* Gets a string parser @@ -417,8 +419,8 @@ is_ancestor({dest}, {source}) *is_ancestor()* Determines whether a node is the ancestor of another Parameters: ~ - {dest} (table) the possible ancestor - {source} (table) the possible descendant node + {dest} (table) Possible ancestor + {source} (table) Possible descendant node Return: ~ (boolean) True if dest is an ancestor of source @@ -427,20 +429,57 @@ is_in_node_range({node}, {line}, {col}) *is_in_node_range()* Determines whether (line, col) position is in node range Parameters: ~ - {node} Node defining the range - {line} A line (0-based) - {col} A column (0-based) + {node} (table) Node defining the range + {line} (number) Line (0-based) + {col} (number) Column (0-based) + + Return: ~ + (boolean) True if the position is in node range node_contains({node}, {range}) *node_contains()* Determines if a node contains a range Parameters: ~ - {node} (table) The node - {range} (table) The range + {node} (table) + {range} (table) Return: ~ (boolean) True if the node contains the range +start({bufnr}, {lang}, {opts}) *start()* + Start treesitter highlighting for a buffer + + Can be used in an ftplugin or FileType autocommand + + Note: By default, disables regex syntax highlighting, which may be + required for some plugins. In this case, add `{ syntax = true }`. + + Example: +> + + vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', + callback = function(args) + vim.treesitter.start(args.buf, 'latex', { syntax = true }) + end + }) +< + + Parameters: ~ + {bufnr} (number|nil) Buffer to be highlighted (default: current + buffer) + {lang} (string|nil) Language of the parser (default: buffer + filetype) + {opts} (table|nil) Optional keyword arguments: + • `syntax` boolean Run regex syntax highlighting (default + false) + +stop({bufnr}) *stop()* + Stop treesitter highlighting for a buffer + + Parameters: ~ + {bufnr} (number|nil) Buffer to stop highlighting (default: current + buffer) + ============================================================================== Lua module: vim.treesitter.language *treesitter-language* diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua new file mode 100644 index 0000000000..415cf28f9a --- /dev/null +++ b/runtime/ftplugin/lua.lua @@ -0,0 +1,3 @@ +if vim.g.ts_highlight_lua then + vim.treesitter.start() +end diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 6431162799..9c43811e03 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -32,9 +32,11 @@ setmetatable(M, { --- --- It is not recommended to use this, use vim.treesitter.get_parser() instead. --- ----@param bufnr The buffer the parser will be tied to ----@param lang The language of the parser ----@param opts Options to pass to the created language tree +---@param bufnr string Buffer the parser will be tied to (0 for current buffer) +---@param lang string Language of the parser +---@param opts table|nil Options to pass to the created language tree +--- +---@returns table Created parser object function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then @@ -79,11 +81,11 @@ end --- If needed this will create the parser. --- Unconditionally attach the provided callback --- ----@param bufnr The buffer the parser should be tied to ----@param lang The filetype of this parser ----@param opts Options object to pass to the created language tree +---@param bufnr number|nil Buffer the parser should be tied to: (default current buffer) +---@param lang string |nil Filetype of this parser (default: buffer filetype) +---@param opts table|nil Options to pass to the created language tree --- ----@returns The parser +---@returns table Parser object function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -120,8 +122,8 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest table the possible ancestor ----@param source table the possible descendant node +---@param dest table Possible ancestor +---@param source table Possible descendant node --- ---@returns (boolean) True if dest is an ancestor of source function M.is_ancestor(dest, source) @@ -156,9 +158,11 @@ end ---Determines whether (line, col) position is in node range --- ----@param node Node defining the range ----@param line A line (0-based) ----@param col A column (0-based) +---@param node table Node defining the range +---@param line number Line (0-based) +---@param col number Column (0-based) +--- +---@returns (boolean) True if the position is in node range function M.is_in_node_range(node, line, col) local start_line, start_col, end_line, end_col = M.get_node_range(node) if line >= start_line and line <= end_line then @@ -177,8 +181,8 @@ function M.is_in_node_range(node, line, col) end ---Determines if a node contains a range ----@param node table The node ----@param range table The range +---@param node table +---@param range table --- ---@returns (boolean) True if the node contains the range function M.node_contains(node, range) @@ -190,9 +194,9 @@ function M.node_contains(node, range) end ---Gets a list of captures for a given cursor position ----@param bufnr number The buffer number ----@param row number The position row ----@param col number The position column +---@param bufnr number Buffer number (0 for current buffer) +---@param row number Position row +---@param col number Position column --- ---@returns (table) A table of captures function M.get_captures_at_position(bufnr, row, col) @@ -241,4 +245,52 @@ function M.get_captures_at_position(bufnr, row, col) return matches end +--- Start treesitter highlighting for a buffer +--- +--- Can be used in an ftplugin or FileType autocommand +--- +--- Note: By default, disables regex syntax highlighting, which may be required for some plugins. +--- In this case, add `{ syntax = true }`. +--- +--- Example: +--- +--- <pre> +--- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', +--- callback = function(args) +--- vim.treesitter.start(args.buf, 'latex', { syntax = true }) +--- end +--- }) +--- </pre> +--- +---@param bufnr number|nil Buffer to be highlighted (default: current buffer) +---@param lang string|nil Language of the parser (default: buffer filetype) +---@param opts table|nil Optional keyword arguments: +--- - `syntax` boolean Run regex syntax highlighting (default false) +function M.start(bufnr, lang, opts) + bufnr = bufnr or a.nvim_get_current_buf() + + local parser = M.get_parser(bufnr, lang) + + M.highlighter.new(parser) + + vim.b[bufnr].ts_highlight = true + + if opts and opts.syntax then + vim.bo[bufnr].syntax = 'on' + end +end + +---Stop treesitter highlighting for a buffer +--- +---@param bufnr number|nil Buffer to stop highlighting (default: current buffer) +function M.stop(bufnr) + bufnr = bufnr or a.nvim_get_current_buf() + + if M.highlighter.active[bufnr] then + M.highlighter.active[bufnr]:destroy() + end + + vim.bo[bufnr].syntax = 'on' +end + return M diff --git a/runtime/queries/c/injections.scm b/runtime/queries/c/injections.scm new file mode 100644 index 0000000000..7e9e73449d --- /dev/null +++ b/runtime/queries/c/injections.scm @@ -0,0 +1,3 @@ +(preproc_arg) @c + +; (comment) @comment diff --git a/runtime/queries/lua/highlights.scm b/runtime/queries/lua/highlights.scm new file mode 100644 index 0000000000..92baba0f39 --- /dev/null +++ b/runtime/queries/lua/highlights.scm @@ -0,0 +1,192 @@ +;; Keywords + +"return" @keyword.return + +[ + "goto" + "in" + "local" +] @keyword + +(label_statement) @label + +(break_statement) @keyword + +(do_statement +[ + "do" + "end" +] @keyword) + +(while_statement +[ + "while" + "do" + "end" +] @repeat) + +(repeat_statement +[ + "repeat" + "until" +] @repeat) + +(if_statement +[ + "if" + "elseif" + "else" + "then" + "end" +] @conditional) + +(elseif_statement +[ + "elseif" + "then" + "end" +] @conditional) + +(else_statement +[ + "else" + "end" +] @conditional) + +(for_statement +[ + "for" + "do" + "end" +] @repeat) + +(function_declaration +[ + "function" + "end" +] @keyword.function) + +(function_definition +[ + "function" + "end" +] @keyword.function) + +;; Operators + +[ + "and" + "not" + "or" +] @keyword.operator + +[ + "+" + "-" + "*" + "/" + "%" + "^" + "#" + "==" + "~=" + "<=" + ">=" + "<" + ">" + "=" + "&" + "~" + "|" + "<<" + ">>" + "//" + ".." +] @operator + +;; Punctuations + +[ + ";" + ":" + "," + "." +] @punctuation.delimiter + +;; Brackets + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +;; Variables + +(identifier) @variable + +((identifier) @variable.builtin + (#eq? @variable.builtin "self")) + +;; Constants + +((identifier) @constant + (#lua-match? @constant "^[A-Z][A-Z_0-9]*$")) + +(vararg_expression) @constant + +(nil) @constant.builtin + +[ + (false) + (true) +] @boolean + +;; Tables + +(field name: (identifier) @field) + +(dot_index_expression field: (identifier) @field) + +(table_constructor +[ + "{" + "}" +] @constructor) + +;; Functions + +(parameters (identifier) @parameter) + +(function_call name: (identifier) @function.call) +(function_declaration name: (identifier) @function) + +(function_call name: (dot_index_expression field: (identifier) @function.call)) +(function_declaration name: (dot_index_expression field: (identifier) @function)) + +(method_index_expression method: (identifier) @method) + +(function_call + (identifier) @function.builtin + (#any-of? @function.builtin + ;; built-in functions in Lua 5.1 + "assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs" + "load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print" + "rawequal" "rawget" "rawset" "require" "select" "setfenv" "setmetatable" + "tonumber" "tostring" "type" "unpack" "xpcall")) + +;; Others + +(comment) @comment + +(hash_bang_line) @comment + +(number) @number + +(string) @string + +;; Error +(ERROR) @error diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm new file mode 100644 index 0000000000..0e67329139 --- /dev/null +++ b/runtime/queries/lua/injections.scm @@ -0,0 +1,22 @@ +((function_call + name: [ + (identifier) @_cdef_identifier + (_ _ (identifier) @_cdef_identifier) + ] + arguments: (arguments (string content: _ @c))) + (#eq? @_cdef_identifier "cdef")) + +((function_call + name: (_) @_vimcmd_identifier + arguments: (arguments (string content: _ @vim))) + (#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_exec" "vim.api.nvim_cmd")) + +; ((function_call +; name: (_) @_vimcmd_identifier +; arguments: (arguments (string content: _ @query) .)) +; (#eq? @_vimcmd_identifier "vim.treesitter.query.set_query")) + +; ;; highlight string as query if starts with `;; query` +; ((string ("string_content") @query) (#lua-match? @query "^%s*;+%s?query")) + +; (comment) @comment diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm new file mode 100644 index 0000000000..c02e226b66 --- /dev/null +++ b/runtime/queries/vim/highlights.scm @@ -0,0 +1,245 @@ +(identifier) @variable +((identifier) @constant + (#lua-match? @constant "^[A-Z][A-Z_0-9]*$")) + +;; Keywords + +[ + "if" + "else" + "elseif" + "endif" +] @conditional + +[ + "try" + "catch" + "finally" + "endtry" + "throw" +] @exception + +[ + "for" + "endfor" + "in" + "while" + "endwhile" + "break" + "continue" +] @repeat + +[ + "function" + "endfunction" +] @keyword.function + +;; Function related +(function_declaration name: (_) @function) +(call_expression function: (identifier) @function) +(parameters (identifier) @parameter) +(default_parameter (identifier) @parameter) + +[ (bang) (spread) (at) ] @punctuation.special + +[ (no_option) (inv_option) (default_option) (option_name) ] @variable.builtin +[ + (scope) + "a:" + "$" +] @namespace + +;; Commands and user defined commands + +[ + "let" + "unlet" + "const" + "call" + "execute" + "normal" + "set" + "setlocal" + "silent" + "echo" + "echomsg" + "autocmd" + "augroup" + "return" + "syntax" + "lua" + "ruby" + "perl" + "python" + "highlight" + "command" + "delcommand" + "comclear" + "colorscheme" + "startinsert" + "stopinsert" + "global" + "runtime" + "wincmd" + "cnext" + "cprevious" + "cNext" + "vertical" + "leftabove" + "aboveleft" + "rightbelow" + "belowright" + "topleft" + "botright" + (unknown_command_name) +] @keyword +(map_statement cmd: _ @keyword) +(command_name) @function.macro + +;; Syntax command + +(syntax_statement (keyword) @string) +(syntax_statement [ + "enable" + "on" + "off" + "reset" + "case" + "spell" + "foldlevel" + "iskeyword" + "keyword" + "match" + "cluster" + "region" +] @keyword) + +(syntax_argument name: _ @keyword) + +[ + "<buffer>" + "<nowait>" + "<silent>" + "<script>" + "<expr>" + "<unique>" +] @constant.builtin + +(hl_attribute + key: _ @property + val: _ @constant) + +(hl_group) @variable +(augroup_name) @namespace + +(au_event) @constant +(normal_statement (commands) @constant) + +;; Highlight command + +(highlight_statement [ + "default" + "link" + "clear" +] @keyword) + +;; Command command + +(command_attribute + name: _ @property + val: (behavior + name: _ @constant + val: (identifier)? @function)?) + +;; Runtime command + +(runtime_statement (where) @keyword.operator) + +;; Colorscheme command + +(colorscheme_statement (name) @string) + +;; Literals + +(string_literal) @string +(integer_literal) @number +(float_literal) @float +(comment) @comment +(pattern) @string.special +(pattern_multi) @string.regex +(filename) @string +(heredoc (body) @string) +((heredoc (parameter) @keyword)) +((scoped_identifier + (scope) @_scope . (identifier) @boolean) + (#eq? @_scope "v:") + (#any-of? @boolean "true" "false")) + +;; Operators + +[ + "||" + "&&" + "&" + "+" + "-" + "*" + "/" + "%" + ".." + "is" + "isnot" + "==" + "!=" + ">" + ">=" + "<" + "<=" + "=~" + "!~" + "=" + "+=" + "-=" + "*=" + "/=" + "%=" + ".=" + "..=" +] @operator + +; Some characters have different meanings based on the context +(unary_operation "!" @operator) +(binary_operation "." @operator) + +;; Punctuation + +[ + "(" + ")" + "{" + "}" + "[" + "]" +] @punctuation.bracket + +(field_expression "." @punctuation.delimiter) + +[ + "," + ":" +] @punctuation.delimiter + +(ternary_expression ["?" ":"] @conditional) + +; Options +((set_value) @number + (#match? @number "^[0-9]+(\.[0-9]+)?$")) + +((set_item + option: (option_name) @_option + value: (set_value) @function) + (#any-of? @_option + "tagfunc" "tfu" + "completefunc" "cfu" + "omnifunc" "ofu" + "operatorfunc" "opfunc")) diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm new file mode 100644 index 0000000000..e2dea8fe75 --- /dev/null +++ b/runtime/queries/vim/injections.scm @@ -0,0 +1,26 @@ +(lua_statement (script (body) @lua)) +(lua_statement (chunk) @lua) +; (ruby_statement (script (body) @ruby)) +; (ruby_statement (chunk) @ruby) +; (python_statement (script (body) @python)) +; (python_statement (chunk) @python) +;; (perl_statement (script (body) @perl)) +;; (perl_statement (chunk) @perl) + +; (autocmd_statement (pattern) @regex) + +((set_item + option: (option_name) @_option + value: (set_value) @vim) + (#any-of? @_option + "includeexpr" "inex" + "printexpr" "pexpr" + "formatexpr" "fex" + "indentexpr" "inde" + "foldtext" "fdt" + "foldexpr" "fde" + "diffexpr" "dex" + "patchexpr" "pex" + "charconvert" "ccv")) + +; (comment) @comment diff --git a/runtime/syntax/syntax.vim b/runtime/syntax/syntax.vim index 55a2ee6d71..5ec99c7e05 100644 --- a/runtime/syntax/syntax.vim +++ b/runtime/syntax/syntax.vim @@ -27,13 +27,13 @@ else endif " Set up the connection between FileType and Syntax autocommands. -" This makes the syntax automatically set when the file type is detected. +" This makes the syntax automatically set when the file type is detected +" unless treesitter highlighting is enabled. " Avoid an error when 'verbose' is set and <amatch> expansion fails. augroup syntaxset - au! FileType * 0verbose exe "set syntax=" . expand("<amatch>") + au! FileType * if !exists('b:ts_highlight') | 0verbose exe "set syntax=" . expand("<amatch>") | endif augroup END - " Execute the syntax autocommands for the each buffer. " If the filetype wasn't detected yet, do that now. " Always do the syntaxset autocommands, for buffers where the 'filetype' diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 5c07784db3..412fe3509d 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -186,7 +186,6 @@ static const char *highlight_init_both[] = { "default link DiagnosticSignInfo DiagnosticInfo", "default link DiagnosticSignHint DiagnosticHint", - "default link @error Error", "default link @text.underline Underlined", "default link @todo Todo", "default link @debug Debug", diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 93fb0f245e..d672037a1e 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -755,16 +755,6 @@ function module.pending_win32(pending_fn) end end -function module.pending_c_parser(pending_fn) - local status, _ = unpack(module.exec_lua([[ return {pcall(vim.treesitter.require_language, 'c')} ]])) - if not status then - pending_fn 'no C parser, skipping' - return true - end - module.exec_lua [[vim._ts_remove_language 'c']] - return false -end - -- Calls pending() and returns `true` if the system is too slow to -- run fragile or expensive tests. Else returns `false`. function module.skip_fragile(pending_fn, cond) diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 4b0bd1eb50..d557b2c012 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -5,7 +5,6 @@ local clear = helpers.clear local insert = helpers.insert local exec_lua = helpers.exec_lua local feed = helpers.feed -local pending_c_parser = helpers.pending_c_parser local command = helpers.command local meths = helpers.meths local eq = helpers.eq @@ -107,12 +106,11 @@ describe('treesitter highlighting', function() } exec_lua([[ hl_query = ... ]], hl_query) + command [[ hi link @error ErrorMsg ]] command [[ hi link @warning WarningMsg ]] end) it('is updated with edits', function() - if pending_c_parser(pending) then return end - insert(hl_text) screen:expect{grid=[[ /// Schedule Lua callback on main loop's event queue | @@ -276,8 +274,6 @@ describe('treesitter highlighting', function() end) it('is updated with :sort', function() - if pending_c_parser(pending) then return end - insert(test_text) exec_lua [[ local parser = vim.treesitter.get_parser(0, "c") @@ -351,8 +347,6 @@ describe('treesitter highlighting', function() end) it("supports with custom parser", function() - if pending_c_parser(pending) then return end - screen:set_default_attr_ids { [1] = {bold = true, foreground = Screen.colors.SeaGreen4}; } @@ -417,8 +411,6 @@ describe('treesitter highlighting', function() end) it("supports injected languages", function() - if pending_c_parser(pending) then return end - insert([[ int x = INT_MAX; #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) @@ -479,8 +471,6 @@ describe('treesitter highlighting', function() end) it("supports overriding queries, like ", function() - if pending_c_parser(pending) then return end - insert([[ int x = INT_MAX; #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) @@ -520,8 +510,6 @@ describe('treesitter highlighting', function() end) it("supports highlighting with custom highlight groups", function() - if pending_c_parser(pending) then return end - insert(hl_text) exec_lua [[ @@ -577,8 +565,6 @@ describe('treesitter highlighting', function() end) it("supports highlighting with priority", function() - if pending_c_parser(pending) then return end - insert([[ int x = INT_MAX; #define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) @@ -594,9 +580,9 @@ describe('treesitter highlighting', function() -- expect everything to have Error highlight screen:expect{grid=[[ {12:int}{8: x = INT_MAX;} | - {8:#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))}| - {8:#define foo void main() { \} | - {8: return 42; \} | + {8:#define READ_STRING(x, y) (}{12:char_u}{8: *)read_string((x), (}{12:size_t}{8:)(y))}| + {8:#define foo }{12:void}{8: main() { \} | + {8: }{12:return}{8: 42; \} | {8: }} | ^ | {1:~ }| @@ -625,8 +611,6 @@ describe('treesitter highlighting', function() end) it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function() - if pending_c_parser(pending) then return end - insert([[ char* x = "Will somebody ever read this?"; ]]) @@ -708,7 +692,6 @@ describe('treesitter highlighting', function() end) it("supports conceal attribute", function() - if pending_c_parser(pending) then return end insert(hl_text) -- conceal can be empty or a single cchar. diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua index 8e9941d797..ed84dedb5a 100644 --- a/test/functional/treesitter/language_spec.lua +++ b/test/functional/treesitter/language_spec.lua @@ -6,7 +6,6 @@ local command = helpers.command local exec_lua = helpers.exec_lua local pcall_err = helpers.pcall_err local matches = helpers.matches -local pending_c_parser = helpers.pending_c_parser local insert = helpers.insert before_each(clear) @@ -28,15 +27,11 @@ describe('treesitter language API', function() eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')")) - if not pending_c_parser(pending) then - matches("Error executing lua: Failed to load parser: uv_dlsym: .+", - pcall_err(exec_lua, 'vim.treesitter.require_language("c", nil, false, "borklang")')) - end + matches("Error executing lua: Failed to load parser: uv_dlsym: .+", + pcall_err(exec_lua, 'vim.treesitter.require_language("c", nil, false, "borklang")')) end) it('inspects language', function() - if pending_c_parser(pending) then return end - local keys, fields, symbols = unpack(exec_lua([[ local lang = vim.treesitter.inspect_language('c') local keys, symbols = {}, {} @@ -76,7 +71,6 @@ describe('treesitter language API', function() end) it('checks if vim.treesitter.get_parser tries to create a new parser on filetype change', function () - if pending_c_parser(pending) then return end command("set filetype=c") -- Should not throw an error when filetype is c eq('c', exec_lua("return vim.treesitter.get_parser(0):lang()")) @@ -87,7 +81,6 @@ describe('treesitter language API', function() end) it('retrieve the tree given a range', function () - if pending_c_parser(pending) then return end insert([[ int main() { int x = 3; @@ -102,7 +95,6 @@ describe('treesitter language API', function() end) it('retrieve the node given a range', function () - if pending_c_parser(pending) then return end insert([[ int main() { int x = 3; diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua index 87ce1b973c..a82dce47b7 100644 --- a/test/functional/treesitter/node_spec.lua +++ b/test/functional/treesitter/node_spec.lua @@ -4,7 +4,6 @@ local clear = helpers.clear local eq = helpers.eq local exec_lua = helpers.exec_lua local insert = helpers.insert -local pending_c_parser = helpers.pending_c_parser before_each(clear) @@ -15,10 +14,6 @@ end describe('treesitter node API', function() clear() - if pending_c_parser(pending) then - return - end - it('can move between siblings', function() insert([[ int main(int x, int y, int z) { diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 7f3b0e770a..ccbd55df0e 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -5,13 +5,11 @@ local eq = helpers.eq local insert = helpers.insert local exec_lua = helpers.exec_lua local feed = helpers.feed -local pending_c_parser = helpers.pending_c_parser before_each(clear) describe('treesitter parser API', function() clear() - if pending_c_parser(pending) then return end it('parses buffer', function() if helpers.pending_win32(pending) then return end @@ -249,7 +247,6 @@ void ui_refresh(void) end) it('supports getting text of multiline node', function() - if pending_c_parser(pending) then return end insert(test_text) local res = exec_lua([[ local parser = vim.treesitter.get_parser(0, "c") diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua index 4f4c18a748..7f5a864c3d 100644 --- a/test/functional/treesitter/utils_spec.lua +++ b/test/functional/treesitter/utils_spec.lua @@ -4,7 +4,6 @@ local clear = helpers.clear local insert = helpers.insert local eq = helpers.eq local exec_lua = helpers.exec_lua -local pending_c_parser = helpers.pending_c_parser before_each(clear) @@ -12,7 +11,6 @@ describe('treesitter utils', function() before_each(clear) it('can find an ancestor', function() - if pending_c_parser(pending) then return end insert([[ int main() { |