diff options
29 files changed, 822 insertions, 328 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea3cbc40..5a6fd71e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,15 +156,16 @@ effect on highlighting. We will work on improving highlighting in the near futur #### Types ```scheme -@type ; type or class definitions and annotations -@type.builtin ; built-in types -@type.definition ; type definitions (e.g. `typedef` in C) -@type.qualifier ; type qualifiers (e.g. `const`) - -@storageclass ; visibility/life-time/etc. modifiers (e.g. `static`) -@attribute ; attribute annotations (e.g. Python decorators) -@field ; object and struct fields -@property ; similar to `@field` +@type ; type or class definitions and annotations +@type.builtin ; built-in types +@type.definition ; type definitions (e.g. `typedef` in C) +@type.qualifier ; type qualifiers (e.g. `const`) + +@storageclass ; visibility/life-time modifiers +@storageclass.lifetime ; life-time modifiers (e.g. `static`) +@attribute ; attribute annotations (e.g. Python decorators) +@field ; object and struct fields +@property ; similar to `@field` ``` #### Identifiers @@ -174,6 +174,7 @@ We are looking for maintainers to add more parsers and to write query files for <!--parserinfo--> - [x] [agda](https://github.com/AusCyberman/tree-sitter-agda) (maintained by @Decodetalkers) - [x] [astro](https://github.com/virchau13/tree-sitter-astro) (maintained by @virchau13) +- [ ] [awk](https://github.com/Beaglefoot/tree-sitter-awk) - [x] [bash](https://github.com/tree-sitter/tree-sitter-bash) (maintained by @TravonteD) - [x] [beancount](https://github.com/polarmutex/tree-sitter-beancount) (maintained by @polarmutex) - [x] [bibtex](https://github.com/latex-lsp/tree-sitter-bibtex) (maintained by @theHamsta, @clason) @@ -300,6 +301,7 @@ We are looking for maintainers to add more parsers and to write query files for - [x] [v](https://github.com/vlang/vls) (maintained by @tami5) - [x] [vala](https://github.com/vala-lang/tree-sitter-vala) (maintained by @Prince781, @vala-lang) - [x] [verilog](https://github.com/tree-sitter/tree-sitter-verilog) (maintained by @zegervdv) +- [x] [vhs](https://github.com/charmbracelet/tree-sitter-vhs) (maintained by @caarlos0, @maaslalani) - [x] [vim](https://github.com/vigoux/tree-sitter-viml) (maintained by @vigoux) - [x] [vue](https://github.com/ikatyang/tree-sitter-vue) (maintained by @WhyNotHugo) - [x] [wgsl](https://github.com/szebniok/tree-sitter-wgsl) (maintained by @szebniok) @@ -388,6 +390,7 @@ Tree-sitter based folding. *(Technically not a module because it's per windows a ```vim set foldmethod=expr set foldexpr=nvim_treesitter#foldexpr() +set nofoldenable " Disable folding at startup. ``` This will respect your `foldminlines` and `foldnestmax` settings. diff --git a/lockfile.json b/lockfile.json index d53211c2..df48b75c 100644 --- a/lockfile.json +++ b/lockfile.json @@ -5,8 +5,11 @@ "astro": { "revision": "947e93089e60c66e681eba22283f4037841451e7" }, + "awk": { + "revision": "a799bc5da7c2a84bc9a06ba5f3540cf1191e4ee3" + }, "bash": { - "revision": "f1a86d3cc5aeeb67e0e52442e893af7f813025b4" + "revision": "77cf8a7cab8904baf1a721762e012644ac1d4c7b" }, "beancount": { "revision": "4cbd1f09cd07c1f1fabf867c2cf354f9da53cc4c" @@ -21,7 +24,7 @@ "revision": "7175a6dd5fc1cee660dce6fe23f6043d75af424a" }, "c_sharp": { - "revision": "5b60f99545fea00a33bbfae5be956f684c4c69e2" + "revision": "3ef3f7f99e16e528e6689eae44dff35150993307" }, "clojure": { "revision": "087bac78c53fe1387756cd5b8e68a69b3f6d7244" @@ -60,7 +63,7 @@ "revision": "330eb648bbc257b4e91621e82a85372be7dde27a" }, "dockerfile": { - "revision": "25c71d6a24cdba8f0c74ef40d4d2d93defd7e196" + "revision": "f913be9bb8689af22114605012693146fbe9ddaa" }, "dot": { "revision": "9ab85550c896d8b294d9b9ca1e30698736f08cea" @@ -77,11 +80,8 @@ "elvish": { "revision": "f32711e31e987fd5c2c002f3daba02f25c68672f" }, - "embdedded_template": { - "revision": "d21df11b0ecc6fd211dbe11278e92ef67bd17e97" - }, "embedded_template": { - "revision": "1a538da253d73f896b9f6c0c7d79cda58791ac5c" + "revision": "91fc5ae1140d5c9d922312431f7d251a48d7b8ce" }, "erlang": { "revision": "3a9c769444f08bbccce03845270efac0c641c5e7" @@ -150,7 +150,7 @@ "revision": "52b804b1cb2d57e58d90090326d3ef9bd19cf16c" }, "help": { - "revision": "8df3266b423d24c9ac3f3b4b9928e65eb1e5e741" + "revision": "49cdef52ded4a886bf34bc474876b09f9270d48f" }, "hjson": { "revision": "02fa3b79b3ff9a296066da6277adfc3f26cbc9e0" @@ -159,7 +159,7 @@ "revision": "384b26ec65e10f26cf147bfcde772c50ca5ef0d0" }, "hocon": { - "revision": "bb412e2633f4a3611a4e16efe58d917093bb4782" + "revision": "c390f10519ae69fdb03b3e5764f5592fb6924bcc" }, "html": { "revision": "29f53d8f4f2335e61bf6418ab8958dac3282077a" @@ -189,10 +189,10 @@ "revision": "0475a5017ad7dc84845d1d33187f2321abcb261d" }, "julia": { - "revision": "0572cebf7b8e8ef5990b4d1e7f44f0b36f62922c" + "revision": "628713553c42f30595a3b0085bb587e9359b986a" }, "kotlin": { - "revision": "a4f71eb9b8c9b19ded3e0e9470be4b1b77c2b569" + "revision": "b953dbdd05257fcb2b64bc4d9c1578fac12e3c28" }, "lalrpop": { "revision": "7744b56f03ac1e5643fad23c9dd90837fe97291e" @@ -207,7 +207,7 @@ "revision": "e9948edc41e9e5869af99dddb2b5ff5cc5581af6" }, "lua": { - "revision": "887dfd4e83c469300c279314ff1619b1d0b85b91" + "revision": "fb30e8cb605e2ebd6c643e6981325a63fbbde320" }, "m68k": { "revision": "d097b123f19c6eaba2bf181c05420d88b9fc489d" @@ -255,7 +255,7 @@ "revision": "2fd40f477d3e2794af152618ccfac8d92eb72a66" }, "perl": { - "revision": "ff5c3108083af6fcb7575e32a7558b8165a05bcd" + "revision": "749d26fe13fb131b92e6515416096e572575b981" }, "php": { "revision": "ab2e72179ceb8bb0b249c8ac9162a148e911b3dc" @@ -288,10 +288,10 @@ "revision": "0695cd0760532de7b54f23c667d459b5d1332b44" }, "r": { - "revision": "0f4f66e5050037b759ea040dafd596bcdda1de94" + "revision": "80efda55672d1293aa738f956c7ae384ecdc31b4" }, "racket": { - "revision": "b9b2e7454d7098e44595dd8c1b471b9d1518b910" + "revision": "09cb27a06415bce529a26774a842f5a80d50d362" }, "rasi": { "revision": "12391343979463a2484e6353e5afb6dcb8c31e8b" @@ -300,7 +300,7 @@ "revision": "e1cfca3c79896ff79842f057ea13e529b66af636" }, "rego": { - "revision": "6d70da3a998fd0081efc5d1019c71e74cc1568e9" + "revision": "6174f05f58e8c35d8c82323dd8c599b90b3171b3" }, "rnoweb": { "revision": "502c1126dc6777f09af5bef16e72a42f75bd081e" @@ -309,16 +309,16 @@ "revision": "25e6328872ac3a764ba8b926aea12719741103f1" }, "ruby": { - "revision": "252ca18be76b0918fb6b34c302292b6931876c25" + "revision": "c91960320d0f337bdd48308a8ad5500bd2616979" }, "rust": { - "revision": "47b061c1e1ba3a7e9c2f450363a50e87de3f7c61" + "revision": "0431a2c60828731f27491ee9fdefe25e250ce9c9" }, "scala": { "revision": "140c96cf398693189d4e50f76d19ddfcd8a018f8" }, "scheme": { - "revision": "af0fd1fa452cb2562dc7b5c8a8c55551c39273b9" + "revision": "bdcd2c8496701153506a9e3e1b76dfed852873ba" }, "scss": { "revision": "c478c6868648eff49eb04a4df90d703dc45b312a" @@ -333,7 +333,7 @@ "revision": "05f949d3c1c15e3261473a244d3ce87777374dec" }, "sql": { - "revision": "2743c7b5e710e6854d4e8c14c302548b436e2a1f" + "revision": "70c50264ae022193adb364ffa7a767d765ed9857" }, "supercollider": { "revision": "90c6d9f777d2b8c4ce497c48b5f270a44bcf3ea0" @@ -345,7 +345,7 @@ "revision": "52e122ae68b316d3aa960a0a422d3645ba717f42" }, "swift": { - "revision": "c88b5d73f193f5b0762b1a5f0299a275e6a728fb" + "revision": "25f8de356e3c33099ed691bd3b8b5c0fe3a11e15" }, "sxhkdrc": { "revision": "440d5f913d9465c9c776a1bd92334d32febcf065" @@ -372,13 +372,13 @@ "revision": "085437f5cb117703b7f520dd92161140a684f092" }, "twig": { - "revision": "6a01f20e73038300d205d370212c361949be3035" + "revision": "035f549ec8c043e734f04341d7ccdc669bb2ba91" }, "typescript": { "revision": "0ab9d99867435a7667c5548a6617a6bf73dbd830" }, "v": { - "revision": "d0e7c755193c762eb1521e3b4740b22929cc91cc" + "revision": "66b92a89ef1e149300df79c0b2a934ad959c8eec" }, "vala": { "revision": "8f690bfa639f2b83d1fb938ed3dd98a7ba453e8b" @@ -386,8 +386,11 @@ "verilog": { "revision": "4457145e795b363f072463e697dfe2f6973c9a52" }, + "vhs": { + "revision": "2f87b9d973597e69552ecf6a4fe16470fbd8c44e" + }, "vim": { - "revision": "9736af8ef0a7f20b4c45f6474342c8f5b473e2cc" + "revision": "4ae7bd67706d7e10afed827ce2ded884ab41650f" }, "vue": { "revision": "91fe2754796cd8fba5f229505a23fa08f3546c06" @@ -402,6 +405,6 @@ "revision": "8e9d175982afcefa3dac8ca20d40d1643accd2bd" }, "zig": { - "revision": "b1803f2a665d228f968a831eac4fcc07a377c7bc" + "revision": "d90d38d28ce8cc27bfea8b4e0c75211e9e2398ca" } } diff --git a/lua/nvim-treesitter/configs.lua b/lua/nvim-treesitter/configs.lua index 87bb8d1a..6db2935a 100644 --- a/lua/nvim-treesitter/configs.lua +++ b/lua/nvim-treesitter/configs.lua @@ -8,6 +8,16 @@ local caching = require "nvim-treesitter.caching" local M = {} +---@class TSConfig +---@field modules {[string]:TSModule} +---@field sync_install boolean +---@field ensure_installed string[]|string +---@field ignore_install string[] +---@field auto_install boolean +---@field update_strategy string +---@field parser_install_dir string|nil + +---@type TSConfig local config = { modules = {}, sync_install = false, @@ -21,6 +31,17 @@ local config = { local queued_modules_defs = {} -- Whether we've initialized the plugin yet. local is_initialized = false + +---@class TSModule +---@field module_path string +---@field enable boolean|string[]|function(string): boolean +---@field disable boolean|string[]|function(string): boolean +---@field is_supported function(string): boolean +---@field attach function(string) +---@field detach function(string) +---@field enabled_buffers table<integer, boolean> + +---@type {[string]: TSModule} local builtin_modules = { highlight = { module_path = "nvim-treesitter.highlight", @@ -54,7 +75,9 @@ local builtin_modules = { local attached_buffers_by_module = caching.create_buffer_cache() --- Resolves a module by requiring the `module_path` or using the module definition. +---Resolves a module by requiring the `module_path` or using the module definition. +---@param mod_name string +---@return TSModule|nil local function resolve_module(mod_name) local config_mod = M.get_module(mod_name) @@ -69,10 +92,10 @@ local function resolve_module(mod_name) end end --- Enables and attaches the module to a buffer for lang. --- @param mod path to module --- @param bufnr buffer number, defaults to current buffer --- @param lang language, defaults to current language +---Enables and attaches the module to a buffer for lang. +---@param mod string path to module +---@param bufnr integer|nil buffer number, defaults to current buffer +---@param lang string|nil language, defaults to current language local function enable_module(mod, bufnr, lang) local module = M.get_module(mod) if not module then @@ -93,9 +116,9 @@ local function enable_module(mod, bufnr, lang) M.attach_module(mod, bufnr, lang) end --- Enables autocomands for the module. --- After the module is loaded `loaded` will be set to true for the module. --- @param mod path to module +---Enables autocomands for the module. +---After the module is loaded `loaded` will be set to true for the module. +---@param mod string path to module local function enable_mod_conf_autocmd(mod) local config_mod = M.get_module(mod) if not config_mod or config_mod.loaded then @@ -113,9 +136,9 @@ local function enable_mod_conf_autocmd(mod) config_mod.loaded = true end --- Enables the module globally and for all current buffers. --- After enabled, `enable` will be set to true for the module. --- @param mod path to module +---Enables the module globally and for all current buffers. +---After enabled, `enable` will be set to true for the module. +---@param mod string path to module local function enable_all(mod) local config_mod = M.get_module(mod) if not config_mod then @@ -131,9 +154,9 @@ local function enable_all(mod) end end --- Disables and detaches the module for a buffer. --- @param mod path to module --- @param bufnr buffer number, defaults to current buffer +---Disables and detaches the module for a buffer. +---@param mod string path to module +---@param bufnr integer buffer number, defaults to current buffer local function disable_module(mod, bufnr) local module = M.get_module(mod) if not module then @@ -147,9 +170,9 @@ local function disable_module(mod, bufnr) M.detach_module(mod, bufnr) end --- Disables autocomands for the module. --- After the module is unloaded `loaded` will be set to false for the module. --- @param mod path to module +---Disables autocomands for the module. +---After the module is unloaded `loaded` will be set to false for the module. +---@param mod string path to module local function disable_mod_conf_autocmd(mod) local config_mod = M.get_module(mod) if not config_mod or not config_mod.loaded then @@ -159,9 +182,9 @@ local function disable_mod_conf_autocmd(mod) config_mod.loaded = false end --- Disables the module globally and for all current buffers. --- After disabled, `enable` will be set to false for the module. --- @param mod path to module +---Disables the module globally and for all current buffers. +---After disabled, `enable` will be set to false for the module. +---@param mod string path to module local function disable_all(mod) local config_mod = M.get_module(mod) if not config_mod then @@ -177,10 +200,10 @@ local function disable_all(mod) end end --- Toggles a module for a buffer --- @param mod path to module --- @param bufnr buffer number, defaults to current buffer --- @param lang language, defaults to current language +---Toggles a module for a buffer +---@param mod string path to module +---@param bufnr integer buffer number, defaults to current buffer +---@param lang string language, defaults to current language local function toggle_module(mod, bufnr, lang) bufnr = bufnr or api.nvim_get_current_buf() lang = lang or parsers.get_buf_lang(bufnr) @@ -207,10 +230,10 @@ local function toggle_all(mod) end end --- Recurses through all modules including submodules --- @param accumulator function called for each module --- @param root root configuration table to start at --- @param path prefix path +---Recurses through all modules including submodules +---@param accumulator function called for each module +---@param root {[string]: TSModule} root configuration table to start at +---@param path string|nil prefix path local function recurse_modules(accumulator, root, path) root = root or config.modules @@ -225,9 +248,9 @@ local function recurse_modules(accumulator, root, path) end end --- Shows current configuration of all nvim-treesitter modules --- @param process_function function used as the `process` parameter --- for vim.inspect (https://github.com/kikito/inspect.lua#optionsprocess) +---Shows current configuration of all nvim-treesitter modules +---@param process_function function used as the `process` parameter +--- for vim.inspect (https://github.com/kikito/inspect.lua#optionsprocess) local function config_info(process_function) process_function = process_function or function(item, path) @@ -242,6 +265,8 @@ local function config_info(process_function) print(vim.inspect(config, { process = process_function })) end +---@param query_group string +---@param lang string function M.edit_query_file(query_group, lang) lang = lang or parsers.get_buf_lang() local files = ts_query.get_query_files(lang, query_group, true) @@ -259,6 +284,8 @@ function M.edit_query_file(query_group, lang) end end +---@param query_group string +---@param lang string function M.edit_query_file_user_after(query_group, lang) lang = lang or parsers.get_buf_lang() local folder = utils.join_path(vim.fn.stdpath "config", "after", "queries", lang) @@ -340,9 +367,9 @@ M.commands = { }, } --- @param mod: module (string) --- @param lang: the language of the buffer (string) --- @param bufnr: the bufnr (number) +---@param mod string module +---@param lang string the language of the buffer +---@param bufnr integer the bufnr function M.is_enabled(mod, lang, bufnr) if not parsers.has_parser(lang) then return false @@ -376,8 +403,8 @@ function M.is_enabled(mod, lang, bufnr) return true end --- Setup call for users to override module configurations. --- @param user_data module overrides +---Setup call for users to override module configurations. +---@param user_data TSConfig module overrides function M.setup(user_data) config.modules = vim.tbl_deep_extend("force", config.modules, user_data) config.ignore_install = user_data.ignore_install or {} @@ -411,32 +438,33 @@ function M.setup(user_data) end, config.modules) end --- Defines a table of modules that can be attached/detached to buffers --- based on language support. A module consist of the following properties: --- * @enable Whether the modules is enabled. Can be true or false. --- * @disable A list of languages to disable the module for. Only relevant if enable is true. --- * @keymaps A list of user mappings for a given module if relevant. --- * @is_supported A function which, given a ft, will return true if the ft works on the module. --- * @module_path A string path to a module file using `require`. The exported module must contain --- an `attach` and `detach` function. This path is not required if `attach` and `detach` --- functions are provided directly on the module definition. --- * @attach An attach function that is called for each buffer that the module is enabled for. This is required --- if a `module_path` is not specified. --- * @detach A detach function that is called for each buffer that the module is enabled for. This is required --- if a `module_path` is not specified. --- Modules are not setup until `init` is invoked by the plugin. This allows modules to be defined in any order --- and can be loaded lazily. --- @example --- require"nvim-treesitter".define_modules { --- my_cool_module = { --- attach = function() --- do_some_cool_setup() --- end, --- detach = function() --- do_some_cool_teardown() --- end --- } --- } +---Defines a table of modules that can be attached/detached to buffers +---based on language support. A module consist of the following properties: +---* @enable Whether the modules is enabled. Can be true or false. +---* @disable A list of languages to disable the module for. Only relevant if enable is true. +---* @keymaps A list of user mappings for a given module if relevant. +---* @is_supported A function which, given a ft, will return true if the ft works on the module. +---* @module_path A string path to a module file using `require`. The exported module must contain +--- an `attach` and `detach` function. This path is not required if `attach` and `detach` +--- functions are provided directly on the module definition. +---* @attach An attach function that is called for each buffer that the module is enabled for. This is required +--- if a `module_path` is not specified. +---* @detach A detach function that is called for each buffer that the module is enabled for. This is required +--- if a `module_path` is not specified. +---Modules are not setup until `init` is invoked by the plugin. This allows modules to be defined in any order +---and can be loaded lazily. +---@example +---require"nvim-treesitter".define_modules { +--- my_cool_module = { +--- attach = function() +--- do_some_cool_setup() +--- end, +--- detach = function() +--- do_some_cool_teardown() +--- end +--- } +---} +---@param mod_defs TSModule[] function M.define_modules(mod_defs) if not is_initialized then table.insert(queued_modules_defs, mod_defs) @@ -463,10 +491,10 @@ function M.define_modules(mod_defs) end end --- Attaches a module to a buffer --- @param mod_name the module name --- @param bufnr the bufnr --- @param lang the language of the buffer +---Attaches a module to a buffer +---@param mod_name string the module name +---@param bufnr integer the bufnr +---@param lang string the language of the buffer function M.attach_module(mod_name, bufnr, lang) bufnr = bufnr or api.nvim_get_current_buf() lang = lang or parsers.get_buf_lang(bufnr) @@ -478,9 +506,9 @@ function M.attach_module(mod_name, bufnr, lang) end end --- Detaches a module to a buffer --- @param mod_name the module name --- @param bufnr the bufnr +---Detaches a module to a buffer +---@param mod_name string the module name +---@param bufnr integer the bufnr function M.detach_module(mod_name, bufnr) local resolved_mod = resolve_module(mod_name) bufnr = bufnr or api.nvim_get_current_buf() @@ -491,17 +519,17 @@ function M.detach_module(mod_name, bufnr) end end --- Same as attach_module, but if the module is already attached, detach it first. --- @param mod_name the module name --- @param bufnr the bufnr --- @param lang the language of the buffer +---Same as attach_module, but if the module is already attached, detach it first. +---@param mod_name string the module name +---@param bufnr integer the bufnr +---@param lang string the language of the buffer function M.reattach_module(mod_name, bufnr, lang) M.detach_module(mod_name, bufnr) M.attach_module(mod_name, bufnr, lang) end --- Gets available modules --- @param root root table to find modules +---Gets available modules +---@param root {[string]:TSModule} table to find modules function M.available_modules(root) local modules = {} @@ -512,25 +540,26 @@ function M.available_modules(root) return modules end --- Gets a module config by path --- @param mod_path path to the module --- @returns the module or nil +---Gets a module config by path +---@param mod_path string path to the module +---@return TSModule|nil the module or nil function M.get_module(mod_path) local mod = utils.get_at_path(config.modules, mod_path) return M.is_module(mod) and mod or nil end --- Determines whether the provided table is a module. --- A module should contain an attach and detach function. --- @param mod the module table +---Determines whether the provided table is a module. +---A module should contain an attach and detach function. +---@param mod table the module table +---@return boolean function M.is_module(mod) return type(mod) == "table" and ((type(mod.attach) == "function" and type(mod.detach) == "function") or type(mod.module_path) == "string") end --- Initializes built-in modules and any queued modules --- registered by plugins or the user. +---Initializes built-in modules and any queued modules +---registered by plugins or the user. function M.init() is_initialized = true M.define_modules(builtin_modules) @@ -540,11 +569,13 @@ function M.init() end end --- If parser_install_dir is not nil is used or created. --- If parser_install_dir is nil try the package dir of the nvim-treesitter --- plugin first, followed by the "site" dir from "runtimepath". "site" dir will --- be created if it doesn't exist. Using only the package dir won't work when --- the plugin is installed with Nix, since the "/nix/store" is read-only. +---If parser_install_dir is not nil is used or created. +---If parser_install_dir is nil try the package dir of the nvim-treesitter +---plugin first, followed by the "site" dir from "runtimepath". "site" dir will +---be created if it doesn't exist. Using only the package dir won't work when +---the plugin is installed with Nix, since the "/nix/store" is read-only. +---@param folder_name string +---@return string|nil, string|nil function M.get_parser_install_dir(folder_name) folder_name = folder_name or "parser" diff --git a/lua/nvim-treesitter/fold.lua b/lua/nvim-treesitter/fold.lua index 1f417414..50272622 100644 --- a/lua/nvim-treesitter/fold.lua +++ b/lua/nvim-treesitter/fold.lua @@ -102,6 +102,8 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr) return levels end) +---@param lnum integer +---@return string function M.get_fold_indic(lnum) if not parsers.has_parser() or not lnum then return "0" diff --git a/lua/nvim-treesitter/highlight.lua b/lua/nvim-treesitter/highlight.lua index 502914fe..5f7dead6 100644 --- a/lua/nvim-treesitter/highlight.lua +++ b/lua/nvim-treesitter/highlight.lua @@ -6,6 +6,9 @@ local configs = require "nvim-treesitter.configs" local M = {} +---@param config table +---@param lang string +---@return boolean local function should_enable_vim_regex(config, lang) local additional_hl = config.additional_vim_regex_highlighting local is_table = type(additional_hl) == "table" @@ -13,29 +16,36 @@ local function should_enable_vim_regex(config, lang) return additional_hl and (not is_table or vim.tbl_contains(additional_hl, lang)) end +---@param bufnr integer local function enable_syntax(bufnr) api.nvim_buf_set_option(bufnr, "syntax", "ON") end +---@param bufnr integer function M.stop(bufnr) if ts.highlighter.active[bufnr] then ts.highlighter.active[bufnr]:destroy() end end +---@param bufnr integer +---@param lang string function M.start(bufnr, lang) local parser = parsers.get_parser(bufnr, lang) ts.highlighter.new(parser, {}) end +---@param bufnr integer +---@param lang string function M.attach(bufnr, lang) local config = configs.get_module "highlight" M.start(bufnr, lang) - if should_enable_vim_regex(config, lang) then + if config and should_enable_vim_regex(config, lang) then enable_syntax(bufnr) end end +---@param bufnr integer function M.detach(bufnr) M.stop(bufnr) enable_syntax(bufnr) diff --git a/lua/nvim-treesitter/install.lua b/lua/nvim-treesitter/install.lua index 95a8a9f9..48810b1e 100644 --- a/lua/nvim-treesitter/install.lua +++ b/lua/nvim-treesitter/install.lua @@ -42,11 +42,14 @@ local function get_job_status() .. "]" end +---@param lang string +---@param validate boolean|nil +---@return InstallInfo local function get_parser_install_info(lang, validate) local parser_config = parsers.get_parser_configs()[lang] if not parser_config then - return error('Parser not available for language "' .. lang .. '"') + error('Parser not available for language "' .. lang .. '"') end local install_info = parser_config.install_info @@ -79,6 +82,8 @@ local function get_revision(lang) return (lockfile[lang] and lockfile[lang].revision) end +---@param lang string +---@return string|nil local function get_installed_revision(lang) local lang_file = utils.join_path(configs.get_parser_info_dir(), lang .. ".revision") if vim.fn.filereadable(lang_file) == 1 then @@ -86,23 +91,30 @@ local function get_installed_revision(lang) end end +---@param lang string +---@return boolean local function is_installed(lang) return #api.nvim_get_runtime_file("parser/" .. lang .. ".so", false) > 0 end +---@param lang string +---@return boolean local function needs_update(lang) local revision = get_revision(lang) return not revision or revision ~= get_installed_revision(lang) end +---@return table local function outdated_parsers() return vim.tbl_filter(function(lang) return needs_update(lang) end, info.installed_parsers()) end +---@param handle userdata +---@param is_stderr boolean local function onread(handle, is_stderr) - return function(err, data) + return function(_, data) if data then if is_stderr then complete_error_output[handle] = (complete_error_output[handle] or "") .. data @@ -147,6 +159,7 @@ function M.iter_cmd(cmd_list, i, lang, success_message) local stdout = luv.new_pipe(false) local stderr = luv.new_pipe(false) attr.opts.stdio = { nil, stdout, stderr } + ---@type userdata handle = luv.spawn( attr.cmd, attr.opts, @@ -225,6 +238,12 @@ local function iter_cmd_sync(cmd_list) return true end +---@param cache_folder string +---@param install_folder string +---@param lang string +---@param repo InstallInfo +---@param with_sync boolean +---@param generate_from_grammar boolean local function run_install(cache_folder, install_folder, lang, repo, with_sync, generate_from_grammar) parsers.reset_cache() @@ -361,6 +380,12 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync, end end +---@param lang string +---@param ask_reinstall boolean +---@param cache_folder string +---@param install_folder string +---@param with_sync boolean +---@param generate_from_grammar boolean local function install_lang(lang, ask_reinstall, cache_folder, install_folder, with_sync, generate_from_grammar) if is_installed(lang) and ask_reinstall ~= "force" then if not ask_reinstall then @@ -389,6 +414,7 @@ local function install_lang(lang, ask_reinstall, cache_folder, install_folder, w run_install(cache_folder, install_folder, lang, install_info, with_sync, generate_from_grammar) end +---@return function local function install(options) options = options or {} local with_sync = options.with_sync @@ -405,11 +431,14 @@ local function install(options) if err then return api.nvim_err_writeln(err) end + assert(cache_folder) - local install_folder, err = configs.get_parser_install_dir() + local install_folder + install_folder, err = configs.get_parser_install_dir() if err then return api.nvim_err_writeln(err) end + assert(install_folder) local languages local ask diff --git a/lua/nvim-treesitter/parsers.lua b/lua/nvim-treesitter/parsers.lua index ee79c09d..e2e52122 100644 --- a/lua/nvim-treesitter/parsers.lua +++ b/lua/nvim-treesitter/parsers.lua @@ -18,8 +18,25 @@ local filetype_to_parsername = { pandoc = "markdown", rmd = "markdown", cs = "c_sharp", + tape = "vhs", } +---@class InstallInfo +---@field url string +---@field branch string|nil +---@field revision string|nil +---@field files string[] +---@field generate_requires_npm boolean|nil +---@field requires_generate_from_grammar boolean|nil +---@field location string|nil + +---@class ParserInfo +---@field install_info InstallInfo +---@field filetype string +---@field maintainers string[] +---@field experimental boolean|nil + +---@type ParserInfo[] local list = setmetatable({}, { __newindex = function(table, parsername, parserconfig) rawset( @@ -1266,6 +1283,23 @@ list.diff = { filetype = "gitdiff", } +list.vhs = { + install_info = { + url = "https://github.com/charmbracelet/tree-sitter-vhs", + branch = "main", + files = { "src/parser.c" }, + }, + maintainers = { "@caarlos0", "@maaslalani" }, + filetype = "tape", +} + +list.awk = { + install_info = { + url = "https://github.com/Beaglefoot/tree-sitter-awk", + files = { "src/parser.c", "src/scanner.c" }, + }, +} + local M = { list = list, filetype_to_parsername = filetype_to_parsername, diff --git a/lua/nvim-treesitter/query.lua b/lua/nvim-treesitter/query.lua index aeaa683b..bc80d51e 100644 --- a/lua/nvim-treesitter/query.lua +++ b/lua/nvim-treesitter/query.lua @@ -11,8 +11,10 @@ local EMPTY_ITER = function() end M.built_in_query_groups = { "highlights", "locals", "folds", "indents", "injections" } --- Creates a function that checks whether a given query exists --- for a specific language. +--- Creates a function that checks whether a given query exists +--- for a specific language. +---@param query string +---@return function(string): boolean local function get_query_guard(query) return function(lang) return M.has_query_files(lang, query) @@ -23,6 +25,7 @@ for _, query in ipairs(M.built_in_query_groups) do M["has_" .. query] = get_query_guard(query) end +---@return string[] function M.available_query_groups() local query_files = api.nvim_get_runtime_file("queries/*/*.scm", true) local groups = {} @@ -57,11 +60,19 @@ do end end +---@param lang string +---@param query_name string +---@return string[] local function runtime_queries(lang, query_name) return api.nvim_get_runtime_file(string.format("queries/%s/%s.scm", lang, query_name), true) or {} end +---@type table<string, table<string, boolean>> local query_files_cache = {} + +---@param lang string +---@param query_name string +---@return boolean function M.has_query_files(lang, query_name) if not query_files_cache[lang] then query_files_cache[lang] = {} @@ -86,6 +97,8 @@ do local cache = setmetatable({}, mt) --- Same as `vim.treesitter.query` except will return cached values + ---@param lang string + ---@param query_name string function M.get_query(lang, query_name) if cache[lang][query_name] == nil then cache[lang][query_name] = tsq.get_query(lang, query_name) @@ -98,6 +111,8 @@ do --- If lang and query_name is both present, will reload for only the lang and query_name. --- If only lang is present, will reload all query_names for that lang --- If none are present, will reload everything + ---@param lang string + ---@param query_name string function M.invalidate_query_cache(lang, query_name) if lang and query_name then cache[lang][query_name] = nil @@ -106,14 +121,14 @@ do end elseif lang and not query_name then query_files_cache[lang] = nil - for query_name, _ in pairs(cache[lang]) do - M.invalidate_query_cache(lang, query_name) + for query_name0, _ in pairs(cache[lang]) do + M.invalidate_query_cache(lang, query_name0) end elseif not lang and not query_name then query_files_cache = {} - for lang, _ in pairs(cache) do - for query_name, _ in pairs(cache[lang]) do - M.invalidate_query_cache(lang, query_name) + for lang0, _ in pairs(cache) do + for query_name0, _ in pairs(cache[lang0]) do + M.invalidate_query_cache(lang0, query_name0) end end else @@ -123,11 +138,23 @@ do end --- This function is meant for an autocommand and not to be used. Only use if file is a query file. +---@param fname string function M.invalidate_query_file(fname) local fnamemodify = vim.fn.fnamemodify M.invalidate_query_cache(fnamemodify(fname, ":p:h:t"), fnamemodify(fname, ":t:r")) end +---@class QueryInfo +---@field root LanguageTree +---@field source integer +---@field start integer +---@field stop integer + +---@param bufnr integer +---@param query_name string +---@param root LanguageTree +---@param root_lang string|nil +---@return Query|nil, QueryInfo|nil local function prepare_query(bufnr, query_name, root, root_lang) local buf_lang = parsers.get_buf_lang(bufnr) @@ -181,6 +208,10 @@ local function prepare_query(bufnr, query_name, root, root_lang) } end +---@param query Query +---@param bufnr integer +---@param start_row integer +---@param end_row integer function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row) -- A function that splits a string on '.' local function split(string) @@ -249,15 +280,16 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row) end --- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type) --- Works like M.get_references or M.get_scopes except you can choose the capture --- Can also be a nested capture like @definition.function to get all nodes defining a function. --- --- @param bufnr the buffer --- @param captures a single string or a list of strings --- @param query_group the name of query group (highlights or injections for example) --- @param root (optional) node from where to start the search --- @param lang (optional) the language from where to get the captures. --- Root nodes can have several languages. +---Works like M.get_references or M.get_scopes except you can choose the capture +---Can also be a nested capture like @definition.function to get all nodes defining a function. +--- +---@param bufnr integer the buffer +---@param captures string|string[] +---@param query_group string the name of query group (highlights or injections for example) +---@param root LanguageTree|nil node from where to start the search +---@param lang string|nil the language from where to get the captures. +--- Root nodes can have several languages. +---@return table|nil function M.get_capture_matches(bufnr, captures, query_group, root, lang) if type(captures) == "string" then captures = { captures } @@ -289,6 +321,7 @@ function M.iter_captures(bufnr, query_name, root, lang) if not query then return EMPTY_ITER end + assert(params) local iter = query:iter_captures(params.root, params.source, params.start, params.stop) @@ -336,16 +369,17 @@ function M.find_best_match(bufnr, capture_string, query_group, filter_predicate, return best end --- Iterates matches from a query file. --- @param bufnr the buffer --- @param query_group the query file to use --- @param root the root node --- @param root the root node lang, if known +---Iterates matches from a query file. +---@param bufnr integer the buffer +---@param query_group string the query file to use +---@param root LanguageTree the root node +---@param root_lang string|nil the root node lang, if known function M.iter_group_results(bufnr, query_group, root, root_lang) local query, params = prepare_query(bufnr, query_group, root, root_lang) if not query then return EMPTY_ITER end + assert(params) return M.iter_prepared_matches(query, params.root, params.source, params.start, params.stop) end @@ -360,18 +394,25 @@ function M.collect_group_results(bufnr, query_group, root, lang) return matches end +---@alias CaptureResFn function(string, LanguageTree, LanguageTree): string, string + --- Same as get_capture_matches except this will recursively get matches for every language in the tree. --- @param bufnr The bufnr --- @param capture_or_fn The capture to get. If a function is provided then that --- function will be used to resolve both the capture and query argument. --- The function can return `nil` to ignore that tree. --- @param query_type The query to get the capture from. This is ignore if a function is provided --- for the captuer argument. +---@param bufnr integer The bufnr +---@param capture_or_fn string|CaptureResFn The capture to get. If a function is provided then that +--- function will be used to resolve both the capture and query argument. +--- The function can return `nil` to ignore that tree. +---@param query_type string The query to get the capture from. This is ignore if a function is provided +--- for the captuer argument. function M.get_capture_matches_recursively(bufnr, capture_or_fn, query_type) - local type_fn = type(capture_or_fn) == "function" and capture_or_fn - or function() + ---@type CaptureResFn + local type_fn + if type(capture_or_fn) == "function" then + type_fn = capture_or_fn + else + type_fn = function(_, _, _) return capture_or_fn, query_type end + end local parser = parsers.get_parser(bufnr) local matches = {} diff --git a/lua/nvim-treesitter/shell_command_selectors.lua b/lua/nvim-treesitter/shell_command_selectors.lua index 522ac727..59bbb0e4 100644 --- a/lua/nvim-treesitter/shell_command_selectors.lua +++ b/lua/nvim-treesitter/shell_command_selectors.lua @@ -49,6 +49,7 @@ function M.select_rm_file_cmd(file, info_msg) end end +---@return string|nil function M.select_executable(executables) return vim.tbl_filter(function(c) return c ~= vim.NIL and fn.executable(c) == 1 diff --git a/lua/nvim-treesitter/utils.lua b/lua/nvim-treesitter/utils.lua index 81ce7017..156ba9c3 100644 --- a/lua/nvim-treesitter/utils.lua +++ b/lua/nvim-treesitter/utils.lua @@ -11,6 +11,7 @@ function M.notify(msg, log_level, opts) end -- Returns the system specific path seperator. +---@return string function M.get_path_sep() return fn.has "win32" == 1 and "\\" or "/" end @@ -82,6 +83,10 @@ function M.setup_commands(mod, commands) end end +---@param dir string +---@param create_err string +---@param writeable_err string +---@return string|nil, string|nil function M.create_or_reuse_writable_dir(dir, create_err, writeable_err) create_err = create_err or M.join_space("Could not create dir '", dir, "': ") writeable_err = writeable_err or M.join_space("Invalid rights, '", dir, "' should be read/write") @@ -201,6 +206,7 @@ function M.to_func(a) return type(a) == "function" and a or M.constant(a) end +---@return string|nil function M.ts_cli_version() if fn.executable "tree-sitter" == 1 then local handle = io.popen "tree-sitter -V" diff --git a/queries/awk/highlights.scm b/queries/awk/highlights.scm new file mode 100644 index 00000000..918d0116 --- /dev/null +++ b/queries/awk/highlights.scm @@ -0,0 +1,154 @@ +; adapted from https://github.com/Beaglefoot/tree-sitter-awk + +[ + (identifier) + (field_ref) +] @variable +(field_ref (_) @variable) + +(number) @number + +(string) @string +(regex) @string.regex +(escape_sequence) @string.escape + +(comment) @comment @spell + +(ns_qualified_name (namespace) @namespace) +(ns_qualified_name "::" @punctuation.delimiter) + +(func_def name: (_ (identifier) @function) @function) +(func_call name: (_ (identifier) @function) @function) + +(func_def (param_list (identifier) @parameter)) + +[ + "print" + "printf" + "getline" +] @function.builtin + +[ + (delete_statement) + (break_statement) + (continue_statement) + (next_statement) + (nextfile_statement) +] @keyword + +[ + "func" + "function" +] @keyword.function + +[ + "return" + "exit" +] @keyword.return + +[ + "do" + "while" + "for" + "in" +] @repeat + +[ + "if" + "else" + "switch" + "case" + "default" +] @conditional + +[ + "@include" + "@load" +] @include + +"@namespace" @preproc + +[ + "BEGIN" + "END" + "BEGINFILE" + "ENDFILE" +] @label + +(binary_exp [ + "^" + "**" + "*" + "/" + "%" + "+" + "-" + "<" + ">" + "<=" + ">=" + "==" + "!=" + "~" + "!~" + "in" + "&&" + "||" +] @operator) + +(unary_exp [ + "!" + "+" + "-" +] @operator) + +(assignment_exp [ + "=" + "+=" + "-=" + "*=" + "/=" + "%=" + "^=" +] @operator) + +(ternary_exp [ + "?" + ":" +] @operator) + +(update_exp [ + "++" + "--" +] @operator) + +(redirected_io_statement [ + ">" + ">>" +] @operator) + +(piped_io_statement [ + "|" + "|&" +] @operator) + +(piped_io_exp [ + "|" + "|&" +] @operator) + +(field_ref "$" @punctuation.delimiter) + +(regex "/" @punctuation.delimiter) +(regex_constant "@" @punctuation.delimiter) + +[ ";" "," ] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket diff --git a/queries/awk/injections.scm b/queries/awk/injections.scm new file mode 100644 index 00000000..8cbffc62 --- /dev/null +++ b/queries/awk/injections.scm @@ -0,0 +1,2 @@ +(comment) @comment +(regex) @regex diff --git a/queries/help/highlights.scm b/queries/help/highlights.scm index 6be4e49c..b2ed3903 100644 --- a/queries/help/highlights.scm +++ b/queries/help/highlights.scm @@ -2,6 +2,8 @@ (h2) @text.title (h3) @text.title (column_heading) @text.title +(column_heading + "~" @conceal (#set! conceal "")) (tag "*" @conceal (#set! conceal "") text: (_) @label) @@ -9,8 +11,15 @@ "|" @conceal (#set! conceal "") text: (_) @text.reference) (optionlink - text: (_) @text.literal) + text: (_) @text.reference) (codespan "`" @conceal (#set! conceal "") - text: (_) @string) + text: (_) @text.literal) +(codeblock) @text.literal +(codeblock + ">" @conceal (#set! conceal "")) +(block + "<" @conceal (#set! conceal "")) (argument) @parameter +(keycode) @string.special +(url) @text.uri diff --git a/queries/julia/folds.scm b/queries/julia/folds.scm index a8cfc940..61718215 100644 --- a/queries/julia/folds.scm +++ b/queries/julia/folds.scm @@ -12,6 +12,6 @@ (quote_statement) (do_clause) - (compound_expression) + (compound_statement) ] @fold diff --git a/queries/julia/highlights.scm b/queries/julia/highlights.scm index 1b7e5b72..8d30ff55 100644 --- a/queries/julia/highlights.scm +++ b/queries/julia/highlights.scm @@ -1,106 +1,110 @@ -(identifier) @variable +;;; Identifiers -(operator) @operator -(range_expression ":" @operator) -(pair_expression "=>" @operator) +(identifier) @variable -;; In case you want type highlighting based on Julia naming conventions (this might collide with mathematical notation) -;((identifier) @type ; exception: mark `A_foo` sort of identifiers as variables - ;(match? @type "^[A-Z][^_]")) +; ;; If you want type highlighting based on Julia naming conventions (this might collide with mathematical notation) +; ((identifier) @type +; (match? @type "^[A-Z][^_]")) ; exception: Highlight `A_foo` sort of identifiers as variables (macro_identifier) @function.macro -(macro_identifier (identifier) @function.macro) ; for any one using the variable highlight +(macro_identifier + (identifier) @function.macro) ; for any one using the variable highlight + (macro_definition - name: (identifier) @function.macro - ["macro" "end" @keyword]) + name: (identifier) @function.macro) + +(quote_expression ":" (identifier)) @symbol + + +;;; Fields and indexes (field_expression - (identifier) (identifier) @field .) +(index_expression + (_) + (range_expression + (identifier) @constant.builtin .) + (#eq? @constant.builtin "end")) + + +;;; Function names + +;; definitions + (function_definition name: (identifier) @function) +(short_function_definition + name: (identifier) @function) + +(function_definition + name: (scoped_identifier (identifier) @function .)) +(short_function_definition + name: (scoped_identifier (identifier) @function .)) + +;; calls + (call_expression (identifier) @function.call) (call_expression - (field_expression (identifier) @method.call .)) + (field_expression (identifier) @function.call .)) + (broadcast_call_expression (identifier) @function.call) (broadcast_call_expression - (field_expression (identifier) @method.call .)) + (field_expression (identifier) @function.call .)) + + +;;; Parameters + (parameter_list (identifier) @parameter) -(parameter_list - (optional_parameter . - (identifier) @parameter)) +(optional_parameter . + (identifier) @parameter) +(slurp_parameter + (identifier) @parameter) + (typed_parameter - (identifier) @parameter - (identifier) @type) -(type_parameter_list - (identifier) @type) + parameter: (identifier) @parameter + type: (_) @type) (typed_parameter - (identifier) @parameter - (parameterized_identifier) @type) + type: (_) @type) + (function_expression - . (identifier) @parameter) -(spread_parameter) @parameter -(spread_parameter - (identifier) @parameter) -(named_argument - . (identifier) @parameter) -(argument_list - (typed_expression - (identifier) @parameter - (identifier) @type)) -(argument_list - (typed_expression - (identifier) @parameter - (parameterized_identifier) @type)) - -;; Symbol expressions (:my-wanna-be-lisp-keyword) -(quote_expression - (identifier)) @symbol - -;; Parsing error! foo (::Type) gets parsed as two quote expressions -(argument_list - (quote_expression - (quote_expression - (identifier) @type))) - -(type_argument_list - (identifier) @type) -(parameterized_identifier (_)) @type -(argument_list - (typed_expression . (identifier) @parameter)) + . (identifier) @parameter) ; Single parameter arrow functions -(typed_expression - (identifier) @type .) -(typed_expression - (parameterized_identifier) @type .) + +;;; Types + +;; Definitions (abstract_definition name: (identifier) @type) +(primitive_definition + name: (identifier) @type) (struct_definition name: (identifier) @type) -(subscript_expression - (_) - (range_expression - (identifier) @constant.builtin .) - (#eq? @constant.builtin "end")) +;; Annotations -"end" @keyword +(parametrized_type_expression (_) @type) -(if_statement - ["if" "end"] @conditional) -(elseif_clause - ["elseif"] @conditional) -(else_clause - ["else"] @conditional) -(ternary_expression - ["?" ":"] @conditional) +(type_parameter_list + (identifier) @type) + +(typed_expression + (identifier) @type .) + +(function_definition + return_type: (identifier) @type) +(short_function_definition + return_type: (identifier) @type) + +(where_clause + (identifier) @type) ; where clause without braces -(function_definition ["function" "end"] @keyword.function) + +;;; Keywords [ "abstract" @@ -110,51 +114,91 @@ "struct" "type" "mutable" + "where" ] @keyword -"return" @keyword.return +"end" @keyword -((identifier) @keyword (#any-of? @keyword "global" "local")) +((identifier) @keyword (#any-of? @keyword "global" "local")) ; Grammar error -(compound_expression +(compound_statement ["begin" "end"] @keyword) +(quote_statement + ["quote" "end"] @keyword) +(let_statement + ["let" "end"] @keyword) + +(if_statement + ["if" "end"] @conditional) +(elseif_clause + ["elseif"] @conditional) +(else_clause + ["else"] @conditional) +(ternary_expression + ["?" ":"] @conditional) + (try_statement - ["try" "end" ] @exception) + ["try" "end"] @exception) (finally_clause "finally" @exception) (catch_clause "catch" @exception) -(quote_statement - ["quote" "end"] @keyword) -(let_statement - ["let" "end"] @keyword) + (for_statement ["for" "end"] @repeat) (while_statement ["while" "end"] @repeat) -(break_statement) @repeat -(continue_statement) @repeat (for_clause "for" @repeat) +[ + (break_statement) + (continue_statement) +] @repeat + +(module_definition + ["module" "baremodule" "end"] @include) +(import_statement + ["import" "using"] @include) +(export_statement + "export" @include) + +(macro_definition + ["macro" "end" @keyword]) + +(function_definition + ["function" "end"] @keyword.function) (do_clause - ["do" "end"] @keyword) + ["do" "end"] @keyword.function) +(function_expression + "->" @keyword.function) +(return_statement + "return" @keyword.return) -"in" @keyword.operator -(export_statement - ["export"] @include) +;;; Operators & Punctuation -(import_statement - ["import" "using"] @include) +(operator) @operator +(for_binding ["in" "=" "∈"] @operator) +(pair_expression "=>" @operator) +(range_expression ":" @operator) -(module_definition - ["module" "end"] @include) +(slurp_parameter "..." @operator) +(spread_expression "..." @operator) + +"." @operator +["::" "<:"] @operator -((identifier) @include (#eq? @include "baremodule")) +["," ";"] @punctuation.delimiter +["(" ")" "[" "]" "{" "}"] @punctuation.bracket ;;; Literals +[ + (true) + (false) +] @boolean + (integer_literal) @number (float_literal) @float @@ -162,9 +206,6 @@ (#any-of? @float "NaN" "NaN16" "NaN32" "Inf" "Inf16" "Inf32")) -((identifier) @boolean - (#any-of? @boolean "true" "false")) - ((identifier) @constant.builtin (#any-of? @constant.builtin "nothing" "missing")) @@ -184,8 +225,3 @@ (block_comment) ] @comment -;;; Punctuation - -(quote_expression ":" @symbol) -["::" "." "," "..."] @punctuation.delimiter -["[" "]" "(" ")" "{" "}"] @punctuation.bracket diff --git a/queries/julia/indents.scm b/queries/julia/indents.scm index e6423d34..9cfdc407 100644 --- a/queries/julia/indents.scm +++ b/queries/julia/indents.scm @@ -11,7 +11,7 @@ (quote_statement) (do_clause) - (compound_expression) + (compound_statement) (assignment_expression) (binary_expression) diff --git a/queries/julia/locals.scm b/queries/julia/locals.scm index f8b34f71..655affe0 100644 --- a/queries/julia/locals.scm +++ b/queries/julia/locals.scm @@ -1,59 +1,79 @@ +;;; Variables +(assignment_expression + (identifier) @definition.var) +(assignment_expression + (tuple_expression + (identifier) @definition.var)) -(import_statement - (identifier) @definition.import) +;;; let/const bindings (variable_declaration (identifier) @definition.var) (variable_declaration (tuple_expression (identifier) @definition.var)) + + +;;; For bindings (for_binding - (identifier) @definition.var) + (identifier) @definition.var) (for_binding - (tuple_expression - (identifier) @definition.var)) + (tuple_expression + (identifier) @definition.var)) -(assignment_expression - (tuple_expression - (identifier) @definition.var)) -(assignment_expression - (bare_tuple_expression - (identifier) @definition.var)) -(assignment_expression - (identifier) @definition.var) -(type_parameter_list - (identifier) @definition.type) -(type_argument_list - (identifier) @definition.type) +;;; Types + (struct_definition name: (identifier) @definition.type) +(abstract_definition + name: (identifier) @definition.type) +(abstract_definition + name: (identifier) @definition.type) + +(type_parameter_list + (identifier) @definition.type) + +;;; Module imports + +(import_statement + (identifier) @definition.import) + + +;;; Parameters (parameter_list - (identifier) @definition.parameter) + (identifier) @definition.parameter) +(optional_parameter . + (identifier) @definition.parameter) +(slurp_parameter + (identifier) @definition.parameter) + (typed_parameter - (identifier) @definition.parameter - (identifier)) + parameter: (identifier) @definition.parameter + (_)) + (function_expression - . (identifier) @definition.parameter) -(argument_list - (typed_expression - (identifier) @definition.parameter - (identifier))) -(spread_parameter - (identifier) @definition.parameter) + . (identifier) @definition.parameter) ;; Single parameter arrow function + + +;;; Function/macro definitions (function_definition - name: (identifier) @definition.function) @scope + name: (identifier) @definition.function) @scope +(short_function_definition + name: (identifier) @definition.function) @scope (macro_definition - name: (identifier) @definition.macro) @scope + name: (identifier) @definition.macro) @scope (identifier) @reference [ + (for_statement) + (while_statement) (try_statement) + (catch_clause) (finally_clause) - (quote_statement) (let_statement) - (compound_expression) - (for_statement) + (quote_statement) + (do_clause) ] @scope diff --git a/queries/lua/highlights.scm b/queries/lua/highlights.scm index 50069258..48aed052 100644 --- a/queries/lua/highlights.scm +++ b/queries/lua/highlights.scm @@ -131,6 +131,11 @@ ((identifier) @variable.builtin (#eq? @variable.builtin "self")) +(variable_list + attribute: (attribute + (["<" ">"] @punctuation.bracket + (identifier) @attribute))) + ;; Constants ((identifier) @constant diff --git a/queries/markdown/highlights.scm b/queries/markdown/highlights.scm index 70c35b39..81cb5a5b 100644 --- a/queries/markdown/highlights.scm +++ b/queries/markdown/highlights.scm @@ -20,11 +20,10 @@ ] @text.literal (pipe_table_header (pipe_table_cell) @text.title) -[ - (pipe_table_row) - (pipe_table_delimiter_row) - (pipe_table_header) -] "|" @punctuation.special + +(pipe_table_header "|" @punctuation.special) +(pipe_table_row "|" @punctuation.special) +(pipe_table_delimiter_row "|" @punctuation.special) (pipe_table_delimiter_cell) @punctuation.special [ diff --git a/queries/ql/folds.scm b/queries/ql/folds.scm new file mode 100644 index 00000000..1a31eeb2 --- /dev/null +++ b/queries/ql/folds.scm @@ -0,0 +1,7 @@ +[ + (module) + (classlessPredicate) + (dataclass) + (charpred) + (memberPredicate) +] @fold diff --git a/queries/rego/highlights.scm b/queries/rego/highlights.scm index 70bf849a..42d276cd 100644 --- a/queries/rego/highlights.scm +++ b/queries/rego/highlights.scm @@ -1,16 +1,64 @@ ; highlights.scm -"import" @include -"package" @include +[ + (import) + (package) +] @include +[ + (with) + (as) + (every) + (some) + (in) + (not) + (if) + (contains) + (else) + (default) + "null" +] @keyword + +[ + "true" + "false" +] @boolean + +[ + (assignment_operator) + (bool_operator) + (arith_operator) + (bin_operator) +] @operator + +[ + (string) + (raw_string) +] @string + +(term (ref (var))) @variable -(reserved_keywords) @keyword (comment) @comment -(rego_block rego_rule_name: (identifier) @function) -(builtin_function function_name: (function_name) @function.builtin) -(opening_parameter) @punctuation.bracket -(closing_parameter) @punctuation.bracket -(string_definition) @string + (number) @number -(operator) @operator -(true) @boolean -(false) @boolean + +(expr_call func_name: (fn_name (var) @function .)) + +(expr_call func_arguments: (fn_args (expr) @parameter)) + +(rule_args (term) @parameter) + +[ + (open_paren) + (close_paren) + (open_bracket) + (close_bracket) + (open_curly) + (close_curly) +] @punctuation.bracket + +(rule (rule_head (var) @method)) + +(rule + (rule_head (term (ref (var) @namespace))) + (rule_body (query (literal (expr (expr_infix (expr (term (ref (var)) @_output)))))) (#eq? @_output @namespace)) +) diff --git a/queries/rust/folds.scm b/queries/rust/folds.scm index d83351cb..97cf2eaf 100644 --- a/queries/rust/folds.scm +++ b/queries/rust/folds.scm @@ -14,7 +14,6 @@ (for_expression) (while_expression) (if_expression) - (if_let_expression) (match_expression) (call_expression) diff --git a/queries/rust/highlights.scm b/queries/rust/highlights.scm index c08912be..c7cd1174 100644 --- a/queries/rust/highlights.scm +++ b/queries/rust/highlights.scm @@ -25,7 +25,6 @@ (self) @variable.builtin -(lifetime ["'" (identifier)] @label) (loop_label ["'" (identifier)] @label) @@ -72,6 +71,9 @@ (scoped_type_identifier path: (identifier) @namespace) (scoped_type_identifier + path: (identifier) @type + (#lua-match? @type "^[A-Z]")) +(scoped_type_identifier (scoped_identifier name: (identifier) @namespace)) ((scoped_identifier @@ -121,14 +123,14 @@ (macro_definition "macro_rules!" @function.macro) ;; Attribute macros -(attribute_item (meta_item (identifier) @function.macro)) -(meta_item (scoped_identifier (identifier) @function.macro .)) +(attribute_item (attribute (identifier) @function.macro)) +(attribute (scoped_identifier (identifier) @function.macro .)) ;; Derive macros (assume all arguments are types) -(meta_item - (identifier) @_name - arguments: (meta_arguments (meta_item (identifier) @type)) - (#eq? @_name "derive")) +; (attribute +; (identifier) @_name +; arguments: (attribute (attribute (identifier) @type)) +; (#eq? @_name "derive")) ;; Function-like macros (macro_invocation @@ -169,7 +171,6 @@ [ "async" "await" - "const" "default" "dyn" "enum" @@ -179,17 +180,26 @@ "match" "move" "pub" - "ref" - "static" "struct" "trait" "type" "union" "unsafe" "where" - (mutable_specifier) ] @keyword +[ + "ref" + (mutable_specifier) +] @type.qualifier + +[ + "const" + "static" +] @storageclass + +(lifetime ["'" (identifier)] @storageclass.lifetime) + "fn" @keyword.function [ "return" @@ -201,7 +211,8 @@ (use_list (self) @keyword) (scoped_use_list (self) @keyword) -(scoped_identifier (self) @keyword) +(scoped_identifier [(crate) (super) (self)] @keyword) +(visibility_modifier [(crate) (super) (self)] @keyword) [ "else" @@ -216,8 +227,7 @@ "while" ] @repeat -(impl_item - "for" @keyword) +"for" @keyword (for_expression "for" @repeat) @@ -266,6 +276,8 @@ (closure_parameters "|" @punctuation.bracket) (type_arguments ["<" ">"] @punctuation.bracket) (type_parameters ["<" ">"] @punctuation.bracket) +(bracketed_type ["<" ">"] @punctuation.bracket) +(for_lifetimes ["<" ">"] @punctuation.bracket) ["," "." ":" "::" ";"] @punctuation.delimiter @@ -273,3 +285,8 @@ (inner_attribute_item ["!" "#"] @punctuation.special) (macro_invocation "!" @function.macro) (empty_type "!" @type.builtin) + +(macro_invocation macro: (identifier) @_ident @exception "!" @exception + (#eq? @_ident "panic")) +(macro_invocation macro: (identifier) @_ident @exception "!" @exception + (#contains? @_ident "assert")) diff --git a/queries/rust/locals.scm b/queries/rust/locals.scm index 010bf4af..1cefcabf 100644 --- a/queries/rust/locals.scm +++ b/queries/rust/locals.scm @@ -34,7 +34,7 @@ (tuple_pattern (identifier) @definition.var) -(if_let_expression +(let_condition pattern: (_ (identifier) @definition.var)) @@ -93,7 +93,6 @@ (for_expression) (loop_expression) (if_expression) - (if_let_expression) (match_expression) (match_arm) diff --git a/queries/scheme/highlights.scm b/queries/scheme/highlights.scm index 4a7393eb..497512b8 100644 --- a/queries/scheme/highlights.scm +++ b/queries/scheme/highlights.scm @@ -81,7 +81,7 @@ ;; quote -(abbreviation +(quote "'" (symbol)) @symbol diff --git a/queries/vhs/highlights.scm b/queries/vhs/highlights.scm new file mode 100644 index 00000000..67fa3cf8 --- /dev/null +++ b/queries/vhs/highlights.scm @@ -0,0 +1,38 @@ +[ + "Output" + "Backspace" + "Down" + "Enter" + "Escape" + "Left" + "Right" + "Space" + "Tab" + "Up" + "Set" + "Type" + "Sleep" + "Hide" + "Show" ] @keyword + +[ "Shell" + "FontFamily" + "FontSize" + "Framerate" + "PlaybackSpeed" + "Height" + "LetterSpacing" + "TypingSpeed" + "LineHeight" + "Padding" + "Theme" + "LoopOffset" + "Width" ] @type + +[ "@" ] @operator +(control) @function.macro +(float) @float +(integer) @number +(comment) @comment @spell +[(path) (string) (json)] @string +(time) @symbol diff --git a/scripts/ci-install-macos-latest.sh b/scripts/ci-install-macos-latest.sh index 79b957cb..9899f17e 100644 --- a/scripts/ci-install-macos-latest.sh +++ b/scripts/ci-install-macos-latest.sh @@ -1,5 +1,6 @@ curl -L https://github.com/neovim/neovim/releases/download/${NVIM_TAG}/nvim-macos.tar.gz | tar -xz sudo ln -s $(pwd)/nvim-macos/bin/nvim /usr/local/bin +rm -rf $(pwd)/nvim-macos/lib/nvim/parser mkdir -p ~/.local/share/nvim/site/pack/nvim-treesitter/start ln -s $(pwd) ~/.local/share/nvim/site/pack/nvim-treesitter/start diff --git a/scripts/ci-install-ubuntu-latest.sh b/scripts/ci-install-ubuntu-latest.sh index ecfc164f..e65c670d 100644 --- a/scripts/ci-install-ubuntu-latest.sh +++ b/scripts/ci-install-ubuntu-latest.sh @@ -1,10 +1,9 @@ wget -O - https://github.com/tree-sitter/tree-sitter/releases/download/${TREE_SITTER_CLI_TAG}/tree-sitter-linux-x64.gz | gunzip -c > tree-sitter sudo cp ./tree-sitter /usr/bin/tree-sitter sudo chmod uog+rwx /usr/bin/tree-sitter -wget https://github.com/neovim/neovim/releases/download/${NVIM_TAG}/nvim.appimage -chmod u+x nvim.appimage +wget https://github.com/neovim/neovim/releases/download/${NVIM_TAG}/nvim-linux64.tar.gz +tar -zxf nvim-linux64.tar.gz +sudo ln -s $(pwd)/nvim-linux64/bin/nvim /usr/local/bin +rm -rf $(pwd)/nvim-linux64/lib/nvim/parser mkdir -p ~/.local/share/nvim/site/pack/nvim-treesitter/start ln -s $(pwd) ~/.local/share/nvim/site/pack/nvim-treesitter/start -sudo cp ./nvim.appimage /usr/bin/nvim -sudo chmod uog+rwx /usr/bin/nvim - |
