From 6320c91c50e4c0ee5c366241f9a413c4edbfdad8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:58:27 +0800 Subject: vim-patch:9.0.1231: completion of :runtime does not handle {where} argument Problem: Completion of :runtime does not handle {where} argument. Solution: Parse the {where} argument. (closes vim/vim#11863) https://github.com/vim/vim/commit/3770f4c9cde7b5fcd10b6fa2e665cd0b69450fb2 --- runtime/doc/builtin.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 4d2c85b134..c20f52967b 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2991,6 +2991,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* messages |:messages| suboptions option options packadd optional package |pack-add| names + runtime runtime file names |:runtime| scriptnames sourced script names |:scriptnames| shellcmd Shell command sign |:sign| suboptions -- cgit From f03f6263bb3eb0b28b759292cb6ef4465a05cafe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 10:38:53 +0800 Subject: vim-patch:9.0.1238: :runtime completion can be further improved Problem: :runtime completion can be further improved. Solution: Also complete the {where} argument values and adjust the completion for that. (closes vim/vim#11874) https://github.com/vim/vim/commit/5c8771bc5a2be123ab8e6325fa60ed524e8efb09 --- runtime/doc/builtin.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c20f52967b..c8f5570bae 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2991,7 +2991,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()* messages |:messages| suboptions option options packadd optional package |pack-add| names - runtime runtime file names |:runtime| + runtime |:runtime| completion scriptnames sourced script names |:scriptnames| shellcmd Shell command sign |:sign| suboptions -- cgit From e02df23b4e24046d99c7bfa6a63b4db16c28a7be Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 19:35:06 +0800 Subject: docs: clarify :runtime behavior without [where] again (#22003) The behavior changed again after #15867, change the docs to describe latest behavior. --- runtime/doc/repeat.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 1bbd20702b..bf77aacdc0 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -211,9 +211,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. When [!] is included, all found files are sourced. Else only the first found file is sourced. - When [where] is omitted, first 'runtimepath' is - searched, then directories under "start" in 'packpath' - are searched. + When [where] is omitted only 'runtimepath' is used. Other values: START search only under "start" in 'packpath' OPT search only under "opt" in 'packpath' -- cgit From aec4b476c5689f032103ab3e0ca068fc2af8bbba Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 27 Jan 2023 11:24:20 +0000 Subject: docs(api): tweak data arg for nvim_create_autocmd (#22008) Fixes #21964 --- runtime/doc/api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 0e1cc3c28c..95a929b808 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3281,7 +3281,7 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()* • match: (string) expanded value of || • buf: (number) expanded value of || • file: (string) expanded value of || - • data: (any) arbitrary data passed to + • data: (any) arbitrary data passed from |nvim_exec_autocmds()| • command (string) optional: Vim command to execute on event. -- cgit From c032e83b22994332dd8769ef34cb817906a63cac Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 26 Jan 2023 09:42:23 +0100 Subject: fix(treesitter): validate language name Problem: Some injections (like markdown) allow specifying arbitrary language names for code blocks, which may be lead to errors when looking for a corresponding parser in runtime path. Solution: Validate that the language name only contains alphanumeric characters and `_` (e.g., for `c_sharp`) and error otherwise. --- runtime/doc/treesitter.txt | 1 + runtime/lua/vim/treesitter/language.lua | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 917863eef8..9bfdc0b94e 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -684,6 +684,7 @@ require_language({lang}, {path}, {silent}, {symbol_name}) Parameters: ~ • {lang} (string) Language the parser should parse + (alphanumerical and `_` only) • {path} (string|nil) Optional path the parser is located at • {silent} (boolean|nil) Don't throw an error if language not found diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index c92d63b8c4..8634e53b7b 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -6,7 +6,7 @@ local M = {} --- --- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ----@param lang string Language the parser should parse +---@param lang string Language the parser should parse (alphanumerical and `_` only) ---@param path (string|nil) Optional path the parser is located at ---@param silent (boolean|nil) Don't throw an error if language not found ---@param symbol_name (string|nil) Internal symbol name for the language to load @@ -16,13 +16,19 @@ function M.require_language(lang, path, silent, symbol_name) return true end if path == nil then - local fname = 'parser/' .. vim.fn.fnameescape(lang) .. '.*' + if not (lang and lang:match('[%w_]+') == lang) then + if silent then + return false + end + error("'" .. lang .. "' is not a valid language name") + end + + local fname = 'parser/' .. lang .. '.*' local paths = a.nvim_get_runtime_file(fname, false) if #paths == 0 then if silent then return false end - error("no parser for '" .. lang .. "' language, see :help treesitter-parsers") end path = paths[1] -- cgit From 8144deb0989ea5c61fe9a1a5802d230eba33dfdd Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 29 Jan 2023 10:39:20 +0100 Subject: vim-patch:9.0.1256: NetworkManager connection files are not recognized (#22038) Problem: NetworkManager connection files are not recognized. Solution: Add a pattern for NetworkManager connection files. (closes vim/vim#11893) https://github.com/vim/vim/commit/04e4f1d98556e67d7337224b67b71c828410ee0f Co-authored-by: ObserverOfTime --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 9293c828b8..0a26e363d5 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -226,6 +226,7 @@ local extension = { hook = function(path, bufnr) return M.getlines(bufnr, 1) == '[Trigger]' and 'conf' end, + nmconnection = 'confini', mklx = 'context', mkiv = 'context', mkii = 'context', -- cgit From c9ac4e487706658852f0e6c2e71cf669dafba90b Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sun, 29 Jan 2023 14:19:07 -0500 Subject: vim-patch:9.0.1261: Elsa files are not recognized (#22047) Problem: Elsa files are not recognized. Solution: Add the name of Elsa files. (Amaan Qureshi) https://github.com/vim/vim/commit/2a99fe6c41efcd5d1eb47823e7e73cf391e230ba --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 0a26e363d5..1e7b85060e 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -332,6 +332,7 @@ local extension = { am = 'elf', exs = 'elixir', elm = 'elm', + lc = 'elsa', elv = 'elvish', ent = function(path, bufnr) return require('vim.filetype.detect').ent(bufnr) -- cgit From 27b81af19c498892f4b0444ad29b7be842f8e7b8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 30 Jan 2023 19:06:32 +0100 Subject: refactor!: remove has("debug") (#22060) This value can not be relied on as it doesn't work for multi-configuration generators. I don't think this undocumented option is used much, if at all, so I think we should remove it. --- runtime/lua/nvim/health.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua index b76106f241..f11899434e 100644 --- a/runtime/lua/nvim/health.lua +++ b/runtime/lua/nvim/health.lua @@ -156,13 +156,10 @@ local function check_performance() health.report_ok(buildtype) else health.report_info(buildtype) - health.report_warn( - 'Non-optimized ' .. (has('debug') and '(DEBUG) ' or '') .. 'build. Nvim will be slower.', - { - 'Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.', - suggest_faq, - } - ) + health.report_warn('Non-optimized debug build. Nvim will be slower.', { + 'Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.', + suggest_faq, + }) end -- check for slow shell invocation -- cgit From b649a96fc09fa7f18a988b0b0be5dadb54ad49de Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 31 Jan 2023 08:12:10 +0100 Subject: vim-patch:9.0.1263: KDL files are not recognized (#22058) Problem: KDL files are not recognized. Solution: Add a pattern for KDL files. (Amaan Qureshi, closes vim/vim#11898) https://github.com/vim/vim/commit/907349a74331fc1bc48cf43c1e7d54cb9e0e4fc9 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 1e7b85060e..b356f3d7aa 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -569,6 +569,7 @@ local extension = { libsonnet = 'jsonnet', jsp = 'jsp', jl = 'julia', + kdl = 'kdl', kv = 'kivy', kix = 'kix', kts = 'kotlin', -- cgit From d6d6ab3f8e77d54c8030c0c18f17d3c72ac4445c Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 26 Feb 2022 15:19:10 +0100 Subject: feat(lua): low-level interpreter mode (nvim -ll) --- runtime/doc/starting.txt | 8 ++++++++ runtime/lua/vim/_init_packages.lua | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 179bacdb24..5e0718c3bb 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -239,6 +239,14 @@ argument. Disables |shada| unless |-i| was given. Disables swapfile (like |-n|). + *-ll* +-ll {script} [args] + Execute a lua script, similarly to |-l|, but the editor is not + initialized. This gives a lua enviroment similar to a worker + thread. See |lua-loop-threading|. + + Unlike `-l` no prior arguments are allowed. + *-b* -b Binary mode. File I/O will only recognize to separate lines. The 'expandtab' option will be reset. The 'textwidth' diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 0c4ee8636d..e3a442af5e 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -42,8 +42,11 @@ function vim._load_package(name) return nil end --- Insert vim._load_package after the preloader at position 2 -table.insert(package.loaders, 2, vim._load_package) +-- TODO(bfredl): dedicated state for this? +if vim.api then + -- Insert vim._load_package after the preloader at position 2 + table.insert(package.loaders, 2, vim._load_package) +end -- builtin functions which always should be available require('vim.shared') @@ -78,6 +81,6 @@ function vim.empty_dict() end -- only on main thread: functions for interacting with editor state -if not vim.is_thread() then +if vim.api and not vim.is_thread() then require('vim._editor') end -- cgit From d63ad600e0571ccf07eed1e841e8519da7d4af9f Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 1 Feb 2023 10:08:50 +0100 Subject: vim-patch:9.0.1268: .clangd and .stylelintrc files don't get a filetype (#22079) Problem: .clangd and .stylelintrc files don't get a filetype. Solution: Use yaml for .clangd and json for .stylelintrc files. (Mark Skelton, closes vim/vim#11916) https://github.com/vim/vim/commit/9c51798a1f3b79ace5ae0551a8bb122025ac94ed Co-authored-by: Mark Skelton --- runtime/lua/vim/filetype.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index b356f3d7aa..d1a84fcecf 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1464,6 +1464,7 @@ local filename = { ['Pipfile.lock'] = 'json', ['.firebaserc'] = 'json', ['.prettierrc'] = 'json', + ['.stylelintrc'] = 'json', ['.babelrc'] = 'jsonc', ['.eslintrc'] = 'jsonc', ['.hintrc'] = 'jsonc', @@ -1699,6 +1700,7 @@ local filename = { fglrxrc = 'xml', ['/etc/blkid.tab'] = 'xml', ['/etc/blkid.tab.old'] = 'xml', + ['.clangd'] = 'yaml', ['.clang-format'] = 'yaml', ['.clang-tidy'] = 'yaml', ['/etc/zprofile'] = 'zsh', -- cgit From 9ce44a750c2a65082962effe6ce4d185b7698d73 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 1 Feb 2023 17:21:42 +0000 Subject: fix(man): use italics for `_` (#22086) fix(man): use italics for _ Even though underline is strictly what this should be. _ was used by nroff to indicate italics which wasn't possible on old typewriters so underline was used. Modern terminals now support italics so lets use that now. See: - https://unix.stackexchange.com/questions/274658/purpose-of-ascii-text-with-overstriking-file-format/274795#274795 - https://cmd.inp.nsk.su/old/cmd2/manuals/unix/UNIX_Unleashed/ch08.htm --- runtime/lua/man.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 732a4ab92e..0956022ac6 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -149,15 +149,21 @@ local function highlight_line(line, linenr) if overstrike then local last_hl = hls[#hls] if char == prev_char then - if char == '_' and attr == UNDERLINE and last_hl and last_hl.final == byte then - -- This underscore is in the middle of an underlined word - attr = UNDERLINE + if char == '_' and attr == ITALIC and last_hl and last_hl.final == byte then + -- This underscore is in the middle of an italic word + attr = ITALIC else attr = BOLD end elseif prev_char == '_' then - -- char is underlined - attr = UNDERLINE + -- Even though underline is strictly what this should be. _ was used by nroff to + -- indicate italics which wasn't possible on old typewriters so underline was used. Modern + -- terminals now support italics so lets use that now. + -- See: + -- - https://unix.stackexchange.com/questions/274658/purpose-of-ascii-text-with-overstriking-file-format/274795#274795 + -- - https://cmd.inp.nsk.su/old/cmd2/manuals/unix/UNIX_Unleashed/ch08.htm + -- attr = UNDERLINE + attr = ITALIC elseif prev_char == '+' and char == 'o' then -- bullet (overstrike text '+^Ho') attr = BOLD -- cgit From cb97d5425a0b6e77267795607ff45255a4ac1c22 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Wed, 1 Feb 2023 23:26:26 -0700 Subject: docs: clarify "pipe" mode for sockconnect Make it more clear that on unix the "pipe" mode of sockconnect uses unix local domain sockets, not named pipes (FIFOs) which are not currently supported. See discussion in #22080. Signed-off-by: Thayne McCombs --- runtime/doc/builtin.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c8f5570bae..2fc7dce7fc 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1959,7 +1959,7 @@ exp({expr}) *exp()* Compute()->exp() expand({string} [, {nosuf} [, {list}]]) *expand()* - Expand wildcards and the following special keywords in + Expand wildcards and the following special keywords in {string}. 'wildignorecase' applies. If {list} is given and it is |TRUE|, a List will be returned. @@ -7569,10 +7569,14 @@ sinh({expr}) *sinh()* sockconnect({mode}, {address} [, {opts}]) *sockconnect()* Connect a socket to an address. If {mode} is "pipe" then - {address} should be the path of a named pipe. If {mode} is - "tcp" then {address} should be of the form "host:port" where - the host should be an ip adderess or host name, and port the - port number. + {address} should be the path of a local domain socket (on + unix) or named pipe (on Windows). If {mode} is "tcp" then + {address} should be of the form "host:port" where the host + should be an ip adderess or host name, and port the port + number. + + For "pipe" mode, see |luv-pipe-handle|. For "tcp" mode, see + |luv-tcp-handle|. Returns a |channel| ID. Close the socket with |chanclose()|. Use |chansend()| to send data over a bytes socket, and -- cgit From 405f0a8c3fb6c9941418c4e205b41e3ad32d0fb0 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 2 Feb 2023 14:37:44 +0100 Subject: build: update release data --- runtime/nvim.appdata.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime') diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml index 7411a7190a..7d2ea49df4 100644 --- a/runtime/nvim.appdata.xml +++ b/runtime/nvim.appdata.xml @@ -26,9 +26,12 @@ + + + -- cgit From c05b3c3bbdef4018ce70f0c822c4a55654a9c186 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 2 Feb 2023 17:26:22 +0100 Subject: vim-patch:9.0.1274: FIRRTL files are not recognized (#22102) Problem: FIRRTL files are not recognized. Solution: Add a pattern for FIRRTL files. (Amaan Qureshi, closes vim/vim#11931) https://github.com/vim/vim/commit/685bf83b73d0fe6fd36bb2949bebd6aae66a139e Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index d1a84fcecf..8144731b09 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -385,6 +385,7 @@ local extension = { ['m4gl'] = 'fgl', ['4gl'] = 'fgl', ['4gh'] = 'fgl', + fir = 'firrtl', fish = 'fish', focexec = 'focexec', fex = 'focexec', -- cgit From 144279ef30a432ac8416746e3491f3120ae9b4e8 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 3 Feb 2023 09:18:18 +0100 Subject: vim-patch:be4e01637e71 (#22103) Update runtime files. https://github.com/vim/vim/commit/be4e01637e71c8d5095c33b9861fd70b41476732 Co-authored-by: Bram Moolenaar --- runtime/autoload/tohtml.vim | 424 ++++++++++++++++++++------------------ runtime/doc/diff.txt | 2 +- runtime/doc/fold.txt | 2 +- runtime/doc/options.txt | 8 +- runtime/doc/quickfix.txt | 2 - runtime/ftplugin/debchangelog.vim | 10 +- runtime/ftplugin/debcontrol.vim | 4 +- runtime/ftplugin/logcheck.vim | 4 +- runtime/plugin/tohtml.vim | 37 ++-- runtime/syntax/2html.vim | 2 +- runtime/syntax/automake.vim | 4 +- runtime/syntax/debchangelog.vim | 4 +- runtime/syntax/debcontrol.vim | 4 +- runtime/syntax/debcopyright.vim | 4 +- runtime/syntax/debsources.vim | 6 +- runtime/syntax/dep3patch.vim | 4 +- runtime/syntax/forth.vim | 30 +-- runtime/syntax/gpg.vim | 162 ++++++++------- runtime/syntax/lc.vim | 31 +++ runtime/syntax/nginx.vim | 33 ++- runtime/syntax/sh.vim | 16 +- runtime/syntax/shared/README.txt | 2 +- runtime/syntax/tpp.vim | 4 +- runtime/syntax/xf86conf.vim | 10 +- 24 files changed, 457 insertions(+), 352 deletions(-) create mode 100644 runtime/syntax/lc.vim (limited to 'runtime') diff --git a/runtime/autoload/tohtml.vim b/runtime/autoload/tohtml.vim index 4ae17815ba..8a1ba14364 100644 --- a/runtime/autoload/tohtml.vim +++ b/runtime/autoload/tohtml.vim @@ -1,6 +1,6 @@ " Vim autoload file for the tohtml plugin. " Maintainer: Ben Fritz -" Last Change: 2019 Aug 16 +" Last Change: 2023 Jan 01 " " Additional contributors: " @@ -351,63 +351,65 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{ let s:old_magic = &magic set magic - if s:settings.use_xhtml - if s:settings.encoding != "" - let xml_line = "" - else - let xml_line = "" + let html = [] + if !s:settings.no_doc + if s:settings.use_xhtml + if s:settings.encoding != "" + let xml_line = "" + else + let xml_line = "" + endif + let tag_close = ' />' endif - let tag_close = ' />' - endif - let style = [s:settings.use_xhtml ? "" : '-->'] - let body_line = '' + let style = [s:settings.use_xhtml ? "" : '-->'] + let body_line = '' - let html = [] - let s:html5 = 0 - if s:settings.use_xhtml - call add(html, xml_line) - endif - if s:settings.use_xhtml - call add(html, "") - call add(html, '') - elseif s:settings.use_css && !s:settings.no_pre - call add(html, "") - call add(html, '') - let s:html5 = 1 - else - call add(html, '') - call add(html, '') - endif - call add(html, '') - - " include encoding as close to the top as possible, but only if not already - " contained in XML information - if s:settings.encoding != "" && !s:settings.use_xhtml - if s:html5 - call add(html, '") + call add(html, '') + elseif s:settings.use_css && !s:settings.no_pre + call add(html, "") + call add(html, '') + let s:html5 = 1 else - call add(html, "') + call add(html, '') endif - endif + call add(html, '') - call add(html, 'diff') - call add(html, '') - let body_line_num = len(html) - call add(html, '') + " include encoding as close to the top as possible, but only if not already + " contained in XML information + if s:settings.encoding != "" && !s:settings.use_xhtml + if s:html5 + call add(html, 'diff') + call add(html, '') + let body_line_num = len(html) + call add(html, '') + endif call add(html, "") call add(html, '') @@ -430,47 +432,53 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{ " When not using CSS or when using xhtml, the line can be important. " Assume it will be the same for all buffers and grab it from the first " buffer. Similarly, need to grab the body end line as well. - if body_line == '' - 1 - call search('', 'b') - let s:body_end_line = getline('.') - endif + if !s:settings.no_doc + if body_line == '' + 1 + call search('', 'b') + let s:body_end_line = getline('.') + endif - " Grab the style information. Some of this will be duplicated so only insert - " it if it's not already there. {{{ - 1 - let style_start = search('^') - 1 - let style_end = search('^') - if style_start > 0 && style_end > 0 - let buf_styles = getline(style_start + 1, style_end - 1) - for a_style in buf_styles - if index(style, a_style) == -1 - if diff_style_start == 0 - if a_style =~ '\') + 1 + let style_end = search('^') + if style_start > 0 && style_end > 0 + let buf_styles = getline(style_start + 1, style_end - 1) + for a_style in buf_styles + if index(style, a_style) == -1 + if diff_style_start == 0 + if a_style =~ '\\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_ - $ - ??,$d_ + " Delete those parts that are not needed so we can include the rest into the + " resulting table. + 1,/^\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_ + $ + ??,$d_ + elseif !s:settings.no_modeline + " remove modeline from source files if it is included and we haven't deleted + " due to removing html footer already + $d + endif let temp = getline(1,'$') " clean out id on the main content container because we already set it on " the table @@ -478,7 +486,11 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{ " undo deletion of start and end part " so we can later save the file as valid html " TODO: restore using grabbed lines if undolevel is 1? - normal! 2u + if !s:settings.no_doc + normal! 2u + elseif !s:settings.no_modeline + normal! u + endif if s:settings.use_css call add(html, '') call add(html, '
') elseif s:settings.use_xhtml @@ -495,17 +507,23 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{ quit! endfor - let html[body_line_num] = body_line + if !s:settings.no_doc + let html[body_line_num] = body_line + endif call add(html, '
') - call add(html, s:body_end_line) - call add(html, '') + if !s:settings.no_doc + call add(html, s:body_end_line) + call add(html, '') + endif " The generated HTML is admittedly ugly and takes a LONG time to fold. " Make sure the user doesn't do syntax folding when loading a generated file, " using a modeline. - call add(html, '') + if !s:settings.no_modeline + call add(html, '') + endif let i = 1 let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html") @@ -542,129 +560,131 @@ func! tohtml#Diff2HTML(win_list, buf_list) "{{{ call append(0, html) - if len(style) > 0 - 1 - let style_start = search('^')-1 + if !s:settings.no_doc + if len(style) > 0 + 1 + let style_start = search('^')-1 - " add required javascript in reverse order so we can just call append again - " and again without adjusting {{{ + " add required javascript in reverse order so we can just call append again + " and again without adjusting {{{ - let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids + let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids - " insert script closing tag if needed - if s:uses_script - call append(style_start, [ - \ '', - \ s:settings.use_xhtml ? '//]]>' : '-->', - \ "" - \ ]) - endif + " insert script closing tag if needed + if s:uses_script + call append(style_start, [ + \ '', + \ s:settings.use_xhtml ? '//]]>' : '-->', + \ "" + \ ]) + endif - " insert javascript to get IDs from line numbers, and to open a fold before - " jumping to any lines contained therein - if s:settings.line_ids - call append(style_start, [ - \ " /* Always jump to new location even if the line was hidden inside a fold, or", - \ " * we corrected the raw number to a line ID.", - \ " */", - \ " if (lineElem) {", - \ " lineElem.scrollIntoView(true);", - \ " }", - \ " return true;", - \ "}", - \ "if ('onhashchange' in window) {", - \ " window.onhashchange = JumpToLine;", - \ "}" - \ ]) + " insert javascript to get IDs from line numbers, and to open a fold before + " jumping to any lines contained therein + if s:settings.line_ids + call append(style_start, [ + \ " /* Always jump to new location even if the line was hidden inside a fold, or", + \ " * we corrected the raw number to a line ID.", + \ " */", + \ " if (lineElem) {", + \ " lineElem.scrollIntoView(true);", + \ " }", + \ " return true;", + \ "}", + \ "if ('onhashchange' in window) {", + \ " window.onhashchange = JumpToLine;", + \ "}" + \ ]) - if s:settings.dynamic_folds + if s:settings.dynamic_folds + call append(style_start, [ + \ "", + \ " /* navigate upwards in the DOM tree to open all folds containing the line */", + \ " var node = lineElem;", + \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')", + \ " {", + \ " if (node.className == 'closed-fold')", + \ " {", + \ " /* toggle open the fold ID (remove window ID) */", + \ " toggleFold(node.id.substr(4));", + \ " }", + \ " node = node.parentNode;", + \ " }", + \ ]) + endif + endif + + if s:settings.line_ids call append(style_start, [ \ "", - \ " /* navigate upwards in the DOM tree to open all folds containing the line */", - \ " var node = lineElem;", - \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')", - \ " {", - \ " if (node.className == 'closed-fold')", - \ " {", - \ " /* toggle open the fold ID (remove window ID) */", - \ " toggleFold(node.id.substr(4));", - \ " }", - \ " node = node.parentNode;", + \ "/* function to open any folds containing a jumped-to line before jumping to it */", + \ "function JumpToLine()", + \ "{", + \ " var lineNum;", + \ " lineNum = window.location.hash;", + \ " lineNum = lineNum.substr(1); /* strip off '#' */", + \ "", + \ " if (lineNum.indexOf('L') == -1) {", + \ " lineNum = 'L'+lineNum;", + \ " }", + \ " if (lineNum.indexOf('W') == -1) {", + \ " lineNum = 'W1'+lineNum;", \ " }", + \ " var lineElem = document.getElementById(lineNum);" \ ]) endif - endif - if s:settings.line_ids - call append(style_start, [ - \ "", - \ "/* function to open any folds containing a jumped-to line before jumping to it */", - \ "function JumpToLine()", - \ "{", - \ " var lineNum;", - \ " lineNum = window.location.hash;", - \ " lineNum = lineNum.substr(1); /* strip off '#' */", - \ "", - \ " if (lineNum.indexOf('L') == -1) {", - \ " lineNum = 'L'+lineNum;", - \ " }", - \ " if (lineNum.indexOf('W') == -1) {", - \ " lineNum = 'W1'+lineNum;", - \ " }", - \ " var lineElem = document.getElementById(lineNum);" - \ ]) - endif + " Insert javascript to toggle matching folds open and closed in all windows, + " if dynamic folding is active. + if s:settings.dynamic_folds + call append(style_start, [ + \ " function toggleFold(objID)", + \ " {", + \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)", + \ " {", + \ " var fold;", + \ ' fold = document.getElementById("win"+win_num+objID);', + \ " if(fold.className == 'closed-fold')", + \ " {", + \ " fold.className = 'open-fold';", + \ " }", + \ " else if (fold.className == 'open-fold')", + \ " {", + \ " fold.className = 'closed-fold';", + \ " }", + \ " }", + \ " }", + \ ]) + endif - " Insert javascript to toggle matching folds open and closed in all windows, - " if dynamic folding is active. - if s:settings.dynamic_folds - call append(style_start, [ - \ " function toggleFold(objID)", - \ " {", - \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)", - \ " {", - \ " var fold;", - \ ' fold = document.getElementById("win"+win_num+objID);', - \ " if(fold.className == 'closed-fold')", - \ " {", - \ " fold.className = 'open-fold';", - \ " }", - \ " else if (fold.className == 'open-fold')", - \ " {", - \ " fold.className = 'closed-fold';", - \ " }", - \ " }", - \ " }", - \ ]) - endif + if s:uses_script + " insert script tag if needed + call append(style_start, [ + \ "", + \ s:settings.use_xhtml ? '//", - \ s:settings.use_xhtml ? '//']+ + \ style+ + \ [ s:settings.use_xhtml ? '' : '', + \ '' + \]) + endif "}}} endif - - " Insert styles from all the generated html documents and additional styles - " for the table-based layout of the side-by-side diff. The diff should take - " up the full browser window (but not more), and be static in size, - " horizontally scrollable when the lines are too long. Otherwise, the diff - " is pretty useless for really long lines. {{{ - if s:settings.use_css - call append(style_start, - \ ['']+ - \ style+ - \ [ s:settings.use_xhtml ? '' : '', - \ '' - \]) - endif "}}} endif let &paste = s:old_paste diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 382d025d3c..ead68c5f4f 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -125,7 +125,7 @@ file for a moment and come back to the same file and be in diff mode again. buffers. The `:diffoff` command resets the relevant options to the values they had when -using `:diffsplit`, `:diffpatch` , `:diffthis`. or starting Vim in diff mode. +using `:diffsplit`, `:diffpatch`, `:diffthis`. or starting Vim in diff mode. When using `:diffoff` twice the last saved values are restored. Otherwise they are set to their default value: diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index 35a3be35fb..859562fae6 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -195,7 +195,7 @@ non-matching marker pairs. Example: > /* funcB() {{{2 */ void funcB() {} - +< *{{{* *}}}* A fold starts at a "{{{" marker. The following number specifies the fold level. What happens depends on the difference between the current fold level and the level given by the marker: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index b1af90a604..1f91b89322 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3864,8 +3864,8 @@ A jump table for the options with a short description can be found at |Q_op|. are left blank. *lcs-multispace* multispace:c... - One or more characters to use cyclically to show for - multiple consecutive spaces. Overrides the "space" + One or more characters to use cyclically to show for + multiple consecutive spaces. Overrides the "space" setting, except for single spaces. When omitted, the "space" setting is used. For example, `:set listchars=multispace:---+` shows ten consecutive @@ -6205,8 +6205,8 @@ A jump table for the options with a short description can be found at |Q_op|. windows. * - Set highlight group to User{N}, where {N} is taken from the minwid field, e.g. %1*. Restore normal highlight with %* or %0*. - The difference between User{N} and StatusLine will be applied - to StatusLineNC for the statusline of non-current windows. + The difference between User{N} and StatusLine will be applied to + StatusLineNC for the statusline of non-current windows. The number N must be between 1 and 9. See |hl-User1..9| When displaying a flag, Vim removes the leading comma, if any, when diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index b1f7c927cc..f70dbd0913 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -353,8 +353,6 @@ processing a quickfix or location list command, it will be aborted. If numbers [from] and/or [to] are given, the respective range of errors is listed. A negative number counts from the last error backwards, -1 being the last error. - The 'switchbuf' settings are respected when jumping - to a buffer. The |:filter| command can be used to display only the quickfix entries matching a supplied pattern. The pattern is matched against the filename, module name, diff --git a/runtime/ftplugin/debchangelog.vim b/runtime/ftplugin/debchangelog.vim index cf8dd17c44..062fc054c8 100644 --- a/runtime/ftplugin/debchangelog.vim +++ b/runtime/ftplugin/debchangelog.vim @@ -3,9 +3,9 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Michael Piefel " Stefano Zacchiroli -" Last Change: 2022 Jul 25 +" Last Change: 2023 Jan 16 " License: Vim License -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/ftplugin/debchangelog.vim +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/debchangelog.vim " Bug completion requires apt-listbugs installed for Debian packages or " python-launchpadlib installed for Ubuntu packages @@ -35,14 +35,14 @@ if exists('g:did_changelog_ftplugin') finish endif +" Don't load another plugin (this is global) +let g:did_changelog_ftplugin = 1 + " Make sure the '<' and 'C' flags are not included in 'cpoptions', otherwise " would not be recognized. See ":help 'cpoptions'". let s:cpo_save = &cpo set cpo&vim -" Don't load another plugin (this is global) -let g:did_changelog_ftplugin = 1 - " {{{1 GUI menu " Helper functions returning various data. diff --git a/runtime/ftplugin/debcontrol.vim b/runtime/ftplugin/debcontrol.vim index 3a6e39a682..bb710e597c 100644 --- a/runtime/ftplugin/debcontrol.vim +++ b/runtime/ftplugin/debcontrol.vim @@ -2,8 +2,8 @@ " Language: Debian control files " Maintainer: Debian Vim Maintainers " Former Maintainer: Pierre Habouzit -" Last Change: 2018-01-28 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/ftplugin/debcontrol.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/debcontrol.vim " Do these settings once per buffer if exists('b:did_ftplugin') diff --git a/runtime/ftplugin/logcheck.vim b/runtime/ftplugin/logcheck.vim index 9d664b2d09..9c1be1108e 100644 --- a/runtime/ftplugin/logcheck.vim +++ b/runtime/ftplugin/logcheck.vim @@ -1,9 +1,9 @@ " Vim filetype plugin file " Language: Logcheck " Maintainer: Debian Vim Maintainers -" Last Change: 2018 Dec 27 +" Last Change: 2023 Jan 16 " License: Vim License -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/ftplugin/logcheck.vim +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/logcheck.vim if exists('b:did_ftplugin') finish diff --git a/runtime/plugin/tohtml.vim b/runtime/plugin/tohtml.vim index 08df19b4f9..0369313f08 100644 --- a/runtime/plugin/tohtml.vim +++ b/runtime/plugin/tohtml.vim @@ -1,6 +1,6 @@ " Vim plugin for converting a syntax highlighted file to HTML. " Maintainer: Ben Fritz -" Last Change: 2019 Nov 13 +" Last Change: 2023 Jan 01 " " The core of the code is in $VIMRUNTIME/autoload/tohtml.vim and " $VIMRUNTIME/syntax/2html.vim @@ -8,11 +8,23 @@ if exists('g:loaded_2html_plugin') finish endif -let g:loaded_2html_plugin = 'vim8.1_v2' +let g:loaded_2html_plugin = 'vim9.0_v1' " " Changelog: {{{ -" 8.1_v2 (this version): - Fix Bitbucket issue #19: fix calculation of tab +" 9.0_v1 (this version): - Implement g:html_no_doc and g:html_no_modeline +" for diff mode. Add tests. +" (Vim 9.0.1122): NOTE: no version string update for this version! +" - Bugfix for variable name in g:html_no_doc +" (Vim 9.0.0819): NOTE: no version string update for this version! +" - Add options g:html_no_doc, g:html_no_lines, +" and g:html_no_modeline (partially included in Vim +" runtime prior to version string update). +" - Updates for new Vim9 string append style (i.e. use +" ".." instead of ".") +" +" 8.1 updates: {{{ +" 8.1_v2 (Vim 8.1.2312): - Fix SourceForge issue #19: fix calculation of tab " stop position to use in expanding a tab, when that " tab occurs after a syntax match which in turn " comes after previously expanded tabs. @@ -20,17 +32,17 @@ let g:loaded_2html_plugin = 'vim8.1_v2' " destination file to ignore FileType events; " speeds up processing when the destination file " already exists and HTML highlight takes too long. -" - Fix Bitbucket issue #20: progress bar could not be +" - Fix SourceForge issue #20: progress bar could not be " seen when DiffDelete background color matched " StatusLine background color. Added TOhtmlProgress " highlight group for manual user override, but " calculate it to be visible compared to StatusLine " by default. -" - Fix Bitbucket issue #1: Remove workaround for old +" - Fix SourceForge issue #1: Remove workaround for old " browsers which don't support 'ch' CSS unit, since " all modern browsers, including IE>=9, support it. -" - Fix Bitbucket issue #10: support termguicolors -" - Fix Bitbucket issue #21: default to using +" - Fix SourceForge issue #10: support termguicolors +" - Fix SourceForge issue #21: default to using " generated content instead of tags for " uncopyable text, so that text is correctly " prevented from being copied in chrome. Use @@ -41,13 +53,14 @@ let g:loaded_2html_plugin = 'vim8.1_v2' " - Fix fallback sizing of tags for browsers " without "ch" support. " - Fix cursor on unselectable diff filler text. -" 8.1_v1 (Vim 8.1.0528): - Fix Bitbucket issue #6: Don't generate empty +" 8.1_v1 (Vim 8.1.0528): - Fix SourceForge issue #6: Don't generate empty " script tag. -" - Fix Bitbucket issue #5: javascript should +" - Fix SourceForge issue #5: javascript should " declare variables with "var". -" - Fix Bitbucket issue #13: errors thrown sourcing +" - Fix SourceForge issue #13: errors thrown sourcing " 2html.vim directly when plugins not loaded. -" - Fix Bitbucket issue #16: support 'vartabstop'. +" - Fix SourceForge issue #16: support 'vartabstop'. +"}}} " " 7.4 updates: {{{ " 7.4_v2 (Vim 7.4.0899): Fix error raised when converting a diff containing @@ -152,7 +165,7 @@ let g:loaded_2html_plugin = 'vim8.1_v2' " TODO: {{{ " * Check the issue tracker: -" https://bitbucket.org/fritzophrenic/vim-tohtml/issues?status=new&status=open +" https://sourceforge.net/p/vim-tohtml/issues/search/?q=%21status%3Aclosed " * Options for generating the CSS in external style sheets. New :TOcss " command to convert the current color scheme into a (mostly) generic CSS " stylesheet which can be re-used. Alternate stylesheet support? Good start diff --git a/runtime/syntax/2html.vim b/runtime/syntax/2html.vim index ce6797deaa..9f43e91309 100644 --- a/runtime/syntax/2html.vim +++ b/runtime/syntax/2html.vim @@ -1,6 +1,6 @@ " Vim syntax support file " Maintainer: Ben Fritz -" Last Change: 2022 Dec 26 +" Last Change: 2023 Jan 01 " " Additional contributors: " diff --git a/runtime/syntax/automake.vim b/runtime/syntax/automake.vim index 8a7db7c27b..2f1ad982c6 100644 --- a/runtime/syntax/automake.vim +++ b/runtime/syntax/automake.vim @@ -2,8 +2,8 @@ " Language: automake Makefile.am " Maintainer: Debian Vim Maintainers " Former Maintainer: John Williams -" Last Change: 2018 Dec 27 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/automake.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/automake.vim " " XXX This file is in need of a new maintainer, Debian VIM Maintainers maintain " it only because patches have been submitted for it by Debian users and the diff --git a/runtime/syntax/debchangelog.vim b/runtime/syntax/debchangelog.vim index 691c3778c1..d3c3d39304 100644 --- a/runtime/syntax/debchangelog.vim +++ b/runtime/syntax/debchangelog.vim @@ -3,8 +3,8 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Gerfried Fuchs " Wichert Akkerman -" Last Change: 2022 Oct 29 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debchangelog.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debchangelog.vim " Standard syntax initialization if exists('b:current_syntax') diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim index 4c7fb5dd63..c79b702f92 100644 --- a/runtime/syntax/debcontrol.vim +++ b/runtime/syntax/debcontrol.vim @@ -3,8 +3,8 @@ " Maintainer: Debian Vim Maintainers " Former Maintainers: Gerfried Fuchs " Wichert Akkerman -" Last Change: 2022 May 11 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debcontrol.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debcontrol.vim " Standard syntax initialization if exists('b:current_syntax') diff --git a/runtime/syntax/debcopyright.vim b/runtime/syntax/debcopyright.vim index c87b876eea..6f76b5c868 100644 --- a/runtime/syntax/debcopyright.vim +++ b/runtime/syntax/debcopyright.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Debian copyright file " Maintainer: Debian Vim Maintainers -" Last Change: 2019 Sep 07 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debcopyright.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debcopyright.vim " Standard syntax initialization if exists('b:current_syntax') diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim index 9b75797b54..69900c7a51 100644 --- a/runtime/syntax/debsources.vim +++ b/runtime/syntax/debsources.vim @@ -2,8 +2,8 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers " Former Maintainer: Matthijs Mohlmann -" Last Change: 2022 Oct 29 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/debsources.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debsources.vim " Standard syntax initialization if exists('b:current_syntax') @@ -14,7 +14,7 @@ endif syn case match " A bunch of useful keywords -syn match debsourcesKeyword /\(deb-src\|deb\|main\|contrib\|non-free\|restricted\|universe\|multiverse\)/ +syn match debsourcesKeyword /\(deb-src\|deb\|main\|contrib\|non-free\|non-free-firmware\|restricted\|universe\|multiverse\)/ " Match comments syn match debsourcesComment /#.*/ contains=@Spell diff --git a/runtime/syntax/dep3patch.vim b/runtime/syntax/dep3patch.vim index cb0eda8931..c00bddfde2 100644 --- a/runtime/syntax/dep3patch.vim +++ b/runtime/syntax/dep3patch.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Debian DEP3 Patch headers " Maintainer: Gabriel Filion -" Last Change: 2022 Apr 06 -" URL: https://salsa.debian.org/vim-team/vim-debian/blob/master/syntax/dep3patch.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/dep3patch.vim " " Specification of the DEP3 patch header format is available at: " https://dep-team.pages.debian.net/deps/dep3/ diff --git a/runtime/syntax/forth.vim b/runtime/syntax/forth.vim index 721bceb367..fe98634079 100644 --- a/runtime/syntax/forth.vim +++ b/runtime/syntax/forth.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: FORTH " Current Maintainer: Johan Kotlinski -" Previous Maintainer: Christian V. J. Brüssow -" Last Change: 2018-03-29 +" Previous Maintainer: Christian V. J. Br�ssow +" Last Change: 2023-01-12 " Filenames: *.fs,*.ft " URL: https://github.com/jkotlinski/forth.vim @@ -23,7 +23,6 @@ syn case ignore " Some special, non-FORTH keywords syn keyword forthTodo contained TODO FIXME XXX -syn match forthTodo contained 'Copyright\(\s([Cc])\)\=\(\s[0-9]\{2,4}\)\=' " Characters allowed in keywords " I don't know if 128-255 are allowed in ANS-FORTH @@ -98,13 +97,16 @@ syn keyword forthEndOfColonDef ; ;M ;m syn keyword forthEndOfClassDef ;class syn keyword forthEndOfObjectDef ;object syn keyword forthDefine CONSTANT 2CONSTANT FCONSTANT VARIABLE 2VARIABLE -syn keyword forthDefine FVARIABLE CREATE USER VALUE TO DEFER IS DOES> IMMEDIATE +syn keyword forthDefine FVARIABLE CREATE USER VALUE TO DEFER IS IMMEDIATE syn keyword forthDefine COMPILE-ONLY COMPILE RESTRICT INTERPRET POSTPONE EXECUTE syn keyword forthDefine LITERAL CREATE-INTERPRET/COMPILE INTERPRETATION> syn keyword forthDefine INT NAME?INT NAME>COMP syn keyword forthDefine NAME>STRING STATE C; CVARIABLE BUFFER: MARKER syn keyword forthDefine , 2, F, C, COMPILE, +syn match forthDefine "\[DEFINED]" +syn match forthDefine "\[UNDEFINED]" +syn match forthDefine "\[IF]" syn match forthDefine "\[IFDEF]" syn match forthDefine "\[IFUNDEF]" syn match forthDefine "\[THEN]" @@ -180,6 +182,7 @@ syn keyword forthBlocks BLOCK-INCLUDED BLK syn keyword forthMath DECIMAL HEX BASE syn match forthInteger '\<-\=[0-9]\+.\=\>' syn match forthInteger '\<&-\=[0-9]\+.\=\>' +syn match forthInteger '\<#-\=[0-9]\+.\=\>' " recognize hex and binary numbers, the '$' and '%' notation is for gforth syn match forthInteger '\<\$\x*\x\+\>' " *1* --- don't mess syn match forthInteger '\<\x*\d\x*\>' " *2* --- this order! @@ -192,18 +195,18 @@ syn match forthFloat '\<-\=\d*[.]\=\d\+[DdEe][-+]\d\+\>' syn region forthComment start='0 \[if\]' end='\[endif\]' end='\[then\]' contains=forthTodo " Strings -syn region forthString start=+\.*\"+ end=+"+ end=+$+ +syn region forthString start=+\.*\"+ end=+"+ end=+$+ contains=@Spell " XXX -syn region forthString start=+s\"+ end=+"+ end=+$+ -syn region forthString start=+s\\\"+ end=+"+ end=+$+ -syn region forthString start=+c\"+ end=+"+ end=+$+ +syn region forthString start=+s\"+ end=+"+ end=+$+ contains=@Spell +syn region forthString start=+s\\\"+ end=+"+ end=+$+ contains=@Spell +syn region forthString start=+c\"+ end=+"+ end=+$+ contains=@Spell " Comments -syn match forthComment '\\\s.*$' contains=forthTodo,forthSpaceError -syn region forthComment start='\\S\s' end='.*' contains=forthTodo,forthSpaceError -syn match forthComment '\.(\s[^)]*)' contains=forthTodo,forthSpaceError -syn region forthComment start='\(^\|\s\)\zs(\s' skip='\\)' end=')' contains=forthTodo,forthSpaceError -syn region forthComment start='/\*' end='\*/' contains=forthTodo,forthSpaceError +syn match forthComment '\\\%(\s.*\)\=$' contains=@Spell,forthTodo,forthSpaceError +syn region forthComment start='\\S\s' end='.*' contains=@Spell,forthTodo,forthSpaceError +syn match forthComment '\.(\s[^)]*)' contains=@Spell,forthTodo,forthSpaceError +syn region forthComment start='\(^\|\s\)\zs(\s' skip='\\)' end=')' contains=@Spell,forthTodo,forthSpaceError +syn region forthComment start='/\*' end='\*/' contains=@Spell,forthTodo,forthSpaceError " Include files syn match forthInclude '^INCLUDE\s\+\k\+' @@ -260,3 +263,4 @@ let b:current_syntax = "forth" let &cpo = s:cpo_save unlet s:cpo_save " vim:ts=8:sw=4:nocindent:smartindent: + diff --git a/runtime/syntax/gpg.vim b/runtime/syntax/gpg.vim index 46e2099994..57f712b6a3 100644 --- a/runtime/syntax/gpg.vim +++ b/runtime/syntax/gpg.vim @@ -1,7 +1,8 @@ " Vim syntax file -" Language: gpg(1) configuration file -" Previous Maintainer: Nikolai Weibull -" Latest Revision: 2010-10-14 +" Language: gpg(1) configuration file +" Previous Maintainer: Nikolai Weibull +" Latest Revision: 2010-10-14 +" Updated: 2023-01-23 @ObserverOfTime: added a couple of keywords if exists("b:current_syntax") finish @@ -12,91 +13,92 @@ set cpo&vim setlocal iskeyword+=- -syn keyword gpgTodo contained FIXME TODO XXX NOTE +syn keyword gpgTodo contained FIXME TODO XXX NOTE -syn region gpgComment contained display oneline start='#' end='$' - \ contains=gpgTodo,gpgID,@Spell +syn region gpgComment contained display oneline start='#' end='$' + \ contains=gpgTodo,gpgID,@Spell -syn match gpgID contained display '\<\(0x\)\=\x\{8,}\>' +syn match gpgID contained display '\<\(0x\)\=\x\{8,}\>' -syn match gpgBegin display '^' skipwhite nextgroup=gpgComment,gpgOption,gpgCommand +syn match gpgBegin display '^' skipwhite nextgroup=gpgComment,gpgOption,gpgCommand -syn keyword gpgCommand contained skipwhite nextgroup=gpgArg - \ check-sigs decrypt decrypt-files delete-key - \ delete-secret-and-public-key delete-secret-key - \ edit-key encrypt-files export export-all - \ export-ownertrust export-secret-keys - \ export-secret-subkeys fast-import fingerprint - \ gen-prime gen-random import import-ownertrust - \ list-keys list-public-keys list-secret-keys - \ list-sigs lsign-key nrsign-key print-md print-mds - \ recv-keys search-keys send-keys sign-key verify - \ verify-files -syn keyword gpgCommand contained skipwhite nextgroup=gpgArgError - \ check-trustdb clearsign desig-revoke detach-sign - \ encrypt gen-key gen-revoke help list-packets - \ rebuild-keydb-caches sign store symmetric - \ update-trustdb version warranty +syn keyword gpgCommand contained skipwhite nextgroup=gpgArg + \ check-sigs decrypt decrypt-files delete-key + \ delete-secret-and-public-key delete-secret-key + \ edit-key encrypt-files export export-all + \ export-ownertrust export-secret-keys + \ export-secret-subkeys fast-import fingerprint + \ gen-prime gen-random import import-ownertrust + \ list-keys list-public-keys list-secret-keys + \ list-sigs lsign-key nrsign-key print-md print-mds + \ recv-keys search-keys send-keys sign-key verify + \ verify-files +syn keyword gpgCommand contained skipwhite nextgroup=gpgArgError + \ check-trustdb clearsign desig-revoke detach-sign + \ encrypt gen-key gen-revoke help list-packets + \ rebuild-keydb-caches sign store symmetric + \ update-trustdb version warranty -syn keyword gpgOption contained skipwhite nextgroup=gpgArg - \ attribute-fd cert-digest-algo charset cipher-algo - \ command-fd comment completes-needed compress - \ compress-algo debug default-cert-check-level - \ default-key default-preference-list - \ default-recipient digest-algo disable-cipher-algo - \ disable-pubkey-algo encrypt-to exec-path - \ export-options group homedir import-options - \ keyring keyserver keyserver-options load-extension - \ local-user logger-fd marginals-needed max-cert-depth - \ notation-data options output override-session-key - \ passphrase-fd personal-cipher-preferences - \ personal-compress-preferences - \ personal-digest-preferences photo-viewer - \ recipient s2k-cipher-algo s2k-digest-algo s2k-mode - \ secret-keyring set-filename set-policy-url status-fd - \ trusted-key verify-options keyid-format list-options -syn keyword gpgOption contained skipwhite nextgroup=gpgArgError - \ allow-freeform-uid allow-non-selfsigned-uid - \ allow-secret-key-import always-trust - \ armor ask-cert-expire ask-sig-expire - \ auto-check-trustdb batch debug-all default-comment - \ default-recipient-self dry-run emit-version - \ emulate-md-encode-bug enable-special-filenames - \ escape-from-lines expert fast-list-mode - \ fixed-list-mode for-your-eyes-only - \ force-mdc force-v3-sigs force-v4-certs - \ gpg-agent-info ignore-crc-error ignore-mdc-error - \ ignore-time-conflict ignore-valid-from interactive - \ list-only lock-multiple lock-never lock-once - \ merge-only no no-allow-non-selfsigned-uid - \ no-armor no-ask-cert-expire no-ask-sig-expire - \ no-auto-check-trustdb no-batch no-comment - \ no-default-keyring no-default-recipient - \ no-encrypt-to no-expensive-trust-checks - \ no-expert no-for-your-eyes-only no-force-v3-sigs - \ no-force-v4-certs no-greeting no-literal - \ no-mdc-warning no-options no-permission-warning - \ no-pgp2 no-pgp6 no-pgp7 no-random-seed-file - \ no-secmem-warning no-show-notation no-show-photos - \ no-show-policy-url no-sig-cache no-sig-create-check - \ no-sk-comments no-tty no-utf8-strings no-verbose - \ no-version not-dash-escaped openpgp pgp2 - \ pgp6 pgp7 preserve-permissions quiet rfc1991 - \ set-filesize show-keyring show-notation show-photos - \ show-policy-url show-session-key simple-sk-checksum - \ sk-comments skip-verify textmode throw-keyid - \ try-all-secrets use-agent use-embedded-filename - \ utf8-strings verbose with-colons with-fingerprint - \ with-key-data yes +syn keyword gpgOption contained skipwhite nextgroup=gpgArg + \ attribute-fd cert-digest-algo charset cipher-algo + \ command-fd comment completes-needed compress + \ compress-algo debug default-cert-check-level + \ default-key default-preference-list + \ default-recipient digest-algo disable-cipher-algo + \ disable-pubkey-algo encrypt-to exec-path + \ export-options group homedir import-options + \ keyring keyserver keyserver-options load-extension + \ local-user logger-fd marginals-needed max-cert-depth + \ notation-data options output override-session-key + \ passphrase-fd personal-cipher-preferences + \ personal-compress-preferences + \ personal-digest-preferences photo-viewer + \ recipient s2k-cipher-algo s2k-digest-algo s2k-mode + \ secret-keyring set-filename set-policy-url status-fd + \ trusted-key verify-options keyid-format list-options + \ default-new-key-algo weak-digest +syn keyword gpgOption contained skipwhite nextgroup=gpgArgError + \ allow-freeform-uid allow-non-selfsigned-uid + \ allow-secret-key-import always-trust + \ armor ask-cert-expire ask-sig-expire + \ auto-check-trustdb batch debug-all default-comment + \ default-recipient-self dry-run emit-version + \ emulate-md-encode-bug enable-special-filenames + \ escape-from-lines expert fast-list-mode + \ fixed-list-mode for-your-eyes-only + \ force-mdc force-v3-sigs force-v4-certs + \ gpg-agent-info ignore-crc-error ignore-mdc-error + \ ignore-time-conflict ignore-valid-from interactive + \ list-only lock-multiple lock-never lock-once + \ merge-only no no-allow-non-selfsigned-uid + \ no-armor no-ask-cert-expire no-ask-sig-expire + \ no-auto-check-trustdb no-batch no-comment + \ no-default-keyring no-default-recipient + \ no-encrypt-to no-expensive-trust-checks + \ no-expert no-for-your-eyes-only no-force-v3-sigs + \ no-force-v4-certs no-greeting no-literal + \ no-mdc-warning no-options no-permission-warning + \ no-pgp2 no-pgp6 no-pgp7 no-random-seed-file + \ no-secmem-warning no-show-notation no-show-photos + \ no-show-policy-url no-sig-cache no-sig-create-check + \ no-sk-comments no-tty no-utf8-strings no-verbose + \ no-version not-dash-escaped openpgp pgp2 + \ pgp6 pgp7 preserve-permissions quiet rfc1991 + \ set-filesize show-keyring show-notation show-photos + \ show-policy-url show-session-key simple-sk-checksum + \ sk-comments skip-verify textmode throw-keyid + \ try-all-secrets use-agent use-embedded-filename + \ utf8-strings verbose with-colons with-fingerprint + \ with-key-data yes -syn match gpgArg contained display '\S\+\(\s\+\S\+\)*' contains=gpgID +syn match gpgArg contained display '\S\+\(\s\+\S\+\)*' contains=gpgID syn match gpgArgError contained display '\S\+\(\s\+\S\+\)*' -hi def link gpgComment Comment -hi def link gpgTodo Todo -hi def link gpgID Number -hi def link gpgOption Keyword -hi def link gpgCommand Error +hi def link gpgComment Comment +hi def link gpgTodo Todo +hi def link gpgID Number +hi def link gpgOption Keyword +hi def link gpgCommand Error hi def link gpgArgError Error let b:current_syntax = "gpg" diff --git a/runtime/syntax/lc.vim b/runtime/syntax/lc.vim new file mode 100644 index 0000000000..a334529385 --- /dev/null +++ b/runtime/syntax/lc.vim @@ -0,0 +1,31 @@ +" Vim syntax file +" Language: Elsa +" Maintainer: Miles Glapa-Grossklag +" Last Change: 2023-01-29 + +if exists('b:current_syntax') + finish +endif + +" Keywords +syntax keyword elsaKeyword let eval +syntax match elsaKeyword "\v:" +highlight link elsaKeyword Keyword + +" Comments +setlocal commentstring=--%s +syntax match elsaComment "\v--.*$" +highlight link elsaComment Comment + +" Operators +syntax match elsaOperator "\v\=" +syntax match elsaOperator "\v\=[abd*~]\>" +syntax match elsaOperator "\v-\>" +syntax match elsaOperator "\v\\" +highlight link elsaOperator Operator + +" Definitions +syntax match elsaConstant "\v[A-Z]+[A-Z_0-9]*" +highlight link elsaConstant Constant + +let b:current_syntax = 'elsa' diff --git a/runtime/syntax/nginx.vim b/runtime/syntax/nginx.vim index 18dd50cbb2..04760e4a20 100644 --- a/runtime/syntax/nginx.vim +++ b/runtime/syntax/nginx.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: nginx.conf " Maintainer: Chris Aumann -" Last Change: Apr 15, 2017 +" Last Change: Jan 25, 2023 if exists("b:current_syntax") finish @@ -84,6 +84,8 @@ syn keyword ngxListenOptions default_server contained syn keyword ngxListenOptions ssl contained syn keyword ngxListenOptions http2 contained syn keyword ngxListenOptions spdy contained +syn keyword ngxListenOptions http3 contained +syn keyword ngxListenOptions quic contained syn keyword ngxListenOptions proxy_protocol contained syn keyword ngxListenOptions setfib contained syn keyword ngxListenOptions fastopen contained @@ -265,8 +267,16 @@ syn keyword ngxDirective http2_max_concurrent_streams syn keyword ngxDirective http2_max_field_size syn keyword ngxDirective http2_max_header_size syn keyword ngxDirective http2_max_requests +syn keyword ngxDirective http2_push +syn keyword ngxDirective http2_push_preload syn keyword ngxDirective http2_recv_buffer_size syn keyword ngxDirective http2_recv_timeout +syn keyword ngxDirective http3_hq +syn keyword ngxDirective http3_max_concurrent_pushes +syn keyword ngxDirective http3_max_concurrent_streams +syn keyword ngxDirective http3_push +syn keyword ngxDirective http3_push_preload +syn keyword ngxDirective http3_stream_buffer_size syn keyword ngxDirective if_modified_since syn keyword ngxDirective ignore_invalid_headers syn keyword ngxDirective image_filter @@ -444,6 +454,10 @@ syn keyword ngxDirective proxy_temp_path syn keyword ngxDirective proxy_timeout syn keyword ngxDirective proxy_upload_rate syn keyword ngxDirective queue +syn keyword ngxDirective quic_gso +syn keyword ngxDirective quic_host_key +syn keyword ngxDirective quic_mtu +syn keyword ngxDirective quic_retry syn keyword ngxDirective random_index syn keyword ngxDirective read_ahead syn keyword ngxDirective real_ip_header @@ -545,8 +559,10 @@ syn keyword ngxDirective ssl_certificate syn keyword ngxDirective ssl_certificate_key syn keyword ngxDirective ssl_ciphers syn keyword ngxDirective ssl_client_certificate +syn keyword ngxDirective ssl_conf_command syn keyword ngxDirective ssl_crl syn keyword ngxDirective ssl_dhparam +syn keyword ngxDirective ssl_early_data syn keyword ngxDirective ssl_ecdh_curve syn keyword ngxDirective ssl_engine syn keyword ngxDirective ssl_handshake_timeout @@ -556,6 +572,7 @@ syn keyword ngxSSLPreferServerCiphersOn on contained syn keyword ngxSSLPreferServerCiphersOff off contained syn keyword ngxDirective ssl_preread syn keyword ngxDirective ssl_protocols nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite +syn keyword ngxDirective ssl_reject_handshake syn match ngxSSLProtocol 'TLSv1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite syn match ngxSSLProtocol 'TLSv1\.1' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite syn match ngxSSLProtocol 'TLSv1\.2' contained nextgroup=ngxSSLProtocol,ngxSSLProtocolDeprecated skipwhite @@ -622,6 +639,7 @@ syn keyword ngxDirective uwsgi_buffering syn keyword ngxDirective uwsgi_buffers syn keyword ngxDirective uwsgi_busy_buffers_size syn keyword ngxDirective uwsgi_cache +syn keyword ngxDirective uwsgi_cache_background_update syn keyword ngxDirective uwsgi_cache_bypass syn keyword ngxDirective uwsgi_cache_key syn keyword ngxDirective uwsgi_cache_lock @@ -2225,6 +2243,19 @@ syn keyword ngxDirectiveThirdParty xss_override_status syn keyword ngxDirectiveThirdParty xss_check_status syn keyword ngxDirectiveThirdParty xss_input_types +" CT Module +" Certificate Transparency module for nginx +syn keyword ngxDirectiveThirdParty ssl_ct +syn keyword ngxDirectiveThirdParty ssl_ct_static_scts + +" Dynamic TLS records patch +" TLS Dynamic Record Resizing +syn keyword ngxDirectiveThirdParty ssl_dyn_rec_enable +syn keyword ngxDirectiveThirdParty ssl_dyn_rec_size_hi +syn keyword ngxDirectiveThirdParty ssl_dyn_rec_size_lo +syn keyword ngxDirectiveThirdParty ssl_dyn_rec_threshold +syn keyword ngxDirectiveThirdParty ssl_dyn_rec_timeout + " ZIP Module " ZIP archiver for nginx diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 6722d62c89..13d74dbc17 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,8 +2,8 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell " Previous Maintainer: Lennart Schultz -" Last Change: Nov 25, 2022 -" Version: 204 +" Last Change: Dec 20, 2022 +" Version: 205 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH " For options and settings, please use: :help ft-sh-syntax " This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras @@ -190,8 +190,10 @@ syn region shEmbeddedEcho contained matchgroup=shStatement start="\" ski " ===== if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") syn match shStatement "\" - syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+\)\@=" skip="\\$" end="\>\|`" - syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+=\)\@=" skip="\\$" end="=" + syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*\)\@=" skip="\\$" end="\>\|`" + syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]*=\)\@=" skip="\\$" end="=" +" syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+\)\@=" skip="\\$" end="\>\|`" +" syn region shAlias matchgroup=shStatement start="\\s\+\(\h[-._[:alnum:]]\+=\)\@=" skip="\\$" end="=" " Touch: {{{1 " ===== @@ -333,7 +335,7 @@ syn match shEscape contained '\%(^\)\@!\%(\\\\\)*\\.' nextgroup=shComment " systems too, however, so the following syntax will flag $(..) as " an Error under /bin/sh. By consensus of vimdev'ers! if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") - syn region shCommandSub matchgroup=shCmdSubRegion start="\$(\ze[^(]" skip='\\\\\|\\.' end=")" contains=@shCommandSubList + syn region shCommandSub matchgroup=shCmdSubRegion start="\$(\ze[^(]\|$" skip='\\\\\|\\.' end=")" contains=@shCommandSubList syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList syn match shSkipInitWS contained "^\s\+" @@ -483,7 +485,9 @@ endif " Parameter Dereferencing: {{{1 " ======================== -if !exists("g:sh_no_error") && !(exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")) +" Note: sh04 failure with following line +"if !exists("g:sh_no_error") && !(exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix")) +if !exists("g:sh_no_error") syn match shDerefWordError "[^}$[~]" contained endif syn match shDerefSimple "\$\%(\h\w*\|\d\)" nextgroup=@shNoZSList diff --git a/runtime/syntax/shared/README.txt b/runtime/syntax/shared/README.txt index f519d44faf..fade4b38a1 100644 --- a/runtime/syntax/shared/README.txt +++ b/runtime/syntax/shared/README.txt @@ -1,2 +1,2 @@ This directory "runtime/syntax/shared" contains Vim script files that are -generated or used by more then one syntax file. +generated or used by more than one syntax file. diff --git a/runtime/syntax/tpp.vim b/runtime/syntax/tpp.vim index ca64b5dce1..e2b307b2a2 100644 --- a/runtime/syntax/tpp.vim +++ b/runtime/syntax/tpp.vim @@ -2,8 +2,8 @@ " Language: tpp - Text Presentation Program " Maintainer: Debian Vim Maintainers " Former Maintainer: Gerfried Fuchs -" Last Change: 2018 Dec 27 -" URL: https://salsa.debian.org/vim-team/vim-debian/master/syntax/tpp.vim +" Last Change: 2023 Jan 16 +" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/tpp.vim " Filenames: *.tpp " License: BSD " diff --git a/runtime/syntax/xf86conf.vim b/runtime/syntax/xf86conf.vim index 545eda7db0..e8162f3a35 100644 --- a/runtime/syntax/xf86conf.vim +++ b/runtime/syntax/xf86conf.vim @@ -1,13 +1,12 @@ " Vim syntax file -" This is a GENERATED FILE. Please always refer to source file at the URI below. " Language: XF86Config (XFree86 configuration file) " Former Maintainer: David Ne\v{c}as (Yeti) -" Last Change: 2010 Nov 01 -" URL: http://trific.ath.cx/Ftp/vim/syntax/xf86conf.vim +" Last Change By David: 2010 Nov 01 +" Last Change: 2023 Jan 23 " Required Vim Version: 6.0 " " Options: let xf86conf_xfree86_version = 3 or 4 -" to force XFree86 3.x or 4.x XF86Config syntax +" to force XFree86 3.x or 4.x XF86Config syntax " Setup " quit when a syntax file was already loaded @@ -147,6 +146,8 @@ syn keyword xf86confKeyword Hskew HTimings InputDevice IOBase MemBase Mode nextg syn keyword xf86confKeyword Modes Ramdac Screen TextClockFreq UseModes VendorName nextgroup=xf86confComment,xf86confValue syn keyword xf86confKeyword VertRefresh VideoRam ViewPort Virtual VScan VTimings nextgroup=xf86confComment,xf86confValue syn keyword xf86confKeyword Weight White nextgroup=xf86confComment,xf86confValue +syn keyword xf86confMatch MatchDevicePath MatchDriver MatchLayout MatchOS MatchPnPID MatchProduct MatchTag MatchUSBID MatchVendor nextgroup=xf86confComment,xf86confString skipwhite +syn keyword xf86confMatch MatchIsPointer MatchIsKeyboard MatchIsTouchpad MatchIsTouchscreen MatchIsJoystick nextgroup=xf86confComment,xf86confValue skipwhite syn keyword xf86confModeLine ModeLine nextgroup=xf86confComment,xf86confModeLineValue skipwhite skipnl " Constants @@ -185,6 +186,7 @@ hi def link xf86confOctalNumberError xf86confError hi def link xf86confError Error hi def link xf86confOption xf86confKeyword +hi def link xf86confMatch xf86confKeyword hi def link xf86confModeLine xf86confKeyword hi def link xf86confKeyword Type -- cgit From 9a5678463c96baf3b39cb3083ddf0da87d39aa23 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 4 Feb 2023 14:58:38 +0000 Subject: fix(treesitter): fix most diagnostics --- runtime/doc/lua.txt | 3 +- runtime/doc/treesitter.txt | 188 ++++++++++++++-------------- runtime/lua/vim/treesitter.lua | 73 ++++++----- runtime/lua/vim/treesitter/_meta.lua | 60 +++++++++ runtime/lua/vim/treesitter/highlighter.lua | 50 +++++++- runtime/lua/vim/treesitter/languagetree.lua | 128 +++++++++++++------ runtime/lua/vim/treesitter/playground.lua | 36 +++--- runtime/lua/vim/treesitter/query.lua | 109 +++++++++++----- 8 files changed, 429 insertions(+), 218 deletions(-) create mode 100644 runtime/lua/vim/treesitter/_meta.lua (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 47249a484b..0472c11a15 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1362,7 +1362,8 @@ defer_fn({fn}, {timeout}) *vim.defer_fn()* Parameters: ~ • {fn} (function) Callback to call once `timeout` expires - • {timeout} integer Number of milliseconds to wait before calling `fn` + • {timeout} (integer) Number of milliseconds to wait before calling + `fn` Return: ~ (table) timer luv timer object diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 9bfdc0b94e..7bc9f3f9a7 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -66,102 +66,102 @@ See |lua-treesitter-languagetree| for the list of available methods. ============================================================================== TREESITTER TREES *treesitter-tree* - *tstree* + *TSTree* A "treesitter tree" represents the parsed contents of a buffer, which can be used to perform further analysis. It is a |luaref-userdata| reference to an object held by the tree-sitter library. -An instance `tstree` of a treesitter tree supports the following methods. +An instance `TSTree` of a treesitter tree supports the following methods. -tstree:root() *tstree:root()* +TSTree:root() *TSTree:root()* Return the root node of this tree. -tstree:copy() *tstree:copy()* - Returns a copy of the `tstree`. +TSTree:copy() *TSTree:copy()* + Returns a copy of the `TSTree`. ============================================================================== TREESITTER NODES *treesitter-node* - *tsnode* + *TSNode* A "treesitter node" represents one specific element of the parsed contents of a buffer, which can be captured by a |Query| for, e.g., highlighting. It is a |luaref-userdata| reference to an object held by the tree-sitter library. -An instance `tsnode` of a treesitter node supports the following methods. +An instance `TSNode` of a treesitter node supports the following methods. -tsnode:parent() *tsnode:parent()* +TSNode:parent() *TSNode:parent()* Get the node's immediate parent. -tsnode:next_sibling() *tsnode:next_sibling()* +TSNode:next_sibling() *TSNode:next_sibling()* Get the node's next sibling. -tsnode:prev_sibling() *tsnode:prev_sibling()* +TSNode:prev_sibling() *TSNode:prev_sibling()* Get the node's previous sibling. -tsnode:next_named_sibling() *tsnode:next_named_sibling()* +TSNode:next_named_sibling() *TSNode:next_named_sibling()* Get the node's next named sibling. -tsnode:prev_named_sibling() *tsnode:prev_named_sibling()* +TSNode:prev_named_sibling() *TSNode:prev_named_sibling()* Get the node's previous named sibling. -tsnode:iter_children() *tsnode:iter_children()* - Iterates over all the direct children of {tsnode}, regardless of whether +TSNode:iter_children() *TSNode:iter_children()* + Iterates over all the direct children of {TSNode}, regardless of whether they are named or not. Returns the child node plus the eventual field name corresponding to this child node. -tsnode:field({name}) *tsnode:field()* +TSNode:field({name}) *TSNode:field()* Returns a table of the nodes corresponding to the {name} field. -tsnode:child_count() *tsnode:child_count()* +TSNode:child_count() *TSNode:child_count()* Get the node's number of children. -tsnode:child({index}) *tsnode:child()* +TSNode:child({index}) *TSNode:child()* Get the node's child at the given {index}, where zero represents the first child. -tsnode:named_child_count() *tsnode:named_child_count()* +TSNode:named_child_count() *TSNode:named_child_count()* Get the node's number of named children. -tsnode:named_child({index}) *tsnode:named_child()* +TSNode:named_child({index}) *TSNode:named_child()* Get the node's named child at the given {index}, where zero represents the first named child. -tsnode:start() *tsnode:start()* +TSNode:start() *TSNode:start()* Get the node's start position. Return three values: the row, column and total byte count (all zero-based). -tsnode:end_() *tsnode:end_()* +TSNode:end_() *TSNode:end_()* Get the node's end position. Return three values: the row, column and total byte count (all zero-based). -tsnode:range() *tsnode:range()* +TSNode:range() *TSNode:range()* Get the range of the node. Return four values: the row, column of the start position, then the row, column of the end position. -tsnode:type() *tsnode:type()* +TSNode:type() *TSNode:type()* Get the node's type as a string. -tsnode:symbol() *tsnode:symbol()* +TSNode:symbol() *TSNode:symbol()* Get the node's type as a numerical id. -tsnode:named() *tsnode:named()* +TSNode:named() *TSNode:named()* Check if the node is named. Named nodes correspond to named rules in the grammar, whereas anonymous nodes correspond to string literals in the grammar. -tsnode:missing() *tsnode:missing()* +TSNode:missing() *TSNode:missing()* Check if the node is missing. Missing nodes are inserted by the parser in order to recover from certain kinds of syntax errors. -tsnode:has_error() *tsnode:has_error()* +TSNode:has_error() *TSNode:has_error()* Check if the node is a syntax error or contains any syntax errors. -tsnode:sexpr() *tsnode:sexpr()* +TSNode:sexpr() *TSNode:sexpr()* Get an S-expression representing the node as a string. -tsnode:id() *tsnode:id()* +TSNode:id() *TSNode:id()* Get an unique identifier for the node inside its own tree. No guarantees are made about this identifier's internal representation, @@ -171,20 +171,20 @@ tsnode:id() *tsnode:id()* Note: The `id` is not guaranteed to be unique for nodes from different trees. - *tsnode:descendant_for_range()* -tsnode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) + *TSNode:descendant_for_range()* +TSNode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest node within this node that spans the given range of (row, column) positions - *tsnode:named_descendant_for_range()* -tsnode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) + *TSNode:named_descendant_for_range()* +TSNode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest named node within this node that spans the given range of (row, column) positions ============================================================================== TREESITTER QUERIES *treesitter-query* -Treesitter queries are a way to extract information about a parsed |tstree|, +Treesitter queries are a way to extract information about a parsed |TSTree|, e.g., for the purpose of highlighting. Briefly, a `query` consists of one or more patterns. A `pattern` is defined over node types in the syntax tree. A `match` corresponds to specific elements of the syntax tree which match a @@ -336,7 +336,7 @@ repeated, for example, the following two modeline blocks are both valid: > TREESITTER SYNTAX HIGHLIGHTING *treesitter-highlight* Syntax highlighting is specified through queries named `highlights.scm`, -which match a |tsnode| in the parsed |tstree| to a `capture` that can be +which match a |TSNode| in the parsed |TSTree| to a `capture` that can be assigned a highlight group. For example, the query > (parameters (identifier) @parameter) @@ -486,7 +486,7 @@ get_captures_at_cursor({winnr}) Returns a list of highlight capture names under the cursor Parameters: ~ - • {winnr} (number|nil) Window handle or 0 for current window (default) + • {winnr} (integer|nil) Window handle or 0 for current window (default) Return: ~ string[] List of capture names @@ -500,9 +500,9 @@ get_captures_at_pos({bufnr}, {row}, {col}) if none are defined). Parameters: ~ - • {bufnr} (number) Buffer number (0 for current buffer) - • {row} (number) Position row - • {col} (number) Position column + • {bufnr} (integer) Buffer number (0 for current buffer) + • {row} (integer) Position row + • {col} (integer) Position column Return: ~ table[] List of captures `{ capture = "capture name", metadata = { ... @@ -512,7 +512,7 @@ get_node_at_cursor({winnr}) *vim.treesitter.get_node_at_cursor()* Returns the smallest named node under the cursor Parameters: ~ - • {winnr} (number|nil) Window handle or 0 for current window (default) + • {winnr} (integer|nil) Window handle or 0 for current window (default) Return: ~ (string) Name of node under the cursor @@ -522,25 +522,28 @@ get_node_at_pos({bufnr}, {row}, {col}, {opts}) Returns the smallest named node at the given position Parameters: ~ - • {bufnr} (number) Buffer number (0 for current buffer) - • {row} (number) Position row - • {col} (number) Position column + • {bufnr} (integer) Buffer number (0 for current buffer) + • {row} (integer) Position row + • {col} (integer) Position column • {opts} (table) Optional keyword arguments: • lang string|nil Parser language • ignore_injections boolean Ignore injected languages (default true) Return: ~ - userdata|nil |tsnode| under the cursor + |TSNode||nil under the cursor get_node_range({node_or_range}) *vim.treesitter.get_node_range()* Returns the node's range or an unpacked range table Parameters: ~ - • {node_or_range} (userdata|table) |tsnode| or table of positions + • {node_or_range} (|TSNode||table) Node or table of positions Return: ~ - (table) `{ start_row, start_col, end_row, end_col }` + (integer) start_row + (integer) start_col + (integer) end_row + (integer) end_col get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()* Returns the parser for a specific buffer and filetype and attaches it to @@ -549,14 +552,14 @@ get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()* If needed, this will create the parser. Parameters: ~ - • {bufnr} (number|nil) Buffer the parser should be tied to (default: + • {bufnr} (integer|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: ~ - LanguageTree |LanguageTree| object to use for parsing + |LanguageTree| object to use for parsing *vim.treesitter.get_string_parser()* get_string_parser({str}, {lang}, {opts}) @@ -568,14 +571,14 @@ get_string_parser({str}, {lang}, {opts}) • {opts} (table|nil) Options to pass to the created language tree Return: ~ - LanguageTree |LanguageTree| object to use for parsing + |LanguageTree| object to use for parsing is_ancestor({dest}, {source}) *vim.treesitter.is_ancestor()* Determines whether a node is the ancestor of another Parameters: ~ - • {dest} userdata Possible ancestor |tsnode| - • {source} userdata Possible descendant |tsnode| + • {dest} |TSNode| Possible ancestor + • {source} |TSNode| Possible descendant Return: ~ (boolean) True if {dest} is an ancestor of {source} @@ -585,9 +588,9 @@ is_in_node_range({node}, {line}, {col}) Determines whether (line, col) position is in node range Parameters: ~ - • {node} userdata |tsnode| defining the range - • {line} (number) Line (0-based) - • {col} (number) Column (0-based) + • {node} |TSNode| defining the range + • {line} (integer) Line (0-based) + • {col} (integer) Column (0-based) Return: ~ (boolean) True if the position is in node range @@ -596,7 +599,7 @@ node_contains({node}, {range}) *vim.treesitter.node_contains()* Determines if a node contains a range Parameters: ~ - • {node} userdata |tsnode| + • {node} |TSNode| • {range} (table) Return: ~ @@ -615,14 +618,14 @@ show_tree({opts}) *vim.treesitter.show_tree()* keys: • lang (string|nil): The language of the source buffer. If omitted, the filetype of the source buffer is used. - • bufnr (number|nil): Buffer to draw the tree into. If + • bufnr (integer|nil): Buffer to draw the tree into. If omitted, a new buffer is created. - • winid (number|nil): Window id to display the tree buffer in. - If omitted, a new window is created with {command}. + • winid (integer|nil): Window id to display the tree buffer + in. If omitted, a new window is created with {command}. • command (string|nil): Vimscript command to create the window. Default value is "topleft 60vnew". Only used when {winid} is nil. - • title (string|fun(bufnr:number):string|nil): Title of the + • title (string|fun(bufnr:integer):string|nil): Title of the window. If a function, it accepts the buffer number of the source buffer as its only argument and should return a string. @@ -647,7 +650,7 @@ start({bufnr}, {lang}) *vim.treesitter.start()* < Parameters: ~ - • {bufnr} (number|nil) Buffer to be highlighted (default: current + • {bufnr} (integer|nil) Buffer to be highlighted (default: current buffer) • {lang} (string|nil) Language of the parser (default: buffer filetype) @@ -656,7 +659,7 @@ stop({bufnr}) *vim.treesitter.stop()* Stops treesitter highlighting for a buffer Parameters: ~ - • {bufnr} (number|nil) Buffer to stop highlighting (default: current + • {bufnr} (integer|nil) Buffer to stop highlighting (default: current buffer) @@ -709,8 +712,8 @@ add_directive({name}, {handler}, {force}) Parameters: ~ • {name} (string) Name of the directive, without leading # - • {handler} function(match:table, pattern:string, bufnr:number, - predicate:string[], metadata:table) + • {handler} function(match:table, pattern:string, + bufnr:number, predicate:string[], metadata:table) • match: see |treesitter-query| • node-level data are accessible via `match[capture_id]` @@ -718,6 +721,7 @@ add_directive({name}, {handler}, {force}) • predicate: list of strings containing the full directive being called, e.g. `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` + • {force} (boolean) *vim.treesitter.query.add_predicate()* add_predicate({name}, {handler}, {force}) @@ -725,17 +729,18 @@ add_predicate({name}, {handler}, {force}) Parameters: ~ • {name} (string) Name of the predicate, without leading # - • {handler} function(match:table, pattern:string, bufnr:number, - predicate:string[]) + • {handler} function(match:table, pattern:string, + bufnr:number, predicate:string[]) • see |vim.treesitter.query.add_directive()| for argument meanings + • {force} (boolean) *vim.treesitter.query.get_node_text()* get_node_text({node}, {source}, {opts}) Gets the text corresponding to a given node Parameters: ~ - • {node} userdata |tsnode| + • {node} |TSNode| • {source} (number|string) Buffer or string from which the {node} is extracted • {opts} (table|nil) Optional parameters. @@ -743,7 +748,7 @@ get_node_text({node}, {source}, {opts}) true) Return: ~ - (string[]|string) + (string[]|string|nil) get_query({lang}, {query_name}) *vim.treesitter.query.get_query()* Returns the runtime query {query_name} for {lang}. @@ -753,7 +758,7 @@ get_query({lang}, {query_name}) *vim.treesitter.query.get_query()* • {query_name} (string) Name of the query (e.g. "highlights") Return: ~ - Query Parsed query + Query|nil Parsed query *vim.treesitter.query.get_query_files()* get_query_files({lang}, {query_name}, {is_included}) @@ -826,16 +831,15 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop}) < Parameters: ~ - • {node} userdata |tsnode| under which the search will occur - • {source} (number|string) Source buffer or string to extract text from + • {node} |TSNode| under which the search will occur + • {source} (integer|string) Source buffer or string to extract text + from • {start} (number) Starting line for the search • {stop} (number) Stopping line for the search (end-exclusive) • {self} Return: ~ - (number) capture Matching capture id - (table) capture_node Capture for {node} - (table) metadata for the {capture} + (fun(): integer, TSNode, TSMetadata ): capture id, capture node, metadata *Query:iter_matches()* Query:iter_matches({self}, {node}, {source}, {start}, {stop}) @@ -861,16 +865,15 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) < Parameters: ~ - • {node} userdata |tsnode| under which the search will occur - • {source} (number|string) Source buffer or string to search - • {start} (number) Starting line for the search - • {stop} (number) Stopping line for the search (end-exclusive) + • {node} |TSNode| under which the search will occur + • {source} (integer|string) Source buffer or string to search + • {start} (integer) Starting line for the search + • {stop} (integer) Stopping line for the search (end-exclusive) • {self} Return: ~ - (number) pattern id - (table) match - (table) metadata + (fun(): integer, table, table): pattern id, match, + metadata *vim.treesitter.query.set_query()* set_query({lang}, {query_name}, {text}) @@ -892,7 +895,7 @@ new({tree}, {opts}) *vim.treesitter.highlighter.new()* Creates a new highlighter using Parameters: ~ - • {tree} LanguageTree |LanguageTree| parser object to use for highlighting + • {tree} |LanguageTree| parser object to use for highlighting • {opts} (table|nil) Configuration of the highlighter: • queries table overwrite queries used by the highlighter @@ -940,9 +943,9 @@ LanguageTree:for_each_child({self}, {fn}, {include_self}) Invokes the callback for each |LanguageTree| and its children recursively Parameters: ~ - • {fn} function(tree: LanguageTree, lang: string) - • {include_self} (boolean) Whether to include the invoking tree in the - results + • {fn} fun(tree: LanguageTree, lang: string) + • {include_self} (boolean|nil) Whether to include the invoking tree in + the results • {self} LanguageTree:for_each_tree({self}, {fn}) *LanguageTree:for_each_tree()* @@ -951,7 +954,7 @@ LanguageTree:for_each_tree({self}, {fn}) *LanguageTree:for_each_tree()* Note: This includes the invoking tree's child trees as well. Parameters: ~ - • {fn} function(tree: TSTree, languageTree: LanguageTree) + • {fn} fun(tree: TSTree, ltree: LanguageTree) • {self} LanguageTree:included_regions({self}) *LanguageTree:included_regions()* @@ -964,6 +967,7 @@ LanguageTree:invalidate({self}, {reload}) *LanguageTree:invalidate()* Invalidates this parser and all its children Parameters: ~ + • {reload} (boolean|nil) • {self} LanguageTree:is_valid({self}) *LanguageTree:is_valid()* @@ -987,7 +991,7 @@ LanguageTree:language_for_range({self}, {range}) • {self} Return: ~ - LanguageTree Managing {range} + |LanguageTree| Managing {range} *LanguageTree:named_node_for_range()* LanguageTree:named_node_for_range({self}, {range}, {opts}) @@ -1001,7 +1005,7 @@ LanguageTree:named_node_for_range({self}, {range}, {opts}) • {self} Return: ~ - userdata|nil Found |tsnode| + |TSNode||nil Found node LanguageTree:parse({self}) *LanguageTree:parse()* Parses all defined regions using a treesitter parser for the language this @@ -1012,8 +1016,8 @@ LanguageTree:parse({self}) *LanguageTree:parse()* • {self} Return: ~ - userdata[] Table of parsed |tstree| - (table) Change list + TSTree[] + (table|nil) Change list LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* Registers callbacks for the |LanguageTree|. @@ -1050,7 +1054,7 @@ LanguageTree:tree_for_range({self}, {range}, {opts}) • {self} Return: ~ - userdata|nil Contained |tstree| + TSTree|nil LanguageTree:trees({self}) *LanguageTree:trees()* Returns all trees this language tree contains. Does not include child @@ -1065,7 +1069,7 @@ new({source}, {lang}, {opts}) *vim.treesitter.languagetree.new()* may contain child languages themselves, hence the name). Parameters: ~ - • {source} (number|string) Buffer or a string of text to parse + • {source} (integer|string) Buffer or a string of text to parse • {lang} (string) Root language this tree represents • {opts} (table|nil) Optional keyword arguments: • injections table Mapping language to injection query @@ -1074,6 +1078,6 @@ new({source}, {lang}, {opts}) *vim.treesitter.languagetree.new()* per language. Return: ~ - LanguageTree |LanguageTree| parser object + |LanguageTree| parser object vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 582922ecb6..96b1e24ba9 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -3,8 +3,11 @@ local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') +---@type table local parsers = setmetatable({}, { __mode = 'v' }) +---@class TreesitterModule +---@field highlighter TSHighlighter local M = vim.tbl_extend('error', query, language) M.language_version = vim._ts_get_language_version() @@ -12,6 +15,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version() setmetatable(M, { __index = function(t, k) + ---@diagnostic disable:no-unknown if k == 'highlighter' then t[k] = require('vim.treesitter.highlighter') return t[k] @@ -29,21 +33,23 @@ setmetatable(M, { --- --- It is not recommended to use this; use |get_parser()| instead. --- ----@param bufnr string Buffer the parser will be tied to (0 for current buffer) +---@param bufnr integer 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 --- ----@return LanguageTree |LanguageTree| object to use for parsing +---@return LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then - bufnr = a.nvim_get_current_buf() + bufnr = vim.api.nvim_get_current_buf() end vim.fn.bufload(bufnr) local self = LanguageTree.new(bufnr, lang, opts) + ---@diagnostic disable:invisible + ---@private local function bytes_cb(_, ...) self:_on_bytes(...) @@ -58,12 +64,14 @@ function M._create_parser(bufnr, lang, opts) end ---@private - local function reload_cb(_, ...) - self:_on_reload(...) + local function reload_cb(_) + self:_on_reload() end + local source = self:source() --[[@as integer]] + a.nvim_buf_attach( - self:source(), + source, false, { on_bytes = bytes_cb, on_detach = detach_cb, on_reload = reload_cb, preview = true } ) @@ -77,11 +85,11 @@ end --- --- If needed, this will create the parser. --- ----@param bufnr (number|nil) Buffer the parser should be tied to (default: current buffer) +---@param bufnr (integer|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 --- ----@return LanguageTree |LanguageTree| object to use for parsing +---@return LanguageTree object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -107,7 +115,7 @@ end ---@param lang string Language of this string ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree |LanguageTree| object to use for parsing +---@return LanguageTree object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -120,8 +128,8 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest userdata Possible ancestor |tsnode| ----@param source userdata Possible descendant |tsnode| +---@param dest TSNode Possible ancestor +---@param source TSNode Possible descendant --- ---@return boolean True if {dest} is an ancestor of {source} function M.is_ancestor(dest, source) @@ -143,9 +151,12 @@ end --- Returns the node's range or an unpacked range table --- ----@param node_or_range (userdata|table) |tsnode| or table of positions +---@param node_or_range (TSNode|table) Node or table of positions --- ----@return table `{ start_row, start_col, end_row, end_col }` +---@return integer start_row +---@return integer start_col +---@return integer end_row +---@return integer end_col function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -156,9 +167,9 @@ end --- Determines whether (line, col) position is in node range --- ----@param node userdata |tsnode| defining the range ----@param line number Line (0-based) ----@param col number Column (0-based) +---@param node TSNode defining the range +---@param line integer Line (0-based) +---@param col integer Column (0-based) --- ---@return boolean True if the position is in node range function M.is_in_node_range(node, line, col) @@ -180,7 +191,7 @@ end --- Determines if a node contains a range --- ----@param node userdata |tsnode| +---@param node TSNode ---@param range table --- ---@return boolean True if the {node} contains the {range} @@ -197,9 +208,9 @@ end --- Each capture is represented by a table containing the capture name as a string as --- well as a table of metadata (`priority`, `conceal`, ...; empty if none are defined). --- ----@param bufnr number Buffer number (0 for current buffer) ----@param row number Position row ----@param col number Position column +---@param bufnr integer Buffer number (0 for current buffer) +---@param row integer Position row +---@param col integer Position column --- ---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` function M.get_captures_at_pos(bufnr, row, col) @@ -250,7 +261,7 @@ end --- Returns a list of highlight capture names under the cursor --- ----@param winnr (number|nil) Window handle or 0 for current window (default) +---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string[] List of capture names function M.get_captures_at_cursor(winnr) @@ -271,14 +282,14 @@ end --- Returns the smallest named node at the given position --- ----@param bufnr number Buffer number (0 for current buffer) ----@param row number Position row ----@param col number Position column +---@param bufnr integer Buffer number (0 for current buffer) +---@param row integer Position row +---@param col integer Position column ---@param opts table Optional keyword arguments: --- - lang string|nil Parser language --- - ignore_injections boolean Ignore injected languages (default true) --- ----@return userdata|nil |tsnode| under the cursor +---@return TSNode|nil under the cursor function M.get_node_at_pos(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -295,7 +306,7 @@ end --- Returns the smallest named node under the cursor --- ----@param winnr (number|nil) Window handle or 0 for current window (default) +---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string Name of node under the cursor function M.get_node_at_cursor(winnr) @@ -323,7 +334,7 @@ end --- }) --- --- ----@param bufnr (number|nil) Buffer to be highlighted (default: current buffer) +---@param bufnr (integer|nil) Buffer to be highlighted (default: current buffer) ---@param lang (string|nil) Language of the parser (default: buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() @@ -333,7 +344,7 @@ end --- Stops treesitter highlighting for a buffer --- ----@param bufnr (number|nil) Buffer to stop highlighting (default: current buffer) +---@param bufnr (integer|nil) Buffer to stop highlighting (default: current buffer) function M.stop(bufnr) bufnr = bufnr or a.nvim_get_current_buf() @@ -351,13 +362,13 @@ end ---@param opts table|nil Optional options table with the following possible keys: --- - lang (string|nil): The language of the source buffer. If omitted, the --- filetype of the source buffer is used. ---- - bufnr (number|nil): Buffer to draw the tree into. If omitted, a new +--- - bufnr (integer|nil): Buffer to draw the tree into. If omitted, a new --- buffer is created. ---- - winid (number|nil): Window id to display the tree buffer in. If omitted, +--- - winid (integer|nil): Window id to display the tree buffer in. If omitted, --- a new window is created with {command}. --- - command (string|nil): Vimscript command to create the window. Default --- value is "topleft 60vnew". Only used when {winid} is nil. ---- - title (string|fun(bufnr:number):string|nil): Title of the window. If a +--- - title (string|fun(bufnr:integer):string|nil): Title of the window. If a --- function, it accepts the buffer number of the source buffer as its only --- argument and should return a string. function M.show_tree(opts) diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua new file mode 100644 index 0000000000..87b4560798 --- /dev/null +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -0,0 +1,60 @@ +---@meta + +---@class TSNode +---@field id fun(self: TSNode): integer +---@field range fun(self: TSNode): integer, integer, integer, integer +---@field start fun(self: TSNode): integer, integer, integer +---@field end_ fun(self: TSNode): integer, integer, integer +---@field type fun(self: TSNode): string +---@field symbol fun(self: TSNode): integer +---@field named fun(self: TSNode): boolean +---@field missing fun(self: TSNode): boolean +---@field child_count fun(self: TSNode): integer +---@field named_child_count fun(self: TSNode): integer +---@field child fun(self: TSNode, integer): TSNode +---@field name_child fun(self: TSNode, integer): TSNode +---@field descendant_for_range fun(self: TSNode, integer, integer, integer, integer): TSNode +---@field named_descendant_for_range fun(self: TSNode, integer, integer, integer, integer): TSNode +---@field parent fun(self: TSNode): TSNode +---@field next_sibling fun(self: TSNode): TSNode +---@field prev_sibling fun(self: TSNode): TSNode +---@field next_named_sibling fun(self: TSNode): TSNode +---@field prev_named_sibling fun(self: TSNode): TSNode +---@field named_children fun(self: TSNode): TSNode[] +---@field has_error fun(self: TSNode): boolean +---@field iter_children fun(self: TSNode): fun(): TSNode, string +local TSNode = {} + +---@param query userdata +---@param captures true +---@param start integer +---@param end_ integer +---@return fun(): integer, TSNode, any +function TSNode:_rawquery(query, captures, start, end_) end + +---@param query userdata +---@param captures false +---@param start integer +---@param end_ integer +---@return fun(): string, any +function TSNode:_rawquery(query, captures, start, end_) end + +---@class TSParser +---@field parse fun(self: TSParser, tree, source: integer|string): TSTree, integer[] +---@field included_ranges fun(self: TSParser): integer[] +---@field set_included_ranges fun(self: TSParser, ranges: integer[][]) + +---@class TSTree +---@field root fun(self: TSTree): TSNode +---@field edit fun(self: TSTree, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _:integer) +---@field copy fun(self: TSTree): TSTree + +---@return integer +vim._ts_get_language_version = function() end + +---@return integer +vim._ts_get_minimum_language_version = function() end + +---@param lang string +---@return TSParser +vim._create_ts_parser = function(lang) end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index d77a0d0d03..8adaa4ef2f 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -1,13 +1,27 @@ local a = vim.api local query = require('vim.treesitter.query') --- support reload for quick experimentation +---@alias TSHlIter fun(): integer, TSNode, TSMetadata + +---@class TSHighlightState +---@field next_row integer +---@field iter TSHlIter|nil + ---@class TSHighlighter +---@field active table +---@field bufnr integer +---@field orig_spelloptions string +---@field _highlight_states table +---@field _queries table +---@field tree LanguageTree local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} TSHighlighter.__index = TSHighlighter TSHighlighter.active = TSHighlighter.active or {} +---@class TSHighlighterQuery +---@field _query Query|nil +---@field hl_cache table local TSHighlighterQuery = {} TSHighlighterQuery.__index = TSHighlighterQuery @@ -46,7 +60,7 @@ end --- Creates a new highlighter using @param tree --- ----@param tree LanguageTree |LanguageTree| parser object to use for highlighting +---@param tree LanguageTree parser object to use for highlighting ---@param opts (table|nil) Configuration of the highlighter: --- - queries table overwrite queries used by the highlighter ---@return TSHighlighter Created highlighter object @@ -57,9 +71,10 @@ function TSHighlighter.new(tree, opts) error('TSHighlighter can not be used with a string parser source.') end - opts = opts or {} + opts = opts or {} ---@type { queries: table } self.tree = tree tree:register_cbs({ + ---@diagnostic disable:invisible on_changedtree = function(...) self:on_changedtree(...) end, @@ -67,17 +82,20 @@ function TSHighlighter.new(tree, opts) self:on_bytes(...) end, on_detach = function(...) + ---@diagnostic disable-next-line:redundant-parameter self:on_detach(...) end, }) - self.bufnr = tree:source() + self.bufnr = tree:source() --[[@as integer]] self.edit_count = 0 self.redraw_count = 0 self.line_count = {} -- A map of highlight states. -- This state is kept during rendering across each line update. self._highlight_states = {} + + ---@type table self._queries = {} -- Queries for a specific language can be overridden by a custom @@ -128,6 +146,8 @@ function TSHighlighter:destroy() end ---@private +---@param tstree TSTree +---@return TSHighlightState function TSHighlighter:get_highlight_state(tstree) if not self._highlight_states[tstree] then self._highlight_states[tstree] = { @@ -145,6 +165,8 @@ function TSHighlighter:reset_highlight_state() end ---@private +---@param start_row integer +---@param new_end integer function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) a.nvim__buf_redraw_range(self.bufnr, start_row, start_row + new_end + 1) end @@ -155,6 +177,7 @@ function TSHighlighter:on_detach() end ---@private +---@param changes integer[][]? function TSHighlighter:on_changedtree(changes) for _, ch in ipairs(changes or {}) do a.nvim__buf_redraw_range(self.bufnr, ch[1], ch[3] + 1) @@ -165,7 +188,7 @@ end -- ---@private ---@param lang string Language used by the highlighter. ----@return Query +---@return TSHighlighterQuery function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) @@ -175,7 +198,12 @@ function TSHighlighter:get_query(lang) end ---@private +---@param self TSHighlighter +---@param buf integer +---@param line integer +---@param is_spell_nav boolean local function on_line_impl(self, buf, line, is_spell_nav) + ---@diagnostic disable:invisible self.tree:for_each_tree(function(tstree, tree) if not tstree then return @@ -213,7 +241,7 @@ local function on_line_impl(self, buf, line, is_spell_nav) local hl = highlighter_query.hl_cache[capture] local capture_name = highlighter_query:query().captures[capture] - local spell = nil + local spell = nil ---@type boolean? if capture_name == 'spell' then spell = true elseif capture_name == 'nospell' then @@ -242,6 +270,9 @@ local function on_line_impl(self, buf, line, is_spell_nav) end ---@private +---@param _win integer +---@param buf integer +---@param line integer function TSHighlighter._on_line(_, _win, buf, line, _) local self = TSHighlighter.active[buf] if not self then @@ -252,6 +283,9 @@ function TSHighlighter._on_line(_, _win, buf, line, _) end ---@private +---@param buf integer +---@param srow integer +---@param erow integer function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _) local self = TSHighlighter.active[buf] if not self then @@ -266,6 +300,7 @@ function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _) end ---@private +---@param buf integer function TSHighlighter._on_buf(_, buf) local self = TSHighlighter.active[buf] if self then @@ -274,6 +309,9 @@ function TSHighlighter._on_buf(_, buf) end ---@private +---@param _win integer +---@param buf integer +---@param _topline integer function TSHighlighter._on_win(_, _win, buf, _topline) local self = TSHighlighter.active[buf] if not self then diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index a1e96f8ef2..89aac3ae26 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -2,20 +2,39 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') ----@class LanguageTree ----@field _callbacks function[] Callback handlers ----@field _children LanguageTree[] Injected languages ----@field _injection_query table Queries defining injected languages ----@field _opts table Options ----@field _parser userdata Parser for language ----@field _regions table List of regions this tree should manage and parse ----@field _lang string Language name ----@field _regions table ----@field _source (number|string) Buffer or string to parse ----@field _trees userdata[] Reference to parsed |tstree| (one for each language) ----@field _valid boolean If the parsed tree is valid +---@alias Range {[1]: integer, [2]: integer, [3]: integer, [4]: integer} +-- +---@alias TSCallbackName +---| 'changedtree' +---| 'bytes' +---| 'detach' +---| 'child_added' +---| 'child_removed' + +---@alias TSCallbackNameOn +---| 'on_changedtree' +---| 'on_bytes' +---| 'on_detach' +---| 'on_child_added' +---| 'on_child_removed' +---@class LanguageTree +---@field private _callbacks table Callback handlers +---@field private _children table Injected languages +---@field private _injection_query Query Queries defining injected languages +---@field private _opts table Options +---@field private _parser TSParser Parser for language +---@field private _regions Range[][] List of regions this tree should manage and parse +---@field private _lang string Language name +---@field private _source (integer|string) Buffer or string to parse +---@field private _trees TSTree[] Reference to parsed tree (one for each language) +---@field private _valid boolean If the parsed tree is valid local LanguageTree = {} + +---@class LanguageTreeOpts +---@field queries table -- Deprecated +---@field injections table + LanguageTree.__index = LanguageTree --- A |LanguageTree| holds the treesitter parser for a given language {lang} used @@ -23,16 +42,17 @@ LanguageTree.__index = LanguageTree --- needs to store parsers for these child languages as well (which in turn may contain --- child languages themselves, hence the name). --- ----@param source (number|string) Buffer or a string of text to parse +---@param source (integer|string) Buffer or a string of text to parse ---@param lang string Root language this tree represents ---@param opts (table|nil) Optional keyword arguments: --- - injections table Mapping language to injection query strings. --- This is useful for overriding the built-in --- runtime file searching for the injection language --- query per language. ----@return LanguageTree |LanguageTree| parser object +---@return LanguageTree parser object function LanguageTree.new(source, lang, opts) language.require_language(lang) + ---@type LanguageTreeOpts opts = opts or {} if opts.queries then @@ -65,6 +85,7 @@ function LanguageTree.new(source, lang, opts) end --- Invalidates this parser and all its children +---@param reload boolean|nil function LanguageTree:invalidate(reload) self._valid = false @@ -73,7 +94,7 @@ function LanguageTree:invalidate(reload) self._trees = {} end - for _, child in ipairs(self._children) do + for _, child in pairs(self._children) do child:invalidate(reload) end end @@ -111,8 +132,8 @@ end --- This will run the injection query for this language to --- determine if any child languages should be created. --- ----@return userdata[] Table of parsed |tstree| ----@return table Change list +---@return TSTree[] +---@return table|nil Change list function LanguageTree:parse() if self._valid then return self._trees @@ -146,7 +167,7 @@ function LanguageTree:parse() end local injections_by_lang = self:_get_injections() - local seen_langs = {} + local seen_langs = {} ---@type table for lang, injection_ranges in pairs(injections_by_lang) do local has_lang = language.require_language(lang, nil, true) @@ -188,8 +209,8 @@ end --- Invokes the callback for each |LanguageTree| and its children recursively --- ----@param fn function(tree: LanguageTree, lang: string) ----@param include_self boolean Whether to include the invoking tree in the results +---@param fn fun(tree: LanguageTree, lang: string) +---@param include_self boolean|nil Whether to include the invoking tree in the results function LanguageTree:for_each_child(fn, include_self) if include_self then fn(self, self._lang) @@ -204,7 +225,7 @@ end --- --- Note: This includes the invoking tree's child trees as well. --- ----@param fn function(tree: TSTree, languageTree: LanguageTree) +---@param fn fun(tree: TSTree, ltree: LanguageTree) function LanguageTree:for_each_tree(fn) for _, tree in ipairs(self._trees) do fn(tree, self) @@ -221,7 +242,7 @@ end --- ---@private ---@param lang string Language to add. ----@return LanguageTree Injected |LanguageTree| +---@return LanguageTree injected function LanguageTree:add_child(lang) if self._children[lang] then self:remove_child(lang) @@ -258,7 +279,7 @@ end --- `remove_child` must be called on the parent to remove it. function LanguageTree:destroy() -- Cleanup here - for _, child in ipairs(self._children) do + for _, child in pairs(self._children) do child:destroy() end end @@ -280,20 +301,22 @@ end --- Note: This call invalidates the tree and requires it to be parsed again. --- ---@private ----@param regions table List of regions this tree should manage and parse. +---@param regions integer[][][] List of regions this tree should manage and parse. function LanguageTree:set_included_regions(regions) -- Transform the tables from 4 element long to 6 element long (with byte offset) for _, region in ipairs(regions) do for i, range in ipairs(region) do if type(range) == 'table' and #range == 4 then + ---@diagnostic disable-next-line:no-unknown local start_row, start_col, end_row, end_col = unpack(range) local start_byte = 0 local end_byte = 0 + local source = self._source -- TODO(vigoux): proper byte computation here, and account for EOL ? - if type(self._source) == 'number' then + if type(source) == 'number' then -- Easy case, this is a buffer parser - start_byte = a.nvim_buf_get_offset(self._source, start_row) + start_col - end_byte = a.nvim_buf_get_offset(self._source, end_row) + end_col + start_byte = a.nvim_buf_get_offset(source, start_row) + start_col + end_byte = a.nvim_buf_get_offset(source, end_row) + end_col elseif type(self._source) == 'string' then -- string parser, single `\n` delimited string start_byte = vim.fn.byteidx(self._source, start_col) @@ -320,9 +343,13 @@ function LanguageTree:included_regions() end ---@private +---@param node TSNode +---@param id integer +---@param metadata TSMetadata +---@return Range local function get_range_from_metadata(node, id, metadata) if metadata[id] and metadata[id].range then - return metadata[id].range + return metadata[id].range --[[@as Range]] end return { node:range() } end @@ -334,11 +361,13 @@ end --- TODO: Allow for an offset predicate to tailor the injection range --- instead of using the entire nodes range. ---@private +---@return table function LanguageTree:_get_injections() if not self._injection_query then return {} end + ---@type table>> local injections = {} for tree_index, tree in ipairs(self._trees) do @@ -348,14 +377,14 @@ function LanguageTree:_get_injections() for pattern, match, metadata in self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1) do - local lang = nil - local ranges = {} - local combined = metadata.combined + local lang = nil ---@type string + local ranges = {} ---@type Range[] + local combined = metadata.combined ---@type boolean -- Directives can configure how injections are captured as well as actual node captures. -- This allows more advanced processing for determining ranges and language resolution. if metadata.content then - local content = metadata.content + local content = metadata.content ---@type any -- Allow for captured nodes to be used if type(content) == 'number' then @@ -368,7 +397,7 @@ function LanguageTree:_get_injections() end if metadata.language then - lang = metadata.language + lang = metadata.language ---@type string end -- You can specify the content and language together @@ -379,7 +408,7 @@ function LanguageTree:_get_injections() -- Lang should override any other language tag if name == 'language' and not lang then - lang = query.get_node_text(node, self._source) + lang = query.get_node_text(node, self._source) --[[@as string]] elseif name == 'combined' then combined = true elseif name == 'content' and #ranges == 0 then @@ -417,6 +446,7 @@ function LanguageTree:_get_injections() end end + ---@type table local result = {} -- Generate a map by lang of node lists. @@ -429,11 +459,13 @@ function LanguageTree:_get_injections() for _, entry in pairs(patterns) do if entry.combined then + ---@diagnostic disable-next-line:no-unknown local regions = vim.tbl_map(function(e) return vim.tbl_flatten(e) end, entry.regions) table.insert(result[lang], regions) else + ---@diagnostic disable-next-line:no-unknown for _, ranges in ipairs(entry.regions) do table.insert(result[lang], ranges) end @@ -446,6 +478,7 @@ function LanguageTree:_get_injections() end ---@private +---@param cb_name TSCallbackName function LanguageTree:_do_callback(cb_name, ...) for _, cb in ipairs(self._callbacks[cb_name]) do cb(...) @@ -453,6 +486,17 @@ function LanguageTree:_do_callback(cb_name, ...) end ---@private +---@param bufnr integer +---@param changed_tick integer +---@param start_row integer +---@param start_col integer +---@param start_byte integer +---@param old_row integer +---@param old_col integer +---@param old_byte integer +---@param new_row integer +---@param new_col integer +---@param new_byte integer function LanguageTree:_on_bytes( bufnr, changed_tick, @@ -523,6 +567,7 @@ end --- - `on_child_added` : emitted when a child is added to the tree. --- - `on_child_removed` : emitted when a child is removed from the tree. function LanguageTree:register_cbs(cbs) + ---@cast cbs table if not cbs then return end @@ -549,6 +594,9 @@ function LanguageTree:register_cbs(cbs) end ---@private +---@param tree TSTree +---@param range Range +---@return boolean local function tree_contains(tree, range) local start_row, start_col, end_row, end_col = tree:root():range() local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) @@ -559,7 +607,7 @@ end --- Determines whether {range} is contained in the |LanguageTree|. --- ----@param range table `{ start_line, start_col, end_line, end_col }` +---@param range Range `{ start_line, start_col, end_line, end_col }` ---@return boolean function LanguageTree:contains(range) for _, tree in pairs(self._trees) do @@ -573,10 +621,10 @@ end --- Gets the tree that contains {range}. --- ----@param range table `{ start_line, start_col, end_line, end_col }` +---@param range Range `{ start_line, start_col, end_line, end_col }` ---@param opts table|nil Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) ----@return userdata|nil Contained |tstree| +---@return TSTree|nil function LanguageTree:tree_for_range(range, opts) opts = opts or {} local ignore = vim.F.if_nil(opts.ignore_injections, true) @@ -602,10 +650,10 @@ end --- Gets the smallest named node that contains {range}. --- ----@param range table `{ start_line, start_col, end_line, end_col }` +---@param range Range `{ start_line, start_col, end_line, end_col }` ---@param opts table|nil Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) ----@return userdata|nil Found |tsnode| +---@return TSNode|nil Found node function LanguageTree:named_node_for_range(range, opts) local tree = self:tree_for_range(range, opts) if tree then @@ -615,7 +663,7 @@ end --- Gets the appropriate language that contains {range}. --- ----@param range table `{ start_line, start_col, end_line, end_col }` +---@param range Range `{ start_line, start_col, end_line, end_col }` ---@return LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua index bb073290c6..be7764e6f0 100644 --- a/runtime/lua/vim/treesitter/playground.lua +++ b/runtime/lua/vim/treesitter/playground.lua @@ -1,12 +1,13 @@ local api = vim.api -local M = {} - ----@class Playground +---@class TSPlayground ---@field ns number API namespace ---@field opts table Options table with the following keys: --- - anon (boolean): If true, display anonymous nodes --- - lang (boolean): If true, display the language alongside each node +---@field nodes Node[] +---@field named Node[] +local TSPlayground = {} --- ---@class Node ---@field id number Node id @@ -18,6 +19,7 @@ local M = {} ---@field end_lnum number Final line number of this node in the source buffer ---@field end_col number Final column number of this node in the source buffer ---@field lang string Source language of this node +---@field root TSNode --- Traverse all child nodes starting at {node}. --- @@ -31,10 +33,10 @@ local M = {} --- node of each of these trees is contained within a node in the primary tree. The {injections} --- table maps nodes in the primary tree to root nodes of injected trees. --- ----@param node userdata Starting node to begin traversal |tsnode| +---@param node TSNode Starting node to begin traversal |tsnode| ---@param depth number Current recursion depth ---@param lang string Language of the tree currently being traversed ----@param injections table Mapping of node ids to root nodes of injected language trees (see +---@param injections table Mapping of node ids to root nodes of injected language trees (see --- explanation above) ---@param tree Node[] Output table containing a list of tables each representing a node in the tree ---@private @@ -48,7 +50,7 @@ local function traverse(node, depth, lang, injections, tree) local type = child:type() local lnum, col, end_lnum, end_col = child:range() local named = child:named() - local text + local text ---@type string if named then if field then text = string.format('%s: (%s)', field, type) @@ -79,14 +81,14 @@ end --- Create a new Playground object. --- ----@param bufnr number Source buffer number +---@param bufnr integer Source buffer number ---@param lang string|nil Language of source buffer --- ----@return Playground|nil +---@return TSPlayground|nil ---@return string|nil Error message, if any --- ---@private -function M.new(self, bufnr, lang) +function TSPlayground:new(bufnr, lang) local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang) if not ok then return nil, 'No parser available for the given buffer' @@ -96,7 +98,7 @@ function M.new(self, bufnr, lang) -- the primary tree that contains that root. Add a mapping from the node in the primary tree to -- the root in the child tree to the {injections} table. local root = parser:parse()[1]:root() - local injections = {} + local injections = {} ---@type table parser:for_each_child(function(child, lang_) child:for_each_tree(function(tree) local r = tree:root() @@ -112,7 +114,7 @@ function M.new(self, bufnr, lang) local nodes = traverse(root, 0, parser:lang(), injections, {}) - local named = {} + local named = {} ---@type Node[] for _, v in ipairs(nodes) do if v.named then named[#named + 1] = v @@ -138,9 +140,9 @@ end --- ---@param bufnr number Buffer number to write into. ---@private -function M.draw(self, bufnr) +function TSPlayground:draw(bufnr) vim.bo[bufnr].modifiable = true - local lines = {} + local lines = {} ---@type string[] for _, item in self:iter() do lines[#lines + 1] = table.concat({ string.rep(' ', item.depth), @@ -168,19 +170,19 @@ end ---@param i number Node number to get ---@return Node ---@private -function M.get(self, i) +function TSPlayground:get(i) local t = self.opts.anon and self.nodes or self.named return t[i] end --- Iterate over all of the nodes in this Playground object. --- ----@return function Iterator over all nodes in this Playground +---@return (fun(): integer, Node) Iterator over all nodes in this Playground ---@return table ---@return number ---@private -function M.iter(self) +function TSPlayground:iter() return ipairs(self.opts.anon and self.nodes or self.named) end -return M +return TSPlayground diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index dbf134573d..84ed2667b9 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -1,21 +1,25 @@ local a = vim.api local language = require('vim.treesitter.language') --- query: pattern matching on trees --- predicate matching is implemented in lua --- ---@class Query ---@field captures string[] List of captures used in query ----@field info table Contains used queries, predicates, directives +---@field info TSQueryInfo Contains used queries, predicates, directives ---@field query userdata Parsed query local Query = {} Query.__index = Query +---@class TSQueryInfo +---@field captures table +---@field patterns table + local M = {} ---@private +---@param files string[] +---@return string[] local function dedupe_files(files) local result = {} + ---@type table local seen = {} for _, path in ipairs(files) do @@ -65,10 +69,10 @@ function M.get_query_files(lang, query_name, is_included) return {} end - local base_query = nil + local base_query = nil ---@type string? local extensions = {} - local base_langs = {} + local base_langs = {} ---@type string[] -- Now get the base languages by looking at the first line of every file -- The syntax is the following : @@ -87,6 +91,7 @@ function M.get_query_files(lang, query_name, is_included) local extension = false for modeline in + ---@return string function() return file:read('*l') end @@ -97,6 +102,7 @@ function M.get_query_files(lang, query_name, is_included) local langlist = modeline:match(MODELINE_FORMAT) if langlist then + ---@diagnostic disable-next-line:param-type-mismatch for _, incllang in ipairs(vim.split(langlist, ',', true)) do local is_optional = incllang:match('%(.*%)') @@ -137,6 +143,8 @@ function M.get_query_files(lang, query_name, is_included) end ---@private +---@param filenames string[] +---@return string local function read_query_files(filenames) local contents = {} @@ -147,7 +155,8 @@ local function read_query_files(filenames) return table.concat(contents, '') end ---- The explicitly set queries from |vim.treesitter.query.set_query()| +-- The explicitly set queries from |vim.treesitter.query.set_query()| +---@type table> local explicit_queries = setmetatable({}, { __index = function(t, k) local lang_queries = {} @@ -174,7 +183,7 @@ end ---@param lang string Language to use for the query ---@param query_name string Name of the query (e.g. "highlights") --- ----@return Query Parsed query +---@return Query|nil Parsed query function M.get_query(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] @@ -188,6 +197,7 @@ function M.get_query(lang, query_name) end end +---@type {[string]: {[string]: Query}} local query_cache = vim.defaulttable(function() return setmetatable({}, { __mode = 'v' }) end) @@ -226,11 +236,11 @@ end --- Gets the text corresponding to a given node --- ----@param node userdata |tsnode| +---@param node TSNode ---@param source (number|string) Buffer or string from which the {node} is extracted ---@param opts (table|nil) Optional parameters. --- - concat: (boolean) Concatenate result in a string (default true) ----@return (string[]|string) +---@return (string[]|string|nil) function M.get_node_text(node, source, opts) opts = opts or {} local concat = vim.F.if_nil(opts.concat, true) @@ -239,12 +249,12 @@ function M.get_node_text(node, source, opts) local end_row, end_col, end_byte = node:end_() if type(source) == 'number' then - local lines local eof_row = a.nvim_buf_line_count(source) if start_row >= eof_row then return nil end + local lines ---@type string[] if end_col == 0 then lines = a.nvim_buf_get_lines(source, start_row, end_row, true) end_col = -1 @@ -267,8 +277,13 @@ function M.get_node_text(node, source, opts) end end +---@alias TSMatch table + +---@alias TSPredicate fun(match: TSMatch, _, _, predicate: any[]): boolean + -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) +---@type table local predicate_handlers = { ['eq?'] = function(match, _, source, predicate) local node = match[predicate[2]] @@ -277,13 +292,13 @@ local predicate_handlers = { end local node_text = M.get_node_text(node, source) - local str + local str ---@type string if type(predicate[3]) == 'string' then -- (#eq? @aa "foo") str = predicate[3] else -- (#eq? @aa @bb) - str = M.get_node_text(match[predicate[3]], source) + str = M.get_node_text(match[predicate[3]], source) --[[@as string]] end if node_text ~= str or str == nil then @@ -299,7 +314,7 @@ local predicate_handlers = { return true end local regex = predicate[3] - return string.find(M.get_node_text(node, source), regex) + return string.find(M.get_node_text(node, source) --[[@as string]], regex) ~= nil end, ['match?'] = (function() @@ -321,10 +336,12 @@ local predicate_handlers = { }) return function(match, _, source, pred) + ---@cast match TSMatch local node = match[pred[2]] if not node then return true end + ---@diagnostic disable-next-line no-unknown local regex = compiled_vim_regexes[pred[3]] return regex:match_str(M.get_node_text(node, source)) end @@ -335,7 +352,7 @@ local predicate_handlers = { if not node then return true end - local node_text = M.get_node_text(node, source) + local node_text = M.get_node_text(node, source) --[[@as string]] for i = 3, #predicate do if string.find(node_text, predicate[i], 1, true) then @@ -359,6 +376,7 @@ local predicate_handlers = { if not string_set then string_set = {} for i = 3, #predicate do + ---@diagnostic disable-next-line:no-unknown string_set[predicate[i]] = true end predicate['string_set'] = string_set @@ -371,21 +389,39 @@ local predicate_handlers = { -- As we provide lua-match? also expose vim-match? predicate_handlers['vim-match?'] = predicate_handlers['match?'] +---@class TSMetadata +---@field [integer] TSMetadata +---@field [string] integer|string +---@field range Range + +---@alias TSDirective fun(match: TSMatch, _, _, predicate: any[], metadata: TSMetadata) + +-- Predicate handler receive the following arguments +-- (match, pattern, bufnr, predicate) + -- Directives store metadata or perform side effects against a match. -- Directives should always end with a `!`. -- Directive handler receive the following arguments -- (match, pattern, bufnr, predicate, metadata) +---@type table local directive_handlers = { ['set!'] = function(_, _, _, pred, metadata) if #pred == 4 then -- (#set! @capture "key" "value") + ---@diagnostic disable-next-line:no-unknown local _, capture_id, key, value = unpack(pred) + ---@cast value integer|string + ---@cast capture_id integer + ---@cast key string if not metadata[capture_id] then metadata[capture_id] = {} end metadata[capture_id][key] = value else + ---@diagnostic disable-next-line:no-unknown local _, key, value = unpack(pred) + ---@cast value integer|string + ---@cast key string -- (#set! "key" "value") metadata[key] = value end @@ -393,9 +429,11 @@ local directive_handlers = { -- Shifts the range of a node. -- Example: (#offset! @_node 0 1 0 -1) ['offset!'] = function(match, _, _, pred, metadata) + ---@cast pred integer[] local capture_id = pred[2] local offset_node = match[capture_id] local range = { offset_node:range() } + ---@cast range integer[] bug in sumneko local start_row_offset = pred[3] or 0 local start_col_offset = pred[4] or 0 local end_row_offset = pred[5] or 0 @@ -419,8 +457,9 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ---@param name string Name of the predicate, without leading # ----@param handler function(match:table, pattern:string, bufnr:number, predicate:string[]) +---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[]) --- - see |vim.treesitter.query.add_directive()| for argument meanings +---@param force boolean function M.add_predicate(name, handler, force) if predicate_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -437,12 +476,13 @@ end --- metadata table `metadata[capture_id].key = value` --- ---@param name string Name of the directive, without leading # ----@param handler function(match:table, pattern:string, bufnr:number, predicate:string[], metadata:table) +---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[], metadata:table) --- - match: see |treesitter-query| --- - node-level data are accessible via `match[capture_id]` --- - pattern: see |treesitter-query| --- - predicate: list of strings containing the full directive being called, e.g. --- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` +---@param force boolean function M.add_directive(name, handler, force) if directive_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -474,6 +514,9 @@ local function is_directive(name) end ---@private +---@param match TSMatch +---@param pattern string +---@param source integer|string function Query:match_preds(match, pattern, source) local preds = self.info.patterns[pattern] @@ -482,8 +525,9 @@ function Query:match_preds(match, pattern, source) -- continue on the other case. This way unknown predicates will not be considered, -- which allows some testing and easier user extensibility (#12173). -- Also, tree-sitter strips the leading # from predicates for us. - local pred_name - local is_not + local pred_name ---@type string + + local is_not ---@type boolean -- Skip over directives... they will get processed after all the predicates. if not is_directive(pred[1]) then @@ -513,6 +557,8 @@ function Query:match_preds(match, pattern, source) end ---@private +---@param match TSMatch +---@param metadata TSMetadata function Query:apply_directives(match, pattern, source, metadata) local preds = self.info.patterns[pattern] @@ -534,6 +580,10 @@ end -- When the node's range is used, the stop is incremented by 1 -- to make the search inclusive. ---@private +---@param start integer +---@param stop integer +---@param node TSNode +---@return integer, integer local function value_or_node_range(start, stop, node) if start == nil and stop == nil then local node_start, _, node_stop, _ = node:range() @@ -565,14 +615,12 @@ end --- end --- --- ----@param node userdata |tsnode| under which the search will occur ----@param source (number|string) Source buffer or string to extract text from +---@param node TSNode under which the search will occur +---@param source (integer|string) Source buffer or string to extract text from ---@param start number Starting line for the search ---@param stop number Stopping line for the search (end-exclusive) --- ----@return number capture Matching capture id ----@return table capture_node Capture for {node} ----@return table metadata for the {capture} +---@return (fun(): integer, TSNode, TSMetadata): capture id, capture node, metadata function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() @@ -622,14 +670,12 @@ end --- end --- --- ----@param node userdata |tsnode| under which the search will occur ----@param source (number|string) Source buffer or string to search ----@param start number Starting line for the search ----@param stop number Stopping line for the search (end-exclusive) +---@param node TSNode under which the search will occur +---@param source (integer|string) Source buffer or string to search +---@param start integer Starting line for the search +---@param stop integer Stopping line for the search (end-exclusive) --- ----@return number pattern id ----@return table match ----@return table metadata +---@return (fun(): integer, table, table): pattern id, match, metadata function Query:iter_matches(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() @@ -638,6 +684,7 @@ function Query:iter_matches(node, source, start, stop) start, stop = value_or_node_range(start, stop, node) local raw_iter = node:_rawquery(self.query, false, start, stop) + ---@cast raw_iter fun(): string, any local function iter() local pattern, match = raw_iter() local metadata = {} -- cgit From 4b9bb3a1841489a18bbeb124fc11cbf359553ef5 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 4 Feb 2023 16:05:45 +0100 Subject: vim-patch:9.0.1278: go.work.sum files are not recognized (#22121) Problem: go.work.sum files are not recognized. Solution: Recognize go.work.sum files as the gosum filetype. (Amaan Qureshi, closes vim/vim#11940) https://github.com/vim/vim/commit/4ad8ae8465e30df38dba31910f130891b16d38a0 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 8144731b09..bc30b3bd11 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1433,6 +1433,7 @@ local filename = { gnashrc = 'gnash', ['.gnuplot'] = 'gnuplot', ['go.sum'] = 'gosum', + ['go.work.sum'] = 'gosum', ['go.work'] = 'gowork', ['.gprc'] = 'gp', ['/.gnupg/gpg.conf'] = 'gpg', -- cgit From bb8845340b1b9c2180fb19f049ff9deff5857d99 Mon Sep 17 00:00:00 2001 From: figsoda Date: Thu, 21 Jul 2022 12:08:37 +0100 Subject: feat(treesitter): allow capture text to be transformed Co-authored-by: Lewis Russell --- runtime/doc/news.txt | 3 +++ runtime/lua/vim/treesitter/languagetree.lua | 10 +++++++++- runtime/lua/vim/treesitter/query.lua | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 5c234677ef..7c3f295560 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -151,6 +151,9 @@ The following new APIs or features were added. • |:highlight| now supports an additional attribute "altfont". +• Treesitter captures can now be transformed by directives. This will allow + more complicated dynamic language injections. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 89aac3ae26..3e1bc5d1cb 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -354,6 +354,14 @@ local function get_range_from_metadata(node, id, metadata) return { node:range() } end +---@private +local function get_node_text(node, id, metadata, source) + if metadata[id] and metadata[id].text then + return metadata[id].text + end + return query.get_node_text(node, source) +end + --- Gets language injection points by language. --- --- This is where most of the injection processing occurs. @@ -408,7 +416,7 @@ function LanguageTree:_get_injections() -- Lang should override any other language tag if name == 'language' and not lang then - lang = query.get_node_text(node, self._source) --[[@as string]] + lang = get_node_text(node, id, metadata, self._source) --[[@as string]] elseif name == 'combined' then combined = true elseif name == 'content' and #ranges == 0 then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 84ed2667b9..5ec8c67462 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -452,6 +452,21 @@ local directive_handlers = { metadata[capture_id].range = range end end, + + -- Transform the content of the node + -- Example: (#gsub! @_node ".*%.(.*)" "%1") + ['gsub!'] = function(match, _, bufnr, pred, metadata) + assert(#pred == 4) + + local id = pred[2] + local node = match[id] + local text = M.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' + + if not metadata[id] then + metadata[id] = {} + end + metadata[id].text = text:gsub(pred[3], pred[4]) + end, } --- Adds a new predicate to be used in queries -- cgit From e1d5ad1cb87d43c3d75619e239312d4ab2029b45 Mon Sep 17 00:00:00 2001 From: figsoda Date: Mon, 26 Dec 2022 16:10:59 -0500 Subject: feat(treesitter): add metadata option for get_node_text --- runtime/doc/news.txt | 3 ++ runtime/doc/treesitter.txt | 3 ++ runtime/lua/vim/treesitter/languagetree.lua | 10 +---- runtime/lua/vim/treesitter/query.lua | 70 +++++++++++++++++------------ 4 files changed, 49 insertions(+), 37 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 7c3f295560..b438595b5f 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -154,6 +154,9 @@ The following new APIs or features were added. • Treesitter captures can now be transformed by directives. This will allow more complicated dynamic language injections. +• |vim.treesitter.query.get_node_text()| now accepts a `metadata` option for + writing custom directives using |vim.treesitter.query.add_directive()|. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 7bc9f3f9a7..693804497d 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -746,6 +746,9 @@ get_node_text({node}, {source}, {opts}) • {opts} (table|nil) Optional parameters. • concat: (boolean) Concatenate result in a string (default true) + • metadata (table) Metadata of a specific capture. This + would be set to `metadata[capture_id]` when using + |vim.treesitter.query.add_directive()|. Return: ~ (string[]|string|nil) diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 3e1bc5d1cb..8255c6f4fe 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -354,14 +354,6 @@ local function get_range_from_metadata(node, id, metadata) return { node:range() } end ----@private -local function get_node_text(node, id, metadata, source) - if metadata[id] and metadata[id].text then - return metadata[id].text - end - return query.get_node_text(node, source) -end - --- Gets language injection points by language. --- --- This is where most of the injection processing occurs. @@ -416,7 +408,7 @@ function LanguageTree:_get_injections() -- Lang should override any other language tag if name == 'language' and not lang then - lang = get_node_text(node, id, metadata, self._source) --[[@as string]] + lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'combined' then combined = true elseif name == 'content' and #ranges == 0 then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 5ec8c67462..9136b596be 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -55,6 +55,38 @@ local function add_included_lang(base_langs, lang, ilang) return false end +---@private +---@param buf (number) +---@param range (table) +---@param concat (boolean) +---@returns (string[]|string|nil) +local function buf_range_get_text(buf, range, concat) + local lines + local start_row, start_col, end_row, end_col = unpack(range) + local eof_row = a.nvim_buf_line_count(buf) + if start_row >= eof_row then + return nil + end + + if end_col == 0 then + lines = a.nvim_buf_get_lines(buf, start_row, end_row, true) + end_col = -1 + else + lines = a.nvim_buf_get_lines(buf, start_row, end_row + 1, true) + end + + if #lines > 0 then + if #lines == 1 then + lines[1] = string.sub(lines[1], start_col + 1, end_col) + else + lines[1] = string.sub(lines[1], start_col + 1) + lines[#lines] = string.sub(lines[#lines], 1, end_col) + end + end + + return concat and table.concat(lines, '\n') or lines +end + --- Gets the list of files used to make up a query --- ---@param lang string Language to get query for @@ -240,40 +272,22 @@ end ---@param source (number|string) Buffer or string from which the {node} is extracted ---@param opts (table|nil) Optional parameters. --- - concat: (boolean) Concatenate result in a string (default true) +--- - metadata (table) Metadata of a specific capture. This would be +--- set to `metadata[capture_id]` when using +--- |vim.treesitter.query.add_directive()|. ---@return (string[]|string|nil) function M.get_node_text(node, source, opts) opts = opts or {} local concat = vim.F.if_nil(opts.concat, true) + local metadata = opts.metadata or {} - local start_row, start_col, start_byte = node:start() - local end_row, end_col, end_byte = node:end_() - - if type(source) == 'number' then - local eof_row = a.nvim_buf_line_count(source) - if start_row >= eof_row then - return nil - end - - local lines ---@type string[] - if end_col == 0 then - lines = a.nvim_buf_get_lines(source, start_row, end_row, true) - end_col = -1 - else - lines = a.nvim_buf_get_lines(source, start_row, end_row + 1, true) - end - - if #lines > 0 then - if #lines == 1 then - lines[1] = string.sub(lines[1], start_col + 1, end_col) - else - lines[1] = string.sub(lines[1], start_col + 1) - lines[#lines] = string.sub(lines[#lines], 1, end_col) - end - end - - return concat and table.concat(lines, '\n') or lines + if metadata.text then + return metadata.text + elseif type(source) == 'number' then + return metadata.range and buf_range_get_text(source, metadata.range, concat) + or buf_range_get_text(source, { node:range() }, concat) elseif type(source) == 'string' then - return source:sub(start_byte + 1, end_byte) + return source:sub(select(3, node:start()) + 1, select(3, node:end_())) end end -- cgit From 4c66f5ff97a52fbc933fdbe1907c4b960d5a7403 Mon Sep 17 00:00:00 2001 From: figsoda Date: Mon, 26 Dec 2022 16:11:45 -0500 Subject: feat(treesitter): respect metadata[id].range for offset! --- runtime/lua/vim/treesitter/query.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 9136b596be..a0522d7cda 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -445,9 +445,11 @@ local directive_handlers = { ['offset!'] = function(match, _, _, pred, metadata) ---@cast pred integer[] local capture_id = pred[2] - local offset_node = match[capture_id] - local range = { offset_node:range() } - ---@cast range integer[] bug in sumneko + if not metadata[capture_id] then + metadata[capture_id] = {} + end + + local range = metadata[capture_id].range or { match[capture_id]:range() } local start_row_offset = pred[3] or 0 local start_col_offset = pred[4] or 0 local end_row_offset = pred[5] or 0 @@ -460,9 +462,6 @@ local directive_handlers = { -- If this produces an invalid range, we just skip it. if range[1] < range[3] or (range[1] == range[3] and range[2] <= range[4]) then - if not metadata[capture_id] then - metadata[capture_id] = {} - end metadata[capture_id].range = range end end, -- cgit From 23e34fe534d201a1323ab040cb2201d21fe865cc Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 5 Feb 2023 17:59:18 +0100 Subject: vim-patch:9.0.1281: Cadence files are not recognized (#22130) Problem: Cadence files are not recognized. Solution: Recognize Cadence files. (Janez Podhostnik, closes vim/vim#11951) https://github.com/vim/vim/commit/cb626a4692df7154be02b47d6089ec679e95cb44 Co-authored-by: Janez Podhostnik --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index bc30b3bd11..a18abf09ac 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -191,6 +191,7 @@ local extension = { qc = 'c', cabal = 'cabal', capnp = 'capnp', + cdc = 'cdc', cdl = 'cdl', toc = 'cdrtoc', cfc = 'cf', -- cgit From 6c39edaa7e5060cedfbbf61e88f4aad20fdff73d Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Mon, 6 Feb 2023 05:24:00 +0100 Subject: fix(health): iterate using ipairs correctly (#22119) In a few places ipairs was used to iterate over elements of the array. However, the first return value of ipairs was erronously used, which is not the value, but rather the index. This would result in errors, for instance when trying to retrieve a field from the value. --- runtime/lua/nvim/health.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua index f11899434e..b6d84404ec 100644 --- a/runtime/lua/nvim/health.lua +++ b/runtime/lua/nvim/health.lua @@ -183,7 +183,7 @@ local function check_rplugin_manifest() existing_rplugins[item.path] = 'python' end - for item in ipairs(vim.fn['remote#host#PluginsForHost']('python3')) do + for _, item in ipairs(vim.fn['remote#host#PluginsForHost']('python3')) do existing_rplugins[item.path] = 'python3' end @@ -200,7 +200,7 @@ local function check_rplugin_manifest() local scripts = vim.fn.glob(python_dir .. '/*.py', true, true) vim.list_extend(scripts, vim.fn.glob(python_dir .. '/*/__init__.py', true, true)) - for script in ipairs(scripts) do + for _, script in ipairs(scripts) do local contents = vim.fn.join(vim.fn.readfile(script)) if vim.regex([[\<\%(from\|import\)\s\+neovim\>]]):match_str(contents) then if vim.regex([[[\/]__init__\.py$]]):match_str(script) then @@ -384,7 +384,13 @@ local function check_terminal() ) end - for env_var in ipairs({ 'XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY' }) do + for _, env_var in ipairs({ + 'XTERM_VERSION', + 'VTE_VERSION', + 'TERM_PROGRAM', + 'COLORTERM', + 'SSH_TTY', + }) do if vim.env[env_var] then health.report_info(vim.fn.printf('$%s="%s"', env_var, vim.env[env_var])) end -- cgit From 1675f0e270579036c454c38f28e650b60a3fba1a Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Mon, 6 Feb 2023 04:01:17 -0500 Subject: vim-patch:9.0.1282: Ron files are not recognized (#22132) Problem: Ron files are not recognized. Solution: Recognize Ron files. (Amaan Qureshi, closes vim/vim#11948) https://github.com/vim/vim/commit/c8ef30bc2eaec956549510cd4b2efc96b7aee563 --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index a18abf09ac..58728a8872 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -871,6 +871,7 @@ local extension = { Snw = 'rnoweb', robot = 'robot', resource = 'robot', + ron = 'ron', rsc = 'routeros', x = 'rpcgen', rpl = 'rpl', -- cgit From e1f03c481a1cf87cead2c5af66b36dbdfbb9a983 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Mon, 6 Feb 2023 10:01:38 +0100 Subject: feat(spell): also source `spell/LANG.lua` when setting `spelllang` (#22111) Problem: only Vimscript files are sourced when setting spelling language Solution: also source Lua files after sourcing Vimscript files Closes #22110 --- runtime/doc/spell.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt index 98a6af1b8b..c6c4da2dea 100644 --- a/runtime/doc/spell.txt +++ b/runtime/doc/spell.txt @@ -440,9 +440,9 @@ find these functions useful: SETTING 'spellcapcheck' AUTOMATICALLY *set-spc-auto* After the 'spelllang' option has been set successfully, Vim will source the -files "spell/LANG.vim" in 'runtimepath'. "LANG" is the value of 'spelllang' -up to the first comma, dot or underscore. This can be used to set options -specifically for the language, especially 'spellcapcheck'. +files "spell/LANG.vim" and "spell/LANG.lua" in 'runtimepath'. "LANG" is the +value of 'spelllang' up to the first comma, dot or underscore. This can be +used to set options specifically for the language, especially 'spellcapcheck'. The distribution includes a few of these files. Use this command to see what they do: > -- cgit From 8fbe75b3dda7ab3b9e6df0d5406539bde4c80887 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 7 Feb 2023 10:29:37 +0100 Subject: vim-patch:9.0.1288: FunC files are not recognized (#22153) Problem: FunC files are not recognized. Solution: Recognize FunC files. (Amaan Qureshi, closes vim/vim#11949) https://github.com/vim/vim/commit/91deac45392fe93094b9c31403b1ae771dc71938 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 58728a8872..cdc6e4bb7c 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -423,6 +423,7 @@ local extension = { fsh = 'fsh', fsi = 'fsharp', fsx = 'fsharp', + fc = 'func', fusion = 'fusion', gdb = 'gdb', gdmo = 'gdmo', -- cgit From 1ca4a8b1ddf5256ad53cf486d0b2125434168270 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 8 Feb 2023 09:47:55 +0100 Subject: vim-patch:9.0.1291: Move language files are not recognized (#22162) Problem: Move language files are not recognized. Solution: Recognize Move language files. (Amaan Qureshi, closes vim/vim#11947) https://github.com/vim/vim/commit/6642982beaf4f1f5164f0315a1b3e3c275156089 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index cdc6e4bb7c..1f605b72f3 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -692,6 +692,7 @@ local extension = { isc = 'monk', moo = 'moo', moon = 'moonscript', + move = 'move', mp = 'mp', mpiv = function(path, bufnr) return 'mp', function(b) -- cgit From d0008bd626bb4fc28fedbba77c2c2ecaaac26683 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 8 Feb 2023 11:28:32 +0100 Subject: docs(luvref): update to version bump --- runtime/doc/luvref.txt | 110 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 11 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt index 859e75e4af..b7ce273f5f 100644 --- a/runtime/doc/luvref.txt +++ b/runtime/doc/luvref.txt @@ -24,7 +24,7 @@ be used in other Lua environments. More information about the core libuv library can be found at the original libuv documentation page (https://docs.libuv.org/). -TCP Echo Server Example~ +TCP Echo Server Example ~ Here is a small example showing a TCP echo server: @@ -51,15 +51,15 @@ Here is a small example showing a TCP echo server: uv.run() -- an explicit run call is necessary outside of luvit < -Module Layout~ +Module Layout ~ The luv library contains a single Lua module referred to hereafter as `uv` for simplicity. This module consists mostly of functions with names corresponding to their original libuv versions. For example, the libuv function -`uv_tcp_bind` has a luv version at |uv.tcp_bind()|. Currently, only one -non-function field exists: `uv.constants`, which is a table. +`uv_tcp_bind` has a luv version at |uv.tcp_bind()|. Currently, only two +non-function fields exists: `uv.constants` and `uv.errno`, which are tables. -Functions vs Methods~ +Functions vs Methods ~ In addition to having simple functions, luv provides an optional method-style API. For example, `uv.tcp_bind(server, host, port)` can alternatively be @@ -67,7 +67,7 @@ called as `server:bind(host, port)` . Note that the first argument `server` becomes the object and `tcp_` is removed from the function name. Method forms are documented below where they exist. -Synchronous vs Asynchronous Functions~ +Synchronous vs Asynchronous Functions ~ Functions that accept a callback are asynchronous. These functions may immediately return results to the caller to indicate their initial status, but @@ -82,7 +82,7 @@ Some (generally FS and DNS) functions can behave either synchronously or asynchronously. If a callback is provided to these functions, they behave asynchronously; if no callback is provided, they behave synchronously. -Pseudo-Types~ +Pseudo-Types ~ Some unique types are defined. These are not actual types in Lua, but they are used here to facilitate documenting consistent behavior: @@ -133,10 +133,10 @@ module. ============================================================================== ERROR HANDLING *luv-error-handling* -In libuv, errors are negative numbered constants; however, these errors and -the functions used to handle them are not exposed to luv users. Instead, if an -internal error is encountered, the luv function will return to the caller an -assertable `nil, err, name` tuple. +In libuv, errors are negative numbered constants; however, while those errors +are exposed through `uv.errno`, the functions used to handle them are not +exposed to luv users. Instead, if an internal error is encountered, the luv +function will return to the caller an assertable `nil, err, name` tuple. - `nil` idiomatically indicates failure - `err` is a string with the format `{name}: {message}` @@ -151,6 +151,94 @@ When a function is called successfully, it will return either a value that is relevant to the operation of the function, or the integer `0` to indicate success, or sometimes nothing at all. These cases are documented below. +`uv.errno` *uv.errno* + +A table value which exposes error constants as a map, where the key is the +error name (without the `UV_` prefix) and its value is a negative number. +See Libuv's "Error constants" page for further details. +(https://docs.libuv.org/en/v1.x/errors.html#error-constants) + +- `E2BIG`: argument list too long. +- `EACCES`: permission denied. +- `EADDRINUSE`: address already in use. +- `EADDRNOTAVAIL`: address not available. +- `EAFNOSUPPORT`: address family not supported. +- `EAGAIN`: resource temporarily unavailable. +- `EAI_ADDRFAMILY`: address family not supported. +- `EAI_AGAIN`: temporary failure. +- `EAI_BADFLAGS`: bad ai_flags value. +- `EAI_BADHINTS`: invalid value for hints. +- `EAI_CANCELED`: request canceled. +- `EAI_FAIL`: permanent failure. +- `EAI_FAMILY`: ai_family not supported. +- `EAI_MEMORY`: out of memory. +- `EAI_NODATA`: no address. +- `EAI_NONAME`: unknown node or service. +- `EAI_OVERFLOW`: argument buffer overflow. +- `EAI_PROTOCOL`: resolved protocol is unknown. +- `EAI_SERVICE`: service not available for socket type. +- `EAI_SOCKTYPE`: socket type not supported. +- `EALREADY`: connection already in progress. +- `EBADF`: bad file descriptor. +- `EBUSY`: resource busy or locked. +- `ECANCELED`: operation canceled. +- `ECHARSET`: invalid Unicode character. +- `ECONNABORTED`: software caused connection abort. +- `ECONNREFUSED`: connection refused. +- `ECONNRESET`: connection reset by peer. +- `EDESTADDRREQ`: destination address required. +- `EEXIST`: file already exists. +- `EFAULT`: bad address in system call argument. +- `EFBIG`: file too large. +- `EHOSTUNREACH`: host is unreachable. +- `EINTR`: interrupted system call. +- `EINVAL`: invalid argument. +- `EIO`: i/o error. +- `EISCONN`: socket is already connected. +- `EISDIR`: illegal operation on a directory. +- `ELOOP`: too many symbolic links encountered. +- `EMFILE`: too many open files. +- `EMSGSIZE`: message too long. +- `ENAMETOOLONG`: name too long. +- `ENETDOWN`: network is down. +- `ENETUNREACH`: network is unreachable. +- `ENFILE`: file table overflow. +- `ENOBUFS`: no buffer space available. +- `ENODEV`: no such device. +- `ENOENT`: no such file or directory. +- `ENOMEM`: not enough memory. +- `ENONET`: machine is not on the network. +- `ENOPROTOOPT`: protocol not available. +- `ENOSPC`: no space left on device. +- `ENOSYS`: function not implemented. +- `ENOTCONN`: socket is not connected. +- `ENOTDIR`: not a directory. +- `ENOTEMPTY`: directory not empty. +- `ENOTSOCK`: socket operation on non-socket. +- `ENOTSUP`: operation not supported on socket. +- `EOVERFLOW`: value too large for defined data type. +- `EPERM`: operation not permitted. +- `EPIPE`: broken pipe. +- `EPROTO`: protocol error. +- `EPROTONOSUPPORT`: protocol not supported. +- `EPROTOTYPE`: protocol wrong type for socket. +- `ERANGE`: result too large. +- `EROFS`: read-only file system. +- `ESHUTDOWN`: cannot send after transport endpoint shutdown. +- `ESPIPE`: invalid seek. +- `ESRCH`: no such process. +- `ETIMEDOUT`: connection timed out. +- `ETXTBSY`: text file is busy. +- `EXDEV`: cross-device link not permitted. +- `UNKNOWN`: unknown error. +- `EOF`: end of file. +- `ENXIO`: no such device or address. +- `EMLINK`: too many links. +- `ENOTTY`: inappropriate ioctl for device. +- `EFTYPE`: inappropriate file type or format. +- `EILSEQ`: illegal byte sequence. +- `ESOCKTNOSUPPORT`: socket type not supported. + ============================================================================== VERSION CHECKING *luv-version-checking* -- cgit From 625e990976540a0e2d2bccb98deb57d0919d1e89 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 8 Feb 2023 16:16:16 +0100 Subject: refactor(ui): cleanup 'redrawdebug', introduce "flush" mode --- runtime/doc/options.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 1f91b89322..17f1c822ff 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4765,7 +4765,7 @@ A jump table for the options with a short description can be found at |Q_op|. Flags to change the way redrawing works, for debugging purposes. Most useful with 'writedelay' set to some reasonable value. Supports the following flags: - compositor Indicate what redraws come from the compositor + compositor Indicate each redraw event handled by the compositor by briefly flashing the redrawn regions in colors indicating the redraw type. These are the highlight groups used (and their default colors): @@ -4777,6 +4777,11 @@ A jump table for the options with a short description can be found at |Q_op|. RedrawDebugRecompose guibg=Red redraw generated by the compositor itself, due to a grid being moved or deleted. + line introduce a delay after each line drawn on the screen. + When using the TUI or another single-grid UI, "compositor" + gives more information and should be preferred (every + line is processed as a separate event by the compositor) + flush introduce a delay after each "flush" event. nothrottle Turn off throttling of the message grid. This is an optimization that joins many small scrolls to one larger scroll when drawing the message area (with @@ -4786,7 +4791,7 @@ A jump table for the options with a short description can be found at |Q_op|. useful when running nvim inside a debugger (and the test suite). nodelta Send all internally redrawn cells to the UI, even if - they are unchanged from the already displayed state. + they are unchanged from the already displayed state. *'redrawtime'* *'rdt'* 'redrawtime' 'rdt' number (default 2000) @@ -7372,8 +7377,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'writedelay'* *'wd'* 'writedelay' 'wd' number (default 0) global - The number of milliseconds to wait for each character sent to the - screen. When positive, characters are sent to the UI one by one. - See 'redrawdebug' for more options. For debugging purposes. + Only takes effect toghether with 'redrawdebug'. + The number of milliseconds to wait after each line or each flush vim:tw=78:ts=8:noet:ft=help:norl: -- cgit From 1aa128b0ea8764b01a433b91ba62faa77cce84f8 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 9 Feb 2023 11:54:37 +0100 Subject: docs(luvref): update version info --- runtime/doc/luvref.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt index 859e75e4af..86f4163f4d 100644 --- a/runtime/doc/luvref.txt +++ b/runtime/doc/luvref.txt @@ -3888,11 +3888,11 @@ uv.metrics_idle_time() *uv.metrics_idle_time()* ============================================================================== CREDITS *luv-credits* -This document is a reformatted version of the LUV documentation, based on -commit c51e705 (5 May 2022) of the luv repository -https://github.com/luvit/luv/commit/c51e7052ec4f0a25058f70c1b4ee99dd36180e59. +This document is a reformatted version of the LUV documentation, up-to-date +with commit e8e7b7e (3 Feb 2023) of the luv repository +https://github.com/luvit/luv/commit/e8e7b7e13225348a8806118a3ea9e021383a9536. -Included from https://github.com/nanotee/luv-vimdocs with kind permission. +Based on https://github.com/nanotee/luv-vimdocs with kind permission. vim:tw=78:ts=8:ft=help:norl: -- cgit From f5bad01869df449cb1e4ae7f264bcd5c8150f606 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 9 Feb 2023 15:20:47 +0000 Subject: feat(treesitter): playground improvements - Render node ranges as virtual text - Set filettype=query. The virtual text is to avoid parsing errors. - Make sure highlights text is always in view. --- runtime/lua/vim/treesitter.lua | 13 ++++++++--- runtime/lua/vim/treesitter/playground.lua | 36 +++++++++++++++++++------------ 2 files changed, 32 insertions(+), 17 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 96b1e24ba9..a15d3ec23c 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -411,6 +411,7 @@ function M.show_tree(opts) vim.bo[b].buflisted = false vim.bo[b].buftype = 'nofile' vim.bo[b].bufhidden = 'wipe' + vim.bo[b].filetype = 'query' local title = opts.title if not title then @@ -425,9 +426,6 @@ function M.show_tree(opts) pg:draw(b) - vim.fn.matchadd('Comment', '\\[[0-9:-]\\+\\]') - vim.fn.matchadd('String', '".*"') - a.nvim_buf_clear_namespace(buf, pg.ns, 0, -1) a.nvim_buf_set_keymap(b, 'n', '', '', { desc = 'Jump to the node under the cursor in the source buffer', @@ -467,6 +465,15 @@ function M.show_tree(opts) end_col = math.max(0, pos.end_col), hl_group = 'Visual', }) + + local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win) + + -- Move the cursor if highlighted range is completely out of view + if pos.lnum < topline and pos.end_lnum < topline then + a.nvim_win_set_cursor(win, { pos.end_lnum + 1, 0 }) + elseif pos.lnum > botline and pos.end_lnum > botline then + a.nvim_win_set_cursor(win, { pos.lnum + 1, 0 }) + end end, }) diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua index be7764e6f0..001bc2d5bf 100644 --- a/runtime/lua/vim/treesitter/playground.lua +++ b/runtime/lua/vim/treesitter/playground.lua @@ -136,6 +136,8 @@ function TSPlayground:new(bufnr, lang) return t end +local decor_ns = api.nvim_create_namespace('ts.playground') + --- Write the contents of this Playground into {bufnr}. --- ---@param bufnr number Buffer number to write into. @@ -144,22 +146,28 @@ function TSPlayground:draw(bufnr) vim.bo[bufnr].modifiable = true local lines = {} ---@type string[] for _, item in self:iter() do - lines[#lines + 1] = table.concat({ - string.rep(' ', item.depth), - item.text, - item.lnum == item.end_lnum - and string.format(' [%d:%d-%d]', item.lnum + 1, item.col + 1, item.end_col) - or string.format( - ' [%d:%d-%d:%d]', - item.lnum + 1, - item.col + 1, - item.end_lnum + 1, - item.end_col - ), - self.opts.lang and string.format(' %s', item.lang) or '', - }) + lines[#lines + 1] = string.rep(' ', item.depth) .. item.text end api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) + + api.nvim_buf_clear_namespace(bufnr, decor_ns, 0, -1) + + for i, item in self:iter() do + local range_str + if item.lnum == item.end_lnum then + range_str = string.format('[%d:%d-%d]', item.lnum + 1, item.col + 1, item.end_col) + else + range_str = + string.format('[%d:%d-%d:%d]', item.lnum + 1, item.col + 1, item.end_lnum + 1, item.end_col) + end + + local lang_str = self.opts.lang and string.format(' %s', item.lang) or '' + + api.nvim_buf_set_extmark(bufnr, decor_ns, i - 1, 0, { + virt_text = { { range_str, 'Comment' }, { lang_str, 'Title' } }, + }) + end + vim.bo[bufnr].modifiable = false end -- cgit From 8a985d12dd6b4a5a4ba825939f36b7b1a324d849 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 9 Feb 2023 16:08:22 +0000 Subject: fix(treesitter): don't trample parsers when filetype!=lang This allows vim.treesitter.show_tree() to work on buffers where the filetype does not match the parser language name e.g, bash/sh. --- runtime/lua/vim/treesitter.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index a15d3ec23c..4127198576 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -96,11 +96,13 @@ function M.get_parser(bufnr, lang, opts) if bufnr == nil or bufnr == 0 then bufnr = a.nvim_get_current_buf() end - if lang == nil then - lang = a.nvim_buf_get_option(bufnr, 'filetype') - end - if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then + if parsers[bufnr] == nil then + lang = lang or a.nvim_buf_get_option(bufnr, 'filetype') + parsers[bufnr] = M._create_parser(bufnr, lang, opts) + elseif lang and parsers[bufnr]:lang() ~= lang then + -- Only try to create a new parser if lang is provided + -- and it doesn't match the stored parser parsers[bufnr] = M._create_parser(bufnr, lang, opts) end -- cgit From 165b07b2692ef131affecbbed432f27f16512124 Mon Sep 17 00:00:00 2001 From: Sizhe Zhao Date: Sat, 11 Feb 2023 17:34:20 +0800 Subject: docs: reword news.txt to ensure a consistent style (#22215) --- runtime/doc/news.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index b438595b5f..c8d40094f3 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -63,7 +63,7 @@ The following new APIs or features were added. < (or the Vimscript equivalent) to their |config| file. -• Run Lua scripts from your shell using |-l|. > +• Added support for running Lua scripts from shell using |-l|. > nvim -l foo.lua --arg1 --arg2 < Also works with stdin: > echo "print(42)" | nvim -l - -- cgit From 7d58de11f49c574a8a305e28e96b9ff810493012 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 18:25:01 +0800 Subject: fix(rpc)!: preseve files when stdio channel is closed (#22137) BREAKING CHANGE: Unsaved changes are now preserved rather than discarded when stdio channel is closed. --- runtime/doc/news.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index c8d40094f3..2afb22bb43 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -47,6 +47,9 @@ The following changes may require adaptations in user config or plugins. • libiconv is now a required build dependency. +• Unsaved changes are now preserved rather than discarded when |channel-stdio| + is closed. + ============================================================================== NEW FEATURES *news-features* -- cgit From 374955bcc571dff05f068ec18d0f578d1f334c5f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 20:00:31 +0800 Subject: vim-patch:9.0.1300: 'statusline' only supports one "%=" item (#22218) Problem: 'statusline' only supports one "%=" item. Solution: Add support for multiple "%=" items. (TJ DeVries, Yegappan Lakshmanan, closes vim/vim#11970, closes vim/vim#11965) https://github.com/vim/vim/commit/3ec78f973fdaec2cea8e036ed38037b2fe40670b Co-authored-by: Yegappan Lakshmanan --- runtime/doc/options.txt | 6 ++++-- runtime/doc/vim_diff.txt | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 17f1c822ff..e4106358f1 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6201,8 +6201,10 @@ A jump table for the options with a short description can be found at |Q_op|. this label. < - Where to truncate line if too long. Default is at the start. No width fields allowed. - = - Separation point between alignment sections. Each section will - be separated by an equal number of spaces. + = - Separation point between alignment sections. Each section will + be separated by an equal number of spaces. With one %= what + comes after it will be right-aligned. With two %= there is a + middle part, with white space left and right of it. No width fields allowed. # - Set highlight group. The name must follow and then a # again. Thus use %#HLname# for highlight group HLname. The same diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index bb3b670b24..97fc211c36 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -267,7 +267,6 @@ Options: 'pumblend' pseudo-transparent popupmenu 'scrollback' 'signcolumn' supports up to 9 dynamic/fixed columns - 'statusline' supports unlimited alignment sections 'tabline' %@Func@foo%X can call any function on mouse-click 'winblend' pseudo-transparency in floating windows |api-floatwin| 'winhighlight' window-local highlights @@ -292,6 +291,7 @@ These Nvim features were later integrated into Vim. - |WinScrolled| - |:sign-define| "numhl" argument - |:source| works with anonymous (no file) scripts +- 'statusline' supports unlimited alignment sections ============================================================================== 5. Changed features *nvim-features-changed* -- cgit From c5b34fa55483d84d1de32937ffff0b7cf1aeba78 Mon Sep 17 00:00:00 2001 From: glacambre Date: Sat, 11 Feb 2023 09:45:11 +0100 Subject: refactor: move init_default_autocmds to lua The original motivation for this change came from developping https://github.com/neovim/neovim/pull/22159, which will require adding more autocommand creation to Neovim's startup sequence. This change requires lightly editing a test that expected no autocommand to have been created from lua. --- runtime/lua/vim/_editor.lua | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'runtime') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index da8764fbd4..3f27e61810 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -894,6 +894,26 @@ function vim._init_default_mappings() ]]) end +function vim._init_default_autocmds() + local nvim_terminal_augroup = vim.api.nvim_create_augroup('nvim_terminal', {}) + vim.api.nvim_create_autocmd({ 'bufreadcmd' }, { + pattern = 'term://*', + group = nvim_terminal_augroup, + nested = true, + command = "if !exists('b:term_title')|call termopen(matchstr(expand(\"\"), '\\c\\mterm://\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), {'cwd': expand(get(matchlist(expand(\"\"), '\\c\\mterm://\\(.\\{-}\\)//'), 1, ''))})", + }) + vim.api.nvim_create_autocmd({ 'cmdwinenter' }, { + pattern = '[:>]', + group = vim.api.nvim_create_augroup('nvim_cmdwin', {}), + command = 'syntax sync minlines=1 maxlines=1', + }) +end + +function vim._init_defaults() + vim._init_default_mappings() + vim._init_default_autocmds() +end + require('vim._meta') return vim -- cgit From 9668c166e88cd71e517cacfb8d266b75047604f7 Mon Sep 17 00:00:00 2001 From: Jonas Strittmatter <40792180+smjonas@users.noreply.github.com> Date: Sat, 11 Feb 2023 16:08:33 +0100 Subject: fix(filetype): make vim.filetype.match() work with contents only (#22181) Co-authored-by: Gregory Anders --- runtime/lua/vim/filetype.lua | 95 ++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 47 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 1f605b72f3..ec568b5b82 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2449,6 +2449,7 @@ local function match_pattern(name, path, tail, pat) return false end end + -- If the pattern contains a / match against the full path, otherwise just the tail local fullpat = '^' .. pat .. '$' local matches @@ -2526,64 +2527,64 @@ function M.match(args) name = api.nvim_buf_get_name(bufnr) end - if name then - name = normalize_path(name) - end - local ft, on_detect - -- First check for the simple case where the full path exists as a key - local path = vim.fn.fnamemodify(name, ':p') - ft, on_detect = dispatch(filename[path], path, bufnr) - if ft then - return ft, on_detect - end + if name then + name = normalize_path(name) - -- Next check against just the file name - local tail = vim.fn.fnamemodify(name, ':t') - ft, on_detect = dispatch(filename[tail], path, bufnr) - if ft then - return ft, on_detect - end + -- First check for the simple case where the full path exists as a key + local path = vim.fn.fnamemodify(name, ':p') + ft, on_detect = dispatch(filename[path], path, bufnr) + if ft then + return ft, on_detect + end - -- Next, check the file path against available patterns with non-negative priority - local j = 1 - for i, v in ipairs(pattern_sorted) do - local k = next(v) - local opts = v[k][2] - if opts.priority < 0 then - j = i - break + -- Next check against just the file name + local tail = vim.fn.fnamemodify(name, ':t') + ft, on_detect = dispatch(filename[tail], path, bufnr) + if ft then + return ft, on_detect end - local filetype = v[k][1] - local matches = match_pattern(name, path, tail, k) - if matches then - ft, on_detect = dispatch(filetype, path, bufnr, matches) - if ft then - return ft, on_detect + -- Next, check the file path against available patterns with non-negative priority + local j = 1 + for i, v in ipairs(pattern_sorted) do + local k = next(v) + local opts = v[k][2] + if opts.priority < 0 then + j = i + break + end + + local filetype = v[k][1] + local matches = match_pattern(name, path, tail, k) + if matches then + ft, on_detect = dispatch(filetype, path, bufnr, matches) + if ft then + return ft, on_detect + end end end - end - -- Next, check file extension - local ext = vim.fn.fnamemodify(name, ':e') - ft, on_detect = dispatch(extension[ext], path, bufnr) - if ft then - return ft, on_detect - end + -- Next, check file extension + local ext = vim.fn.fnamemodify(name, ':e') + ft, on_detect = dispatch(extension[ext], path, bufnr) + if ft then + return ft, on_detect + end - -- Next, check patterns with negative priority - for i = j, #pattern_sorted do - local v = pattern_sorted[i] - local k = next(v) + -- Next, check patterns with negative priority + for i = j, #pattern_sorted do + local v = pattern_sorted[i] + local k = next(v) - local filetype = v[k][1] - local matches = match_pattern(name, path, tail, k) - if matches then - ft, on_detect = dispatch(filetype, path, bufnr, matches) - if ft then - return ft, on_detect + local filetype = v[k][1] + local matches = match_pattern(name, path, tail, k) + if matches then + ft, on_detect = dispatch(filetype, path, bufnr, matches) + if ft then + return ft, on_detect + end end end end -- cgit From b518aceaa8f738e581e58aacae93514699b5ff8e Mon Sep 17 00:00:00 2001 From: Jonas Strittmatter <40792180+smjonas@users.noreply.github.com> Date: Tue, 14 Feb 2023 00:04:16 +0100 Subject: feat(filetype): fall back to file extension when matching from hashbang (#22140) If nothing matched in match_from_hashbang, also check the file extension table. For a hashbang like '#!/bin/env foo', this will set the filetype to 'fooscript' assuming the filetype for the 'foo' extension is 'fooscript' in the extension table. --- runtime/lua/vim/filetype.lua | 4 +++- runtime/lua/vim/filetype/detect.lua | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index ec568b5b82..ca91f3f402 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2604,7 +2604,9 @@ function M.match(args) -- If the function tries to use the filename that is nil then it will fail, -- but this enables checks which do not need a filename to still work. local ok - ok, ft = pcall(require('vim.filetype.detect').match_contents, contents, name) + ok, ft = pcall(require('vim.filetype.detect').match_contents, contents, name, function(ext) + return dispatch(extension[ext], name, bufnr) + end) if ok and ft then return ft end diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index edffdde9c7..b3d9fedeae 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1420,7 +1420,7 @@ local patterns_hashbang = { ---@private -- File starts with "#!". -local function match_from_hashbang(contents, path) +local function match_from_hashbang(contents, path, dispatch_extension) local first_line = contents[1] -- Check for a line like "#!/usr/bin/env {options} bash". Turn it into -- "#!/usr/bin/bash" to make matching easier. @@ -1473,6 +1473,11 @@ local function match_from_hashbang(contents, path) return ft end end + + -- If nothing matched, check the extension table. For a hashbang like + -- '#!/bin/env foo', this will set the filetype to 'fooscript' assuming + -- the filetype for the 'foo' extension is 'fooscript' in the extension table. + return dispatch_extension(name) end local patterns_text = { @@ -1652,10 +1657,10 @@ local function match_from_text(contents, path) return cvs_diff(path, contents) end -M.match_contents = function(contents, path) +function M.match_contents(contents, path, dispatch_extension) local first_line = contents[1] if first_line:find('^#!') then - return match_from_hashbang(contents, path) + return match_from_hashbang(contents, path, dispatch_extension) else return match_from_text(contents, path) end -- cgit From 2e450efb9525308708dd9e26d6ea1d029ac781b8 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 15 Feb 2023 09:55:23 +0100 Subject: feat(treesitter)!: remove g:ts_highlight_lua (#22257) This variable was only meant for easy testing during the development cycle for treesitter highlighting while Lua was the only parser useable for daily driving. Now that we have a good vimdoc parser, this approach simply doesn't scale and should be removed sooner rather than later. Instead of setting this variable, people for now should add the autocommand directly to their config: ```lua vim.api.nvim_create_autocmd('FileType', { pattern = 'lua', -- or { 'lua', 'help' } callback = function() vim.treesitter.start() end, }) ``` (or put `vim.treesitter.start()` in an `ftplugin`). --- runtime/ftplugin/lua.lua | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 runtime/ftplugin/lua.lua (limited to 'runtime') diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua deleted file mode 100644 index 415cf28f9a..0000000000 --- a/runtime/ftplugin/lua.lua +++ /dev/null @@ -1,3 +0,0 @@ -if vim.g.ts_highlight_lua then - vim.treesitter.start() -end -- cgit From a289e82142fdc5ff657dd30198546eeb1e115fe9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 15 Feb 2023 12:26:07 +0000 Subject: fix(treesitter): make params optional --- runtime/doc/treesitter.txt | 4 ++-- runtime/lua/vim/treesitter/query.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 693804497d..d4799053f7 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -721,7 +721,7 @@ add_directive({name}, {handler}, {force}) • predicate: list of strings containing the full directive being called, e.g. `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` - • {force} (boolean) + • {force} (boolean|nil) *vim.treesitter.query.add_predicate()* add_predicate({name}, {handler}, {force}) @@ -733,7 +733,7 @@ add_predicate({name}, {handler}, {force}) bufnr:number, predicate:string[]) • see |vim.treesitter.query.add_directive()| for argument meanings - • {force} (boolean) + • {force} (boolean|nil) *vim.treesitter.query.get_node_text()* get_node_text({node}, {source}, {opts}) diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index a0522d7cda..008e5a54d7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -487,7 +487,7 @@ local directive_handlers = { ---@param name string Name of the predicate, without leading # ---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[]) --- - see |vim.treesitter.query.add_directive()| for argument meanings ----@param force boolean +---@param force boolean|nil function M.add_predicate(name, handler, force) if predicate_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -510,7 +510,7 @@ end --- - pattern: see |treesitter-query| --- - predicate: list of strings containing the full directive being called, e.g. --- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` ----@param force boolean +---@param force boolean|nil function M.add_directive(name, handler, force) if directive_handlers[name] and not force then error(string.format('Overriding %s', name)) -- cgit From da3cb6ebe4ef40e11192db79925bb5f3dd8defef Mon Sep 17 00:00:00 2001 From: blt__ <63462729+blt-r@users.noreply.github.com> Date: Thu, 16 Feb 2023 03:11:49 +0400 Subject: dist: use valid application id in nvim.appdata.xml #22046 According to [AppStream spec](https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-id-generic), the element should contain a reverse-DNS scheme: {tld}.{vendor}.{product} Since the flathub requires that, the flatpak build replaces `nvim` with `io.neovim.nvim`. That results in ID mismatch between flatpak version and version from distribution's repositories. Because of that, software stores are displaying two different neovims, instead of one neovim with options to download it either from flatpak or from distribution's repos. We can use the `nvim`, for everyone who was expecting the id to be `nvim`. --- runtime/nvim.appdata.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml index 7d2ea49df4..1fe672b80b 100644 --- a/runtime/nvim.appdata.xml +++ b/runtime/nvim.appdata.xml @@ -7,7 +7,7 @@ https://github.com/flathub/io.neovim.nvim --> - nvim + io.neovim.nvim nvim Apache-2.0 CC0-1.0 @@ -61,5 +61,6 @@ https://github.com/neovim/neovim/tree/master/src/nvim/po nvim + nvim -- cgit From d34c64e342dfba9248d1055e702d02620a1b31a8 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Thu, 16 Feb 2023 13:15:02 +0100 Subject: feat: $NVIM_APPNAME #22128 This commit implements the ability to control all of the XDG paths Neovim should use. This is done by setting an environment variable named NVIM_APPNAME. For example, setting $NVIM_APPNAME makes Neovim look for its configuration directory in $XDG_CONFIG_HOME/$NVIM_APPNAME instead of $XDG_CONFIG_HOME/nvim. If NVIM_APPNAME is not set or is an empty string, "nvim" will be used as default. The usecase for this feature is to enable an easy way to switch from configuration to configuration. One might argue that the various $XDG environment variables can already be used for this usecase. However, setting $XDG environment variables also affects tools spawned by Neovim. For example, while setting $XDG_CONFIG_HOME will enable Neovim to use a different configuration directory, it will also prevent Git from finding its "default" configuration. Closes https://github.com/neovim/neovim/issues/21691 --- runtime/doc/news.txt | 4 ++++ runtime/doc/starting.txt | 12 ++++++++++++ 2 files changed, 16 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 2afb22bb43..ae21bc47ca 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -55,6 +55,10 @@ NEW FEATURES *news-features* The following new APIs or features were added. +• A new environment variable named NVIM_APPNAME enables configuring the + directories where Neovim should find its configuration and state files. See + `:help $NVIM_APPNAME` . + • |nvim_open_win()| now accepts a relative `mouse` option to open a floating win relative to the mouse. Note that the mouse doesn't update frequently without setting `vim.o.mousemoveevent = true` diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 5e0718c3bb..67a88913fb 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1385,6 +1385,18 @@ STATE DIRECTORY (DEFAULT) ~ Note: Throughout the user manual these defaults are used as placeholders, e.g. "~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config". +NVIM_APPNAME *$NVIM_APPNAME* +The XDG directories used by Nvim can be further configured by setting the +`$NVIM_APPNAME` environment variable. This variable controls the directory +Neovim will look for (and auto-create) in the various XDG parent directories. +For example, setting `$NVIM_APPNAME` to "neovim" before running Neovim will +result in Neovim looking for configuration files in `$XDG_CONFIG_HOME/neovim` +instead of `$XDG_CONFIG_HOME/nvim`. + +Note: Similarly to the $XDG environment variables, when +`$XDG_CONFIG_HOME/nvim` is mentionned, it should be understood as +`$XDG_CONFIG_HOME/$NVIM_APPNAME`. + LOG FILE *$NVIM_LOG_FILE* *E5430* Besides 'debug' and 'verbose', Nvim keeps a general log file for internal debugging, plugins and RPC clients. > -- cgit From bcae4af3743dbc8fc51027bbe323ddc9211cd8ca Mon Sep 17 00:00:00 2001 From: Jonas Strittmatter <40792180+smjonas@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:54:25 +0100 Subject: docs: remove mentions of 'balloonexpr' #22049 'balloonexpr' option was removed in Nvim. --- runtime/doc/cmdline.txt | 2 +- runtime/doc/eval.txt | 36 ++---------------------------------- 2 files changed, 3 insertions(+), 35 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index b4923b0d70..e0c4e14b01 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -891,7 +891,7 @@ Note: these are typed literally, they are not special keys! to form a C expression. E.g., when the cursor is on "arg" of "ptr->arg" then the result is "ptr->arg"; when the cursor is on "]" of "list[idx]" then the result is - "list[idx]". This is used for |v:beval_text|. + "list[idx]". *:* ** is replaced with the path name under the cursor (like what |gf| uses) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 58759a6053..0e77fb182e 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1670,38 +1670,6 @@ v:argv The command line arguments Vim was invoked with. This is a list of strings. The first item is the Vim command. See |v:progpath| for the command with full path. - *v:beval_col* *beval_col-variable* -v:beval_col The number of the column, over which the mouse pointer is. - This is the byte index in the |v:beval_lnum| line. - Only valid while evaluating the 'balloonexpr' option. - - *v:beval_bufnr* *beval_bufnr-variable* -v:beval_bufnr The number of the buffer, over which the mouse pointer is. Only - valid while evaluating the 'balloonexpr' option. - - *v:beval_lnum* *beval_lnum-variable* -v:beval_lnum The number of the line, over which the mouse pointer is. Only - valid while evaluating the 'balloonexpr' option. - - *v:beval_text* *beval_text-variable* -v:beval_text The text under or after the mouse pointer. Usually a word as - it is useful for debugging a C program. 'iskeyword' applies, - but a dot and "->" before the position is included. When on a - ']' the text before it is used, including the matching '[' and - word before it. When on a Visual area within one line the - highlighted text is used. Also see ||. - Only valid while evaluating the 'balloonexpr' option. - - *v:beval_winnr* *beval_winnr-variable* -v:beval_winnr The number of the window, over which the mouse pointer is. Only - valid while evaluating the 'balloonexpr' option. The first - window has number zero (unlike most other places where a - window gets a number). - - *v:beval_winid* *beval_winid-variable* -v:beval_winid The |window-ID| of the window, over which the mouse pointer - is. Otherwise like v:beval_winnr. - *v:char* *char-variable* v:char Argument for evaluating 'formatexpr' and used for the typed character when using in an abbreviation |:map-|. @@ -4244,8 +4212,8 @@ Textlock *textlock* In a few situations it is not allowed to change the text in the buffer, jump to another window and some other things that might confuse or break what Vim is currently doing. This mostly applies to things that happen when Vim is -actually doing something else. For example, evaluating the 'balloonexpr' may -happen any moment the mouse cursor is resting at some position. +actually doing something else. For example, a TextYankPost autocommand cannot +edit the text it is yanking. This is not allowed when the textlock is active: - changing the buffer text -- cgit From f43fa301c1a2817239e046a242902af65b7cac71 Mon Sep 17 00:00:00 2001 From: Eduard Baturin Date: Sat, 18 Feb 2023 09:43:59 +0300 Subject: fix(lsp): check if the buffer is a directory before w! it (#22289) --- runtime/lua/vim/lsp/util.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 38051e6410..4beb4fc367 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -759,9 +759,11 @@ function M.rename(old_fname, new_fname, opts) vim.fn.bufload(oldbuf) -- The there may be pending changes in the buffer - api.nvim_buf_call(oldbuf, function() - vim.cmd('w!') - end) + if vim.fn.isdirectory(old_fname) == 0 then + api.nvim_buf_call(oldbuf, function() + vim.cmd('w!') + end) + end local ok, err = os.rename(old_fname, new_fname) assert(ok, err) -- cgit From 2f6413797499a1bdac28c20a491e8ea3be33bda3 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 19 Feb 2023 01:27:32 +0100 Subject: vim-patch:9.0.1319: PRQL files are not recognized (#22319) Problem: PRQL files are not recognized. Solution: Add a filetype pattern for PRQL files. (Matthias Queitsch, closes vim/vim#12018) https://github.com/vim/vim/commit/9de960ace0f017fcfeaf64a2f6492f0f88b11fdb Co-authored-by: Matthias Queitsch --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index ca91f3f402..4ee7d46b20 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -810,6 +810,7 @@ local extension = { pdb = 'prolog', pml = 'promela', proto = 'proto', + prql = 'prql', ['psd1'] = 'ps1', ['psm1'] = 'ps1', ['ps1'] = 'ps1', -- cgit From b62c0c8d9c22ae7fc9ee200733f8312efa6dbced Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:12:59 +0100 Subject: docs: fix typos (#21961) Co-authored-by: Ben Morgan --- runtime/doc/eval.txt | 4 ++-- runtime/doc/intro.txt | 2 +- runtime/doc/tagsrch.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 0e77fb182e..3889b8e9a5 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1827,8 +1827,8 @@ v:event Dictionary of event data for the current |autocommand|. Valid |CompleteChanged|. scrollbar Is |v:true| if popup menu have scrollbar, or |v:false| if not. - changed_window Is |v:true| if the the event fired - while changing window (or tab) on |DirChanged|. + changed_window Is |v:true| if the event fired while + changing window (or tab) on |DirChanged|. status Job status or exit code, -1 means "unknown". |TermClose| *v:exception* *exception-variable* diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 6bf6850ccf..11ba1b408c 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -382,7 +382,7 @@ Note: - If numlock is on the |TUI| receives plain ASCII values, so mapping , , ..., and will not work. - Nvim supports mapping multibyte chars with modifiers such as ``. Which - combinations actually work depends on the the UI or host terminal. + combinations actually work depends on the UI or host terminal. - When a key is pressed using a meta or alt modifier and no mapping exists for that keypress, Nvim may behave as though was pressed before the key. - It is possible to notate combined modifiers (e.g. for CTRL-ALT-T), diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 0f785dd1eb..49e51d6736 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -92,7 +92,7 @@ The ignore-case matches are found when: - when 'tagcase' is "followscs" and 'ignorecase' is on or the 'smartcase' option is on and the pattern does not contain an upper case character - when 'tagcase' is "ignore" -- when 'tagcase' is "smart" and the patter does not contain an upper case +- when 'tagcase' is "smart" and the pattern does not contain an upper case character Note that using ignore-case tag searching disables binary searching in the -- cgit From f1816f9ee2a8b811fd6ce4e60a843087f855f97d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Feb 2023 15:13:55 +0800 Subject: refactor(main.c): remove unreachable use_builtin_ui conditions (#22338) When use_builtin_ui is true, Nvim will exit before line 385 is reached. --- runtime/doc/eval.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 3889b8e9a5..49d4546f95 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1794,7 +1794,7 @@ v:event Dictionary of event data for the current |autocommand|. Valid abort Whether the event triggered during an aborting condition (e.g. |c_Esc| or |c_CTRL-C| for |CmdlineLeave|). - chan |channel-id| or 0 for "internal". + chan |channel-id| cmdlevel Level of cmdline. cmdtype Type of cmdline, |cmdline-char|. cwd Current working directory. -- cgit From bdf6d8733e2a954031de86e9a2d09c3b03f6641d Mon Sep 17 00:00:00 2001 From: Jason Hansen Date: Mon, 20 Feb 2023 23:24:47 -0700 Subject: fix(lsp): wrong format of bufnr and client order in error message (#22336) --- runtime/lua/vim/lsp.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index c5392ac154..0a620e1367 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1736,8 +1736,8 @@ function lsp.buf_detach_client(bufnr, client_id) vim.notify( string.format( 'Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', - client_id, - bufnr + bufnr, + client_id ) ) return -- cgit From 2d99830706a8560ac6f4668b4a384afc776cc7f4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 21 Feb 2023 12:19:09 +0000 Subject: refactor(man): add type annotations --- runtime/lua/man.lua | 106 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 20 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 0956022ac6..61a9575312 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -2,6 +2,8 @@ local api, fn = vim.api, vim.fn local FIND_ARG = '-w' local localfile_arg = true -- Always use -l if possible. #6683 + +---@type table[] local buf_hls = {} local M = {} @@ -12,26 +14,28 @@ local function man_error(msg) end -- Run a system command and timeout after 30 seconds. +---@param cmd_ string[] +---@param silent boolean? +---@param env string[] +---@return string local function system(cmd_, silent, env) - local stdout_data = {} - local stderr_data = {} - local stdout = vim.loop.new_pipe(false) - local stderr = vim.loop.new_pipe(false) + local stdout_data = {} ---@type string[] + local stderr_data = {} ---@type string[] + local stdout = assert(vim.loop.new_pipe(false)) + local stderr = assert(vim.loop.new_pipe(false)) local done = false - local exit_code + local exit_code ---@type integer? -- We use the `env` command here rather than the env option to vim.loop.spawn since spawn will -- completely overwrite the environment when we just want to modify the existing one. -- -- Overwriting mainly causes problems NixOS which relies heavily on a non-standard environment. - local cmd + local cmd = cmd_ if env then cmd = { 'env' } vim.list_extend(cmd, env) vim.list_extend(cmd, cmd_) - else - cmd = cmd_ end local handle @@ -84,11 +88,17 @@ local function system(cmd_, silent, env) return table.concat(stdout_data) end +---@param line string +---@param linenr integer local function highlight_line(line, linenr) + ---@type string[] local chars = {} local prev_char = '' local overstrike, escape = false, false + + ---@type table local hls = {} -- Store highlight groups as { attr, start, final } + local NONE, BOLD, UNDERLINE, ITALIC = 0, 1, 2, 3 local hl_groups = { [BOLD] = 'manBold', [UNDERLINE] = 'manUnderline', [ITALIC] = 'manItalic' } local attr = NONE @@ -194,11 +204,12 @@ local function highlight_line(line, linenr) -- We only want to match against SGR sequences, which consist of ESC -- followed by '[', then a series of parameter and intermediate bytes in -- the range 0x20 - 0x3f, then 'm'. (See ECMA-48, sections 5.4 & 8.3.117) + ---@type string? local sgr = prev_char:match('^%[([\032-\063]*)m$') -- Ignore escape sequences with : characters, as specified by ITU's T.416 -- Open Document Architecture and interchange format. if sgr and not string.find(sgr, ':') then - local match + local match ---@type string? while sgr and #sgr > 0 do -- Match against SGR parameters, which may be separated by ';' match, sgr = sgr:match('^(%d*);?(.*)') @@ -261,11 +272,16 @@ end -- intended for PostgreSQL, which has man pages like 'CREATE_TABLE(7)'; -- while editing SQL source code, it's nice to visually select 'CREATE TABLE' -- and hit 'K', which requires this transformation +---@param str string +---@return string local function spaces_to_underscores(str) local res = str:gsub('%s', '_') return res end +---@param sect string|nil +---@param name string|nil +---@param silent boolean local function get_path(sect, name, silent) name = name or '' sect = sect or '' @@ -287,7 +303,7 @@ local function get_path(sect, name, silent) -- -- Finally, we can avoid relying on -S or -s here since they are very -- inconsistently supported. Instead, call -w with a section and a name. - local cmd + local cmd ---@type string[] if sect == '' then cmd = { 'man', FIND_ARG, name } else @@ -310,12 +326,14 @@ local function get_path(sect, name, silent) end -- find any that match the specified name + ---@param v string local namematches = vim.tbl_filter(function(v) return fn.fnamemodify(v, ':t'):match(name) end, results) or {} local sectmatches = {} if #namematches > 0 and sect ~= '' then + ---@param v string sectmatches = vim.tbl_filter(function(v) return fn.fnamemodify(v, ':e') == sect end, namematches) @@ -324,9 +342,12 @@ local function get_path(sect, name, silent) return fn.substitute(sectmatches[1] or namematches[1] or results[1], [[\n\+$]], '', '') end +---@param text string +---@param pat_or_re string local function matchstr(text, pat_or_re) local re = type(pat_or_re) == 'string' and vim.regex(pat_or_re) or pat_or_re + ---@type integer, integer local s, e = re:match_str(text) if s == nil then @@ -338,6 +359,8 @@ end -- attempt to extract the name and sect out of 'name(sect)' -- otherwise just return the largest string of valid characters in ref +---@param ref string +---@return string, string local function extract_sect_and_name_ref(ref) ref = ref or '' if ref:sub(1, 1) == '-' then -- try ':Man -pandoc' with this disabled. @@ -368,6 +391,9 @@ end -- 2. If it still could not be found, then we try again without a section. -- 3. If still not found but $MANSECT is set, then we try again with $MANSECT -- unset. +---@param sect string? +---@param name string +---@param silent boolean? local function verify_exists(sect, name, silent) if sect and sect ~= '' then local ret = get_path(sect, name, true) @@ -416,6 +442,8 @@ local EXT_RE = vim.regex([[\.\%([glx]z\|bz2\|lzma\|Z\)$]]) -- more specific than what we provided to `man` (try `:Man 3 App::CLI`). -- Also on linux, name seems to be case-insensitive. So for `:Man PRIntf`, we -- still want the name of the buffer to be 'printf'. +---@param path string +---@return string, string local function extract_sect_and_name_path(path) local tail = fn.fnamemodify(path, ':t') if EXT_RE:match_str(path) then -- valid extensions @@ -425,6 +453,7 @@ local function extract_sect_and_name_path(path) return sect, name end +---@return boolean local function find_man() if vim.bo.filetype == 'man' then return true @@ -442,6 +471,7 @@ local function find_man() return false end +---@param pager boolean local function set_options(pager) vim.bo.swapfile = false vim.bo.buftype = 'nofile' @@ -453,11 +483,14 @@ local function set_options(pager) vim.bo.filetype = 'man' end +---@param path string +---@param silent boolean? +---@return string local function get_page(path, silent) -- Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065). -- Soft-wrap: ftplugin/man.lua sets wrap/breakindent/…. -- Hard-wrap: driven by `man`. - local manwidth + local manwidth ---@type integer|string if (vim.g.man_hardwrap or 1) ~= 1 then manwidth = 999 elseif vim.env.MANWIDTH then @@ -478,6 +511,14 @@ local function get_page(path, silent) }) end +---@param lnum integer +---@return string +local function getline(lnum) + ---@diagnostic disable-next-line + return fn.getline(lnum) +end + +---@param page string local function put_page(page) vim.bo.modifiable = true vim.bo.readonly = false @@ -485,7 +526,7 @@ local function put_page(page) api.nvim_buf_set_lines(0, 0, -1, false, vim.split(page, '\n')) - while fn.getline(1):match('^%s*$') do + while getline(1):match('^%s*$') do api.nvim_buf_set_lines(0, 0, 1, false, {}) end -- XXX: nroff justifies text by filling it with whitespace. That interacts @@ -512,13 +553,21 @@ local function format_candidate(path, psect) return '' end +---@generic T +---@param list T[] +---@param elem T +---@return T[] local function move_elem_to_head(list, elem) + ---@diagnostic disable-next-line:no-unknown local list1 = vim.tbl_filter(function(v) return v ~= elem end, list) return { elem, unpack(list1) } end +---@param sect string +---@param name string +---@return string[] local function get_paths(sect, name) -- Try several sources for getting the list man directories: -- 1. `man -w` (works on most systems) @@ -533,6 +582,7 @@ local function get_paths(sect, name) end local mandirs = table.concat(vim.split(mandirs_raw, '[:\n]', { trimempty = true }), ',') + ---@type string[] local paths = fn.globpath(mandirs, 'man?/' .. name .. '*.' .. sect .. '*', false, true) -- Prioritize the result from verify_exists as it obeys b:man_default_sects. @@ -544,6 +594,10 @@ local function get_paths(sect, name) return paths end +---@param sect string +---@param psect string +---@param name string +---@return string[] local function complete(sect, psect, name) local pages = get_paths(sect, name) -- We remove duplicates in case the same manpage in different languages was found. @@ -553,6 +607,8 @@ local function complete(sect, psect, name) end -- see extract_sect_and_name_ref on why tolower(sect) +---@param arg_lead string +---@param cmd_line string function M.man_complete(arg_lead, cmd_line, _) local args = vim.split(cmd_line, '%s+', { trimempty = true }) local cmd_offset = fn.index(args, 'Man') @@ -589,6 +645,7 @@ function M.man_complete(arg_lead, cmd_line, _) end if #args == 2 then + ---@type string, string local name, sect if arg_lead == '' then -- cursor (|) is at ':Man 1 |' @@ -618,10 +675,13 @@ function M.man_complete(arg_lead, cmd_line, _) return complete(sect, sect, name) end +---@param pattern string +---@return {name:string,filename:string,cmd:string}[] function M.goto_tag(pattern, _, _) local sect, name = extract_sect_and_name_ref(pattern) local paths = get_paths(sect, name) + ---@type {name:string,title:string}[] local structured = {} for _, path in ipairs(paths) do @@ -634,6 +694,7 @@ function M.goto_tag(pattern, _, _) end end + ---@param entry {name:string,title:string} return vim.tbl_map(function(entry) return { name = entry.name, @@ -645,7 +706,7 @@ end -- Called when Nvim is invoked as $MANPAGER. function M.init_pager() - if fn.getline(1):match('^%s*$') then + if getline(1):match('^%s*$') then api.nvim_buf_set_lines(0, 0, 1, false, {}) else vim.cmd('keepjumps 1') @@ -653,7 +714,7 @@ function M.init_pager() highlight_man_page() -- Guess the ref from the heading (which is usually uppercase, so we cannot -- know the correct casing, cf. `man glDrawArraysInstanced`). - local ref = fn.substitute(matchstr(fn.getline(1), [[^[^)]\+)]]) or '', ' ', '_', 'g') + local ref = fn.substitute(matchstr(getline(1), [[^[^)]\+)]]) or '', ' ', '_', 'g') local ok, res = pcall(extract_sect_and_name_ref, ref) vim.b.man_sect = ok and res or '' @@ -664,12 +725,14 @@ function M.init_pager() set_options(true) end +---@param count integer +---@param args string[] function M.open_page(count, smods, args) if #args > 2 then man_error('too many arguments') end - local ref + local ref ---@type string if #args == 0 then ref = vim.bo.filetype == 'man' and fn.expand('') or fn.expand('') if ref == '' then @@ -731,24 +794,27 @@ function M.read_page(ref) end function M.show_toc() - local bufname = fn.bufname('%') + local bufnr = api.nvim_get_current_buf() + local bufname = api.nvim_buf_get_name(bufnr) local info = fn.getloclist(0, { winid = 1 }) if info ~= '' and vim.w[info.winid].qf_toc == bufname then vim.cmd.lopen() return end + ---@type {bufnr:integer, lnum:integer, text:string}[] local toc = {} + local lnum = 2 local last_line = fn.line('$') - 1 local section_title_re = vim.regex([[^\%( \{3\}\)\=\S.*$]]) local flag_title_re = vim.regex([[^\s\+\%(+\|-\)\S\+]]) while lnum and lnum < last_line do - local text = fn.getline(lnum) + local text = getline(lnum) if section_title_re:match_str(text) then -- if text is a section title toc[#toc + 1] = { - bufnr = fn.bufnr('%'), + bufnr = bufnr, lnum = lnum, text = text, } @@ -756,7 +822,7 @@ function M.show_toc() -- if text is a flag title. we strip whitespaces and prepend two -- spaces to have a consistent format in the loclist. toc[#toc + 1] = { - bufnr = fn.bufnr('%'), + bufnr = bufnr, lnum = lnum, text = ' ' .. fn.substitute(text, [[^\s*\(.\{-}\)\s*$]], [[\1]], ''), } @@ -772,7 +838,7 @@ end local function init() local path = get_path('', 'man', true) - local page + local page ---@type string? if path ~= nil then -- Check for -l support. page = get_page(path, true) -- cgit From ee26b227e15abc263195d4c746d5dba9f0e6dec4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 21 Feb 2023 23:50:29 +0800 Subject: vim-patch:partial:938ae280c79b (#22356) Update runtime files. https://github.com/vim/vim/commit/938ae280c79b8cdb0fca60336ec4c090ecd8bb5a Partially skip autocmd.txt: needs patch 8.2.5011. Partially skip builtin.txt: needs patch 9.0.0411. Partially skip eval.txt: needs patch 8.2.3783. Cherry-pick :map-meta-keys from patch 9.0.1276. Co-authored-by: Bram Moolenaar --- runtime/doc/autocmd.txt | 1 + runtime/doc/builtin.txt | 17 ++-- runtime/doc/cmdline.txt | 1 + runtime/doc/eval.txt | 2 +- runtime/doc/filetype.txt | 5 +- runtime/doc/if_pyth.txt | 2 +- runtime/doc/index.txt | 4 +- runtime/doc/insert.txt | 6 +- runtime/doc/map.txt | 27 ++++- runtime/doc/options.txt | 16 +-- runtime/doc/pattern.txt | 16 +-- runtime/doc/pi_netrw.txt | 38 +++---- runtime/doc/remote.txt | 2 +- runtime/doc/repeat.txt | 20 ++-- runtime/doc/sign.txt | 2 +- runtime/doc/syntax.txt | 28 ++++-- runtime/doc/uganda.txt | 2 +- runtime/doc/userfunc.txt | 7 +- runtime/doc/usr_02.txt | 2 +- runtime/doc/usr_05.txt | 2 +- runtime/doc/usr_22.txt | 40 ++++---- runtime/ftplugin/dosbatch.vim | 18 +++- runtime/ftplugin/fish.vim | 15 +++ runtime/ftplugin/vim.vim | 23 +++-- runtime/indent/fish.vim | 82 +++++++++++++++ runtime/syntax/debsources.vim | 10 +- runtime/syntax/dosbatch.vim | 39 ++++---- runtime/syntax/fish.vim | 225 ++++++++++++++++++++++++++++++++++++++++++ runtime/syntax/fstab.vim | 8 +- runtime/syntax/go.vim | 7 +- runtime/syntax/html.vim | 4 +- runtime/syntax/poefilter.vim | 4 +- 32 files changed, 533 insertions(+), 142 deletions(-) create mode 100644 runtime/ftplugin/fish.vim create mode 100644 runtime/indent/fish.vim create mode 100644 runtime/syntax/fish.vim (limited to 'runtime') diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 8cc4754880..89252145f2 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -380,6 +380,7 @@ CmdlineChanged After a change was made to the text inside CmdlineEnter After entering the command-line (including non-interactive use of ":" in a mapping: use || instead to avoid this). + The pattern is matched against |cmdline-char|. expands to the |cmdline-char|. Sets these |v:event| keys: cmdlevel diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 2fc7dce7fc..60a1035da3 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -225,7 +225,7 @@ gettabwinvar({tabnr}, {winnr}, {name} [, {def}]) gettagstack([{nr}]) Dict get the tag stack of window {nr} gettext({text}) String lookup translation of {text} getwininfo([{winid}]) List list of info about each window -getwinpos([{timeout}]) List X and Y coord in pixels of the Vim window +getwinpos([{timeout}]) List X and Y coord in pixels of Vim window getwinposx() Number X coord in pixels of Vim window getwinposy() Number Y coord in pixels of Vim window getwinvar({nr}, {varname} [, {def}]) @@ -326,7 +326,7 @@ max({expr}) Number maximum value of items in {expr} menu_get({path} [, {modes}]) List description of |menus| matched by {path} menu_info({name} [, {mode}]) Dict get menu item information min({expr}) Number minimum value of items in {expr} -mkdir({name} [, {path} [, {prot}]]) +mkdir({name} [, {flags} [, {prot}]]) Number create directory {name} mode([expr]) String current editing mode msgpackdump({list} [, {type}]) List/Blob dump objects to msgpack @@ -5432,11 +5432,14 @@ min({expr}) Return the minimum value of all items in {expr}. Example: > mylist->min() < *mkdir()* *E739* -mkdir({name} [, {path} [, {prot}]]) +mkdir({name} [, {flags} [, {prot}]]) Create directory {name}. - If {path} is "p" then intermediate directories are created as - necessary. Otherwise it must be "". + When {flags} is present it must be a string. An empty string + has no effect. + + If {flags} is "p" then intermediate directories are created as + necessary. If {prot} is given it is used to set the protection bits of the new directory. The default is 0o755 (rwxr-xr-x: r/w for @@ -5449,7 +5452,7 @@ mkdir({name} [, {path} [, {prot}]]) < This function is not available in the |sandbox|. - If you try to create an existing directory with {path} set to + If you try to create an existing directory with {flags} set to "p" mkdir() will silently exit. The function result is a Number, which is TRUE if the call was @@ -6957,7 +6960,7 @@ setcellwidths({list}) *setcellwidths()* {width} must be either 1 or 2, indicating the character width in screen cells. *E1112* An error is given if the argument is invalid, also when a - range overlaps with another. *E1113* + range overlaps with another. *E1113* If the new value causes 'fillchars' or 'listchars' to become invalid it is rejected and an error is given. diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index e0c4e14b01..844aab6fa3 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -584,6 +584,7 @@ followed by another Vim command: :registers :read ! :sign + :tabdo :terminal :vglobal :windo diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 49d4546f95..af67e2b67d 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1445,7 +1445,7 @@ See below |functions|. ------------------------------------------------------------------------------ lambda expression *expr-lambda* *lambda* -{args -> expr1} lambda expression +{args -> expr1} lambda expression *E451* A lambda expression creates a new unnamed function which returns the result of evaluating |expr1|. Lambda expressions differ from |user-function|s in diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index a53c287d48..f69ffeabfe 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -634,7 +634,10 @@ MARKDOWN *ft-markdown-plugin* To enable folding use this: > let g:markdown_folding = 1 -< + +'expandtab' will be set by default. If you do not want that use this: > + let g:markdown_recommended_style = 0 + PDF *ft-pdf-plugin* diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index 4c184ddf94..45accc2e03 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -629,7 +629,7 @@ You can test if Python is available with: >vim if has('pythonx') echo 'there is Python' endif - if has('python3') + if has('python3') echo 'there is Python 3.x' endif diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index a6aa036b55..174683a8c3 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -220,7 +220,7 @@ tag char note action in Normal mode ~ |CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode (no-op) |CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode (no-op) CTRL-\ a - z reserved for extensions - CTRL-\ others not used + CTRL-\ others not used |CTRL-]| CTRL-] :ta to ident under cursor |CTRL-^| CTRL-^ edit Nth alternate file (equivalent to ":e #N") @@ -233,7 +233,7 @@ tag char note action in Normal mode ~ 2 filter Nmove text through the {filter} command |!!| !!{filter} 2 filter N lines through the {filter} command -|quote| "{register} use {register} for next delete, yank or put +|quote| "{register} use {register} for next delete, yank or put ({.%#:} only work with put) |#| # 1 search backward for the Nth occurrence of the ident under the cursor diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index e608b431f2..84aee43af4 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1101,8 +1101,8 @@ cursor column will be replaced with the matches. If the returned value is larger than the cursor column, the cursor column is used. Negative return values: - -2 To cancel silently and stay in completion mode. - -3 To cancel silently and leave completion mode. + -2 To cancel silently and stay in completion mode. + -3 To cancel silently and leave completion mode. Another negative value: completion starts at the cursor column On the second invocation the arguments are: @@ -1154,7 +1154,7 @@ items: item with the same word is already present. empty when non-zero this match will be added even when it is an empty string - user_data custom data which is associated with the item and + user_data custom data which is associated with the item and available in |v:completed_item|; it can be any type; defaults to an empty string diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index cb8b162eb6..ad0570e9f7 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -764,7 +764,7 @@ option). After that it assumes that the 'q' is to be interpreted as such. If you type slowly, or your system is slow, reset the 'timeout' option. Then you might want to set the 'ttimeout' option. - *map-precedence* + *map-precedence* Buffer-local mappings (defined using |:map-|) take precedence over global mappings. When a buffer-local mapping is the same as a global mapping, Vim will use the buffer-local mapping. In addition, Vim will use a complete @@ -838,6 +838,11 @@ in the original Vi, you would get back the text before the first undo). 1.10 MAPPING ALT-KEYS *:map-alt-keys* +For a readable mapping command the form can be used. Note that +and are different, the latter will use an upper case letter. Actually, + and are the same. Instead of "A" you can use "M". If you have +an actual Meta modifier key, please see |:map-meta-keys|. + In the GUI Nvim handles the |ALT| key itself, thus mapping keys with ALT should always work. But in a terminal Nvim gets a sequence of bytes and has to figure out whether ALT was pressed. Terminals may use ESC to indicate that @@ -847,7 +852,21 @@ milliseconds, the ESC is interpreted as: otherwise it is interpreted as two key presses: {key} -1.11 MAPPING AN OPERATOR *:map-operator* +1.11 MAPPING META-KEYS *:map-meta-keys* + +Mapping keys with the Meta modifier works very similar to using the Alt key. +What key on your keyboard produces the Meta modifier depends on your keyboard +and configuration. + +Note that mapping actually is for using the Alt key. That can be +confusing! It cannot be changed, it would not be backwards compatible. + +For the Meta modifier the "T" character is used. For example, to map Meta-b +in Insert mode: > + :imap terrible + + +1.12 MAPPING AN OPERATOR *:map-operator* An operator is used before a {motion} command. To define your own operator you must create a mapping that first sets the 'operatorfunc' option and then @@ -984,7 +1003,7 @@ non-id The "non-id" type ends in a non-keyword character, the other Examples of strings that cannot be abbreviations: "a.b", "#def", "a b", "_$r" An abbreviation is only recognized when you type a non-keyword character. -This can also be the that ends insert mode or the that ends a +This can also be the that ends Insert mode or the that ends a command. The non-keyword character which ends the abbreviation is inserted after the expanded abbreviation. An exception to this is the character , which is used to expand an abbreviation without inserting any extra @@ -1484,7 +1503,7 @@ which by default correspond to the current line, last line and the whole buffer, relate to arguments, (loaded) buffers, windows or tab pages. Possible values are (second column is the short name used in listing): - -addr=lines Range of lines (this is the default for -range) + -addr=lines Range of lines (this is the default for -range) -addr=arguments arg Range for arguments -addr=buffers buf Range for buffers (also not loaded buffers) -addr=loaded_buffers load Range for loaded buffers diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e4106358f1..d13ab8c393 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1186,7 +1186,7 @@ A jump table for the options with a short description can be found at |Q_op|. case mapping, the current locale is not effective. This probably only matters for Turkish. - *'cdhome'* *'cdh'* + *'cdhome'* *'cdh'* *'nocdhome'* *'nocdh'* 'cdhome' 'cdh' boolean (default: off) global When on, |:cd|, |:tcd| and |:lcd| without an argument changes the @@ -4291,7 +4291,7 @@ A jump table for the options with a short description can be found at |Q_op|. The 'mousemodel' option is set by the |:behave| command. - *'mousemoveevent'* *'mousemev'* + *'mousemoveevent'* *'mousemev'* *'nomousemoveevent'* *'nomousemev'* 'mousemoveevent' 'mousemev' boolean (default off) global When on, mouse move events are delivered to the input queue and are @@ -5550,7 +5550,7 @@ A jump table for the options with a short description can be found at |Q_op|. A don't give the "ATTENTION" message when an existing *shm-A* swap file is found I don't give the intro message when starting Vim, *shm-I* - see |:intro| + see |:intro| c don't give |ins-completion-menu| messages; for *shm-c* example, "-- XXX completion (YYY)", "match 1 of 2", "The only match", "Pattern not found", "Back at original", etc. @@ -5559,8 +5559,8 @@ A jump table for the options with a short description can be found at |Q_op|. q use "recording" instead of "recording @a" *shm-q* F don't give the file info when editing a file, like *shm-F* `:silent` was used for the command - S do not show search count message when searching, e.g. *shm-S* - "[1/5]" + S do not show search count message when searching, e.g. *shm-S* + "[1/5]" This gives you the opportunity to avoid that a change between buffers requires you to hit , but still gives as useful a message as @@ -5709,7 +5709,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'signcolumn' 'scl' string (default "auto") local to window When and how to draw the signcolumn. Valid values are: - "auto" only when there is a sign to display + "auto" only when there is a sign to display "auto:[1-9]" resize to accommodate multiple signs up to the given number (maximum 9), e.g. "auto:4" "auto:[1-8]-[2-9]" @@ -5718,8 +5718,8 @@ A jump table for the options with a short description can be found at |Q_op|. at least the given minimum (maximum 8) fixed space. The minimum number should always be less than the maximum number, e.g. "auto:2-5" - "no" never - "yes" always + "no" never + "yes" always "yes:[1-9]" always, with fixed space for signs up to the given number (maximum 9), e.g. "yes:3" "number" display signs in the 'number' column. If the number diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 5357aaa3f1..625e1f95e1 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -97,6 +97,8 @@ g# Like "#", but don't put "\<" and "\>" around the word. *gd* gd Goto local Declaration. When the cursor is on a local variable, this command will jump to its declaration. + This was made to work for C code, in other languages + it may not work well. First Vim searches for the start of the current function, just like "[[". If it is not found the search stops in line 1. If it is found, Vim goes back @@ -1129,21 +1131,21 @@ x A single character, with no special meaning, matches itself are supported: Name Func Contents ~ *[:alnum:]* [:alnum:] isalnum ASCII letters and digits -*[:alpha:]* [:alpha:] isalpha ASCII letters -*[:blank:]* [:blank:] space and tab -*[:cntrl:]* [:cntrl:] iscntrl ASCII control characters -*[:digit:]* [:digit:] decimal digits '0' to '9' +*[:alpha:]* [:alpha:] isalpha ASCII letters +*[:blank:]* [:blank:] space and tab +*[:cntrl:]* [:cntrl:] iscntrl ASCII control characters +*[:digit:]* [:digit:] decimal digits '0' to '9' *[:graph:]* [:graph:] isgraph ASCII printable characters excluding space *[:lower:]* [:lower:] (1) lowercase letters (all letters when 'ignorecase' is used) -*[:print:]* [:print:] (2) printable characters including space +*[:print:]* [:print:] (2) printable characters including space *[:punct:]* [:punct:] ispunct ASCII punctuation characters -*[:space:]* [:space:] whitespace characters: space, tab, CR, +*[:space:]* [:space:] whitespace characters: space, tab, CR, NL, vertical tab, form feed *[:upper:]* [:upper:] (3) uppercase letters (all letters when 'ignorecase' is used) -*[:xdigit:]* [:xdigit:] hexadecimal digits: 0-9, a-f, A-F +*[:xdigit:]* [:xdigit:] hexadecimal digits: 0-9, a-f, A-F *[:return:]* [:return:] the character *[:tab:]* [:tab:] the character *[:escape:]* [:escape:] the character diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 5167b4baf7..d3d5e4605a 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1085,8 +1085,8 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2 Shrink/expand a netrw/explore window |netrw-c-tab| - Makes Netrw go up one directory |netrw--| a Cycles between normal display, |netrw-a| - hiding (suppress display of files matching g:netrw_list_hide) - and showing (display only files which match g:netrw_list_hide) + hiding (suppress display of files matching g:netrw_list_hide) + and showing (display only files which match g:netrw_list_hide) cd Make browsing directory the current directory |netrw-cd| C Setting the editing window |netrw-C| d Make a directory |netrw-d| @@ -1118,7 +1118,7 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2 mX Apply arbitrary shell command to marked files en bloc|netrw-mX| mz Compress/decompress marked files |netrw-mz| o Enter the file/directory under the cursor in a new |netrw-o| - browser window. A horizontal split is used. + browser window. A horizontal split is used. O Obtain a file specified by cursor |netrw-O| p Preview the file |netrw-p| P Browse in the previously used window |netrw-P| @@ -1134,7 +1134,7 @@ QUICK REFERENCE: MAPS *netrw-browse-maps* {{{2 u Change to recently-visited directory |netrw-u| U Change to subsequently-visited directory |netrw-U| v Enter the file/directory under the cursor in a new |netrw-v| - browser window. A vertical split is used. + browser window. A vertical split is used. x View file with an associated program |netrw-x| X Execute filename under cursor via |system()| |netrw-X| @@ -2271,7 +2271,7 @@ Example: ... -MARKED FILES, ARBITRARY SHELL COMMAND, EN BLOC *netrw-mX* {{{2 +MARKED FILES, ARBITRARY SHELL COMMAND, EN BLOC *netrw-mX* {{{2 (See |netrw-mf| and |netrw-mr| for how to mark files) (uses the global marked-file list) @@ -2611,7 +2611,7 @@ your browsing preferences. (see also: |netrw-settings|) Used to change access permission for a file. *g:netrw_clipboard* =1 - By default, netrw will attempt to insure that + By default, netrw will attempt to insure that the clipboard's values will remain unchanged. However, some users report that they have speed problems with this; consequently, this @@ -2759,7 +2759,7 @@ your browsing preferences. (see also: |netrw-settings|) escaped before applying glob() *g:netrw_gx* ="" - This option controls how gx (|netrw-gx|) picks + This option controls how gx (|netrw-gx|) picks up the text under the cursor. See |expand()| for possibilities. @@ -2824,11 +2824,11 @@ your browsing preferences. (see also: |netrw-settings|) directory (|netrw-mt|, |netrw-mc|) *g:netrw_localcopycmdopt* ='' Linux/Unix/MacOS/Cygwin - =' \c copy' Windows + =' \c copy' Windows Options for the |g:netrw_localcopycmd| *g:netrw_localcopydircmd* ="cp" Linux/Unix/MacOS/Cygwin - =expand("$COMSPEC") Windows + =expand("$COMSPEC") Windows Copies directories to target directory. (|netrw-mc|, |netrw-mt|) @@ -2854,7 +2854,7 @@ your browsing preferences. (see also: |netrw-settings|) Options for |g:netrw_localmovecmd| *g:netrw_localrmdir* ="rmdir" Linux/Unix/MacOS/Cygwin - =expand("$COMSPEC") Windows + =expand("$COMSPEC") Windows Remove directory command (rmdir) This variable is only used if your vim is earlier than 7.4 or if your vim doesn't @@ -2890,10 +2890,10 @@ your browsing preferences. (see also: |netrw-settings|) (see |'ballooneval'|) *g:netrw_sizestyle* not defined: actual bytes (default) - ="b" : actual bytes (default) - ="h" : human-readable (ex. 5k, 4m, 3g) + ="b" : actual bytes (default) + ="h" : human-readable (ex. 5k, 4m, 3g) uses 1000 base - ="H" : human-readable (ex. 5K, 4M, 3G) + ="H" : human-readable (ex. 5K, 4M, 3G) uses 1024 base The long listing (|netrw-i|) and query-file maps (|netrw-qf|) will display file size @@ -2941,7 +2941,7 @@ your browsing preferences. (see also: |netrw-settings|) default: "NETRWSERVER" *g:netrw_sort_by* sort by "name", "time", "size", or - "exten". + "exten". default: "name" *g:netrw_sort_direction* sorting direction: "normal" or "reverse" @@ -2998,7 +2998,7 @@ your browsing preferences. (see also: |netrw-settings|) .vim/after/syntax/netrw.vim. < The netrwGray highlighting is set up by netrw when > - * netrwGray has not been previously + * netrwGray has not been previously defined * the gui is running < As an example, I myself use a dark-background @@ -3256,7 +3256,7 @@ If there are marked files: (see |netrw-mf|) name, applying that substitute, and renaming each file to the result. As an example : > - mr [query: reply with *.c] + mr [query: reply with *.c] R [query: reply with s/^\(.*\)\.c$/\1.cpp/] < This example will mark all "*.c" files and then rename them to "*.cpp" @@ -3265,7 +3265,7 @@ If there are marked files: (see |netrw-mf|) The ctrl-X character has special meaning for renaming files: > - : a single ctrl-x tells netrw to ignore the portion of the response + : a single ctrl-x tells netrw to ignore the portion of the response lying between the last '/' and the ctrl-x. : a pair of contiguous ctrl-x's tells netrw to ignore any @@ -3833,7 +3833,7 @@ netrw: Decho.vim is provided as a "vimball". You should edit the Decho.vba.gz file and source it in: > - vim Decho.vba.gz + vim Decho.vba.gz :so % :q < @@ -3875,7 +3875,7 @@ netrw: To save the file: under linux, the output will be in a separate remote server window; in it, just save the file with > - :w! DBG + :w! DBG < Under a vim that doesn't support clientserver, your debugging output will appear in another tab: > diff --git a/runtime/doc/remote.txt b/runtime/doc/remote.txt index 4610088ab0..804645f774 100644 --- a/runtime/doc/remote.txt +++ b/runtime/doc/remote.txt @@ -46,7 +46,7 @@ The following command line arguments are available: new tabpage. *--remote-send* --remote-send {keys} Send {keys} to server and exit. The {keys} - are not mapped. Special key names are + are not mapped. Special key names are recognized, e.g., "" results in a CR character. *--remote-expr* diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index bf77aacdc0..23030761dd 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -214,7 +214,7 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. When [where] is omitted only 'runtimepath' is used. Other values: START search only under "start" in 'packpath' - OPT search only under "opt" in 'packpath' + OPT search only under "opt" in 'packpath' PACK search under "start" and "opt" in 'packpath' ALL first use 'runtimepath', then search @@ -641,15 +641,15 @@ up-to-date easily, but it requires a program like "git" to be available. You can do both, github can automatically create an archive for a release. Your directory layout would be like this: - start/foobar/plugin/foo.vim " always loaded, defines commands - start/foobar/plugin/bar.vim " always loaded, defines commands - start/foobar/autoload/foo.vim " loaded when foo command used - start/foobar/doc/foo.txt " help for foo.vim - start/foobar/doc/tags " help tags - opt/fooextra/plugin/extra.vim " optional plugin, defines commands - opt/fooextra/autoload/extra.vim " loaded when extra command used - opt/fooextra/doc/extra.txt " help for extra.vim - opt/fooextra/doc/tags " help tags + start/foobar/plugin/foo.vim " always loaded, defines commands + start/foobar/plugin/bar.vim " always loaded, defines commands + start/foobar/autoload/foo.vim " loaded when foo command used + start/foobar/doc/foo.txt " help for foo.vim + start/foobar/doc/tags " help tags + opt/fooextra/plugin/extra.vim " optional plugin, defines commands + opt/fooextra/autoload/extra.vim " loaded when extra command used + opt/fooextra/doc/extra.txt " help for extra.vim + opt/fooextra/doc/tags " help tags This allows for the user to do: > mkdir ~/.local/share/nvim/site/pack diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index d09d0f226f..53ef03eb63 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -610,7 +610,7 @@ sign_placelist({list}) be placed. For the accepted values, see |line()|. name name of the sign to place. See |sign_define()| - for more information. + for more information. priority priority of the sign. When multiple signs are placed on a line, the sign with the highest priority is used. If not specified, the diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index bd5a4f1926..7102e93f0a 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1271,18 +1271,32 @@ When not set 4 is used. DOSBATCH *dosbatch.vim* *ft-dosbatch-syntax* -There is one option with highlighting DOS batch files. This covers new -extensions to the Command Interpreter introduced with Windows 2000 and -is controlled by the variable dosbatch_cmdextversion. For Windows NT -this should have the value 1, and for Windows 2000 it should be 2. +Select the set of Windows Command interpreter extensions that should be +supported with the variable dosbatch_cmdextversion. For versions of Windows +NT (before Windows 2000) this should have the value of 1. For Windows 2000 +and later it should be 2. Select the version you want with the following line: > :let dosbatch_cmdextversion = 1 If this variable is not defined it defaults to a value of 2 to support -Windows 2000. +Windows 2000 and later. -A second option covers whether *.btm files should be detected as type +The original MS-DOS supports an idiom of using a double colon (::) as an +alternative way to enter a comment line. This idiom can be used with the +current Windows Command Interpreter, but it can lead to problems when used +inside ( ... ) command blocks. You can find a discussion about this on +Stack Overflow - + +https://stackoverflow.com/questions/12407800/which-comment-style-should-i-use-in-batch-files + +To allow the use of the :: idiom for comments in the Windows Command +Interpreter or working with MS-DOS bat files, set the +dosbatch_colons_comment variable to anything: > + + :let dosbatch_colons_comment = 1 + +There is an option that covers whether *.btm files should be detected as type "dosbatch" (MS-DOS batch files) or type "btm" (4DOS batch files). The latter is used by default. You may select the former with the following line: > @@ -3784,7 +3798,7 @@ SYNTAX ISKEYWORD SETTING *:syn-iskeyword* clear: Syntax specific iskeyword setting is disabled and the buffer-local 'iskeyword' setting is used. - {option} Set the syntax 'iskeyword' option to a new value. + {option} Set the syntax 'iskeyword' option to a new value. Example: > :syntax iskeyword @,48-57,192-255,$,_ diff --git a/runtime/doc/uganda.txt b/runtime/doc/uganda.txt index d8fc26ad17..fc38f5b73c 100644 --- a/runtime/doc/uganda.txt +++ b/runtime/doc/uganda.txt @@ -246,7 +246,7 @@ Credit Card: You can use PayPal to send money with a Credit card. This is Bram@iccf-holland.org Others: Transfer to this account if possible: - ING bank: IBAN: NL95 INGB 0004 5487 74 + ING bank: IBAN: NL95 INGB 0004 5487 74 Swift code: INGBNL2A under the name "stichting ICCF Holland", Amersfoort Checks are not accepted. diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt index 9c428175bb..ce6f2fc2e9 100644 --- a/runtime/doc/userfunc.txt +++ b/runtime/doc/userfunc.txt @@ -234,9 +234,10 @@ Example: > call Something('key', 20) "key: 20" The argument default expressions are evaluated at the time of the function -call, not definition. Thus it is possible to use an expression which is -invalid the moment the function is defined. The expressions are also only -evaluated when arguments are not specified during a call. +call, not when the function is defined. Thus it is possible to use an +expression which is invalid the moment the function is defined. The +expressions are also only evaluated when arguments are not specified during a +call. *E989* Optional arguments with default expressions must occur after any mandatory diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt index 11afe39742..259bb41200 100644 --- a/runtime/doc/usr_02.txt +++ b/runtime/doc/usr_02.txt @@ -495,7 +495,7 @@ You can use the error ID at the start to find help about it: > :help E37 -Summary: *help-summary* > +Summary: *help-summary* > 1) Use Ctrl-D after typing a topic and let Vim show all available topics. Or press Tab to complete: > diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt index 24d6185eae..d8fb2acedb 100644 --- a/runtime/doc/usr_05.txt +++ b/runtime/doc/usr_05.txt @@ -273,7 +273,7 @@ an archive or as a repository. For an archive you can follow these steps: package. 2. unpack the archive in that directory. This assumes the top directory in the archive is "start": > - cd ~/.local/share/nvim/site/pack/fancy + cd ~/.local/share/nvim/site/pack/fancy unzip /tmp/fancy.zip < If the archive layout is different make sure that you end up with a path like this: diff --git a/runtime/doc/usr_22.txt b/runtime/doc/usr_22.txt index 539bda3980..d977b20ecc 100644 --- a/runtime/doc/usr_22.txt +++ b/runtime/doc/usr_22.txt @@ -77,25 +77,25 @@ browser. This is what you get: > 9. Directory Browsing netrw-browse netrw-dir netrw-list netrw-help MAPS netrw-maps - .............Help.......................................|netrw-help| - .............Browsing...................................|netrw-cr| - ............Deleting Files or Directories..............|netrw-delete| - -................Going Up...................................|netrw--| - a................Hiding Files or Directories................|netrw-a| - mb...............Bookmarking a Directory....................|netrw-mb| - gb...............Changing to a Bookmarked Directory.........|netrw-gb| - cd...............Make Browsing Directory The Current Dir....|netrw-c| - d................Make A New Directory.......................|netrw-d| - D................Deleting Files or Directories..............|netrw-D| - ............Edit File/Directory Hiding List............|netrw-ctrl-h| - i................Change Listing Style.......................|netrw-i| - ............Refreshing the Listing.....................|netrw-ctrl-l| - o................Browsing with a Horizontal Split...........|netrw-o| - p................Use Preview Window.........................|netrw-p| - P................Edit in Previous Window....................|netrw-p| - q................Listing Bookmarks and History..............|netrw-qb| - r................Reversing Sorting Order....................|netrw-r| -< (etc) + .............Help.......................................|netrw-help| + .............Browsing...................................|netrw-cr| + ............Deleting Files or Directories..............|netrw-delete| + -................Going Up...................................|netrw--| + a................Hiding Files or Directories................|netrw-a| + mb...............Bookmarking a Directory....................|netrw-mb| + gb...............Changing to a Bookmarked Directory.........|netrw-gb| + cd...............Make Browsing Directory The Current Dir....|netrw-c| + d................Make A New Directory.......................|netrw-d| + D................Deleting Files or Directories..............|netrw-D| + ............Edit File/Directory Hiding List............|netrw-ctrl-h| + i................Change Listing Style.......................|netrw-i| + ............Refreshing the Listing.....................|netrw-ctrl-l| + o................Browsing with a Horizontal Split...........|netrw-o| + p................Use Preview Window.........................|netrw-p| + P................Edit in Previous Window....................|netrw-p| + q................Listing Bookmarks and History..............|netrw-qb| + r................Reversing Sorting Order....................|netrw-r| +< (etc) The key thus brings you to a netrw directory browsing contents help page. It's a regular help page; use the usual |CTRL-]| to jump to tagged help items @@ -106,7 +106,7 @@ To select files for display and editing: (with the cursor is atop a filename) Open the file in the current window. |netrw-cr| o Horizontally split window and display file |netrw-o| v Vertically split window and display file |netrw-v| - p Use the |preview-window| |netrw-p| + p Use the |preview-window| |netrw-p| P Edit in the previous window |netrw-P| t Open file in a new tab |netrw-t| diff --git a/runtime/ftplugin/dosbatch.vim b/runtime/ftplugin/dosbatch.vim index 0c5cde2503..f02f26b1fd 100644 --- a/runtime/ftplugin/dosbatch.vim +++ b/runtime/ftplugin/dosbatch.vim @@ -1,7 +1,10 @@ " Vim filetype plugin file -" Language: MS-DOS .bat files -" Maintainer: Mike Williams -" Last Change: 7th May 2020 +" Language: MS-DOS/Windows .bat files +" Maintainer: Mike Williams +" Last Change: 12th February 2023 +" +" Options Flags: +" dosbatch_colons_comment - any value to treat :: as comment line " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -15,8 +18,13 @@ let s:cpo_save = &cpo set cpo&vim " BAT comment formatting -setlocal comments=b:rem,b:@rem,b:REM,b:@REM,::: -setlocal commentstring=::\ %s +setlocal comments=b:rem,b:@rem,b:REM,b:@REM +if exists("dosbatch_colons_comment") + setlocal comments+=::: + setlocal commentstring=::\ %s +else + setlocal commentstring=REM\ %s +endif setlocal formatoptions-=t formatoptions+=rol " Lookup DOS keywords using Windows command help. diff --git a/runtime/ftplugin/fish.vim b/runtime/ftplugin/fish.vim new file mode 100644 index 0000000000..7acbf44210 --- /dev/null +++ b/runtime/ftplugin/fish.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin file +" Language: fish +" Maintainer: Nicholas Boyle (github.com/nickeb96) +" Repository: https://github.com/nickeb96/fish.vim +" Last Change: February 1, 2023 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal iskeyword=@,48-57,_,192-255,-,. +setlocal comments=:# +setlocal commentstring=#%s +setlocal formatoptions+=crjq diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index b64bb55d68..a2cbc28971 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar -" Last Change: 2022 Nov 27 +" Last Change: 2023 Feb 07 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -98,18 +98,23 @@ if exists("loaded_matchit") " func name " require a parenthesis following, then there can be an "endfunc". let b:match_words = - \ '\<\%(fu\%[nction]\|def\)!\=\s\+\S\+\s*(:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\<\%(endf\%[unction]\|enddef\)\>,' . - \ '\<\(wh\%[ile]\|for\)\>:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' . - \ '\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' . - \ '{:},' . - \ '\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' . - \ '\\)\@!\S:\,' + \ '\<\%(fu\%[nction]\|def\)!\=\s\+\S\+\s*(:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\<\%(endf\%[unction]\|enddef\)\>,' .. + \ '\<\%(wh\%[ile]\|for\)\>:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' .. + \ '\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' .. + \ '{:},' .. + \ '\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\:\%(\%(^\||\)\s*\)\@<=\,' .. + \ '\\)\@!\S:\,' .. + \ '\:\,' .. + \ '\:\,' .. + \ '\:\,' + " Ignore syntax region commands and settings, any 'en*' would clobber " if-endif. " - set spl=de,en " - au! FileType javascript syntax region foldBraces start=/{/ end=/}/ … - let b:match_skip = 'synIDattr(synID(line("."),col("."),1),"name") - \ =~? "comment\\|string\\|vimLetHereDoc\\|vimSynReg\\|vimSet"' + " Also ignore here-doc and dictionary keys (vimVar). + let b:match_skip = 'synIDattr(synID(line("."), col("."), 1), "name") + \ =~? "comment\\|string\\|vimSynReg\\|vimSet\\|vimLetHereDoc\\|vimVar"' endif let &cpo = s:cpo_save diff --git a/runtime/indent/fish.vim b/runtime/indent/fish.vim new file mode 100644 index 0000000000..7455287ec0 --- /dev/null +++ b/runtime/indent/fish.vim @@ -0,0 +1,82 @@ +" Vim indent file +" Language: fish +" Maintainer: Nicholas Boyle (github.com/nickeb96) +" Repository: https://github.com/nickeb96/fish.vim +" Last Change: February 4, 2023 + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetFishIndent(v:lnum) +setlocal indentkeys+==end,=else,=case + +function s:PrevCmdStart(linenum) + let l:linenum = a:linenum + " look for the first line that isn't a line continuation + while l:linenum > 1 && getline(l:linenum - 1) =~# '\\$' + let l:linenum = l:linenum - 1 + endwhile + return l:linenum +endfunction + +function GetFishIndent(lnum) + let l:shiftwidth = shiftwidth() + + let l:prevlnum = prevnonblank(a:lnum - 1) + if l:prevlnum ==# 0 + return 0 + endif + + " if the previous line ended with a line continuation + if getline(a:lnum - 1) =~# '\\$' + if a:lnum ==# 0 || getline(a:lnum - 2) !~# '\\$' + " this is the first line continuation in a chain, so indent it + return indent(a:lnum - 1) + l:shiftwidth + else + " use the same indentation as the previous continued line + return indent(a:lnum - 1) + endif + endif + + let l:prevlnum = s:PrevCmdStart(l:prevlnum) + + let l:prevline = getline(l:prevlnum) + if l:prevline =~# '^\s*\(begin\|if\|else\|while\|for\|function\|case\|switch\)\>' + let l:indent = l:shiftwidth + else + let l:indent = 0 + endif + + let l:line = getline(a:lnum) + if l:line =~# '^\s*end\>' + " find end's matching start + let l:depth = 1 + let l:currentlnum = a:lnum + while l:depth > 0 && l:currentlnum > 0 + let l:currentlnum = s:PrevCmdStart(prevnonblank(l:currentlnum - 1)) + let l:currentline = getline(l:currentlnum) + if l:currentline =~# '^\s*end\>' + let l:depth = l:depth + 1 + elseif l:currentline =~# '^\s*\(begin\|if\|while\|for\|function\|switch\)\>' + let l:depth = l:depth - 1 + endif + endwhile + if l:currentline =~# '^\s*switch\>' + return indent(l:currentlnum) + else + return indent(l:prevlnum) + l:indent - l:shiftwidth + endif + elseif l:line =~# '^\s*else\>' + return indent(l:prevlnum) + l:indent - l:shiftwidth + elseif l:line =~# '^\s*case\>' + if getline(l:prevlnum) =~# '^\s*switch\>' + return indent(l:prevlnum) + l:indent + else + return indent(l:prevlnum) + l:indent - l:shiftwidth + endif + else + return indent(l:prevlnum) + l:indent + endif +endfunction diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim index 69900c7a51..cbb3b36c10 100644 --- a/runtime/syntax/debsources.vim +++ b/runtime/syntax/debsources.vim @@ -2,7 +2,7 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers " Former Maintainer: Matthijs Mohlmann -" Last Change: 2023 Jan 16 +" Last Change: 2023 Feb 06 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debsources.vim " Standard syntax initialization @@ -14,7 +14,9 @@ endif syn case match " A bunch of useful keywords -syn match debsourcesKeyword /\(deb-src\|deb\|main\|contrib\|non-free\|non-free-firmware\|restricted\|universe\|multiverse\)/ +syn match debsourcesType /\(deb-src\|deb\)/ +syn match debsourcesFreeComponent /\(main\|universe\)/ +syn match debsourcesNonFreeComponent /\(contrib\|non-free-firmware\|non-free\|restricted\|multiverse\)/ " Match comments syn match debsourcesComment /#.*/ contains=@Spell @@ -48,7 +50,9 @@ exe 'syn match debsourcesUnsupportedDistrKeyword +\([[:alnum:]_./]*\)\<\('. join " Associate our matches and regions with pretty colours hi def link debsourcesLine Error -hi def link debsourcesKeyword Statement +hi def link debsourcesType Statement +hi def link debsourcesFreeComponent Statement +hi def link debsourcesNonFreeComponent Statement hi def link debsourcesDistrKeyword Type hi def link debsourcesUnsupportedDistrKeyword WarningMsg hi def link debsourcesComment Comment diff --git a/runtime/syntax/dosbatch.vim b/runtime/syntax/dosbatch.vim index f003a65909..a75771bd2d 100644 --- a/runtime/syntax/dosbatch.vim +++ b/runtime/syntax/dosbatch.vim @@ -1,12 +1,12 @@ " Vim syntax file -" Language: MS-DOS batch file (with NT command extensions) -" Maintainer: Mike Williams +" Language: MS-DOS/Windows batch file (with NT command extensions) +" Maintainer: Mike Williams " Filenames: *.bat -" Last Change: 6th September 2009 -" Web Page: http://www.eandem.co.uk/mrw/vim +" Last Change: 12th February 2023 " " Options Flags: " dosbatch_cmdextversion - 1 = Windows NT, 2 = Windows 2000 [default] +" dosbatch_colons_comment - any value to treat :: as comment line " " quit when a syntax file was already loaded @@ -92,7 +92,11 @@ syn match dosbatchComment "^rem\($\|\s.*$\)"lc=3 contains=dosbatchTodo,dosbatchS syn match dosbatchComment "^@rem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell syn match dosbatchComment "\srem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell syn match dosbatchComment "\s@rem\($\|\s.*$\)"lc=5 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell -syn match dosbatchComment "\s*:\s*:.*$" contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell +if exists("dosbatch_colons_comment") + syn match dosbatchComment "\s*:\s*:.*$" contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell +else + syn match dosbatchError "\s*:\s*:.*$" +endif " Comments in ()'s - still to handle spaces before rem syn match dosbatchComment "(rem\([^)]\|\^\@<=)\)*"lc=4 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell @@ -110,34 +114,35 @@ syn keyword dosbatchImplicit vol xcopy " Define the default highlighting. " Only when an item doesn't have highlighting yet -hi def link dosbatchTodo Todo +hi def link dosbatchTodo Todo +hi def link dosbatchError Error hi def link dosbatchStatement Statement hi def link dosbatchCommands dosbatchStatement -hi def link dosbatchLabel Label +hi def link dosbatchLabel Label hi def link dosbatchConditional Conditional -hi def link dosbatchRepeat Repeat +hi def link dosbatchRepeat Repeat -hi def link dosbatchOperator Operator -hi def link dosbatchEchoOperator dosbatchOperator -hi def link dosbatchIfOperator dosbatchOperator +hi def link dosbatchOperator Operator +hi def link dosbatchEchoOperator dosbatchOperator +hi def link dosbatchIfOperator dosbatchOperator hi def link dosbatchArgument Identifier -hi def link dosbatchIdentifier Identifier +hi def link dosbatchIdentifier Identifier hi def link dosbatchVariable dosbatchIdentifier hi def link dosbatchSpecialChar SpecialChar -hi def link dosbatchString String -hi def link dosbatchNumber Number +hi def link dosbatchString String +hi def link dosbatchNumber Number hi def link dosbatchInteger dosbatchNumber hi def link dosbatchHex dosbatchNumber -hi def link dosbatchBinary dosbatchNumber -hi def link dosbatchOctal dosbatchNumber +hi def link dosbatchBinary dosbatchNumber +hi def link dosbatchOctal dosbatchNumber hi def link dosbatchComment Comment hi def link dosbatchImplicit Function -hi def link dosbatchSwitch Special +hi def link dosbatchSwitch Special hi def link dosbatchCmd PreProc diff --git a/runtime/syntax/fish.vim b/runtime/syntax/fish.vim new file mode 100644 index 0000000000..266878bbdc --- /dev/null +++ b/runtime/syntax/fish.vim @@ -0,0 +1,225 @@ +" Vim syntax file +" Language: fish +" Maintainer: Nicholas Boyle (github.com/nickeb96) +" Repository: https://github.com/nickeb96/fish.vim +" Last Change: February 1, 2023 + +if exists("b:current_syntax") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + + +" Statements +syn cluster fishStatement contains=fishKeywordAndOr,fishNot,fishSelectStatement,fishKeyword,fishKeywordIf,fishCommand,fishVariable + +syn keyword fishKeywordAndOr and or nextgroup=fishNot,fishSelectStatement,fishKeyword,fishKeywordIf,fishCommand +hi def link fishKeywordAndOr fishOperator + +syn keyword fishNot not skipwhite nextgroup=fishSelectStatement,fishKeyword,fishKeywordIf,fishCommand +syn match fishNot /!/ skipwhite nextgroup=fishSelectStatement,fishKeyword,fishKeywordIf,fishCommand +hi def link fishNot fishOperator + +syn keyword fishSelectStatement command builtin skipwhite nextgroup=fishKeyword,fishKeywordIf,fishCommand,fishOption +hi def link fishSelectStatement fishKeyword + +syn keyword fishKeyword end skipwhite nextgroup=@fishTerminator + +syn keyword fishKeywordIf if skipwhite nextgroup=@fishStatement +syn keyword fishKeyword else skipwhite nextgroup=fishKeywordIf,fishSemicolon +hi def link fishKeywordIf fishKeyword + +syn keyword fishKeyword switch skipwhite nextgroup=@fishArgument +syn keyword fishKeyword case skipwhite nextgroup=@fishArgument + +syn keyword fishKeyword while skipwhite nextgroup=@fishStatement + +syn keyword fishKeyword for skipwhite nextgroup=fishForVariable +syn match fishForVariable /[[:alnum:]_]\+/ contained skipwhite nextgroup=fishKeywordIn +syn keyword fishKeywordIn in contained skipwhite nextgroup=@fishArgument +hi def link fishForVariable fishParameter +hi def link fishKeywordIn fishKeyword + +syn keyword fishKeyword _ abbr argparse begin bg bind block break breakpoint cd commandline + \ complete continue count disown echo emit eval exec exit false fg function functions + \ history jobs math printf pwd random read realpath return set set_color source status + \ string test time true type ulimit wait + \ skipwhite nextgroup=@fishNext +syn match fishKeyword /\/ skipwhite nextgroup=@fishNext + +syn match fishCommand /[[:alnum:]_\/[][[:alnum:]+._-]*/ skipwhite nextgroup=@fishNext + + +" Internally Nested Arguments + +syn cluster fishSubscriptArgs contains=fishInnerVariable,fishIndexNum,fishIndexRange,fishInnerCommandSub + +syn match fishInnerVariable /\$\+[[:alnum:]_]\+/ contained +syn match fishInnerVariable /\$\+[[:alnum:]_]\+\[/me=e-1,he=e-1 contained nextgroup=fishInnerSubscript +hi def link fishInnerVariable fishVariable + +syn region fishInnerSubscript matchgroup=fishVariable start=/\[/ end=/]/ contained + \ keepend contains=@fishSubscriptArgs +hi def link fishInnerSubscript fishSubscript + +syn match fishIndexNum /[+-]?[[:digit:]]\+/ contained +hi def link fishIndexNum fishParameter + +syn match fishIndexRange /\.\./ contained +hi def link fishIndexRange fishParameter + +syn region fishInnerCommandSub matchgroup=fishOperator start=/(/ start=/\$(/ end=/)/ contained + \ contains=@fishStatement +hi def link fishInnerCommandSub fishCommandSub + +syn region fishQuotedCommandSub matchgroup=fishOperator start=/\$(/ end=/)/ contained + \ contains=@fishStatement +hi def link fishQuotedCommandSub fishCommandSub + +syn match fishBraceExpansionComma /,/ contained +hi def link fishBraceExpansionComma fishOperator + +syn match fishBracedParameter '[[:alnum:]\u5b\u5d@:=+.%/!_-]\+' contained contains=fishInnerPathGlob +hi def link fishBracedParameter fishParameter + +syn region fishBracedQuote start=/'/ skip=/\\'/ end=/'/ contained + \ contains=fishEscapedEscape,fishEscapedSQuote +syn region fishBracedQuote start=/"/ skip=/\\"/ end=/"/ contained + \ contains=fishEscapedEscape,fishEscapedDQuote,fishEscapedDollar,fishInnerVariable,fishInnerCommandSub +hi def link fishBracedQuote fishQuote + + +" Arguments + +syn cluster fishArgument contains=fishParameter,fishOption,fishVariable,fishPathGlob,fishBraceExpansion,fishQuote,fishCharacter,fishCommandSub,fishRedirection,fishSelfPid + +syn match fishParameter '[[:alnum:]\u5b\u5d@:=+.,%/!_-]\+' contained skipwhite nextgroup=@fishNext + +syn match fishOption /-[[:alnum:]=_-]*/ contained skipwhite nextgroup=@fishNext + +syn match fishPathGlob /\(\~\|*\|?\)/ contained skipwhite nextgroup=@fishNext + +syn region fishBraceExpansion matchgroup=fishOperator start=/{/ end=/}/ contained + \ contains=fishBraceExpansionComma,fishInnerVariable,fishInnerCommandSub,fishBracedParameter,fishBracedQuote + \ skipwhite nextgroup=@fishNext + +syn match fishVariable /\$\+[[:alnum:]_]\+/ skipwhite nextgroup=@fishNext +syn match fishVariable /\$\+[[:alnum:]_]\+\[/me=e-1,he=e-1 nextgroup=fishSubscript + +syn region fishSubscript matchgroup=fishVariable start=/\[/ end=/]/ contained + \ keepend contains=@fishSubscriptArgs + \ skipwhite nextgroup=@fishNext + +syn region fishCommandSub matchgroup=fishOperator start=/(/ start=/\$(/ end=/)/ contained + \ contains=@fishStatement + \ skipwhite nextgroup=@fishNext + +syn region fishQuote start=/'/ skip=/\\'/ end=/'/ contained + \ contains=fishEscapedEscape,fishEscapedSQuote + \ skipwhite nextgroup=@fishNext +syn region fishQuote start=/"/ skip=/\\"/ end=/"/ contained + \ contains=fishEscapedEscape,fishEscapedDQuote,fishEscapedDollar,fishInnerVariable,fishQuotedCommandSub + \ skipwhite nextgroup=@fishNext + +syn match fishEscapedEscape /\\\\/ contained +syn match fishEscapedSQuote /\\'/ contained +syn match fishEscapedDQuote /\\"/ contained +syn match fishEscapedDollar /\\\$/ contained +hi def link fishEscapedEscape fishCharacter +hi def link fishEscapedSQuote fishCharacter +hi def link fishEscapedDQuote fishCharacter +hi def link fishEscapedDollar fishCharacter + +syn match fishCharacter /\\[0-7]\{1,3}/ contained skipwhite nextgroup=@fishNext +syn match fishCharacter /\\u[0-9a-fA-F]\{4}/ contained skipwhite nextgroup=@fishNext +syn match fishCharacter /\\U[0-9a-fA-F]\{8}/ contained skipwhite nextgroup=@fishNext +syn match fishCharacter /\\x[0-7][0-9a-fA-F]\|\\x[0-9a-fA-F]/ contained skipwhite nextgroup=@fishNext +syn match fishCharacter /\\X[0-9a-fA-F]\{1,2}/ contained skipwhite nextgroup=@fishNext +syn match fishCharacter /\\[abcefnrtv[\](){}<>\\*?~%#$|&;'" ]/ contained skipwhite nextgroup=@fishNext + +syn match fishRedirection /[>?]\?/ contained skipwhite nextgroup=fishRedirectionTarget +syn match fishRedirection /[0-9&]\?>&[0-9-]/ contained skipwhite nextgroup=@fishNext + +syn match fishRedirectionTarget /[[:alnum:]$~*?{,}"'\/._-]\+/ contained contains=fishInnerVariable skipwhite nextgroup=@fishNext +hi def link fishRedirectionTarget fishRedirection + +syn match fishSelfPid /%self\>/ contained nextgroup=@fishNext +hi def link fishSelfPid fishOperator + + +" Terminators + +syn cluster fishTerminator contains=fishPipe,fishBackgroundJob,fishSemicolon,fishSymbolicAndOr + +syn match fishPipe /\(1>\|2>\|&\)\?|/ contained skipwhite nextgroup=@fishStatement +hi def link fishPipe fishEnd + +syn match fishBackgroundJob /&$/ contained skipwhite nextgroup=@fishStatement +syn match fishBackgroundJob /&[^<>&|]/me=s+1,he=s+1 contained skipwhite nextgroup=@fishStatement +hi def link fishBackgroundJob fishEnd + +syn match fishSemicolon /;/ skipwhite nextgroup=@fishStatement +hi def link fishSemicolon fishEnd + +syn match fishSymbolicAndOr /\(&&\|||\)/ contained skipwhite skipempty nextgroup=@fishStatement +hi def link fishSymbolicAndOr fishOperator + + +" Other + +syn cluster fishNext contains=fishEscapedNl,@fishArgument,@fishTerminator + +syn match fishEscapedNl /\\$/ skipnl skipwhite contained nextgroup=@fishNext + +syn match fishComment /#.*/ contains=fishTodo,@Spell + +syn keyword fishTodo TODO contained + + + +syn sync minlines=200 +syn sync maxlines=300 + + +" Intermediate highlight groups matching $fish_color_* variables + +hi def link fishCommand fish_color_command +hi def link fishComment fish_color_comment +hi def link fishEnd fish_color_end +hi def link fishCharacter fish_color_escape +hi def link fishKeyword fish_color_keyword +hi def link fishEscapedNl fish_color_normal +hi def link fishOperator fish_color_operator +hi def link fishVariable fish_color_operator +hi def link fishInnerVariable fish_color_operator +hi def link fishPathGlob fish_color_operator +hi def link fishOption fish_color_option +hi def link fishParameter fish_color_param +hi def link fishQuote fish_color_quote +hi def link fishRedirection fish_color_redirection + + +" Default highlight groups + +hi def link fish_color_param Normal +hi def link fish_color_normal Normal +hi def link fish_color_option Normal +hi def link fish_color_command Function +hi def link fish_color_keyword Keyword +hi def link fish_color_end Delimiter +hi def link fish_color_operator Operator +hi def link fish_color_redirection Type +hi def link fish_color_quote String +hi def link fish_color_escape Character +hi def link fish_color_comment Comment + +hi def link fishTodo Todo + + +let b:current_syntax = 'fish' + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/syntax/fstab.vim b/runtime/syntax/fstab.vim index 7e18c267f7..91150bc37b 100644 --- a/runtime/syntax/fstab.vim +++ b/runtime/syntax/fstab.vim @@ -2,8 +2,8 @@ " Language: fstab file " Maintainer: Radu Dineiu " URL: https://raw.github.com/rid9/vim-fstab/master/syntax/fstab.vim -" Last Change: 2022 Dec 11 -" Version: 1.6.2 +" Last Change: 2023 Feb 19 +" Version: 1.6.3 " " Credits: " David Necas (Yeti) @@ -389,7 +389,7 @@ syn match fsFreqPassNumber /\d\+\s\+[012]\s*/ contained syn match fsDevice /^\s*\zs.\{-1,}\s/me=e-1 nextgroup=fsMountPoint contains=@fsDeviceCluster,@fsGeneralCluster syn match fsMountPoint /\s\+.\{-}\s/me=e-1 nextgroup=fsType contains=@fsMountPointCluster,@fsGeneralCluster contained syn match fsType /\s\+.\{-}\s/me=e-1 nextgroup=fsOptions contains=@fsTypeCluster,@fsGeneralCluster contained -syn match fsOptions /\s\+.\{-}\s/me=e-1 nextgroup=fsFreqPass contains=@fsOptionsCluster,@fsGeneralCluster contained +syn match fsOptions /\s\+.\{-}\%(\s\|$\)/ nextgroup=fsFreqPass contains=@fsOptionsCluster,@fsGeneralCluster contained syn match fsFreqPass /\s\+.\{-}$/ contains=@fsFreqPassCluster,@fsGeneralCluster contained " Whole line comments @@ -491,4 +491,4 @@ let b:current_syntax = "fstab" let &cpo = s:cpo_save unlet s:cpo_save -" vim: ts=8 ft=vim +" vim: ts=8 noet ft=vim diff --git a/runtime/syntax/go.vim b/runtime/syntax/go.vim index 904c8ad7f2..bf967fdcd9 100644 --- a/runtime/syntax/go.vim +++ b/runtime/syntax/go.vim @@ -5,7 +5,7 @@ " go.vim: Vim syntax file for Go. " Language: Go " Maintainer: Billie Cleek -" Latest Revision: 2022-11-17 +" Latest Revision: 2023-02-19 " License: BSD-style. See LICENSE file in source repository. " Repository: https://github.com/fatih/vim-go @@ -136,8 +136,11 @@ syn keyword goBoolean true false syn keyword goPredefinedIdentifiers nil iota hi def link goBuiltins Identifier +hi def link goPredefinedIdentifiers Constant +" Boolean links to Constant by default by vim: goBoolean and goPredefinedIdentifiers +" will be highlighted the same, but having the separate groups allows users to +" have separate highlighting for them if they desire. hi def link goBoolean Boolean -hi def link goPredefinedIdentifiers goBoolean " Comments; their contents syn keyword goTodo contained TODO FIXME XXX BUG diff --git a/runtime/syntax/html.vim b/runtime/syntax/html.vim index 605db3ae1c..82c829a2e1 100644 --- a/runtime/syntax/html.vim +++ b/runtime/syntax/html.vim @@ -3,7 +3,7 @@ " Maintainer: Doug Kearns " Previous Maintainers: Jorge Maldonado Ventura " Claudio Fleiner -" Last Change: 2022 Nov 18 +" Last Change: 2023 Feb 20 " Please check :help html.vim for some comments and a description of the options @@ -221,7 +221,7 @@ if main_syntax != 'java' || exists("java_javascript") " JAVA SCRIPT syn include @htmlJavaScript syntax/javascript.vim unlet b:current_syntax - syn region javaScript start=+]*>+ keepend end=+]*>+me=s-1 contains=@htmlJavaScript,htmlCssStyleComment,htmlScriptTag,@htmlPreproc + syn region javaScript start=+\_[^>]*>+ keepend end=+]*>+me=s-1 contains=@htmlJavaScript,htmlCssStyleComment,htmlScriptTag,@htmlPreproc syn region htmlScriptTag contained start=++ fold contains=htmlTagN,htmlString,htmlArg,htmlValue,htmlTagError,htmlEvent hi def link htmlScriptTag htmlTag diff --git a/runtime/syntax/poefilter.vim b/runtime/syntax/poefilter.vim index f7e92034ee..6561f7a704 100644 --- a/runtime/syntax/poefilter.vim +++ b/runtime/syntax/poefilter.vim @@ -2,7 +2,7 @@ " Language: PoE item filter " Maintainer: ObserverOfTime " Filenames: *.filter -" Last Change: 2022 Oct 07 +" Last Change: 2023 Feb 10 if exists('b:current_syntax') finish @@ -17,7 +17,7 @@ syn match poefilterCommentTag /\[[0-9A-Z\[\]]\+\]/ contained syn match poefilterComment /#.*$/ contains=poefilterTodo,poefilterCommentTag,@Spell " Blocks -syn keyword poefilterBlock Show Hide +syn keyword poefilterBlock Show Hide Minimal " Conditions syn keyword poefilterCondition -- cgit From 344a1ee8e6b7d78120f8393d1babfd285e866334 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 22 Feb 2023 00:07:26 +0800 Subject: docs: fix typos (#22353) --- runtime/doc/api.txt | 2 +- runtime/doc/autocmd.txt | 2 +- runtime/doc/builtin.txt | 4 ++-- runtime/doc/deprecated.txt | 4 ++-- runtime/doc/develop.txt | 4 ++-- runtime/doc/eval.txt | 18 +++++++++--------- runtime/doc/help.txt | 28 ++++++++++++++-------------- runtime/doc/if_perl.txt | 2 +- runtime/doc/intro.txt | 2 +- runtime/doc/motion.txt | 2 +- runtime/doc/nvim_terminal_emulator.txt | 6 +++--- runtime/doc/provider.txt | 8 ++++---- runtime/doc/remote_plugin.txt | 2 +- runtime/doc/starting.txt | 4 ++-- runtime/doc/ui.txt | 22 +++++++++++----------- runtime/doc/various.txt | 2 +- runtime/doc/windows.txt | 2 +- 17 files changed, 57 insertions(+), 57 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 95a929b808..7bcae79852 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -2644,7 +2644,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) buffer. • right_gravity : boolean that indicates the direction the extmark will be shifted in when new text is inserted (true - for right, false for left). defaults to true. + for right, false for left). Defaults to true. • end_right_gravity : boolean that indicates the direction the extmark end position (if it exists) will be shifted in when new text is inserted (true for right, false for diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 89252145f2..e9a4196252 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -426,7 +426,7 @@ ColorSchemePre Before loading a color scheme. |:colorscheme| Useful to setup removing things added by a color scheme, before another one is loaded. -CompleteChanged *CompleteChanged* +CompleteChanged *CompleteChanged* After each time the Insert mode completion menu changed. Not fired on popup menu hide, use |CompleteDonePre| or |CompleteDone| for diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 60a1035da3..af5ba9ab8f 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1055,7 +1055,7 @@ chansend({id}, {data}) *chansend()* newlines in an item will be sent as NUL. To send a final newline, include a final empty string. Example: > :call chansend(id, ["abc", "123\n456", ""]) -< will send "abc123456". +< will send "abc123456". chansend() writes raw data, not RPC messages. If the channel was created with `"rpc":v:true` then the channel expects RPC @@ -4846,7 +4846,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()* "lhs" The {lhs} of the mapping as it would be typed "lhsraw" The {lhs} of the mapping as raw bytes "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate - form, only present when it differs from "lhsraw" + form, only present when it differs from "lhsraw" "rhs" The {rhs} of the mapping as typed. "silent" 1 for a |:map-silent| mapping, else 0. "noremap" 1 if the {rhs} of the mapping is not remappable. diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 1bdd13ac0c..e7b0a710e8 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -113,14 +113,14 @@ LSP FUNCTIONS - *vim.lsp.util.set_qflist()* Use |setqflist()| instead. - *vim.lsp.util.set_loclist()* Use |setloclist()| instead. - *vim.lsp.buf_get_clients()* Use |vim.lsp.get_active_clients()| with - {buffer = bufnr} instead. + {buffer = bufnr} instead. - *vim.lsp.buf.formatting()* Use |vim.lsp.buf.format()| with {async = true} instead. - *vim.lsp.buf.range_formatting()* Use |vim.lsp.formatexpr()| or |vim.lsp.buf.format()| instead. LUA -- *vim.register_keystroke_callback()* Use |vim.on_key()| instead. +- *vim.register_keystroke_callback()* Use |vim.on_key()| instead. NORMAL COMMANDS - *]f* *[f* Same as "gf". diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index ff48ae3e26..87190d7f33 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -81,7 +81,7 @@ include the kitchen sink... but it's good for plumbing." Developer guidelines *dev-guidelines* -PROVIDERS *dev-provider* +PROVIDERS *dev-provider* A primary goal of Nvim is to allow extension of the editor without special knowledge in the core. Some core functions are delegated to "providers" @@ -391,7 +391,7 @@ API client implementation guidelines ~ https://github.com/msgpack-rpc/msgpack-rpc -EXTERNAL UI *dev-ui* +EXTERNAL UI *dev-ui* External UIs should be aware of the |api-contract|. In particular, future versions of Nvim may add new items to existing events. The API is strongly diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index af67e2b67d..d79b446986 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1817,17 +1817,17 @@ v:event Dictionary of event data for the current |autocommand|. Valid completed_item Current selected complete item on |CompleteChanged|, Is `{}` when no complete item selected. - height Height of popup menu on |CompleteChanged| - width width of popup menu on |CompleteChanged| - row Row count of popup menu on |CompleteChanged|, + height Height of popup menu on |CompleteChanged| + width width of popup menu on |CompleteChanged| + row Row count of popup menu on |CompleteChanged|, relative to screen. - col Col count of popup menu on |CompleteChanged|, + col Col count of popup menu on |CompleteChanged|, relative to screen. - size Total number of completion items on + size Total number of completion items on |CompleteChanged|. - scrollbar Is |v:true| if popup menu have scrollbar, or + scrollbar Is |v:true| if popup menu have scrollbar, or |v:false| if not. - changed_window Is |v:true| if the event fired while + changed_window Is |v:true| if the event fired while changing window (or tab) on |DirChanged|. status Job status or exit code, -1 means "unknown". |TermClose| @@ -2668,8 +2668,8 @@ text... Example with [depth] 0: > let mylist = [1, 2, 3] lockvar 0 mylist - let mylist[0] = 77 " OK - call add(mylist, 4] " OK + let mylist[0] = 77 " OK + call add(mylist, 4] " OK let mylist = [7, 8, 9] " Error! < *E743* For unlimited depth use [!] and omit [depth]. diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 07f898f99c..68c886887f 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -120,15 +120,15 @@ PROGRAMMING LANGUAGE SUPPORT |lsp| Language Server Protocol (LSP) |diagnostic-api| Diagnostic framework |treesitter| Incremental syntax parsing -|indent.txt| automatic indenting for C and other languages +|indent.txt| automatic indenting for C and other languages |syntax| syntax highlighting |filetype| Settings for specific types of files |quickfix| Commands for a quick edit-compile-fix cycle -|ft_ada.txt| Ada filetype plugin -|ft_ps1.txt| PowerShell filetype plugin -|ft_raku.txt| Raku filetype plugin -|ft_rust.txt| Rust filetype plugin -|ft_sql.txt| SQL filetype plugin +|ft_ada.txt| Ada filetype plugin +|ft_ps1.txt| PowerShell filetype plugin +|ft_raku.txt| Raku filetype plugin +|ft_rust.txt| Rust filetype plugin +|ft_sql.txt| SQL filetype plugin ------------------------------------------------------------------------------ UI @@ -172,14 +172,14 @@ DEVELOPING NVIM *standard-plugin-list* Standard plugins ~ |matchit.txt| Extended |%| matching -|pi_gzip.txt| Reading and writing compressed files -|pi_health.txt| Healthcheck framework -|pi_msgpack.txt| msgpack utilities -|pi_netrw.txt| Reading and writing files over a network -|pi_paren.txt| Highlight matching parens -|pi_spec.txt| Filetype plugin to work with rpm spec files -|pi_tar.txt| Tar file explorer -|pi_zip.txt| Zip archive explorer +|pi_gzip.txt| Reading and writing compressed files +|pi_health.txt| Healthcheck framework +|pi_msgpack.txt| msgpack utilities +|pi_netrw.txt| Reading and writing files over a network +|pi_paren.txt| Highlight matching parens +|pi_spec.txt| Filetype plugin to work with rpm spec files +|pi_tar.txt| Tar file explorer +|pi_zip.txt| Zip archive explorer LOCAL ADDITIONS: *local-additions* diff --git a/runtime/doc/if_perl.txt b/runtime/doc/if_perl.txt index 3787ca69ba..e4ec6dcf45 100644 --- a/runtime/doc/if_perl.txt +++ b/runtime/doc/if_perl.txt @@ -116,7 +116,7 @@ Overview > VIM::SetOption("ai") # sets a vim option $nbuf = VIM::Buffers() # returns the number of buffers @buflist = VIM::Buffers() # returns array of all buffers - $mybuf = (VIM::Buffers('a.c'))[0] # returns buffer object for 'a.c' + $mybuf = (VIM::Buffers('a.c'))[0] # returns buffer object for 'a.c' @winlist = VIM::Windows() # returns array of all windows $nwin = VIM::Windows() # returns the number of windows ($success, $v) = VIM::Eval('&path') # $v: option 'path', $success: 1 diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 11ba1b408c..685c953718 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -358,7 +358,7 @@ notation meaning equivalent decimal value(s) ~ keypad origin (middle) *keypad-origin* keypad page-up (upper right) *keypad-page-up* keypad page-down (lower right) *keypad-page-down* - keypad delete *keypad-delete* + keypad delete *keypad-delete* keypad + *keypad-plus* keypad - *keypad-minus* keypad * *keypad-multiply* diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 929efee19f..59ae209aa9 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -589,7 +589,7 @@ i( *vib* *v_ib* *v_i(* *ib* ib "inner block", select [count] blocks, from "[count] [(" to the matching ')', excluding the '(' and ')' (see |[(|). If the cursor is not inside a () block, then - find the next "(". + find the next "(". When used in Visual mode it is made charwise. a> *v_a>* *v_a<* *a>* *a<* diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index 96f99528ed..50a241f515 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -239,7 +239,7 @@ gdb window and use a "print" command, e.g.: > print *eap If mouse pointer movements are working, Vim will also show a balloon when the mouse rests on text that can be evaluated by gdb. -You can also use the "K" mapping that will either use neovim floating windows +You can also use the "K" mapping that will either use Nvim floating windows if available to show the results or print below the status bar. Now go back to the source window and put the cursor on the first line after @@ -428,14 +428,14 @@ If the command needs an argument use a List: >vim If there is no g:termdebug_config you can use: >vim let g:termdebugger = ['rr', 'replay', '--'] -To not use neovim floating windows for previewing variable evaluation, set the +To not use Nvim floating windows for previewing variable evaluation, set the `g:termdebug_useFloatingHover` variable like this: >vim let g:termdebug_useFloatingHover = 0 If you are a mouse person, you can also define a mapping using your right click to one of the terminal command like evaluate the variable under the cursor: >vim - nnoremap :Evaluate + nnoremap :Evaluate or set/unset a breakpoint: >vim nnoremap :Break diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index 5375d971f0..432e6138fa 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -4,7 +4,7 @@ NVIM REFERENCE MANUAL by Thiago de Arruda -Providers *provider* +Providers *provider* Nvim delegates some features to dynamic "providers". This document describes the providers and how to install them. @@ -82,7 +82,7 @@ The last command reports the interpreter path, add it to your init.vim: >vim See also: https://github.com/zchee/deoplete-jedi/wiki/Setting-up-Python-for-Neovim ============================================================================== -Ruby integration *provider-ruby* +Ruby integration *provider-ruby* Nvim supports Ruby |remote-plugin|s and the Vim legacy |ruby-vim| interface (which is itself implemented as a Nvim remote-plugin). @@ -169,7 +169,7 @@ can be slow. To avoid this, set g:node_host_prog to the host path: >vim let g:node_host_prog = '/usr/local/bin/neovim-node-host' < ============================================================================== -Clipboard integration *provider-clipboard* *clipboard* +Clipboard integration *provider-clipboard* *clipboard* Nvim has no direct connection to the system clipboard. Instead it depends on a |provider| which transparently uses shell commands to communicate with the @@ -255,7 +255,7 @@ For Windows WSL, try this g:clipboard definition: \ } ============================================================================== -Paste *provider-paste* *paste* +Paste *provider-paste* *paste* "Paste" is a separate concept from |clipboard|: paste means "dump a bunch of text to the editor", whereas clipboard provides features like |quote+| to get diff --git a/runtime/doc/remote_plugin.txt b/runtime/doc/remote_plugin.txt index 4cdcbed250..348f6c86a5 100644 --- a/runtime/doc/remote_plugin.txt +++ b/runtime/doc/remote_plugin.txt @@ -4,7 +4,7 @@ NVIM REFERENCE MANUAL by Thiago de Arruda -Nvim support for remote plugins *remote-plugin* +Nvim support for remote plugins *remote-plugin* Type |gO| to see the table of contents. diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 67a88913fb..a8a149def8 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -368,7 +368,7 @@ argument. -W {scriptout} Like -w, but do not append, overwrite an existing file. *--api-info* ---api-info Print msgpack-encoded |api-metadata| and exit. +--api-info Print msgpack-encoded |api-metadata| and exit. *--embed* --embed Use stdin/stdout as a msgpack-RPC channel, so applications can @@ -392,7 +392,7 @@ argument. < See also: |ui-startup| |channel-stdio| *--headless* ---headless Start without UI, and do not wait for `nvim_ui_attach`. The +--headless Start without UI, and do not wait for `nvim_ui_attach`. The builtin TUI is not used, so stdio works as an arbitrary communication channel. |channel-stdio| diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 3110d0817c..4e4f88f275 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -53,11 +53,11 @@ with these (optional) keys: - `term_name` Sets the name of the terminal 'term'. - `term_colors` Sets the number of supported colors 't_Co'. - `term_background` Sets the default value of 'background'. -- `stdin_fd` Read buffer from `fd` as if it was a stdin pipe - This option can only used by |--embed| ui, - see |ui-startup-stdin|. - `stdin_tty` Tells if `stdin` is a `tty` or not. - `stdout_tty` Tells if `stdout` is a `tty` or not. +- `stdin_fd` Read buffer from `fd` as if it was a stdin pipe. + This option can only used by |--embed| ui on startup. + See |ui-startup-stdin|. +- `stdin_tty` Tells if `stdin` is a `tty` or not. +- `stdout_tty` Tells if `stdout` is a `tty` or not. Specifying an unknown option is an error; UIs can check the |api-metadata| `ui_options` key for supported options. @@ -154,11 +154,11 @@ procedure: An UI can support the native read from stdin feature as invoked with `command | nvim -` for the builtin TUI. |--| The embedding process can detect that its stdin is open to a file which -not is a terminal, just like nvim does. It then needs to forward this fd +not is a terminal, just like Nvim does. It then needs to forward this fd to Nvim. As fd=0 is already is used to send rpc data from the embedder to Nvim, it needs to use some other file descriptor, like fd=3 or higher. -Then, `stdin_fd` option should be passed to `nvim_ui_attach` and nvim will +Then, `stdin_fd` option should be passed to `nvim_ui_attach` and Nvim will implicitly read it as a buffer. This option can only be used when Nvim is launched with `--embed` option, as described above. @@ -356,8 +356,8 @@ numerical highlight ids to the actual attributes. The bulitin highlight group `name` was set to use the attributes `hl_id` defined by a previous `hl_attr_define` call. This event is not needed to render the grids which use attribute ids directly, but is useful - for an UI who want to render its own elements with consistent - highlighting. For instance an UI using |ui-popupmenu| events, might + for a UI who want to render its own elements with consistent + highlighting. For instance a UI using |ui-popupmenu| events, might use the |hl-Pmenu| family of builtin highlights. *ui-event-grid_line* @@ -532,7 +532,7 @@ is not active. New UIs should implement |ui-linegrid| instead. +-------------------------+ < ============================================================================== -Detailed highlight state Extension *ui-hlstate* +Detailed highlight state Extension *ui-hlstate* Activated by the `ext_hlstate` |ui-option|. Activates |ui-linegrid| implicitly. @@ -566,7 +566,7 @@ highlight group is cleared, so `ui_name` can always be used to reliably identify screen elements, even if no attributes have been applied. ============================================================================== -Multigrid Events *ui-multigrid* +Multigrid Events *ui-multigrid* Activated by the `ext_multigrid` |ui-option|. Activates |ui-linegrid| implicitly. diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index e13d892fd6..ccde53cc06 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -473,7 +473,7 @@ will be no "Last set" message. When it was defined while executing a function, user command or autocommand, the script in which it was defined is reported. *K* -[count]K Runs the program given by 'keywordprg' to lookup the +[count]K Runs the program given by 'keywordprg' to lookup the |word| (defined by 'iskeyword') under or right of the cursor. Default is "man". Works like this: > :tabnew | terminal {program} {keyword} diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 61f5013f47..4b7901e614 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -223,7 +223,7 @@ CTRL-W ^ Split the current window in two and edit the alternate file. CTRL-W ge *CTRL-W_ge* Detach the current window as an external window. - Only available when using an UI with |ui-multigrid| support. + Only available when using a UI with |ui-multigrid| support. Note that the 'splitbelow' and 'splitright' options influence where a new window will appear. -- cgit From 8714a4009c0f0be0bb27a6b3eb486eeb3d9f3049 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 21 Feb 2023 17:09:18 +0000 Subject: feat(treesitter): add filetype -> lang API Problem: vim.treesitter does not know how to map a specific filetype to a parser. This creates problems since in a few places (including in vim.treesitter itself), the filetype is incorrectly used in place of lang. Solution: Add an API to enable this: - Add vim.treesitter.language.add() as a replacement for vim.treesitter.language.require_language(). - Optional arguments are now passed via an opts table. - Also takes a filetype (or list of filetypes) so we can keep track of what filetypes are associated with which langs. - Deprecated vim.treesitter.language.require_language(). - Add vim.treesitter.language.get_lang() which returns the associated lang for a given filetype. - Add vim.treesitter.language.register() to associate filetypes to a lang without loading the parser. --- runtime/doc/news.txt | 5 ++ runtime/doc/treesitter.txt | 50 +++++++++++------ runtime/lua/vim/treesitter.lua | 24 +++++---- runtime/lua/vim/treesitter/health.lua | 2 +- runtime/lua/vim/treesitter/language.lua | 84 ++++++++++++++++++++++++++--- runtime/lua/vim/treesitter/languagetree.lua | 4 +- runtime/lua/vim/treesitter/query.lua | 2 +- 7 files changed, 133 insertions(+), 38 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index ae21bc47ca..8b41f2d104 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -164,6 +164,9 @@ The following new APIs or features were added. • |vim.treesitter.query.get_node_text()| now accepts a `metadata` option for writing custom directives using |vim.treesitter.query.add_directive()|. +• |vim.treesitter.language.add()| as a new replacement for + `vim.treesitter.language.require_language`. + ============================================================================== CHANGED FEATURES *news-changes* @@ -202,6 +205,8 @@ DEPRECATIONS *news-deprecations* The following functions are now deprecated and will be removed in the next release. +• `vim.treesitter.language.require_language()` has been deprecated in favour + of |vim.treesitter.language.add()|. vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index d4799053f7..e35e145301 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -666,6 +666,36 @@ stop({bufnr}) *vim.treesitter.stop()* ============================================================================== Lua module: vim.treesitter.language *lua-treesitter-language* +add({lang}, {opts}) *vim.treesitter.language.add()* + Asserts that a parser for the language {lang} is installed. + + Parsers are searched in the `parser` runtime directory, or the provided + {path} + + Parameters: ~ + • {lang} (string) Language the parser should parse (alphanumerical and + `_` only) + • {opts} (table|nil) Options: + • filetype (string|string[]) Filetype(s) that lang can be + parsed with. Note this is not strictly the same as lang + since a single lang can parse multiple filetypes. Defaults + to lang. + • path (string|nil) Optional path the parser is located at + • symbol_name (string|nil) Internal symbol name for the + language to load + • silent (boolean|nil) Don't throw an error if language not + found + + Return: ~ + (boolean) If the specified language is installed + +get_lang({filetype}) *vim.treesitter.language.get_lang()* + Parameters: ~ + • {filetype} (string) + + Return: ~ + (string|nil) + inspect_language({lang}) *vim.treesitter.language.inspect_language()* Inspects the provided language. @@ -678,24 +708,12 @@ inspect_language({lang}) *vim.treesitter.language.inspect_language()* Return: ~ (table) - *vim.treesitter.language.require_language()* -require_language({lang}, {path}, {silent}, {symbol_name}) - Asserts that a parser for the language {lang} is installed. - - Parsers are searched in the `parser` runtime directory, or the provided - {path} +register({lang}, {filetype}) *vim.treesitter.language.register()* + Register a lang to be used for a filetype (or list of filetypes). Parameters: ~ - • {lang} (string) Language the parser should parse - (alphanumerical and `_` only) - • {path} (string|nil) Optional path the parser is located at - • {silent} (boolean|nil) Don't throw an error if language not - found - • {symbol_name} (string|nil) Internal symbol name for the language to - load - - Return: ~ - (boolean) If the specified language is installed + • {lang} (string) Language to register + • {filetype} string|string[] Filetype(s) to associate with lang ============================================================================== diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 4127198576..c524b20bc2 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -29,6 +29,8 @@ setmetatable(M, { end, }) +---@diagnostic disable:invisible + --- Creates a new parser --- --- It is not recommended to use this; use |get_parser()| instead. @@ -39,16 +41,15 @@ setmetatable(M, { --- ---@return LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) - language.require_language(lang) if bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end vim.fn.bufload(bufnr) - local self = LanguageTree.new(bufnr, lang, opts) + language.add(lang, { filetype = vim.bo[bufnr].filetype }) - ---@diagnostic disable:invisible + local self = LanguageTree.new(bufnr, lang, opts) ---@private local function bytes_cb(_, ...) @@ -96,13 +97,16 @@ function M.get_parser(bufnr, lang, opts) if bufnr == nil or bufnr == 0 then bufnr = a.nvim_get_current_buf() end + if lang == nil then + local ft = vim.bo[bufnr].filetype + lang = language.get_lang(ft) or ft + -- TODO(lewis6991): we should error here and not default to ft + -- if not lang then + -- error(string.format('filetype %s of buffer %d is not associated with any lang', ft, bufnr)) + -- end + end - if parsers[bufnr] == nil then - lang = lang or a.nvim_buf_get_option(bufnr, 'filetype') - parsers[bufnr] = M._create_parser(bufnr, lang, opts) - elseif lang and parsers[bufnr]:lang() ~= lang then - -- Only try to create a new parser if lang is provided - -- and it doesn't match the stored parser + if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then parsers[bufnr] = M._create_parser(bufnr, lang, opts) end @@ -123,7 +127,7 @@ function M.get_string_parser(str, lang, opts) str = { str, 'string' }, lang = { lang, 'string' }, }) - language.require_language(lang) + language.add(lang) return LanguageTree.new(str, lang, opts) end diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index c0a1eca0ce..1abcdd0b31 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -17,7 +17,7 @@ function M.check() for _, parser in pairs(parsers) do local parsername = vim.fn.fnamemodify(parser, ':t:r') - local is_loadable, ret = pcall(ts.language.require_language, parsername) + local is_loadable, ret = pcall(ts.language.add, parsername) if not is_loadable or not ret then health.report_error( diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 8634e53b7b..8637d7d544 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -2,19 +2,66 @@ local a = vim.api local M = {} +---@type table +local ft_to_lang = {} + +---@param filetype string +---@return string|nil +function M.get_lang(filetype) + return ft_to_lang[filetype] +end + +---@deprecated +function M.require_language(lang, path, silent, symbol_name) + return M.add(lang, { + silent = silent, + path = path, + symbol_name = symbol_name, + }) +end + +---@class treesitter.RequireLangOpts +---@field path? string +---@field silent? boolean +---@field filetype? string|string[] +---@field symbol_name? string + --- Asserts that a parser for the language {lang} is installed. --- --- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ---@param lang string Language the parser should parse (alphanumerical and `_` only) ----@param path (string|nil) Optional path the parser is located at ----@param silent (boolean|nil) Don't throw an error if language not found ----@param symbol_name (string|nil) Internal symbol name for the language to load +---@param opts (table|nil) Options: +--- - filetype (string|string[]) Filetype(s) that lang can be parsed with. +--- Note this is not strictly the same as lang since a single lang can +--- parse multiple filetypes. +--- Defaults to lang. +--- - path (string|nil) Optional path the parser is located at +--- - symbol_name (string|nil) Internal symbol name for the language to load +--- - silent (boolean|nil) Don't throw an error if language not found ---@return boolean If the specified language is installed -function M.require_language(lang, path, silent, symbol_name) +function M.add(lang, opts) + ---@cast opts treesitter.RequireLangOpts + opts = opts or {} + local path = opts.path + local silent = opts.silent + local filetype = opts.filetype or lang + local symbol_name = opts.symbol_name + + vim.validate({ + lang = { lang, 'string' }, + path = { path, 'string', true }, + silent = { silent, 'boolean', true }, + symbol_name = { symbol_name, 'string', true }, + filetype = { filetype, { 'string', 'table' }, true }, + }) + + M.register(lang, filetype or lang) + if vim._ts_has_language(lang) then return true end + if path == nil then if not (lang and lang:match('[%w_]+') == lang) then if silent then @@ -35,9 +82,9 @@ function M.require_language(lang, path, silent, symbol_name) end if silent then - return pcall(function() - vim._ts_add_language(path, lang, symbol_name) - end) + if not pcall(vim._ts_add_language, path, lang, symbol_name) then + return false + end else vim._ts_add_language(path, lang, symbol_name) end @@ -45,6 +92,27 @@ function M.require_language(lang, path, silent, symbol_name) return true end +--- Register a lang to be used for a filetype (or list of filetypes). +---@param lang string Language to register +---@param filetype string|string[] Filetype(s) to associate with lang +function M.register(lang, filetype) + vim.validate({ + lang = { lang, 'string' }, + filetype = { filetype, { 'string', 'table' } }, + }) + + local filetypes ---@type string[] + if type(filetype) == 'string' then + filetypes = { filetype } + else + filetypes = filetype + end + + for _, f in ipairs(filetypes) do + ft_to_lang[f] = lang + end +end + --- Inspects the provided language. --- --- Inspecting provides some useful information on the language like node names, ... @@ -52,7 +120,7 @@ end ---@param lang string Language ---@return table function M.inspect_language(lang) - M.require_language(lang) + M.add(lang) return vim._ts_inspect_language(lang) end diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 8255c6f4fe..81ad83db2c 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -51,7 +51,7 @@ LanguageTree.__index = LanguageTree --- query per language. ---@return LanguageTree parser object function LanguageTree.new(source, lang, opts) - language.require_language(lang) + language.add(lang) ---@type LanguageTreeOpts opts = opts or {} @@ -170,7 +170,7 @@ function LanguageTree:parse() local seen_langs = {} ---@type table for lang, injection_ranges in pairs(injections_by_lang) do - local has_lang = language.require_language(lang, nil, true) + local has_lang = language.add(lang, { silent = true }) -- Child language trees should just be ignored if not found, since -- they can depend on the text of a node. Intermediate strings diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 008e5a54d7..83910316a6 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -252,7 +252,7 @@ end) --- ---@return Query Parsed query function M.parse_query(lang, query) - language.require_language(lang) + language.add(lang) local cached = query_cache[lang][query] if cached then return cached -- cgit From d1b34b74580fc09d86144c35e24a1a8a0d531b36 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 22 Feb 2023 10:58:15 +0100 Subject: vim-patch:9.0.1337: yuck files are not recognized (#22358) Problem: Yuck files are not recognized. Solution: Add a filetype pattern for yuck files. (Amaan Qureshi, closes vim/vim#12033) https://github.com/vim/vim/commit/cfce5cf542db20c7beba5b4211c0ae3305a64a43 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 4ee7d46b20..0dd2dcfcbe 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1131,6 +1131,7 @@ local extension = { yml = 'yaml', yaml = 'yaml', yang = 'yang', + yuck = 'yuck', ['z8a'] = 'z8a', zig = 'zig', zir = 'zir', -- cgit From 675826da63e879efa97c0998fea192ed5c79d56e Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 22 Feb 2023 08:01:08 -0700 Subject: refactor(treesitter): Add vim.treesitter.get_node() (#22360) This function replaces both vim.treesitter.get_node_at_pos() and vim.treesitter.get_node_at_cursor(). These two functions are similar enough that they don't need separate interfaces. Even worse, get_node_at_pos() returns a TSNode while get_node_at_cursor() returns a string, so the two functions behave slightly differently. vim.treesitter.get_node() combines these two into a more streamlined interface. With no arguments, it returns the node under the cursor in the current buffer. Optionally, it can accept a buffer number or a position to get the node at a given position in a given buffer. --- runtime/doc/deprecated.txt | 8 ++++++ runtime/doc/news.txt | 2 ++ runtime/doc/treesitter.txt | 29 ++++++++------------- runtime/lua/vim/treesitter.lua | 57 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 23 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index e7b0a710e8..42dfb53e77 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -119,6 +119,14 @@ LSP FUNCTIONS - *vim.lsp.buf.range_formatting()* Use |vim.lsp.formatexpr()| or |vim.lsp.buf.format()| instead. +TREESITTER FUNCTIONS +- *vim.treesitter.language.require_language()* Use |vim.treesitter.language.add()| + instead. +- *vim.treesitter.get_node_at_pos()* Use |vim.treesitter.get_node()| + instead. +- *vim.treesitter.get_node_at_cursor()* Use |vim.treesitter.get_node()| + and |TSNode:type()| instead. + LUA - *vim.register_keystroke_callback()* Use |vim.on_key()| instead. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 8b41f2d104..2a12a144e6 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -208,5 +208,7 @@ release. • `vim.treesitter.language.require_language()` has been deprecated in favour of |vim.treesitter.language.add()|. +• |vim.treesitter.get_node_at_pos()| and |vim.treesitter.get_node_at_cursor()| + are both deprecated in favor of |vim.treesitter.get_node()|. vim:tw=78:ts=8:sw=2:et:ft=help:norl: diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index e35e145301..16de49029e 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -508,30 +508,21 @@ get_captures_at_pos({bufnr}, {row}, {col}) table[] List of captures `{ capture = "capture name", metadata = { ... } }` -get_node_at_cursor({winnr}) *vim.treesitter.get_node_at_cursor()* - Returns the smallest named node under the cursor - - Parameters: ~ - • {winnr} (integer|nil) Window handle or 0 for current window (default) - - Return: ~ - (string) Name of node under the cursor - - *vim.treesitter.get_node_at_pos()* -get_node_at_pos({bufnr}, {row}, {col}, {opts}) +get_node({opts}) *vim.treesitter.get_node()* Returns the smallest named node at the given position Parameters: ~ - • {bufnr} (integer) Buffer number (0 for current buffer) - • {row} (integer) Position row - • {col} (integer) Position column - • {opts} (table) Optional keyword arguments: - • lang string|nil Parser language - • ignore_injections boolean Ignore injected languages - (default true) + • {opts} (table|nil) Optional keyword arguments: + • bufnr integer|nil Buffer number (nil or 0 for current + buffer) + • pos table|nil 0-indexed (row, col) tuple. Defaults to cursor + position in the current window. Required if {bufnr} is not + the current buffer + • ignore_injections boolean Ignore injected languages (default + true) Return: ~ - |TSNode||nil under the cursor + |TSNode| | nil Node at the given position get_node_range({node_or_range}) *vim.treesitter.get_node_range()* Returns the node's range or an unpacked range table diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c524b20bc2..c1e5325519 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -286,6 +286,50 @@ function M.get_captures_at_cursor(winnr) return captures end +--- Returns the smallest named node at the given position +--- +---@param opts table|nil Optional keyword arguments: +--- - bufnr integer|nil Buffer number (nil or 0 for current buffer) +--- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the +--- current window. Required if {bufnr} is not the current buffer +--- - ignore_injections boolean Ignore injected languages (default true) +--- +---@return TSNode | nil Node at the given position +function M.get_node(opts) + opts = opts or {} + + local bufnr = opts.bufnr + + if not bufnr or bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + + local row, col + if opts.pos then + assert(#opts.pos == 2, 'Position must be a (row, col) tuple') + row, col = opts.pos[1], opts.pos[2] + else + assert( + bufnr == a.nvim_get_current_buf(), + 'Position must be explicitly provided when not using the current buffer' + ) + local pos = a.nvim_win_get_cursor(0) + -- Subtract one to account for 1-based row indexing in nvim_win_get_cursor + row, col = pos[1] - 1, pos[2] + end + + assert(row >= 0 and col >= 0, 'Invalid position: row and col must be non-negative') + + local ts_range = { row, col, row, col } + + local root_lang_tree = M.get_parser(bufnr) + if not root_lang_tree then + return + end + + return root_lang_tree:named_node_for_range(ts_range, opts) +end + --- Returns the smallest named node at the given position --- ---@param bufnr integer Buffer number (0 for current buffer) @@ -296,12 +340,16 @@ end --- - ignore_injections boolean Ignore injected languages (default true) --- ---@return TSNode|nil under the cursor +---@deprecated function M.get_node_at_pos(bufnr, row, col, opts) + vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10') if bufnr == 0 then bufnr = a.nvim_get_current_buf() end local ts_range = { row, col, row, col } + opts = opts or {} + local root_lang_tree = M.get_parser(bufnr, opts.lang) if not root_lang_tree then return @@ -315,12 +363,13 @@ end ---@param winnr (integer|nil) Window handle or 0 for current window (default) --- ---@return string Name of node under the cursor +---@deprecated function M.get_node_at_cursor(winnr) + vim.deprecate('vim.treesitter.get_node_at_cursor()', 'vim.treesitter.get_node():type()', '0.10') winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) - local cursor = a.nvim_win_get_cursor(winnr) - return M.get_node_at_pos(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }):type() + return M.get_node({ bufnr = bufnr, ignore_injections = false }):type() end --- Starts treesitter highlighting for a buffer @@ -493,8 +542,8 @@ function M.show_tree(opts) a.nvim_buf_clear_namespace(b, pg.ns, 0, -1) - local cursor = a.nvim_win_get_cursor(win) - local cursor_node = M.get_node_at_pos(buf, cursor[1] - 1, cursor[2], { + local cursor_node = M.get_node({ + bufnr = buf, lang = opts.lang, ignore_injections = false, }) -- cgit From b496605fea0117b517a47f0f300e2161ac75dcc0 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 10 Jan 2023 15:49:39 +0100 Subject: docs: vim_diff.txt --- runtime/doc/news.txt | 4 +- runtime/doc/vim_diff.txt | 239 ++++++++++++++++++++++++----------------------- 2 files changed, 124 insertions(+), 119 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 8b41f2d104..c6588fdeab 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -13,7 +13,7 @@ BREAKING CHANGES *news-breaking* The following changes may require adaptations in user config or plugins. -• Cscope support is now removed (see |cscope| and |nvim-features-removed|): +• Cscope support is now removed (see |cscope| and |nvim-removed|): - Commands removed: - `:cscope` - `:lcscope` @@ -34,7 +34,7 @@ The following changes may require adaptations in user config or plugins. See https://github.com/neovim/neovim/pull/20545 for more information. -• `:hardcopy` is now removed (see |hardcopy| and |nvim-features-removed|): +• `:hardcopy` is now removed (see |hardcopy| and |nvim-removed|): - Commands removed: - `:hardcopy` - Options removed: diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 97fc211c36..b274c02945 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -13,7 +13,7 @@ centralized reference of the differences. Type |gO| to see the table of contents. ============================================================================== -1. Configuration *nvim-config* +Configuration *nvim-config* - Use `$XDG_CONFIG_HOME/nvim/init.vim` instead of `.vimrc` for your |config|. - Use `$XDG_CONFIG_HOME/nvim` instead of `.vim` to store configuration files. @@ -21,7 +21,7 @@ centralized reference of the differences. session information. |shada| ============================================================================== -2. Defaults *nvim-defaults* +Defaults *nvim-defaults* - Filetype detection is enabled by default. This can be disabled by adding ":filetype off" to |init.vim|. @@ -78,7 +78,7 @@ centralized reference of the differences. - |g:vimsyn_embed| defaults to "l" to enable Lua highlighting -Default Mouse ~ +DEFAULT MOUSE *default-mouse* *disable-mouse* By default the mouse is enabled, and opens a |popup-menu| with standard actions ("Cut", "Copy", "Paste", …). Mouse is NOT enabled in @@ -102,7 +102,7 @@ To remove the "How-to disable mouse" menu item and the separator above it: >vim aunmenu PopUp.How-to\ disable\ mouse aunmenu PopUp.-1- < -Default Mappings ~ +DEFAULT MAPPINGS *default-mappings* Nvim creates the following default mappings at |startup|. You can disable any of these in your config by simply removing the mapping, e.g. ":unmap Y". @@ -115,7 +115,7 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y". xnoremap # y?\V" nnoremap & :&& < -Default Autocommands ~ +DEFAULT AUTOCOMMANDS *default-autocmds* Default autocommands exist in the following groups. Use ":autocmd! {group}" to remove them and ":autocmd {group}" to see how they're defined. @@ -127,35 +127,36 @@ nvim_cmdwin: - CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|. ============================================================================== -3. New Features *nvim-features* +New Features *nvim-features* MAJOR COMPONENTS -API |API| -Job control |job-control| -LSP framework |lsp| -Lua scripting |lua| -Parsing engine |treesitter| -Providers - Clipboard |provider-clipboard| - Node.js plugins |provider-nodejs| - Python plugins |provider-python| - Ruby plugins |provider-ruby| -Remote plugins |remote-plugin| -Shared data |shada| -Terminal emulator |terminal| -Vimscript parser |nvim_parse_expression()| -XDG base directories |xdg| +- API |API| +- Job control |job-control| +- LSP framework |lsp| +- Lua scripting |lua| +- Parsing engine |treesitter| +- Providers + - Clipboard |provider-clipboard| + - Node.js plugins |provider-nodejs| + - Python plugins |provider-python| + - Ruby plugins |provider-ruby| +- Remote plugins |remote-plugin| +- Shared data |shada| +- Terminal emulator |terminal| +- UI |ui| |--listen| |--server| +- Vimscript parser |nvim_parse_expression()| +- XDG base directories |xdg| USER EXPERIENCE Working intuitively and consistently is a major goal of Nvim. *feature-compile* -- Nvim always includes ALL features, in contrast to Vim (which ships with - various combinations of 100+ optional features). Think of it as a leaner - version of Vim's "HUGE" build. This reduces surface area for bugs, and - removes a common source of confusion and friction for users. +- Nvim always includes ALL features, in contrast to Vim (which ships various + combinations of 100+ optional features). |feature-compile| Think of it as + a leaner version of Vim's "HUGE" build. This reduces surface area for bugs, + and removes a common source of confusion and friction for users. - Nvim avoids features that cannot be provided on all platforms; instead that is delegated to external plugins/extensions. E.g. the `-X` platform-specific @@ -173,6 +174,7 @@ backwards-compatibility cost. Some examples: - Directories for 'directory' and 'undodir' are auto-created. - Terminal features such as 'guicursor' are enabled where possible. +- Various "nvim" |cli-arguments| were redesigned. Some features are built in that otherwise required external plugins: @@ -180,6 +182,11 @@ Some features are built in that otherwise required external plugins: ARCHITECTURE +The Nvim UI is "decoupled" from the core editor: all UIs, including the +builtin |TUI| are just plugins that connect to a Nvim server (via |--server| +or |--embed|). Multiple Nvim UI clients can connect to the same Nvim editor +server. + External plugins run in separate processes. |remote-plugin| This improves stability and allows those plugins to work without blocking the editor. Even "legacy" Python and Ruby plugins which use the old Vim interfaces (|if_pyth|, @@ -191,7 +198,7 @@ by Nvim developers. FEATURES -Command-line highlighting: +Command-line: The expression prompt (|@=|, |c_CTRL-R_=|, |i_CTRL-R_=|) is highlighted using a built-in Vimscript expression parser. |expr-highlight| *E5408* *E5409* @@ -253,34 +260,105 @@ Input/Mappings: Normal commands: |gO| shows a filetype-defined "outline" of the current buffer. + |Q| replays the last recorded macro instead of switching to Ex mode (|gQ|). Options: 'cpoptions' flags: |cpo-_| - 'guicursor' works in the terminal + 'diffopt' "linematch" feature + 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The + user is prompted whether to trust the file. 'fillchars' flags: "msgsep", "horiz", "horizup", "horizdown", "vertleft", "vertright", "verthoriz" 'foldcolumn' supports up to 9 dynamic/fixed columns + 'guicursor' works in the terminal (TUI) 'inccommand' shows interactive results for |:substitute|-like commands and |:command-preview| commands + 'jumpoptions' "stack" behavior + 'jumpoptions' "view" tries to restore the |mark-view| when moving through + the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|. 'laststatus' global statusline support 'mousescroll' amount to scroll by when scrolling with a mouse 'pumblend' pseudo-transparent popupmenu 'scrollback' + 'shortmess' "F" flag does not affect output from autocommands 'signcolumn' supports up to 9 dynamic/fixed columns + 'statuscolumn' full control of columns using 'statusline' format + 'statusline' supports unlimited alignment sections 'tabline' %@Func@foo%X can call any function on mouse-click + 'ttimeout', 'ttimeoutlen' behavior was simplified 'winblend' pseudo-transparency in floating windows |api-floatwin| 'winhighlight' window-local highlights - 'diffopt' has the option `linematch`. + +Providers: + If a Python interpreter is available on your `$PATH`, |:python| and + |:python3| are always available. See |provider-python|. + +Shell: + Shell output (|:!|, |:make|, …) is always routed through the UI, so it + cannot "mess up" the screen. (You can still use "chansend(v:stderr,…)" if + you want to mess up the screen :) + + Nvim throttles (skips) messages from shell commands (|:!|, |:grep|, |:make|) + if there is too much output. No data is lost, this only affects display and + improves performance. |:terminal| output is never throttled. + + |:!| does not support "interactive" commands. Use |:terminal| instead. + (GUI Vim has a similar limitation, see ":help gui-pty" in Vim.) + + :!start is not special-cased on Windows. + + |system()| does not support writing/reading "backgrounded" commands. |E5677| Signs: Signs are removed if the associated line is deleted. +Startup: + |-e| and |-es| invoke the same "improved Ex mode" as -E and -Es. + |-E| and |-Es| read stdin as text (into buffer 1). + |-es| and |-Es| have improved behavior: + - Quits automatically, don't need "-c qa!". + - Skips swap-file dialog. + |-s| reads Normal commands from stdin if the script name is "-". + Reading text (instead of commands) from stdin |--|: + - works by default: "-" file is optional + - works in more cases: |-Es|, file args + +TUI: + *:set-termcap* + Start Nvim with 'verbose' level 3 to show terminal capabilities: > + nvim -V3 +< + *'term'* *E529* *E530* *E531* + 'term' reflects the terminal type derived from |$TERM| and other environment + checks. For debugging only; not reliable during startup. >vim + :echo &term +< "builtin_x" means one of the |builtin-terms| was chosen, because the expected + terminfo file was not found on the system. + + Nvim will use 256-colour capability on Linux virtual terminals. Vim uses + only 8 colours plus bright foreground on Linux VTs. + + Vim combines what is in its |builtin-terms| with what it reads from terminfo, + and has a 'ttybuiltin' setting to control how that combination works. Nvim + uses one or the other, it does not attempt to merge the two. + +UI/Display: + |Visual| selection highlights the character at cursor. |visual-use| + + messages: When showing messages longer than 'cmdheight', only + scroll the message lines, not the entire screen. The + separator line is decorated by |hl-MsgSeparator| and + the "msgsep" flag of 'fillchars'. *msgsep* + Variables: |v:progpath| is always absolute ("full") |v:windowid| is always available (for use by external UIs) +Vimscript: + |:redir| nested in |execute()| works. + ============================================================================== -4. Upstreamed features *nvim-upstreamed* +Upstreamed features *nvim-upstreamed* These Nvim features were later integrated into Vim. @@ -294,17 +372,9 @@ These Nvim features were later integrated into Vim. - 'statusline' supports unlimited alignment sections ============================================================================== -5. Changed features *nvim-features-changed* - -Nvim always builds with all features, in contrast to Vim which may have -certain features removed/added at compile-time. |feature-compile| - -Some Vim features were changed in Nvim, and vice versa. +Changed features *nvim-changed* -If a Python interpreter is available on your `$PATH`, |:python| and |:python3| -are always available and may be used simultaneously. See |provider-python|. - -|:redir| nested in |execute()| works. +This section lists various low-level details about other behavior changes. |mkdir()| behaviour changed: 1. Assuming /tmp/foo does not exist and /tmp can be written to @@ -345,7 +415,7 @@ are always available and may be used simultaneously. See |provider-python|. |json_encode()| behaviour slightly changed: now |msgpack-special-dict| values are accepted, but |v:none| is not. -Viminfo text files were replaced with binary (messagepack) ShaDa files. +Viminfo text files were replaced with binary (messagepack) |shada| files. Additional differences: - |shada-c| has no effect. @@ -387,7 +457,7 @@ Commands: |:wincmd| accepts a count. `:write!` does not show a prompt if the file was updated externally. -Command line completion: +Command-line: The meanings of arrow keys do not change depending on 'wildoptions'. Functions: @@ -424,46 +494,6 @@ Mappings: Motion: The |jumplist| avoids useless/phantom jumps. -Normal commands: - |Q| replays the last recorded macro instead of switching to Ex mode. - Instead |gQ| can be used to enter Ex mode. - -Options: - 'ttimeout', 'ttimeoutlen' behavior was simplified - 'jumpoptions' "stack" behavior - 'jumpoptions' "view" tries to restore the |mark-view| when moving through - the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|. - 'shortmess' the "F" flag does not affect output from autocommands - 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The user is - prompted whether to trust the file. - -Shell: - Shell output (|:!|, |:make|, …) is always routed through the UI, so it - cannot "mess up" the screen. (You can still use "chansend(v:stderr,…)" if - you want to mess up the screen :) - - Nvim throttles (skips) messages from shell commands (|:!|, |:grep|, |:make|) - if there is too much output. No data is lost, this only affects display and - improves performance. |:terminal| output is never throttled. - - |:!| does not support "interactive" commands. Use |:terminal| instead. - (GUI Vim has a similar limitation, see ":help gui-pty" in Vim.) - - :!start is not special-cased on Windows. - - |system()| does not support writing/reading "backgrounded" commands. |E5677| - -Startup: - |-e| and |-es| invoke the same "improved Ex mode" as -E and -Es. - |-E| and |-Es| read stdin as text (into buffer 1). - |-es| and |-Es| have improved behavior: - - Quits automatically, don't need "-c qa!". - - Skips swap-file dialog. - |-s| reads Normal commands from stdin if the script name is "-". - Reading text (instead of commands) from stdin |--|: - - works by default: "-" file is optional - - works in more cases: |-Es|, file args - Syntax highlighting: syncolor.vim has been removed. Nvim now sets up default highlighting groups automatically for both light and dark backgrounds, regardless of whether or @@ -472,40 +502,13 @@ Syntax highlighting: after/syntax/syncolor.vim file should transition that file into a colorscheme. |:colorscheme| -TUI: - *:set-termcap* - Start Nvim with 'verbose' level 3 to show terminal capabilities: > - nvim -V3 -< - *'term'* *E529* *E530* *E531* - 'term' reflects the terminal type derived from |$TERM| and other environment - checks. For debugging only; not reliable during startup. >vim - :echo &term -< "builtin_x" means one of the |builtin-terms| was chosen, because the expected - terminfo file was not found on the system. - - Nvim will use 256-colour capability on Linux virtual terminals. Vim uses - only 8 colours plus bright foreground on Linux VTs. - - Vim combines what is in its |builtin-terms| with what it reads from terminfo, - and has a 'ttybuiltin' setting to control how that combination works. Nvim - uses one or the other, it does not attempt to merge the two. - -UI/Display: - |Visual| selection highlights the character at cursor. |visual-use| - - messages: When showing messages longer than 'cmdheight', only - scroll the message lines, not the entire screen. The - separator line is decorated by |hl-MsgSeparator| and - the "msgsep" flag of 'fillchars'. *msgsep* - Vimscript compatibility: `count` does not alias to |v:count| `errmsg` does not alias to |v:errmsg| `shell_error` does not alias to |v:shell_error| `this_session` does not alias to |v:this_session| -Working directory (Vim implemented some of these later than Nvim): +Working directory (Vim implemented some of these after Nvim): - |DirChanged| and |DirChangedPre| can be triggered when switching to another window or tab. - |getcwd()| and |haslocaldir()| may throw errors if the tab page or window @@ -516,20 +519,15 @@ Working directory (Vim implemented some of these later than Nvim): working directory. Use `getcwd(-1, -1)` to get the global working directory. ============================================================================== -6. Missing legacy features *nvim-features-missing* - -Some legacy Vim features are not yet implemented: +Missing legacy features *nvim-missing* -- *if_lua* : Nvim |Lua| API is not compatible with Vim's "if_lua" -- *if_mzscheme* -- |if_pyth|: *python-bindeval* *python-Function* are not supported -- *if_tcl* +These legacy Vim features are not yet implemented: *:gui* *:gvim* ============================================================================== -7. Removed features *nvim-features-removed* +Removed legacy features *nvim-removed* These Vim features were intentionally removed from Nvim. @@ -687,6 +685,13 @@ Options: Performance: Folds are not updated during insert-mode. +Providers: + +- *if_lua* : Nvim |Lua| API is not compatible with Vim's "if_lua". +- *if_mzscheme* +- |if_pyth|: *python-bindeval* *python-Function* are not supported. +- *if_tcl* + Startup: --literal (file args are always literal; to expand wildcards on Windows, use |:n| e.g. `nvim +"n *"`) -- cgit From 0b36145c696fb58e002169edd4f9a1d9a8176fc3 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Wed, 22 Feb 2023 16:23:24 +0100 Subject: docs: mention getmousepos() for click execute function label close #18741 close #11312 --- runtime/doc/options.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d13ab8c393..2260cd8377 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6199,6 +6199,8 @@ A jump table for the options with a short description can be found at |Q_op|. is a bug that denotes that new mouse button recognition was added without modifying code that reacts on mouse clicks on this label. + Use |getmousepos()|.winid in the specified function to get the + corresponding window id of the clicked item. < - Where to truncate line if too long. Default is at the start. No width fields allowed. = - Separation point between alignment sections. Each section will -- cgit From 6752f1005d26c93a033d856a60b7b296f3e51634 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 14 Dec 2022 19:58:18 +0100 Subject: docs: naming conventions, guidelines close #21063 --- runtime/doc/api.txt | 57 ++++++------- runtime/doc/develop.txt | 191 ++++++++++++++++++++++++++----------------- runtime/doc/editing.txt | 41 +++++----- runtime/doc/editorconfig.txt | 24 +++--- runtime/doc/lua-guide.txt | 6 +- runtime/doc/lua.txt | 63 ++++++-------- runtime/doc/options.txt | 37 ++++----- runtime/doc/support.txt | 6 +- runtime/doc/ui.txt | 3 + runtime/doc/vim_diff.txt | 1 + runtime/lua/vim/keymap.lua | 50 ++++------- runtime/lua/vim/ui.lua | 7 +- 12 files changed, 241 insertions(+), 245 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 7bcae79852..3ca50dda15 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1461,16 +1461,15 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()* "!" for |:map!|, or empty string for |:map|. • {lhs} Left-hand-side |{lhs}| of the mapping. • {rhs} Right-hand-side |{rhs}| of the mapping. - • {opts} Optional parameters map: keys are |:map-arguments|, values are - booleans (default false). Accepts all |:map-arguments| as keys - excluding || but including |:noremap| and "desc". - Unknown key is an error. "desc" can be used to give a - description to the mapping. When called from Lua, also accepts - a "callback" key that takes a Lua function to call when the - mapping is executed. When "expr" is true, "replace_keycodes" - (boolean) can be used to replace keycodes in the resulting - string (see |nvim_replace_termcodes()|), and a Lua callback - returning `nil` is equivalent to returning an empty string. + • {opts} Optional parameters map: Accepts all |:map-arguments| as keys + except ||, values are booleans (default false). Also: + • "noremap" non-recursive mapping |:noremap| + • "desc" human-readable description. + • "callback" Lua function called when the mapping is executed. + • "replace_keycodes" (boolean) When "expr" is true, replace + keycodes in the resulting string (see + |nvim_replace_termcodes()|). Returning nil from the Lua + "callback" is equivalent to returning an empty string. nvim_set_var({name}, {value}) *nvim_set_var()* Sets a global (g:) variable. @@ -1678,7 +1677,7 @@ Command Functions *api-command* *nvim_buf_create_user_command()* nvim_buf_create_user_command({buffer}, {name}, {command}, {*opts}) - Create a new user command |user-commands| in the given buffer. + Creates a buffer-local command |user-commands|. Parameters: ~ • {buffer} Buffer handle, or 0 for current buffer. @@ -1743,15 +1742,12 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* *nvim_create_user_command()* nvim_create_user_command({name}, {command}, {*opts}) - Create a new user command |user-commands| + Creates a global |user-commands| command. - {name} is the name of the new command. The name must begin with an - uppercase letter. - - {command} is the replacement text or Lua function to execute. + For Lua usage see |lua-guide-commands-create|. Example: >vim - :call nvim_create_user_command('SayHello', 'echo "Hello world!"', {}) + :call nvim_create_user_command('SayHello', 'echo "Hello world!"', {'bang': v:true}) :SayHello Hello world! < @@ -1783,19 +1779,20 @@ nvim_create_user_command({name}, {command}, {*opts}) • smods: (table) Command modifiers in a structured format. Has the same structure as the "mods" key of |nvim_parse_cmd()|. - • {opts} Optional command attributes. See |command-attributes| for - more details. To use boolean attributes (such as - |:command-bang| or |:command-bar|) set the value to "true". - In addition to the string options listed in - |:command-complete|, the "complete" key also accepts a Lua - function which works like the "customlist" completion mode - |:command-completion-customlist|. Additional parameters: - • desc: (string) Used for listing the command when a Lua - function is used for {command}. - • force: (boolean, default true) Override any previous - definition. - • preview: (function) Preview callback for 'inccommand' - |:command-preview| + • {opts} Optional |command-attributes|. + • Set boolean attributes such as |:command-bang| or + |:command-bar| to true (but not |:command-buffer|, use + |nvim_buf_create_user_command()| instead). + • "complete" |:command-complete| also accepts a Lua + function which works like + |:command-completion-customlist|. + • Other parameters: + • desc: (string) Used for listing the command when a Lua + function is used for {command}. + • force: (boolean, default true) Override any previous + definition. + • preview: (function) Preview callback for 'inccommand' + |:command-preview| nvim_del_user_command({name}) *nvim_del_user_command()* Delete a user-defined command. diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 87190d7f33..b090fd4f09 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -132,6 +132,18 @@ DOCUMENTATION *dev-doc* optimize for the reader's time and energy: be "precise yet concise". - See https://developers.google.com/style/tone - Prefer the active voice: "Foo does X", not "X is done by Foo". +- Start function docstrings with present tense ("Gets"), not imperative + ("Get"). This tends to reduce ambiguity and improve clarity. > + GOOD: + /// Gets a highlight definition. + BAD: + /// Get a highlight definition. +- Avoid starting docstrings with "The" or "A" unless needed to avoid + ambiguity. This is a visual aid and reduces noise. > + GOOD: + /// @param dirname Path fragment before `pend` + BAD: + /// @param dirname The path fragment before `pend` - Vim differences: - Do not prefix help tags with "nvim-". Use |vim_diff.txt| to catalog differences from Vim; no other distinction is necessary. @@ -143,13 +155,6 @@ DOCUMENTATION *dev-doc* not "the user host terminal". - Use "tui-" to prefix help tags related to the host terminal, and "TUI" in prose if possible. -- Docstrings: do not start parameter descriptions with "The" or "A" unless it - is critical to avoid ambiguity. > - GOOD: - /// @param dirname Path fragment before `pend` - BAD: - /// @param dirname The path fragment before `pend` -< Documentation format ~ @@ -159,14 +164,14 @@ https://neovim.io/doc/user ). Strict "vimdoc" subset: -- Use lists (like this!) prefixed with "-", "*", or "•", for adjacent lines - that you don't want auto-wrapped. Lists are always rendered with "flow" - (soft-wrapped) layout instead of preformatted (hard-wrapped) layout common - in legacy :help docs. +- Use lists (like this!) prefixed with "-" or "•", for adjacent lines that you + don't want to auto-wrap. Lists are always rendered with "flow" layout + (soft-wrapped) instead of preformatted (hard-wrapped) layout common in + legacy :help docs. - Limitation: currently the parser https://github.com/neovim/tree-sitter-vimdoc does not understand numbered listitems, so use a bullet symbol (- or •) - before numbered items, e.g. "- 1." instead of "1.". -- Separate blocks (paragraphs) of content by a blank line(s). + before numbered items, e.g. "• 1." instead of "1.". +- Separate blocks (paragraphs) of content by a blank line. - Do not use indentation in random places—that prevents the page from using "flow" layout. If you need a preformatted section, put it in a |help-codeblock| starting with ">". @@ -246,7 +251,9 @@ vim.paste in runtime/lua/vim/_editor.lua like this: > ---@returns false if client should cancel the paste. -LUA *dev-lua* +LUA STDLIB DESIGN GUIDELINES *dev-lua* + +See also |dev-naming|. - Keep the core Lua modules |lua-stdlib| simple. Avoid elaborate OOP or pseudo-OOP designs. Plugin authors just want functions to call, not a big, @@ -255,10 +262,26 @@ LUA *dev-lua* tables or values are easier to serialize, easier to construct from literals, easier to inspect and print, and inherently compatible with all Lua plugins. (This guideline doesn't apply to opaque, non-data objects like `vim.cmd`.) - - -API *dev-api* - +- stdlib functions should follow these common patterns: + - accept iterable instead of table + - exception: in some cases iterable doesn't make sense, e.g. spair() sorts + the input by definition, so there is no reason for it to accept an + iterable, because the input needs to be "hydrated", it can't operate on + a "stream". + - return iterable instead of table + - mimic the pairs() or ipairs() interface if the function is intended to be + used in a "for" loop. + + +API DESIGN GUIDELINES *dev-api* + +See also |dev-naming|. + +- When adding an API, check the following: + - What precedents did you draw from? How does your solution compare to them? + - Does your new API allow future expansion? How? Or why not? + - Is the new API similar to existing APIs? Do we need to deprecate the old ones? + - Did you cross-reference related concepts in the docs? - Avoid "mutually exclusive" parameters--via constraints or limitations, if necessary. For example nvim_create_autocmd() has mutually exclusive "callback" and "command" args; but the "command" arg could be eliminated by @@ -266,66 +289,95 @@ API *dev-api* "callback" arg as an Ex command (which can call Vimscript functions). The "buffer" arg could also be eliminated by treating a number "pattern" as a buffer number. +- Avoid functions that depend on cursor position, current buffer, etc. Instead + the function should take a position parameter, buffer parameter, etc. - *dev-api-naming* -Use this format to name new RPC |API| functions: +NAMING GUIDELINES *dev-naming* - nvim_{thing}_{action}_{arbitrary-qualifiers} +Naming is exceedingly important: the name of a thing is the primary interface +for uses it, discusses it, searches for it, shares it... Consistent +naming in the stdlib, API, and UI helps both users and developers discover and +intuitively understand related concepts ("families"), and reduces cognitive +burden. Discoverability encourages code re-use and likewise avoids redundant, +overlapping mechanisms, which reduces code surface-area, and thereby minimizes +bugs... -If the function acts on an object then {thing} is the name of that object -(e.g. "buf" or "win"). If the function operates in a "global" context then -{thing} is usually omitted (but consider "namespacing" your global operations -with a {thing} that groups functions under a common concept). - -Use existing common {action} names if possible: - - add Append to, or insert into, a collection - - call Call a function - - create Create a new (non-trivial) thing - - del Delete a thing (or group of things) - - eval Evaluate an expression - - exec Execute code - - fmt Format - - get Get things (often by a query) - - open Open - - parse Parse something into a structured form - - set Set a thing (or group of things) +Naming conventions ~ + +In general, look for precedent when choosing a name, that is, look at existing +(non-deprecated) functions. In particular, see below... + + *dev-name-common* +Use existing common {verb} names (actions) if possible: + - add: Appends or inserts into a collection + - attach: Listens to something to get events from it (TODO: rename to "on"?) + - call: Calls a function + - clear: Clears state but does not destroy the container + - create: Creates a new (non-trivial) thing (TODO: rename to "def"?) + - del: Deletes a thing (or group of things) + - detach: Dispose attached listener (TODO: rename to "un"?) + - eval: Evaluates an expression + - exec: Executes code + - fmt: Formats + - get: Gets things (often by a query) + - inspect: Presents a high-level, often interactive, view + - open: Opens something (a buffer, window, …) + - parse: Parses something into a structured form + - set: Sets a thing (or group of things) + - try_{verb}: Best-effort operation, failure returns null or error obj Do NOT use these deprecated verbs: - - list Redundant with "get" + - list: Redundant with "get" + - show: Redundant with "print", "echo" + - notify: Redundant with "print", "echo" -Use consistent names for {thing} (nouns) in API functions: buffer is called +Use consistent names for {noun} (nouns) in API functions: buffer is called "buf" everywhere, not "buffer" in some places and "buf" in others. - - buf Buffer - - chan |channel| - - cmd Command - - cmdline Command-line UI or input - - fn Function - - hl Highlight - - pos Position - - proc System process - - tabpage Tabpage - - win Window + - buf: Buffer + - chan: |channel| + - cmd: Command + - cmdline: Command-line UI or input + - fn: Function + - hl: Highlight + - pos: Position + - proc: System process + - tabpage: Tabpage + - win: Window Do NOT use these deprecated nouns: - buffer - command - window -Example: - `nvim_get_keymap('v')` operates in a global context (first parameter is not - a Buffer). The "get" {action} indicates that it gets anything matching the - given filter parameter. There is no need for a "list" action because - `nvim_get_keymap('')` (i.e., empty filter) returns all items. + *dev-name-events* +Use the "on_" prefix to name event-handling callbacks and also the interface for +"registering" such handlers (on_key). The dual nature is acceptable to avoid +a confused collection of naming conventions for these related concepts. + +Editor |events| (autocommands) are historically named like: > + {Noun}{Event} + +Use this format to name API (RPC) events: > + nvim_{noun}_{event-name}_event -Example: - `nvim_buf_del_mark` acts on a `Buffer` object (the first parameter) - and uses the "del" {action}. +Example: > + nvim_buf_changedtick_event +< + *dev-name-api* +Use this format to name new RPC |API| functions: > + nvim_{noun}_{verb}_{arbitrary-qualifiers} -Use this format to name new API events: - nvim_{thing}_{event}_event +If the function acts on an object then {noun} is the name of that object +(e.g. "buf" or "win"). If the function operates in a "global" context then +{noun} is usually omitted (but consider "namespacing" your global operations +with a {noun} that groups functions under a common concept). -Example: - `nvim_buf_changedtick_event` +- Example: `nvim_get_keymap('v')` operates in a global context (first + parameter is not a Buffer). The "get" verb indicates that it gets anything + matching the given filter parameter. A "list" verb is unnecessary because + `nvim_get_keymap('')` (empty filter) returns all items. +- Example: `nvim_buf_del_mark` acts on a `Buffer` object (the first parameter) + and uses the "del" {verb}. API-CLIENT *dev-api-client* @@ -417,19 +469,4 @@ External UIs are expected to implement these common features: published in this event. See also "mouse_on", "mouse_off". -NAMING *dev-naming* - -Naming is important. Consistent naming in the API and UI helps both users and -developers discover and intuitively understand related concepts ("families"), -and reduces cognitive burden. Discoverability encourages code re-use and -likewise avoids redundant, overlapping mechanisms, which reduces code -surface-area, and thereby minimizes bugs... - -Naming conventions ~ - -Use the "on_" prefix to name event handlers and also the interface for -"registering" such handlers (on_key). The dual nature is acceptable to avoid -a confused collection of naming conventions for these related concepts. - - vim:tw=78:ts=8:sw=4:et:ft=help:norl: diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index f77db5fab3..bd1b62635e 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1668,29 +1668,26 @@ There are three different types of searching: ============================================================================== 12. Trusted Files *trust* -Nvim has the ability to execute arbitrary code through the 'exrc' option. In -order to prevent executing code from untrusted sources, Nvim has the concept of -"trusted files". An untrusted file will not be executed without the user's -consent, and a user can permanently mark a file as trusted or untrusted using -the |:trust| command or the |vim.secure.read()| function. +Nvim executes arbitrary code found on the filesystem if 'exrc' is enabled. To +prevent executing malicious code, only "trusted files" are executed. You can +mark a file as trusted or untrusted using the |:trust| command or the +|vim.secure.read()| function. *:trust* *E5570* -:trust [++deny] [++remove] [{file}] - - Manage files in the trust database. Without any options - or arguments, :trust adds the file associated with the - current buffer to the trust database, along with the - SHA256 hash of its contents. - - [++deny] marks the file associated with the current - buffer (or {file}, if given) as denied; no prompts will - be displayed to the user and the file will never be - executed. - - [++remove] removes the file associated with the current - buffer (or {file}, if given) from the trust database. - Future attempts to read the file in a secure setting - (i.e. with 'exrc' or |vim.secure.read()|) will prompt - the user if the file is trusted. +:trust [++deny] [++remove] [file] + + Manage trusted files. Without ++ options, :trust marks + [file] (or current buffer if no [file]) as trusted, + keyed on a hash of its contents. The trust list is + stored on disk, Nvim will re-use it after restarting. + + [++deny] marks [file] (or current buffer if no [file]) as + untrusted: it will never be executed, 'exrc' will + ignore it. + + [++remove] removes [file] (or current buffer if no + [file]) from the trust list. When the file is + discovered by 'exrc' or |vim.secure.read()|, the user + will be asked whether to trust or deny the file. vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/editorconfig.txt b/runtime/doc/editorconfig.txt index 04a057e5ff..52fd860d2d 100644 --- a/runtime/doc/editorconfig.txt +++ b/runtime/doc/editorconfig.txt @@ -6,25 +6,21 @@ EditorConfig integration *editorconfig* -Nvim natively supports EditorConfig. When a file is opened, Nvim searches -upward through all of the parent directories of that file looking for -".editorconfig" files. Each of these is parsed and any properties that match -the opened file are applied. - -For more information on EditorConfig, see https://editorconfig.org/. +Nvim supports EditorConfig. When a file is opened, Nvim searches all parent +directories of that file for ".editorconfig" files, parses them, and applies +any properties that match the opened file. Think of it like 'modeline' for an +entire (recursive) directory. For more information see +https://editorconfig.org/. *g:editorconfig* *b:editorconfig* -EditorConfig integration can be disabled globally by adding >lua +EditorConfig is enabled by default. To disable it, add to your config: >lua vim.g.editorconfig = false < -to the user's |init.lua| file (or the Vimscript equivalent to |init.vim|). It -can also be disabled per-buffer by setting the |b:editorconfig| buffer-local -variable to `false`. +(Vimscript: `let g:editorconfig = v:false`). It can also be disabled +per-buffer by setting the |b:editorconfig| buffer-local variable to `false`. -When Nvim finds a valid .editorconfig file it will store the applied -properties in the buffer variable |b:editorconfig| if it was not already set to -`false` by the user. +Nvim stores the applied properties in |b:editorconfig| if it is not `false`. *editorconfig-properties* The following properties are supported by default: @@ -88,4 +84,4 @@ Example: >lua vim.b[bufnr].foo = val end < - vim:tw=78:ts=8:noet:ft=help:norl: + vim:tw=78:ts=8:et:sw=4:ft=help:norl: diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt index b971a7d2ad..236905a077 100644 --- a/runtime/doc/lua-guide.txt +++ b/runtime/doc/lua-guide.txt @@ -657,7 +657,7 @@ See also • |nvim_exec_autocmds()|: execute all matching autocommands ============================================================================== -User commands *lua-guide-usercommands* +User commands *lua-guide-commands* |user-commands| are custom Vim commands that call a Vimscript or Lua function. Just like built-in commands, they can have arguments, act on ranges, or have @@ -665,7 +665,7 @@ custom completion of arguments. As these are most useful for plugins, we will cover only the basics of this advanced topic. ------------------------------------------------------------------------------ -Creating user commands *lua-guide-usercommands-create* +Creating user commands *lua-guide-commands-create* User commands can be created through the Neovim API with `vim.api.`|nvim_create_user_command()|. This function takes three mandatory @@ -734,7 +734,7 @@ the remaining arguments are the same as for |nvim_create_user_command()|: { nargs = 1 }) < ------------------------------------------------------------------------------ -Deleting user commands *lua-guide-usercommands-delete* +Deleting user commands *lua-guide-commands-delete* User commands can be deleted with `vim.api.`|nvim_del_user_command()|. The only argument is the name of the command: diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 0472c11a15..32e89bd237 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -2029,7 +2029,8 @@ uri_to_fname({uri}) *vim.uri_to_fname()* Lua module: ui *lua-ui* input({opts}, {on_confirm}) *vim.ui.input()* - Prompts the user for input + Prompts the user for input, allowing arbitrary (potentially asynchronous) + work until `on_confirm`. Example: >lua @@ -2054,7 +2055,8 @@ input({opts}, {on_confirm}) *vim.ui.input()* entered), or `nil` if the user aborted the dialog. select({items}, {opts}, {on_choice}) *vim.ui.select()* - Prompts the user to pick a single item from a collection of entries + Prompts the user to pick from a list of items, allowing arbitrary + (potentially asynchronous) work until `on_choice`. Example: >lua @@ -2253,57 +2255,38 @@ del({modes}, {lhs}, {opts}) *vim.keymap.del()* |vim.keymap.set()| set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()* - Add a new |mapping|. Examples: >lua + Adds a new |mapping|. Examples: >lua - -- Can add mapping to Lua functions + -- Map to a Lua function: vim.keymap.set('n', 'lhs', function() print("real lua function") end) - - -- Can use it to map multiple modes + -- Map to multiple modes: vim.keymap.set({'n', 'v'}, 'lr', vim.lsp.buf.references, { buffer=true }) - - -- Can add mapping for specific buffer + -- Buffer-local mapping: vim.keymap.set('n', 'w', "w", { silent = true, buffer = 5 }) - - -- Expr mappings + -- Expr mapping: vim.keymap.set('i', '', function() return vim.fn.pumvisible() == 1 and "" or "" end, { expr = true }) - -- mappings + -- mapping: vim.keymap.set('n', '[%', '(MatchitNormalMultiBackward)') < - Note that in a mapping like: >lua - - vim.keymap.set('n', 'asdf', require('jkl').my_fun) -< - - the `require('jkl')` gets evaluated during this call in order to access the function. If you - want to avoid this cost at startup you can wrap it in a function, for - example: >lua - - vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end) -< - Parameters: ~ - • {mode} string|table Same mode short names as |nvim_set_keymap()|. Can + • {mode} string|table Mode short-name, see |nvim_set_keymap()|. Can also be list of modes to create mapping on multiple modes. • {lhs} (string) Left-hand side |{lhs}| of the mapping. - • {rhs} string|function Right-hand side |{rhs}| of the mapping. Can - also be a Lua function. - • {opts} (table|nil) A table of |:map-arguments|. - • Accepts options accepted by the {opts} parameter in - |nvim_set_keymap()|, with the following notable differences: - • replace_keycodes: Defaults to `true` if "expr" is `true`. - • noremap: Always overridden with the inverse of "remap" - (see below). - - • In addition to those options, the table accepts the - following keys: - • buffer: (number or boolean) Add a mapping to the given - buffer. When `0` or `true`, use the current buffer. - • remap: (boolean) Make the mapping recursive. This is the - inverse of the "noremap" option from |nvim_set_keymap()|. - Defaults to `false`. + • {rhs} string|function Right-hand side |{rhs}| of the mapping, can be + a Lua function. + • {opts} (table|nil) Table of |:map-arguments|. + • Same as |nvim_set_keymap()| {opts}, except: + • "replace_keycodes" defaults to `true` if "expr" is `true`. + • "noremap": inverse of "remap" (see below). + + • Also accepts: + • "buffer" number|boolean Creates buffer-local mapping, `0` + or `true` for current buffer. + • remap: (boolean) Make the mapping recursive. Inverses + "noremap". Defaults to `false`. See also: ~ |nvim_set_keymap()| diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 2260cd8377..f44b6f28e3 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -401,20 +401,15 @@ the system, mostly it is something like 256 or 1024 characters. ============================================================================== 2. Automatically setting options *auto-setting* -Besides changing options with the ":set" command, there are three alternatives -to set options automatically for one or more files: - -1. When starting Vim initializations are read from various places. See - |initialization|. Most of them are performed for all editing sessions, - and some of them depend on the directory where Vim is started. - You can create an initialization file with |:mkvimrc|, |:mkview| and - |:mksession|. -2. If you start editing a new file, the automatic commands are executed. - This can be used to set options for files matching a particular pattern and - many other things. See |autocommand|. -3. If you start editing a new file, and the 'modeline' option is on, a - number of lines at the beginning and end of the file are checked for - modelines. This is explained here. +Besides changing options with the ":set" command, you can set options +automatically in various ways: + +1. With a |config| file or a |startup| argument. You can create an + initialization file with |:mkvimrc|, |:mkview| and |:mksession|. +2. |autocommand|s executed when you edit a file. +3. ".nvim.lua" files in the current directory, if 'exrc' is enabled. +4. |editorconfig| in the current buffer's directory or ancestors. +5. 'modeline' settings found at the beginning or end of the file. See below. *modeline* *vim:* *vi:* *ex:* *E520* There are two forms of modelines. The first form: @@ -2267,15 +2262,13 @@ A jump table for the options with a short description can be found at |Q_op|. *'exrc'* *'ex'* *'noexrc'* *'noex'* 'exrc' 'ex' boolean (default off) global - Enables the reading of .nvim.lua, .nvimrc, and .exrc files in the current - directory. - - The file is only sourced if the user indicates the file is trusted. If - it is, the SHA256 hash of the file contents and the full path of the - file are persisted to a trust database. The user is only prompted - again if the file contents change. See |vim.secure.read()|. + Automatically execute .nvim.lua, .nvimrc, and .exrc files in the + current directory, if the file is in the |trust| list. Use |:trust| to + manage trusted files. See also |vim.secure.read()|. - Use |:trust| to manage the trusted file database. + Compare 'exrc' to |editorconfig|: + - 'exrc' can execute any code; editorconfig only specifies settings. + - 'exrc' is Nvim-specific; editorconfig works in other editors. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. diff --git a/runtime/doc/support.txt b/runtime/doc/support.txt index 481959d8f1..e4641751f2 100644 --- a/runtime/doc/support.txt +++ b/runtime/doc/support.txt @@ -14,12 +14,16 @@ Supported platforms *supported-platforms* `System` `Tier` `Versions` `Tested versions` Linux 1 >= 2.6.32, glibc >= 2.12 Ubuntu 22.04 macOS (Intel) 1 >= 10.15 macOS 12 -Windows 64-bit 1 >= 8 Windows Server 2019 +Windows 64-bit 1 >= 8 (see note below) Windows Server 2019 FreeBSD 1 >= 10 FreeBSD 13 macOS (M1) 2 >= 10.15 OpenBSD 2 >= 7 MinGW 2 MinGW-w64 +Note: Windows 10 "Version 1809" or later is required for |:terminal|. To check +your Windows version, run the "winver" command and look for "Version xxxx" +(NOT "OS Build"). + Support types ~ * Tier 1: Officially supported and tested with CI. Any contributed patch diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 4e4f88f275..bb567e021e 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -809,5 +809,8 @@ events, which the UI must handle. Sent when |:messages| command is invoked. History is sent as a list of entries, where each entry is a `[kind, content]` tuple. +["msg_history_clear"] ~ + Clear the |:messages| history. + ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index b274c02945..79808eccc9 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -72,6 +72,7 @@ Defaults *nvim-defaults* - 'wildmenu' is enabled - 'wildoptions' defaults to "pum,tagfile" +- |editorconfig| plugin is enabled, .editorconfig settings are applied. - |man.lua| plugin is enabled, so |:Man| is available by default. - |matchit| plugin is enabled. To disable it in your config: >vim :let loaded_matchit = 1 diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index ef1c66ea20..911b584c14 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -1,51 +1,35 @@ local keymap = {} ---- Add a new |mapping|. +--- Adds a new |mapping|. --- Examples: ---
lua
----   -- Can add mapping to Lua functions
+---   -- Map to a Lua function:
 ---   vim.keymap.set('n', 'lhs', function() print("real lua function") end)
----
----   -- Can use it to map multiple modes
+---   -- Map to multiple modes:
 ---   vim.keymap.set({'n', 'v'}, 'lr', vim.lsp.buf.references, { buffer=true })
----
----   -- Can add mapping for specific buffer
+---   -- Buffer-local mapping:
 ---   vim.keymap.set('n', 'w', "w", { silent = true, buffer = 5 })
----
----   -- Expr mappings
+---   -- Expr mapping:
 ---   vim.keymap.set('i', '', function()
 ---     return vim.fn.pumvisible() == 1 and "" or ""
 ---   end, { expr = true })
----   --  mappings
+---   --  mapping:
 ---   vim.keymap.set('n', '[%%', '(MatchitNormalMultiBackward)')
 --- 
--- ---- Note that in a mapping like: ----
lua
----    vim.keymap.set('n', 'asdf', require('jkl').my_fun)
---- 
---- ---- the ``require('jkl')`` gets evaluated during this call in order to access the function. ---- If you want to avoid this cost at startup you can wrap it in a function, for example: ----
lua
----    vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
---- 
---- ----@param mode string|table Same mode short names as |nvim_set_keymap()|. +---@param mode string|table Mode short-name, see |nvim_set_keymap()|. --- Can also be list of modes to create mapping on multiple modes. ---@param lhs string Left-hand side |{lhs}| of the mapping. ----@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function. --- ----@param opts table|nil A table of |:map-arguments|. ---- + Accepts options accepted by the {opts} parameter in |nvim_set_keymap()|, ---- with the following notable differences: ---- - replace_keycodes: Defaults to `true` if "expr" is `true`. ---- - noremap: Always overridden with the inverse of "remap" (see below). ---- + In addition to those options, the table accepts the following keys: ---- - buffer: (number or boolean) Add a mapping to the given buffer. ---- When `0` or `true`, use the current buffer. ---- - remap: (boolean) Make the mapping recursive. ---- This is the inverse of the "noremap" option from |nvim_set_keymap()|. +---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function. +--- +---@param opts table|nil Table of |:map-arguments|. +--- - Same as |nvim_set_keymap()| {opts}, except: +--- - "replace_keycodes" defaults to `true` if "expr" is `true`. +--- - "noremap": inverse of "remap" (see below). +--- - Also accepts: +--- - "buffer" number|boolean Creates buffer-local mapping, `0` or `true` +--- for current buffer. +--- - remap: (boolean) Make the mapping recursive. Inverses "noremap". --- Defaults to `false`. ---@see |nvim_set_keymap()| function keymap.set(mode, lhs, rhs, opts) diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 8f5be15221..aaee175f3a 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -1,6 +1,7 @@ local M = {} ---- Prompts the user to pick a single item from a collection of entries +--- Prompts the user to pick from a list of items, allowing arbitrary (potentially asynchronous) +--- work until `on_choice`. --- ---@param items table Arbitrary items ---@param opts table Additional options @@ -35,7 +36,6 @@ local M = {} --- end --- end) --- - function M.select(items, opts, on_choice) vim.validate({ items = { items, 'table', false }, @@ -55,7 +55,8 @@ function M.select(items, opts, on_choice) end end ---- Prompts the user for input +--- Prompts the user for input, allowing arbitrary (potentially asynchronous) work until +--- `on_confirm`. --- ---@param opts table Additional options. See |input()| --- - prompt (string|nil) -- cgit From 799edca18a4ddcf8edcb63dd391219e01e187f0d Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 28 Nov 2022 22:43:10 +0100 Subject: feat(lua): make sure require'bit' always works, even with PUC lua 5.1 --- runtime/doc/lua.txt | 16 ++++++++++++++++ runtime/doc/news.txt | 1 + 2 files changed, 17 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 32e89bd237..8ae1c6dc40 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -33,6 +33,22 @@ Lua 5.1, not worry about forward-compatibility with future Lua versions. If Nvim ever ships with Lua 5.4+, a Lua 5.1 compatibility shim will be provided so that old plugins continue to work transparently. + *lua-luajit* +Neovim is built with luajit on platforms which support it, which provides +extra functionality. Lua code in |init.lua| and plugins can assume its presence +on installations on common platforms. For maximum compatibility with less +common platforms, availability can be checked using the `jit` global variable: >lua + if jit then + -- code for luajit + else + -- code for plain lua 5.1 + end +< + *lua-bit* +In particular, the luajit "bit" extension module is _always_ available. +A fallback implementation is included when nvim is built with PUC lua 5.1, +and will be transparently used when `require("bit")` is invoked. + ============================================================================== LUA CONCEPTS AND IDIOMS *lua-concepts* diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 6f505a958a..4dee958108 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -167,6 +167,7 @@ The following new APIs or features were added. • |vim.treesitter.language.add()| as a new replacement for `vim.treesitter.language.require_language`. +• `require'bit'` is now always available |lua-bit| ============================================================================== CHANGED FEATURES *news-changes* -- cgit From 05de0f4fea237132ff3a9a5a35e9c711c4ece579 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 21 Feb 2023 17:03:04 +0100 Subject: docs(treesitter): fix parse errors --- runtime/lua/vim/treesitter.lua | 4 ++-- runtime/lua/vim/treesitter/languagetree.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c1e5325519..c4df5b2d24 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -157,7 +157,7 @@ end --- Returns the node's range or an unpacked range table --- ----@param node_or_range (TSNode|table) Node or table of positions +---@param node_or_range (TSNode | table) Node or table of positions --- ---@return integer start_row ---@return integer start_col @@ -339,7 +339,7 @@ end --- - lang string|nil Parser language --- - ignore_injections boolean Ignore injected languages (default true) --- ----@return TSNode|nil under the cursor +---@return TSNode | nil Node at the given position ---@deprecated function M.get_node_at_pos(bufnr, row, col, opts) vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10') diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 81ad83db2c..c9fd4bb2ea 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -653,7 +653,7 @@ end ---@param range Range `{ start_line, start_col, end_line, end_col }` ---@param opts table|nil Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) ----@return TSNode|nil Found node +---@return TSNode | nil Found node function LanguageTree:named_node_for_range(range, opts) local tree = self:tree_for_range(range, opts) if tree then -- cgit From 1c37553476f268d08d290dfee1fa3da4135b54b4 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 21 Feb 2023 17:00:48 +0100 Subject: test(help): drop treesitter parse error to 0 All parser errors have been fixed; make sure we don't introduce new ones. --- runtime/doc/treesitter. | 0 runtime/doc/treesitter.txt | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 runtime/doc/treesitter. (limited to 'runtime') diff --git a/runtime/doc/treesitter. b/runtime/doc/treesitter. new file mode 100644 index 0000000000..e69de29bb2 diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 16de49029e..99fe55b6cb 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -528,7 +528,7 @@ get_node_range({node_or_range}) *vim.treesitter.get_node_range()* Returns the node's range or an unpacked range table Parameters: ~ - • {node_or_range} (|TSNode||table) Node or table of positions + • {node_or_range} (|TSNode| | table) Node or table of positions Return: ~ (integer) start_row @@ -1017,7 +1017,7 @@ LanguageTree:named_node_for_range({self}, {range}, {opts}) • {self} Return: ~ - |TSNode||nil Found node + |TSNode| | nil Found node LanguageTree:parse({self}) *LanguageTree:parse()* Parses all defined regions using a treesitter parser for the language this -- cgit From 6dfbeb0d990d24657754463c6ab155c19e7f5f56 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 21 Feb 2023 17:39:29 +0100 Subject: docs: fix more treesitter parsing errors --- runtime/doc/diagnostic.txt | 8 ++++---- runtime/doc/lua-guide.txt | 2 +- runtime/doc/treesitter. | 0 runtime/doc/treesitter.txt | 7 +++---- runtime/lua/vim/treesitter.lua | 2 +- runtime/lua/vim/treesitter/query.lua | 4 ++-- 6 files changed, 11 insertions(+), 12 deletions(-) delete mode 100644 runtime/doc/treesitter. (limited to 'runtime') diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 7066a3739a..c661bf02bf 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -40,15 +40,15 @@ requires a namespace. *diagnostic-structure* A diagnostic is a Lua table with the following keys. Required keys are -indicated with (*): +indicated with (+): bufnr: Buffer number - lnum(*): The starting line of the diagnostic + lnum(+): The starting line of the diagnostic end_lnum: The final line of the diagnostic - col(*): The starting column of the diagnostic + col(+): The starting column of the diagnostic end_col: The final column of the diagnostic severity: The severity of the diagnostic |vim.diagnostic.severity| - message(*): The diagnostic text + message(+): The diagnostic text source: The source of the diagnostic code: The diagnostic code user_data: Arbitrary data plugins or users can add diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt index 236905a077..8ea84f8c60 100644 --- a/runtime/doc/lua-guide.txt +++ b/runtime/doc/lua-guide.txt @@ -71,7 +71,7 @@ local keyword are not accessible outside of the command. This won't work: < You can also use `:lua=`, which is the same as `:lua vim.pretty_print(...)`, to conveniently check the value of a variable or a table: ->lua +>vim :lua=package < To run a Lua script in an external file, you can use the |:source| command diff --git a/runtime/doc/treesitter. b/runtime/doc/treesitter. deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 99fe55b6cb..3f505e5d19 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -505,8 +505,7 @@ get_captures_at_pos({bufnr}, {row}, {col}) • {col} (integer) Position column Return: ~ - table[] List of captures `{ capture = "capture name", metadata = { ... - } }` + table[] List of captures `{ capture = "name", metadata = { ... } }` get_node({opts}) *vim.treesitter.get_node()* Returns the smallest named node at the given position @@ -838,7 +837,7 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop}) -- typically useful info about the node: local type = node:type() -- type of the captured node local row1, col1, row2, col2 = node:range() -- range of the capture - ... use the info here ... + -- ... use the info here ... end < @@ -871,7 +870,7 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) local node_data = metadata[id] -- Node level metadata - ... use the info here ... + -- ... use the info here ... end end < diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c4df5b2d24..44922bbc4d 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -218,7 +218,7 @@ end ---@param row integer Position row ---@param col integer Position column --- ----@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` +---@return table[] List of captures `{ capture = "name", metadata = { ... } }` function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 83910316a6..58a29f2fe0 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -639,7 +639,7 @@ end --- -- typically useful info about the node: --- local type = node:type() -- type of the captured node --- local row1, col1, row2, col2 = node:range() -- range of the capture ---- ... use the info here ... +--- -- ... use the info here ... --- end --- --- @@ -693,7 +693,7 @@ end --- --- local node_data = metadata[id] -- Node level metadata --- ---- ... use the info here ... +--- -- ... use the info here ... --- end --- end --- -- cgit From f140175564001cc1ad84128a0147a5d2f7798a63 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Thu, 23 Feb 2023 13:35:46 +0100 Subject: refactor(lsp): remove workaround for missing bit module (#22373) --- runtime/lua/vim/lsp/semantic_tokens.lua | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index b1bc48dac6..00b4757ea9 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -1,6 +1,7 @@ local api = vim.api local handlers = require('vim.lsp.handlers') local util = require('vim.lsp.util') +local bit = require('bit') --- @class STTokenRange --- @field line number line number 0-based @@ -58,18 +59,10 @@ local function modifiers_from_number(x, modifiers_table) local modifiers = {} local idx = 1 while x > 0 do - if _G.bit then - if _G.bit.band(x, 1) == 1 then - modifiers[#modifiers + 1] = modifiers_table[idx] - end - x = _G.bit.rshift(x, 1) - else - --TODO(jdrouhard): remove this branch once `bit` module is available for non-LuaJIT (#21222) - if x % 2 == 1 then - modifiers[#modifiers + 1] = modifiers_table[idx] - end - x = math.floor(x / 2) + if bit.band(x, 1) == 1 then + modifiers[#modifiers + 1] = modifiers_table[idx] end + x = bit.rshift(x, 1) idx = idx + 1 end -- cgit From 75e53341f37eeeda7d9be7f934249f7e5e4397e9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 15:19:52 +0000 Subject: perf(treesitter): smarter languagetree invalidation Problem: Treesitter injections are slow because all injected trees are invalidated on every change. Solution: Implement smarter invalidation to avoid reparsing injected regions. - In on_bytes, try and update self._regions as best we can. This PR just offsets any regions after the change. - Add valid flags for each region in self._regions. - Call on_bytes recursively for all children. - We still need to run the query every time for the top level tree. I don't know how to avoid this. However, if the new injection ranges don't change, then we re-use the old trees and avoid reparsing children. This should result in roughly a 2-3x reduction in tree parsing when the comment injections are enabled. --- runtime/lua/vim/treesitter/_range.lua | 126 ++++++++++++++ runtime/lua/vim/treesitter/languagetree.lua | 249 ++++++++++++++++++---------- runtime/lua/vim/treesitter/query.lua | 2 +- 3 files changed, 290 insertions(+), 87 deletions(-) create mode 100644 runtime/lua/vim/treesitter/_range.lua (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua new file mode 100644 index 0000000000..b87542c20f --- /dev/null +++ b/runtime/lua/vim/treesitter/_range.lua @@ -0,0 +1,126 @@ +local api = vim.api + +local M = {} + +---@alias Range4 {[1]: integer, [2]: integer, [3]: integer, [4]: integer} +---@alias Range6 {[1]: integer, [2]: integer, [3]: integer, [4]: integer, [5]: integer, [6]: integer} + +---@private +---@param a_row integer +---@param a_col integer +---@param b_row integer +---@param b_col integer +---@return integer +--- 1: a > b +--- 0: a == b +--- -1: a < b +local function cmp_pos(a_row, a_col, b_row, b_col) + if a_row == b_row then + if a_col > b_col then + return 1 + elseif a_col < b_col then + return -1 + else + return 0 + end + elseif a_row > b_row then + return 1 + end + + return -1 +end + +M.cmp_pos = { + lt = function(...) + return cmp_pos(...) == -1 + end, + le = function(...) + return cmp_pos(...) ~= 1 + end, + gt = function(...) + return cmp_pos(...) == 1 + end, + ge = function(...) + return cmp_pos(...) ~= -1 + end, + eq = function(...) + return cmp_pos(...) == 0 + end, + ne = function(...) + return cmp_pos(...) ~= 0 + end, +} + +setmetatable(M.cmp_pos, { __call = cmp_pos }) + +---@private +---@param r1 Range4|Range6 +---@param r2 Range4|Range6 +---@return boolean +function M.intercepts(r1, r2) + local off_1 = #r1 == 6 and 1 or 0 + local off_2 = #r1 == 6 and 1 or 0 + + local srow_1, scol_1, erow_1, ecol_1 = r1[1], r2[2], r1[3 + off_1], r1[4 + off_1] + local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2] + + -- r1 is above r2 + if M.cmp_pos.le(erow_1, ecol_1, srow_2, scol_2) then + return false + end + + -- r1 is below r2 + if M.cmp_pos.ge(srow_1, scol_1, erow_2, ecol_2) then + return false + end + + return true +end + +---@private +---@param r1 Range4|Range6 +---@param r2 Range4|Range6 +---@return boolean whether r1 contains r2 +function M.contains(r1, r2) + local off_1 = #r1 == 6 and 1 or 0 + local off_2 = #r1 == 6 and 1 or 0 + + local srow_1, scol_1, erow_1, ecol_1 = r1[1], r2[2], r1[3 + off_1], r1[4 + off_1] + local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2] + + -- start doesn't fit + if M.cmp_pos.gt(srow_1, scol_1, srow_2, scol_2) then + return false + end + + -- end doesn't fit + if M.cmp_pos.lt(erow_1, ecol_1, erow_2, ecol_2) then + return false + end + + return true +end + +---@private +---@param source integer|string +---@param range Range4 +---@return Range6 +function M.add_bytes(source, range) + local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4] + local start_byte = 0 + local end_byte = 0 + -- TODO(vigoux): proper byte computation here, and account for EOL ? + if type(source) == 'number' then + -- Easy case, this is a buffer parser + start_byte = api.nvim_buf_get_offset(source, start_row) + start_col + end_byte = api.nvim_buf_get_offset(source, end_row) + end_col + elseif type(source) == 'string' then + -- string parser, single `\n` delimited string + start_byte = vim.fn.byteidx(source, start_col) + end_byte = vim.fn.byteidx(source, end_col) + end + + return { start_row, start_col, start_byte, end_row, end_col, end_byte } +end + +return M diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index c9fd4bb2ea..2d4e2e595b 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -1,9 +1,8 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') +local Range = require('vim.treesitter._range') ----@alias Range {[1]: integer, [2]: integer, [3]: integer, [4]: integer} --- ---@alias TSCallbackName ---| 'changedtree' ---| 'bytes' @@ -24,11 +23,13 @@ local language = require('vim.treesitter.language') ---@field private _injection_query Query Queries defining injected languages ---@field private _opts table Options ---@field private _parser TSParser Parser for language ----@field private _regions Range[][] List of regions this tree should manage and parse +---@field private _regions Range6[][] List of regions this tree should manage and parse ---@field private _lang string Language name ---@field private _source (integer|string) Buffer or string to parse ---@field private _trees TSTree[] Reference to parsed tree (one for each language) ----@field private _valid boolean If the parsed tree is valid +---@field private _valid boolean|table If the parsed tree is valid +--- TODO(lewis6991): combine _regions, _valid and _trees +---@field private _is_child boolean local LanguageTree = {} ---@class LanguageTreeOpts @@ -114,6 +115,9 @@ end --- If the tree is invalid, call `parse()`. --- This will return the updated tree. function LanguageTree:is_valid() + if type(self._valid) == 'table' then + return #self._valid == #self._regions + end return self._valid end @@ -127,6 +131,16 @@ function LanguageTree:source() return self._source end +---@private +---This is only exposed so it can be wrapped for profiling +---@param old_tree TSTree +---@return TSTree, integer[] +function LanguageTree:_parse_tree(old_tree) + local tree, tree_changes = self._parser:parse(old_tree, self._source) + self:_do_callback('changedtree', tree_changes, tree) + return tree, tree_changes +end + --- Parses all defined regions using a treesitter parser --- for the language this tree represents. --- This will run the injection query for this language to @@ -135,35 +149,27 @@ end ---@return TSTree[] ---@return table|nil Change list function LanguageTree:parse() - if self._valid then + if self:is_valid() then return self._trees end - local parser = self._parser local changes = {} - local old_trees = self._trees - self._trees = {} - -- If there are no ranges, set to an empty list -- so the included ranges in the parser are cleared. - if self._regions and #self._regions > 0 then + if #self._regions > 0 then for i, ranges in ipairs(self._regions) do - local old_tree = old_trees[i] - parser:set_included_ranges(ranges) - - local tree, tree_changes = parser:parse(old_tree, self._source) - self:_do_callback('changedtree', tree_changes, tree) - - table.insert(self._trees, tree) - vim.list_extend(changes, tree_changes) + if not self._valid or not self._valid[i] then + self._parser:set_included_ranges(ranges) + local tree, tree_changes = self:_parse_tree(self._trees[i]) + self._trees[i] = tree + vim.list_extend(changes, tree_changes) + end end else - local tree, tree_changes = parser:parse(old_trees[1], self._source) - self:_do_callback('changedtree', tree_changes, tree) - - table.insert(self._trees, tree) - vim.list_extend(changes, tree_changes) + local tree, tree_changes = self:_parse_tree(self._trees[1]) + self._trees = { tree } + changes = tree_changes end local injections_by_lang = self:_get_injections() @@ -249,6 +255,7 @@ function LanguageTree:add_child(lang) end self._children[lang] = LanguageTree.new(self._source, lang, self._opts) + self._children[lang]._is_child = true self:invalidate() self:_do_callback('child_added', self._children[lang]) @@ -298,43 +305,35 @@ end --- This allows for embedded languages to be parsed together across different --- nodes, which is useful for templating languages like ERB and EJS. --- ---- Note: This call invalidates the tree and requires it to be parsed again. ---- ---@private ----@param regions integer[][][] List of regions this tree should manage and parse. +---@param regions Range4[][] List of regions this tree should manage and parse. function LanguageTree:set_included_regions(regions) -- Transform the tables from 4 element long to 6 element long (with byte offset) for _, region in ipairs(regions) do for i, range in ipairs(region) do if type(range) == 'table' and #range == 4 then - ---@diagnostic disable-next-line:no-unknown - local start_row, start_col, end_row, end_col = unpack(range) - local start_byte = 0 - local end_byte = 0 - local source = self._source - -- TODO(vigoux): proper byte computation here, and account for EOL ? - if type(source) == 'number' then - -- Easy case, this is a buffer parser - start_byte = a.nvim_buf_get_offset(source, start_row) + start_col - end_byte = a.nvim_buf_get_offset(source, end_row) + end_col - elseif type(self._source) == 'string' then - -- string parser, single `\n` delimited string - start_byte = vim.fn.byteidx(self._source, start_col) - end_byte = vim.fn.byteidx(self._source, end_col) - end + region[i] = Range.add_bytes(self._source, range) + end + end + end - region[i] = { start_row, start_col, start_byte, end_row, end_col, end_byte } + if #self._regions ~= #regions then + self._trees = {} + self:invalidate() + elseif self._valid ~= false then + if self._valid == true then + self._valid = {} + end + for i = 1, #regions do + self._valid[i] = true + if not vim.deep_equal(self._regions[i], regions[i]) then + self._valid[i] = nil + self._trees[i] = nil end end end self._regions = regions - -- Trees are no longer valid now that we have changed regions. - -- TODO(vigoux,steelsojka): Look into doing this smarter so we can use some of the - -- old trees for incremental parsing. Currently, this only - -- affects injected languages. - self._trees = {} - self:invalidate() end --- Gets the set of included regions @@ -346,10 +345,10 @@ end ---@param node TSNode ---@param id integer ---@param metadata TSMetadata ----@return Range +---@return Range4 local function get_range_from_metadata(node, id, metadata) if metadata[id] and metadata[id].range then - return metadata[id].range --[[@as Range]] + return metadata[id].range --[[@as Range4]] end return { node:range() } end @@ -378,7 +377,7 @@ function LanguageTree:_get_injections() self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1) do local lang = nil ---@type string - local ranges = {} ---@type Range[] + local ranges = {} ---@type Range4[] local combined = metadata.combined ---@type boolean -- Directives can configure how injections are captured as well as actual node captures. @@ -408,6 +407,7 @@ function LanguageTree:_get_injections() -- Lang should override any other language tag if name == 'language' and not lang then + ---@diagnostic disable-next-line lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'combined' then combined = true @@ -426,6 +426,8 @@ function LanguageTree:_get_injections() end end + assert(type(lang) == 'string') + -- Each tree index should be isolated from the other nodes. if not injections[tree_index] then injections[tree_index] = {} @@ -446,7 +448,7 @@ function LanguageTree:_get_injections() end end - ---@type table + ---@type table local result = {} -- Generate a map by lang of node lists. @@ -485,6 +487,45 @@ function LanguageTree:_do_callback(cb_name, ...) end end +---@private +---@param regions Range6[][] +---@param old_range Range6 +---@param new_range Range6 +---@return table region indices to invalidate +local function update_regions(regions, old_range, new_range) + ---@type table + local valid = {} + + for i, ranges in ipairs(regions or {}) do + valid[i] = true + for j, r in ipairs(ranges) do + if Range.intercepts(r, old_range) then + valid[i] = nil + break + end + + -- Range after change. Adjust + if Range.cmp_pos.gt(r[1], r[2], old_range[4], old_range[5]) then + local byte_offset = new_range[6] - old_range[6] + local row_offset = new_range[4] - old_range[4] + + -- Update the range to avoid invalidation in set_included_regions() + -- which will compare the regions against the parsed injection regions + ranges[j] = { + r[1] + row_offset, + r[2], + r[3] + byte_offset, + r[4] + row_offset, + r[5], + r[6] + byte_offset, + } + end + end + end + + return valid +end + ---@private ---@param bufnr integer ---@param changed_tick integer @@ -510,14 +551,53 @@ function LanguageTree:_on_bytes( new_col, new_byte ) - self:invalidate() - local old_end_col = old_col + ((old_row == 0) and start_col or 0) local new_end_col = new_col + ((new_row == 0) and start_col or 0) - -- Edit all trees recursively, together BEFORE emitting a bytes callback. - -- In most cases this callback should only be called from the root tree. - self:for_each_tree(function(tree) + local old_range = { + start_row, + start_col, + start_byte, + start_row + old_row, + old_end_col, + start_byte + old_byte, + } + + local new_range = { + start_row, + start_col, + start_byte, + start_row + new_row, + new_end_col, + start_byte + new_byte, + } + + local valid_regions = update_regions(self._regions, old_range, new_range) + + if #self._regions == 0 or #valid_regions == 0 then + self._valid = false + else + self._valid = valid_regions + end + + for _, child in pairs(self._children) do + child:_on_bytes( + bufnr, + changed_tick, + start_row, + start_col, + start_byte, + old_row, + old_col, + old_byte, + new_row, + new_col, + new_byte + ) + end + + -- Edit trees together BEFORE emitting a bytes callback. + for _, tree in ipairs(self._trees) do tree:edit( start_byte, start_byte + old_byte, @@ -529,22 +609,24 @@ function LanguageTree:_on_bytes( start_row + new_row, new_end_col ) - end) + end - self:_do_callback( - 'bytes', - bufnr, - changed_tick, - start_row, - start_col, - start_byte, - old_row, - old_col, - old_byte, - new_row, - new_col, - new_byte - ) + if not self._is_child then + self:_do_callback( + 'bytes', + bufnr, + changed_tick, + start_row, + start_col, + start_byte, + old_row, + old_col, + old_byte, + new_row, + new_col, + new_byte + ) + end end ---@private @@ -595,19 +677,15 @@ end ---@private ---@param tree TSTree ----@param range Range +---@param range Range4 ---@return boolean local function tree_contains(tree, range) - local start_row, start_col, end_row, end_col = tree:root():range() - local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) - local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) - - return start_fits and end_fits + return Range.contains({ tree:root():range() }, range) end --- Determines whether {range} is contained in the |LanguageTree|. --- ----@param range Range `{ start_line, start_col, end_line, end_col }` +---@param range Range4 `{ start_line, start_col, end_line, end_col }` ---@return boolean function LanguageTree:contains(range) for _, tree in pairs(self._trees) do @@ -621,7 +699,7 @@ end --- Gets the tree that contains {range}. --- ----@param range Range `{ start_line, start_col, end_line, end_col }` +---@param range Range4 `{ start_line, start_col, end_line, end_col }` ---@param opts table|nil Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) ---@return TSTree|nil @@ -631,10 +709,9 @@ function LanguageTree:tree_for_range(range, opts) if not ignore then for _, child in pairs(self._children) do - for _, tree in pairs(child:trees()) do - if tree_contains(tree, range) then - return tree - end + local tree = child:tree_for_range(range, opts) + if tree then + return tree end end end @@ -650,7 +727,7 @@ end --- Gets the smallest named node that contains {range}. --- ----@param range Range `{ start_line, start_col, end_line, end_col }` +---@param range Range4 `{ start_line, start_col, end_line, end_col }` ---@param opts table|nil Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) ---@return TSNode | nil Found node @@ -663,7 +740,7 @@ end --- Gets the appropriate language that contains {range}. --- ----@param range Range `{ start_line, start_col, end_line, end_col }` +---@param range Range4 `{ start_line, start_col, end_line, end_col }` ---@return LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 58a29f2fe0..13d98a0625 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -406,7 +406,7 @@ predicate_handlers['vim-match?'] = predicate_handlers['match?'] ---@class TSMetadata ---@field [integer] TSMetadata ---@field [string] integer|string ----@field range Range +---@field range Range4 ---@alias TSDirective fun(match: TSMatch, _, _, predicate: any[], metadata: TSMetadata) -- cgit From 8c339aa04b2a1ca99a297b2eada8ebc6218f5f1c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 23 Feb 2023 17:52:33 +0100 Subject: vim-patch:9.0.1346: Starlark files are not recognized (#22380) Problem: Starlark files are not recognized. Solution: Add patterns for Starlark files. (Amaan Qureshi, closes vim/vim#12049) https://github.com/vim/vim/commit/ca06b30073de22dc120b532e90fbee2a10ef9772 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 0dd2dcfcbe..ae3ad6f628 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -995,6 +995,9 @@ local extension = { ssa = 'ssa', ass = 'ssa', st = 'st', + ipd = 'starlark', + star = 'starlark', + starlark = 'starlark', imata = 'stata', ['do'] = 'stata', mata = 'stata', -- cgit From 1df3f5ec6aca24cbe7b78ead5c37ad06a65c84e8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 17:05:20 +0000 Subject: feat(treesitter): upstream foldexpr from nvim-treesitter --- runtime/doc/news.txt | 3 + runtime/doc/treesitter.txt | 13 +++ runtime/lua/vim/treesitter.lua | 20 ++++ runtime/lua/vim/treesitter/_fold.lua | 173 +++++++++++++++++++++++++++++++++++ runtime/queries/c/folds.scm | 19 ++++ runtime/queries/lua/folds.scm | 10 ++ runtime/queries/vim/folds.scm | 4 + 7 files changed, 242 insertions(+) create mode 100644 runtime/lua/vim/treesitter/_fold.lua create mode 100644 runtime/queries/c/folds.scm create mode 100644 runtime/queries/lua/folds.scm create mode 100644 runtime/queries/vim/folds.scm (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 4dee958108..23bb6d4343 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -168,6 +168,9 @@ The following new APIs or features were added. `vim.treesitter.language.require_language`. • `require'bit'` is now always available |lua-bit| + +• |vim.treesitter.foldexpr()| can be used for 'foldexpr' to use treesitter for folding. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 3f505e5d19..ccb3c445df 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -481,6 +481,19 @@ library. ============================================================================== Lua module: vim.treesitter *lua-treesitter-core* +foldexpr({lnum}) *vim.treesitter.foldexpr()* + Returns the fold level for {lnum} in the current buffer. Can be set + directly to 'foldexpr': >lua + + vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' +< + + Parameters: ~ + • {lnum} (integer|nil) Line number to calculate fold level for + + Return: ~ + (string) + *vim.treesitter.get_captures_at_cursor()* get_captures_at_cursor({winnr}) Returns a list of highlight capture names under the cursor diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 44922bbc4d..fead7b7b1b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -115,6 +115,16 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end +---@private +---@param bufnr (integer|nil) Buffer number +---@return boolean +function M._has_parser(bufnr) + if bufnr == nil or bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + return parsers[bufnr] ~= nil +end + --- Returns a string parser --- ---@param str string Text to parse @@ -612,4 +622,14 @@ function M.show_tree(opts) }) end +--- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': +---
lua
+--- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
+--- 
+---@param lnum integer|nil Line number to calculate fold level for +---@return string +function M.foldexpr(lnum) + return require('vim.treesitter._fold').foldexpr(lnum) +end + return M diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua new file mode 100644 index 0000000000..a66cc6d543 --- /dev/null +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -0,0 +1,173 @@ +local api = vim.api + +local M = {} + +--- Memoizes a function based on the buffer tick of the provided bufnr. +--- The cache entry is cleared when the buffer is detached to avoid memory leaks. +---@generic F: function +---@param fn F fn to memoize, taking the bufnr as first argument +---@return F +local function memoize_by_changedtick(fn) + ---@type table + local cache = {} + + ---@param bufnr integer + return function(bufnr, ...) + local tick = api.nvim_buf_get_changedtick(bufnr) + + if cache[bufnr] then + if cache[bufnr].last_tick == tick then + return cache[bufnr].result + end + else + local function detach_handler() + cache[bufnr] = nil + end + + -- Clean up logic only! + api.nvim_buf_attach(bufnr, false, { + on_detach = detach_handler, + on_reload = detach_handler, + }) + end + + cache[bufnr] = { + result = fn(bufnr, ...), + last_tick = tick, + } + + return cache[bufnr].result + end +end + +---@param bufnr integer +---@param capture string +---@param query_name string +---@param callback fun(id: integer, node:TSNode, metadata: TSMetadata) +local function iter_matches_with_capture(bufnr, capture, query_name, callback) + local parser = vim.treesitter.get_parser(bufnr) + + if not parser then + return + end + + parser:for_each_tree(function(tree, lang_tree) + local lang = lang_tree:lang() + local query = vim.treesitter.query.get_query(lang, query_name) + if query then + local root = tree:root() + local start, _, stop = root:range() + for _, match, metadata in query:iter_matches(root, bufnr, start, stop) do + for id, node in pairs(match) do + if query.captures[id] == capture then + callback(id, node, metadata) + end + end + end + end + end) +end + +---@private +--- TODO(lewis6991): copied from languagetree.lua. Consolidate +---@param node TSNode +---@param id integer +---@param metadata TSMetadata +---@return Range +local function get_range_from_metadata(node, id, metadata) + if metadata[id] and metadata[id].range then + return metadata[id].range --[[@as Range]] + end + return { node:range() } +end + +-- This is cached on buf tick to avoid computing that multiple times +-- Especially not for every line in the file when `zx` is hit +---@param bufnr integer +---@return table +local folds_levels = memoize_by_changedtick(function(bufnr) + local max_fold_level = vim.wo.foldnestmax + local function trim_level(level) + if level > max_fold_level then + return max_fold_level + end + return level + end + + -- start..stop is an inclusive range + local start_counts = {} ---@type table + local stop_counts = {} ---@type table + + local prev_start = -1 + local prev_stop = -1 + + local min_fold_lines = vim.wo.foldminlines + + iter_matches_with_capture(bufnr, 'fold', 'folds', function(id, node, metadata) + local range = get_range_from_metadata(node, id, metadata) + local start, stop, stop_col = range[1], range[3], range[4] + + if stop_col == 0 then + stop = stop - 1 + end + + local fold_length = stop - start + 1 + + -- Fold only multiline nodes that are not exactly the same as previously met folds + -- Checking against just the previously found fold is sufficient if nodes + -- are returned in preorder or postorder when traversing tree + if fold_length > min_fold_lines and not (start == prev_start and stop == prev_stop) then + start_counts[start] = (start_counts[start] or 0) + 1 + stop_counts[stop] = (stop_counts[stop] or 0) + 1 + prev_start = start + prev_stop = stop + end + end) + + ---@type table + local levels = {} + local current_level = 0 + + -- We now have the list of fold opening and closing, fill the gaps and mark where fold start + for lnum = 0, api.nvim_buf_line_count(bufnr) do + local last_trimmed_level = trim_level(current_level) + current_level = current_level + (start_counts[lnum] or 0) + local trimmed_level = trim_level(current_level) + current_level = current_level - (stop_counts[lnum] or 0) + + -- Determine if it's the start/end of a fold + -- NB: vim's fold-expr interface does not have a mechanism to indicate that + -- two (or more) folds start at this line, so it cannot distinguish between + -- ( \n ( \n )) \n (( \n ) \n ) + -- versus + -- ( \n ( \n ) \n ( \n ) \n ) + -- If it did have such a mechanism, (trimmed_level - last_trimmed_level) + -- would be the correct number of starts to pass on. + local prefix = '' + if trimmed_level - last_trimmed_level > 0 then + prefix = '>' + end + + levels[lnum + 1] = prefix .. tostring(trimmed_level) + end + + return levels +end) + +---@param lnum integer|nil +---@return string +function M.foldexpr(lnum) + lnum = lnum or vim.v.lnum + local bufnr = api.nvim_get_current_buf() + + ---@diagnostic disable-next-line:invisible + if not vim.treesitter._has_parser(bufnr) or not lnum then + return '0' + end + + local levels = folds_levels(bufnr) or {} + + return levels[lnum] or '0' +end + +return M diff --git a/runtime/queries/c/folds.scm b/runtime/queries/c/folds.scm new file mode 100644 index 0000000000..80c3039b6b --- /dev/null +++ b/runtime/queries/c/folds.scm @@ -0,0 +1,19 @@ +[ + (for_statement) + (if_statement) + (while_statement) + (switch_statement) + (case_statement) + (function_definition) + (struct_specifier) + (enum_specifier) + (comment) + (preproc_if) + (preproc_elif) + (preproc_else) + (preproc_ifdef) + (initializer_list) +] @fold + + (compound_statement + (compound_statement) @fold) diff --git a/runtime/queries/lua/folds.scm b/runtime/queries/lua/folds.scm new file mode 100644 index 0000000000..d8f0b42df3 --- /dev/null +++ b/runtime/queries/lua/folds.scm @@ -0,0 +1,10 @@ +[ + (do_statement) + (while_statement) + (repeat_statement) + (if_statement) + (for_statement) + (function_declaration) + (function_definition) + (table_constructor) +] @fold diff --git a/runtime/queries/vim/folds.scm b/runtime/queries/vim/folds.scm new file mode 100644 index 0000000000..4c99735836 --- /dev/null +++ b/runtime/queries/vim/folds.scm @@ -0,0 +1,4 @@ +[ + (if_statement) + (function_definition) +] @fold -- cgit From 3f35ebb14dd8b1ceeef45c4f42949f14e3b54b88 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 18:09:44 +0000 Subject: fix(treesitter): fixup language invalidation (#22381) --- runtime/lua/vim/treesitter/languagetree.lua | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 2d4e2e595b..122496cff3 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -27,7 +27,7 @@ local Range = require('vim.treesitter._range') ---@field private _lang string Language name ---@field private _source (integer|string) Buffer or string to parse ---@field private _trees TSTree[] Reference to parsed tree (one for each language) ----@field private _valid boolean|table If the parsed tree is valid +---@field private _valid boolean|table If the parsed tree is valid --- TODO(lewis6991): combine _regions, _valid and _trees ---@field private _is_child boolean local LanguageTree = {} @@ -115,10 +115,18 @@ end --- If the tree is invalid, call `parse()`. --- This will return the updated tree. function LanguageTree:is_valid() - if type(self._valid) == 'table' then - return #self._valid == #self._regions + local valid = self._valid + + if type(valid) == 'table' then + for _, v in ipairs(valid) do + if not v then + return false + end + end + return true end - return self._valid + + return valid end --- Returns a map of language to child tree. @@ -323,11 +331,17 @@ function LanguageTree:set_included_regions(regions) elseif self._valid ~= false then if self._valid == true then self._valid = {} + for i = 1, #regions do + self._valid[i] = true + end end + for i = 1, #regions do - self._valid[i] = true if not vim.deep_equal(self._regions[i], regions[i]) then - self._valid[i] = nil + self._valid[i] = false + end + + if not self._valid[i] then self._trees[i] = nil end end @@ -491,16 +505,16 @@ end ---@param regions Range6[][] ---@param old_range Range6 ---@param new_range Range6 ----@return table region indices to invalidate +---@return table region indices to invalidate local function update_regions(regions, old_range, new_range) - ---@type table + ---@type table local valid = {} for i, ranges in ipairs(regions or {}) do valid[i] = true for j, r in ipairs(ranges) do if Range.intercepts(r, old_range) then - valid[i] = nil + valid[i] = false break end @@ -572,12 +586,10 @@ function LanguageTree:_on_bytes( start_byte + new_byte, } - local valid_regions = update_regions(self._regions, old_range, new_range) - - if #self._regions == 0 or #valid_regions == 0 then + if #self._regions == 0 then self._valid = false else - self._valid = valid_regions + self._valid = update_regions(self._regions, old_range, new_range) end for _, child in pairs(self._children) do -- cgit From 5e1308b7caa89b458cc97d2db956379aa54ed68a Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Thu, 23 Feb 2023 16:12:01 -0500 Subject: vim-patch:9.0.1348: Un-grammar files are not recognized (#22383) Problem: Un-grammar files are not recognized. Solution: Add patterns for Un-grammar files. (Amaan Qureshi, closes vim/vim#12034) https://github.com/vim/vim/commit/44e08c1cf83f5a50f8b21613551304a6651c1161 --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index ae3ad6f628..3a68b61914 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1056,6 +1056,7 @@ local extension = { uc = 'uc', uit = 'uil', uil = 'uil', + ungram = 'ungrammar', sba = 'vb', vb = 'vb', dsm = 'vb', -- cgit From 904d0995837a2569ae640f5253da3dd4569fec6f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:03:28 +0800 Subject: vim-patch:8.2.2449: Vim9: flatten() always changes the list type Problem: Vim9: flatten() always changes the list type. Solution: Disallow using flatten() and add flattennew(). https://github.com/vim/vim/commit/3b690069730805a147d45d92eaca4dc838272d1d Co-authored-by: Bram Moolenaar --- runtime/doc/builtin.txt | 8 +++++++- runtime/doc/usr_41.txt | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index af5ba9ab8f..5f279ed09c 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -148,6 +148,8 @@ finddir({name} [, {path} [, {count}]]) findfile({name} [, {path} [, {count}]]) String find file {name} in {path} flatten({list} [, {maxdepth}]) List flatten {list} up to {maxdepth} levels +flattennew({list} [, {maxdepth}]) + List flatten a copy of {list} float2nr({expr}) Number convert Float {expr} to a Number floor({expr}) Float round {expr} down fmod({expr1}, {expr2}) Float remainder of {expr1} / {expr2} @@ -2277,7 +2279,7 @@ flatten({list} [, {maxdepth}]) *flatten()* Flatten {list} up to {maxdepth} levels. Without {maxdepth} the result is a |List| without nesting, as if {maxdepth} is a very large number. - The {list} is changed in place, make a copy first if you do + The {list} is changed in place, use |flattennew()| if you do not want that. *E900* {maxdepth} means how deep in nested lists changes are made. @@ -2295,6 +2297,10 @@ flatten({list} [, {maxdepth}]) *flatten()* Can also be used as a |method|: > mylist->flatten() < +flattennew({list} [, {maxdepth}]) *flattennew()* + Like |flatten()| but first make a copy of {list}. + + float2nr({expr}) *float2nr()* Convert {expr} to a Number by omitting the part after the decimal point. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 910aebae70..27c5927cf9 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -670,6 +670,7 @@ List manipulation: *list-functions* count() count number of times a value appears in a List repeat() repeat a List multiple times flatten() flatten a List + flattennew() flatten a copy of a List Dictionary manipulation: *dict-functions* get() get an entry without an error for a wrong key -- cgit From c57af5d41cd039194dbd9c6fb5b68b377d2a5b59 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 24 Feb 2023 09:50:59 +0000 Subject: feat(treesitter)!: remove silent option from language.add() Simply use `pcall` if you want to silence an error. --- runtime/doc/treesitter.txt | 5 ----- runtime/lua/vim/treesitter/language.lua | 32 ++++++++++------------------- runtime/lua/vim/treesitter/languagetree.lua | 2 +- 3 files changed, 12 insertions(+), 27 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index ccb3c445df..76cde91920 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -686,11 +686,6 @@ add({lang}, {opts}) *vim.treesitter.language.add()* • path (string|nil) Optional path the parser is located at • symbol_name (string|nil) Internal symbol name for the language to load - • silent (boolean|nil) Don't throw an error if language not - found - - Return: ~ - (boolean) If the specified language is installed get_lang({filetype}) *vim.treesitter.language.get_lang()* Parameters: ~ diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 8637d7d544..0796383bf5 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -13,11 +13,19 @@ end ---@deprecated function M.require_language(lang, path, silent, symbol_name) - return M.add(lang, { + local opts = { silent = silent, path = path, symbol_name = symbol_name, - }) + } + + if silent then + local installed = pcall(M.add, lang, opts) + return installed + end + + M.add(lang, opts) + return true end ---@class treesitter.RequireLangOpts @@ -38,20 +46,16 @@ end --- Defaults to lang. --- - path (string|nil) Optional path the parser is located at --- - symbol_name (string|nil) Internal symbol name for the language to load ---- - silent (boolean|nil) Don't throw an error if language not found ----@return boolean If the specified language is installed function M.add(lang, opts) ---@cast opts treesitter.RequireLangOpts opts = opts or {} local path = opts.path - local silent = opts.silent local filetype = opts.filetype or lang local symbol_name = opts.symbol_name vim.validate({ lang = { lang, 'string' }, path = { path, 'string', true }, - silent = { silent, 'boolean', true }, symbol_name = { symbol_name, 'string', true }, filetype = { filetype, { 'string', 'table' }, true }, }) @@ -64,32 +68,18 @@ function M.add(lang, opts) if path == nil then if not (lang and lang:match('[%w_]+') == lang) then - if silent then - return false - end error("'" .. lang .. "' is not a valid language name") end local fname = 'parser/' .. lang .. '.*' local paths = a.nvim_get_runtime_file(fname, false) if #paths == 0 then - if silent then - return false - end error("no parser for '" .. lang .. "' language, see :help treesitter-parsers") end path = paths[1] end - if silent then - if not pcall(vim._ts_add_language, path, lang, symbol_name) then - return false - end - else - vim._ts_add_language(path, lang, symbol_name) - end - - return true + vim._ts_add_language(path, lang, symbol_name) end --- Register a lang to be used for a filetype (or list of filetypes). diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 122496cff3..7ec7bbfa12 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -184,7 +184,7 @@ function LanguageTree:parse() local seen_langs = {} ---@type table for lang, injection_ranges in pairs(injections_by_lang) do - local has_lang = language.add(lang, { silent = true }) + local has_lang = pcall(language.add, lang) -- Child language trees should just be ignored if not found, since -- they can depend on the text of a node. Intermediate strings -- cgit From 1803dadb209b9193ad8673b243091a4602b3a855 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 24 Feb 2023 19:55:50 +0800 Subject: refactor(lsp): remove deprecated code (#22389) --- runtime/lua/vim/lsp.lua | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 0a620e1367..206c7c9b7e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1294,26 +1294,6 @@ function lsp.start_client(config) client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities") client.server_capabilities = protocol.resolve_capabilities(client.server_capabilities) - - -- Deprecation wrapper: this will be removed in 0.8 - local mt = {} - mt.__index = function(table, key) - if key == 'resolved_capabilities' then - vim.notify_once( - '[LSP] Accessing client.resolved_capabilities is deprecated, ' - .. 'update your plugins or configuration to access client.server_capabilities instead.' - .. 'The new key/value pairs in server_capabilities directly match those ' - .. 'defined in the language server protocol', - vim.log.levels.WARN - ) - rawset(table, key, protocol._resolve_capabilities_compat(client.server_capabilities)) - return rawget(table, key) - else - return rawget(table, key) - end - end - setmetatable(client, mt) - client.supports_method = function(method) local required_capability = lsp._request_name_to_capability[method] -- if we don't know about the method, assume that the client supports it. -- cgit From 4297127f14fa1b9062db7de0d63981887ebed063 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 24 Feb 2023 15:34:52 +0100 Subject: vim-patch:9.0.1350: CPON files are not recognized (#22392) Problem: CPON files are not recognized. Solution: Add patterns for CPON files. (Amaan Qureshi, closes vim/vim#12053) https://github.com/vim/vim/commit/c2254764bcada43eea894eb5852a26d5ac5ca8b0 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 3a68b61914..5475f09444 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -242,6 +242,7 @@ local extension = { csh = function(path, bufnr) return require('vim.filetype.detect').csh(path, bufnr) end, + cpon = 'cpon', moc = 'cpp', hh = 'cpp', tlh = 'cpp', -- cgit From 15cce77b383d0b0bfdaa1415cdde005cc43267d0 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 24 Feb 2023 17:50:37 +0100 Subject: vim-patch:9.0.1351: Dhall files are not recognized (#22393) Problem: Dhall files are not recognized. Solution: Add patterns for Dhall files. (Amaan Qureshi, closes vim/vim#12052) https://github.com/vim/vim/commit/def5521752abefe12db8cc3111a3b205ad1ac929 Co-authored-by: Amaan Qureshi --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 5475f09444..a4e078fd04 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -296,6 +296,7 @@ local extension = { desc = 'desc', directory = 'desktop', desktop = 'desktop', + dhall = 'dhall', diff = 'diff', rej = 'diff', Dockerfile = 'dockerfile', -- cgit From 5732aa706c639b3d775573d91d1139f24624629c Mon Sep 17 00:00:00 2001 From: Jon Huhn Date: Sat, 25 Feb 2023 03:07:18 -0600 Subject: feat(lsp): implement workspace/didChangeWatchedFiles (#21293) --- runtime/doc/news.txt | 3 + runtime/lua/vim/_editor.lua | 1 + runtime/lua/vim/_watch.lua | 174 +++++++++++++++++++++++ runtime/lua/vim/lsp/_watchfiles.lua | 274 ++++++++++++++++++++++++++++++++++++ runtime/lua/vim/lsp/handlers.lua | 38 +++-- runtime/lua/vim/lsp/protocol.lua | 9 ++ 6 files changed, 490 insertions(+), 9 deletions(-) create mode 100644 runtime/lua/vim/_watch.lua create mode 100644 runtime/lua/vim/lsp/_watchfiles.lua (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 23bb6d4343..53c2b44c5f 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -171,6 +171,9 @@ The following new APIs or features were added. • |vim.treesitter.foldexpr()| can be used for 'foldexpr' to use treesitter for folding. +• Added support for the `workspace/didChangeWatchedFiles` capability to the + LSP client to notify servers of file changes on disk. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 3f27e61810..92444ff550 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -37,6 +37,7 @@ for k, v in pairs({ health = true, fs = true, secure = true, + _watch = true, }) do vim._submodules[k] = v end diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua new file mode 100644 index 0000000000..dba1522ec8 --- /dev/null +++ b/runtime/lua/vim/_watch.lua @@ -0,0 +1,174 @@ +local M = {} + +--- Enumeration describing the types of events watchers will emit. +M.FileChangeType = vim.tbl_add_reverse_lookup({ + Created = 1, + Changed = 2, + Deleted = 3, +}) + +---@private +--- Joins filepath elements by static '/' separator +--- +---@param ... (string) The path elements. +local function filepath_join(...) + return table.concat({ ... }, '/') +end + +---@private +--- Stops and closes a libuv |uv_fs_event_t| or |uv_fs_poll_t| handle +--- +---@param handle (uv_fs_event_t|uv_fs_poll_t) The handle to stop +local function stop(handle) + local _, stop_err = handle:stop() + assert(not stop_err, stop_err) + local is_closing, close_err = handle:is_closing() + assert(not close_err, close_err) + if not is_closing then + handle:close() + end +end + +--- Initializes and starts a |uv_fs_event_t| +--- +---@param path (string) The path to watch +---@param opts (table|nil) Additional options +--- - uvflags (table|nil) +--- Same flags as accepted by |uv.fs_event_start()| +---@param callback (function) The function called when new events +---@returns (function) A function to stop the watch +function M.watch(path, opts, callback) + vim.validate({ + path = { path, 'string', false }, + opts = { opts, 'table', true }, + callback = { callback, 'function', false }, + }) + + path = vim.fs.normalize(path) + local uvflags = opts and opts.uvflags or {} + local handle, new_err = vim.loop.new_fs_event() + assert(not new_err, new_err) + local _, start_err = handle:start(path, uvflags, function(err, filename, events) + assert(not err, err) + local fullpath = path + if filename then + filename = filename:gsub('\\', '/') + fullpath = filepath_join(fullpath, filename) + end + local change_type = events.change and M.FileChangeType.Changed or 0 + if events.rename then + local _, staterr, staterrname = vim.loop.fs_stat(fullpath) + if staterrname == 'ENOENT' then + change_type = M.FileChangeType.Deleted + else + assert(not staterr, staterr) + change_type = M.FileChangeType.Created + end + end + callback(fullpath, change_type) + end) + assert(not start_err, start_err) + return function() + stop(handle) + end +end + +local default_poll_interval_ms = 2000 + +---@private +--- Implementation for poll, hiding internally-used parameters. +--- +---@param watches (table|nil) A tree structure to maintain state for recursive watches. +--- - handle (uv_fs_poll_t) +--- The libuv handle +--- - cancel (function) +--- A function that cancels the handle and all children's handles +--- - is_dir (boolean) +--- Indicates whether the path is a directory (and the poll should +--- be invoked recursively) +--- - children (table|nil) +--- A mapping of directory entry name to its recursive watches +local function poll_internal(path, opts, callback, watches) + path = vim.fs.normalize(path) + local interval = opts and opts.interval or default_poll_interval_ms + watches = watches or { + is_dir = true, + } + + if not watches.handle then + local poll, new_err = vim.loop.new_fs_poll() + assert(not new_err, new_err) + watches.handle = poll + local _, start_err = poll:start( + path, + interval, + vim.schedule_wrap(function(err) + if err == 'ENOENT' then + return + end + assert(not err, err) + poll_internal(path, opts, callback, watches) + callback(path, M.FileChangeType.Changed) + end) + ) + assert(not start_err, start_err) + callback(path, M.FileChangeType.Created) + end + + watches.cancel = function() + if watches.children then + for _, w in pairs(watches.children) do + w.cancel() + end + end + stop(watches.handle) + end + + if watches.is_dir then + watches.children = watches.children or {} + local exists = {} + for name, ftype in vim.fs.dir(path) do + exists[name] = true + if not watches.children[name] then + watches.children[name] = { + is_dir = ftype == 'directory', + } + poll_internal(filepath_join(path, name), opts, callback, watches.children[name]) + end + end + + local newchildren = {} + for name, watch in pairs(watches.children) do + if exists[name] then + newchildren[name] = watch + else + watch.cancel() + watches.children[name] = nil + callback(path .. '/' .. name, M.FileChangeType.Deleted) + end + end + watches.children = newchildren + end + + return watches.cancel +end + +--- Initializes and starts a |uv_fs_poll_t| recursively watching every file underneath the +--- directory at path. +--- +---@param path (string) The path to watch. Must refer to a directory. +---@param opts (table|nil) Additional options +--- - interval (number|nil) +--- Polling interval in ms as passed to |uv.fs_poll_start()|. Defaults to 2000. +---@param callback (function) The function called when new events +---@returns (function) A function to stop the watch. +function M.poll(path, opts, callback) + vim.validate({ + path = { path, 'string', false }, + opts = { opts, 'table', true }, + callback = { callback, 'function', false }, + }) + return poll_internal(path, opts, callback, nil) +end + +return M diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua new file mode 100644 index 0000000000..b9268b963c --- /dev/null +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -0,0 +1,274 @@ +local bit = require('bit') +local watch = require('vim._watch') +local protocol = require('vim.lsp.protocol') + +local M = {} + +---@private +---Parses the raw pattern into a number of Lua-native patterns. +--- +---@param pattern string The raw glob pattern +---@return table A list of Lua patterns. A match with any of them matches the input glob pattern. +local function parse(pattern) + local patterns = { '' } + + local path_sep = '[/\\]' + local non_path_sep = '[^/\\]' + + local function append(chunks) + local new_patterns = {} + for _, p in ipairs(patterns) do + for _, chunk in ipairs(chunks) do + table.insert(new_patterns, p .. chunk) + end + end + patterns = new_patterns + end + + local function split(s, sep) + local segments = {} + local segment = '' + local in_braces = false + local in_brackets = false + for i = 1, #s do + local c = string.sub(s, i, i) + if c == sep and not in_braces and not in_brackets then + table.insert(segments, segment) + segment = '' + else + if c == '{' then + in_braces = true + elseif c == '}' then + in_braces = false + elseif c == '[' then + in_brackets = true + elseif c == ']' then + in_brackets = false + end + segment = segment .. c + end + end + if segment ~= '' then + table.insert(segments, segment) + end + return segments + end + + local function escape(c) + if + c == '?' + or c == '.' + or c == '(' + or c == ')' + or c == '%' + or c == '[' + or c == ']' + or c == '*' + or c == '+' + or c == '-' + then + return '%' .. c + end + return c + end + + local segments = split(pattern, '/') + for i, segment in ipairs(segments) do + local last_seg = i == #segments + if segment == '**' then + local chunks = { + path_sep .. '-', + '.-' .. path_sep, + } + if last_seg then + chunks = { '.-' } + end + append(chunks) + else + local in_braces = false + local brace_val = '' + local in_brackets = false + local bracket_val = '' + for j = 1, #segment do + local char = string.sub(segment, j, j) + if char ~= '}' and in_braces then + brace_val = brace_val .. char + else + if in_brackets and (char ~= ']' or bracket_val == '') then + local res + if char == '-' then + res = char + elseif bracket_val == '' and char == '!' then + res = '^' + elseif char == '/' then + res = '' + else + res = escape(char) + end + bracket_val = bracket_val .. res + else + if char == '{' then + in_braces = true + elseif char == '[' then + in_brackets = true + elseif char == '}' then + local choices = split(brace_val, ',') + local parsed_choices = {} + for _, choice in ipairs(choices) do + table.insert(parsed_choices, parse(choice)) + end + append(vim.tbl_flatten(parsed_choices)) + in_braces = false + brace_val = '' + elseif char == ']' then + append({ '[' .. bracket_val .. ']' }) + in_brackets = false + bracket_val = '' + elseif char == '?' then + append({ non_path_sep }) + elseif char == '*' then + append({ non_path_sep .. '-' }) + else + append({ escape(char) }) + end + end + end + end + + if not last_seg and (segments[i + 1] ~= '**' or i + 1 < #segments) then + append({ path_sep }) + end + end + end + + return patterns +end + +---@private +--- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern +--- Modeled after VSCode's implementation: https://github.com/microsoft/vscode/blob/0319eed971719ad48e9093daba9d65a5013ec5ab/src/vs/base/common/glob.ts#L509 +--- +---@param pattern string|table The glob pattern (raw or parsed) to match. +---@param s string The string to match against pattern. +---@return boolean Whether or not pattern matches s. +function M._match(pattern, s) + if type(pattern) == 'string' then + pattern = parse(pattern) + end + -- Since Lua's built-in string pattern matching does not have an alternate + -- operator like '|', `parse` will construct one pattern for each possible + -- alternative. Any pattern that matches thus matches the glob. + for _, p in ipairs(pattern) do + if s:match('^' .. p .. '$') then + return true + end + end + return false +end + +M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll + +---@type table> client id -> registration id -> cancel function +local cancels = vim.defaulttable() + +local queue_timeout_ms = 100 +---@type table client id -> libuv timer which will send queued changes at its timeout +local queue_timers = {} +---@type table client id -> set of queued changes to send in a single LSP notification +local change_queues = {} +---@type table> client id -> URI -> last type of change processed +--- Used to prune consecutive events of the same type for the same file +local change_cache = vim.defaulttable() + +local to_lsp_change_type = { + [watch.FileChangeType.Created] = protocol.FileChangeType.Created, + [watch.FileChangeType.Changed] = protocol.FileChangeType.Changed, + [watch.FileChangeType.Deleted] = protocol.FileChangeType.Deleted, +} + +--- Registers the workspace/didChangeWatchedFiles capability dynamically. +--- +---@param reg table LSP Registration object. +---@param ctx table Context from the |lsp-handler|. +function M.register(reg, ctx) + local client_id = ctx.client_id + local client = vim.lsp.get_client_by_id(client_id) + for _, w in ipairs(reg.registerOptions.watchers) do + local glob_patterns = {} + if type(w.globPattern) == 'string' then + for _, folder in ipairs(client.workspace_folders) do + table.insert(glob_patterns, { baseUri = folder.uri, pattern = w.globPattern }) + end + else + table.insert(glob_patterns, w.globPattern) + end + for _, glob_pattern in ipairs(glob_patterns) do + local pattern = parse(glob_pattern.pattern) + local base_dir = nil + if type(glob_pattern.baseUri) == 'string' then + base_dir = glob_pattern.baseUri + elseif type(glob_pattern.baseUri) == 'table' then + base_dir = glob_pattern.baseUri.uri + end + assert(base_dir, "couldn't identify root of watch") + base_dir = vim.uri_to_fname(base_dir) + local kind = w.kind + or protocol.WatchKind.Create + protocol.WatchKind.Change + protocol.WatchKind.Delete + + table.insert( + cancels[client_id][reg.id], + M._watchfunc(base_dir, { uvflags = { recursive = true } }, function(fullpath, change_type) + change_type = to_lsp_change_type[change_type] + -- e.g. match kind with Delete bit (0b0100) to Delete change_type (3) + local kind_mask = bit.lshift(1, change_type - 1) + local change_type_match = bit.band(kind, kind_mask) == kind_mask + if not M._match(pattern, fullpath) or not change_type_match then + return + end + + local change = { + uri = vim.uri_from_fname(fullpath), + type = change_type, + } + + local last_type = change_cache[client_id][change.uri] + if last_type ~= change.type then + change_queues[client_id] = change_queues[client_id] or {} + table.insert(change_queues[client_id], change) + change_cache[client_id][change.uri] = change.type + end + + if not queue_timers[client_id] then + queue_timers[client_id] = vim.defer_fn(function() + client.notify('workspace/didChangeWatchedFiles', { + changes = change_queues[client_id], + }) + queue_timers[client_id] = nil + change_queues[client_id] = nil + change_cache[client_id] = nil + end, queue_timeout_ms) + end + end) + ) + end + end +end + +--- Unregisters the workspace/didChangeWatchedFiles capability dynamically. +--- +---@param unreg table LSP Unregistration object. +---@param ctx table Context from the |lsp-handler|. +function M.unregister(unreg, ctx) + local client_id = ctx.client_id + local client_cancels = cancels[client_id] + local reg_cancels = client_cancels[unreg.id] + while #reg_cancels > 0 do + table.remove(reg_cancels)() + end + client_cancels[unreg.id] = nil + if not next(cancels[client_id]) then + cancels[client_id] = nil + end +end + +return M diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 5096100a60..ee5b63d260 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -117,15 +117,35 @@ M['window/showMessageRequest'] = function(_, result) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability -M['client/registerCapability'] = function(_, _, ctx) - local client_id = ctx.client_id - local warning_tpl = 'The language server %s triggers a registerCapability ' - .. 'handler despite dynamicRegistration set to false. ' - .. 'Report upstream, this warning is harmless' - local client = vim.lsp.get_client_by_id(client_id) - local client_name = client and client.name or string.format('id=%d', client_id) - local warning = string.format(warning_tpl, client_name) - log.warn(warning) +M['client/registerCapability'] = function(_, result, ctx) + local log_unsupported = false + for _, reg in ipairs(result.registrations) do + if reg.method == 'workspace/didChangeWatchedFiles' then + require('vim.lsp._watchfiles').register(reg, ctx) + else + log_unsupported = true + end + end + if log_unsupported then + local client_id = ctx.client_id + local warning_tpl = 'The language server %s triggers a registerCapability ' + .. 'handler despite dynamicRegistration set to false. ' + .. 'Report upstream, this warning is harmless' + local client = vim.lsp.get_client_by_id(client_id) + local client_name = client and client.name or string.format('id=%d', client_id) + local warning = string.format(warning_tpl, client_name) + log.warn(warning) + end + return vim.NIL +end + +--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability +M['client/unregisterCapability'] = function(_, result, ctx) + for _, unreg in ipairs(result.unregisterations) do + if unreg.method == 'workspace/didChangeWatchedFiles' then + require('vim.lsp._watchfiles').unregister(unreg, ctx) + end + end return vim.NIL end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 12345b6c8c..df1ab26667 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -28,6 +28,10 @@ end ---@class lsp.MessageActionItem ---@field title string +---@class lsp.FileEvent +---@field uri string +---@field type lsp.FileChangeType + local constants = { DiagnosticSeverity = { -- Reports an error. @@ -60,6 +64,7 @@ local constants = { }, -- The file event type. + ---@enum lsp.FileChangeType FileChangeType = { -- The file got created. Created = 1, @@ -841,6 +846,10 @@ function protocol.make_client_capabilities() semanticTokens = { refreshSupport = true, }, + didChangeWatchedFiles = { + dynamicRegistration = true, + relativePatternSupport = true, + }, }, experimental = nil, window = { -- cgit From f0f27e9aef7c237dd55fbb5c2cd47c2f42d01742 Mon Sep 17 00:00:00 2001 From: Mathias Fussenegger Date: Sat, 25 Feb 2023 11:17:28 +0100 Subject: Revert "feat(lsp): implement workspace/didChangeWatchedFiles (#21293)" This reverts commit 5732aa706c639b3d775573d91d1139f24624629c. Causes editor to freeze in projects with many watcher registrations --- runtime/doc/news.txt | 3 - runtime/lua/vim/_editor.lua | 1 - runtime/lua/vim/_watch.lua | 174 ----------------------- runtime/lua/vim/lsp/_watchfiles.lua | 274 ------------------------------------ runtime/lua/vim/lsp/handlers.lua | 38 ++--- runtime/lua/vim/lsp/protocol.lua | 9 -- 6 files changed, 9 insertions(+), 490 deletions(-) delete mode 100644 runtime/lua/vim/_watch.lua delete mode 100644 runtime/lua/vim/lsp/_watchfiles.lua (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 53c2b44c5f..23bb6d4343 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -171,9 +171,6 @@ The following new APIs or features were added. • |vim.treesitter.foldexpr()| can be used for 'foldexpr' to use treesitter for folding. -• Added support for the `workspace/didChangeWatchedFiles` capability to the - LSP client to notify servers of file changes on disk. - ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 92444ff550..3f27e61810 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -37,7 +37,6 @@ for k, v in pairs({ health = true, fs = true, secure = true, - _watch = true, }) do vim._submodules[k] = v end diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua deleted file mode 100644 index dba1522ec8..0000000000 --- a/runtime/lua/vim/_watch.lua +++ /dev/null @@ -1,174 +0,0 @@ -local M = {} - ---- Enumeration describing the types of events watchers will emit. -M.FileChangeType = vim.tbl_add_reverse_lookup({ - Created = 1, - Changed = 2, - Deleted = 3, -}) - ----@private ---- Joins filepath elements by static '/' separator ---- ----@param ... (string) The path elements. -local function filepath_join(...) - return table.concat({ ... }, '/') -end - ----@private ---- Stops and closes a libuv |uv_fs_event_t| or |uv_fs_poll_t| handle ---- ----@param handle (uv_fs_event_t|uv_fs_poll_t) The handle to stop -local function stop(handle) - local _, stop_err = handle:stop() - assert(not stop_err, stop_err) - local is_closing, close_err = handle:is_closing() - assert(not close_err, close_err) - if not is_closing then - handle:close() - end -end - ---- Initializes and starts a |uv_fs_event_t| ---- ----@param path (string) The path to watch ----@param opts (table|nil) Additional options ---- - uvflags (table|nil) ---- Same flags as accepted by |uv.fs_event_start()| ----@param callback (function) The function called when new events ----@returns (function) A function to stop the watch -function M.watch(path, opts, callback) - vim.validate({ - path = { path, 'string', false }, - opts = { opts, 'table', true }, - callback = { callback, 'function', false }, - }) - - path = vim.fs.normalize(path) - local uvflags = opts and opts.uvflags or {} - local handle, new_err = vim.loop.new_fs_event() - assert(not new_err, new_err) - local _, start_err = handle:start(path, uvflags, function(err, filename, events) - assert(not err, err) - local fullpath = path - if filename then - filename = filename:gsub('\\', '/') - fullpath = filepath_join(fullpath, filename) - end - local change_type = events.change and M.FileChangeType.Changed or 0 - if events.rename then - local _, staterr, staterrname = vim.loop.fs_stat(fullpath) - if staterrname == 'ENOENT' then - change_type = M.FileChangeType.Deleted - else - assert(not staterr, staterr) - change_type = M.FileChangeType.Created - end - end - callback(fullpath, change_type) - end) - assert(not start_err, start_err) - return function() - stop(handle) - end -end - -local default_poll_interval_ms = 2000 - ----@private ---- Implementation for poll, hiding internally-used parameters. ---- ----@param watches (table|nil) A tree structure to maintain state for recursive watches. ---- - handle (uv_fs_poll_t) ---- The libuv handle ---- - cancel (function) ---- A function that cancels the handle and all children's handles ---- - is_dir (boolean) ---- Indicates whether the path is a directory (and the poll should ---- be invoked recursively) ---- - children (table|nil) ---- A mapping of directory entry name to its recursive watches -local function poll_internal(path, opts, callback, watches) - path = vim.fs.normalize(path) - local interval = opts and opts.interval or default_poll_interval_ms - watches = watches or { - is_dir = true, - } - - if not watches.handle then - local poll, new_err = vim.loop.new_fs_poll() - assert(not new_err, new_err) - watches.handle = poll - local _, start_err = poll:start( - path, - interval, - vim.schedule_wrap(function(err) - if err == 'ENOENT' then - return - end - assert(not err, err) - poll_internal(path, opts, callback, watches) - callback(path, M.FileChangeType.Changed) - end) - ) - assert(not start_err, start_err) - callback(path, M.FileChangeType.Created) - end - - watches.cancel = function() - if watches.children then - for _, w in pairs(watches.children) do - w.cancel() - end - end - stop(watches.handle) - end - - if watches.is_dir then - watches.children = watches.children or {} - local exists = {} - for name, ftype in vim.fs.dir(path) do - exists[name] = true - if not watches.children[name] then - watches.children[name] = { - is_dir = ftype == 'directory', - } - poll_internal(filepath_join(path, name), opts, callback, watches.children[name]) - end - end - - local newchildren = {} - for name, watch in pairs(watches.children) do - if exists[name] then - newchildren[name] = watch - else - watch.cancel() - watches.children[name] = nil - callback(path .. '/' .. name, M.FileChangeType.Deleted) - end - end - watches.children = newchildren - end - - return watches.cancel -end - ---- Initializes and starts a |uv_fs_poll_t| recursively watching every file underneath the ---- directory at path. ---- ----@param path (string) The path to watch. Must refer to a directory. ----@param opts (table|nil) Additional options ---- - interval (number|nil) ---- Polling interval in ms as passed to |uv.fs_poll_start()|. Defaults to 2000. ----@param callback (function) The function called when new events ----@returns (function) A function to stop the watch. -function M.poll(path, opts, callback) - vim.validate({ - path = { path, 'string', false }, - opts = { opts, 'table', true }, - callback = { callback, 'function', false }, - }) - return poll_internal(path, opts, callback, nil) -end - -return M diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua deleted file mode 100644 index b9268b963c..0000000000 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ /dev/null @@ -1,274 +0,0 @@ -local bit = require('bit') -local watch = require('vim._watch') -local protocol = require('vim.lsp.protocol') - -local M = {} - ----@private ----Parses the raw pattern into a number of Lua-native patterns. ---- ----@param pattern string The raw glob pattern ----@return table A list of Lua patterns. A match with any of them matches the input glob pattern. -local function parse(pattern) - local patterns = { '' } - - local path_sep = '[/\\]' - local non_path_sep = '[^/\\]' - - local function append(chunks) - local new_patterns = {} - for _, p in ipairs(patterns) do - for _, chunk in ipairs(chunks) do - table.insert(new_patterns, p .. chunk) - end - end - patterns = new_patterns - end - - local function split(s, sep) - local segments = {} - local segment = '' - local in_braces = false - local in_brackets = false - for i = 1, #s do - local c = string.sub(s, i, i) - if c == sep and not in_braces and not in_brackets then - table.insert(segments, segment) - segment = '' - else - if c == '{' then - in_braces = true - elseif c == '}' then - in_braces = false - elseif c == '[' then - in_brackets = true - elseif c == ']' then - in_brackets = false - end - segment = segment .. c - end - end - if segment ~= '' then - table.insert(segments, segment) - end - return segments - end - - local function escape(c) - if - c == '?' - or c == '.' - or c == '(' - or c == ')' - or c == '%' - or c == '[' - or c == ']' - or c == '*' - or c == '+' - or c == '-' - then - return '%' .. c - end - return c - end - - local segments = split(pattern, '/') - for i, segment in ipairs(segments) do - local last_seg = i == #segments - if segment == '**' then - local chunks = { - path_sep .. '-', - '.-' .. path_sep, - } - if last_seg then - chunks = { '.-' } - end - append(chunks) - else - local in_braces = false - local brace_val = '' - local in_brackets = false - local bracket_val = '' - for j = 1, #segment do - local char = string.sub(segment, j, j) - if char ~= '}' and in_braces then - brace_val = brace_val .. char - else - if in_brackets and (char ~= ']' or bracket_val == '') then - local res - if char == '-' then - res = char - elseif bracket_val == '' and char == '!' then - res = '^' - elseif char == '/' then - res = '' - else - res = escape(char) - end - bracket_val = bracket_val .. res - else - if char == '{' then - in_braces = true - elseif char == '[' then - in_brackets = true - elseif char == '}' then - local choices = split(brace_val, ',') - local parsed_choices = {} - for _, choice in ipairs(choices) do - table.insert(parsed_choices, parse(choice)) - end - append(vim.tbl_flatten(parsed_choices)) - in_braces = false - brace_val = '' - elseif char == ']' then - append({ '[' .. bracket_val .. ']' }) - in_brackets = false - bracket_val = '' - elseif char == '?' then - append({ non_path_sep }) - elseif char == '*' then - append({ non_path_sep .. '-' }) - else - append({ escape(char) }) - end - end - end - end - - if not last_seg and (segments[i + 1] ~= '**' or i + 1 < #segments) then - append({ path_sep }) - end - end - end - - return patterns -end - ----@private ---- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern ---- Modeled after VSCode's implementation: https://github.com/microsoft/vscode/blob/0319eed971719ad48e9093daba9d65a5013ec5ab/src/vs/base/common/glob.ts#L509 ---- ----@param pattern string|table The glob pattern (raw or parsed) to match. ----@param s string The string to match against pattern. ----@return boolean Whether or not pattern matches s. -function M._match(pattern, s) - if type(pattern) == 'string' then - pattern = parse(pattern) - end - -- Since Lua's built-in string pattern matching does not have an alternate - -- operator like '|', `parse` will construct one pattern for each possible - -- alternative. Any pattern that matches thus matches the glob. - for _, p in ipairs(pattern) do - if s:match('^' .. p .. '$') then - return true - end - end - return false -end - -M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll - ----@type table> client id -> registration id -> cancel function -local cancels = vim.defaulttable() - -local queue_timeout_ms = 100 ----@type table client id -> libuv timer which will send queued changes at its timeout -local queue_timers = {} ----@type table client id -> set of queued changes to send in a single LSP notification -local change_queues = {} ----@type table> client id -> URI -> last type of change processed ---- Used to prune consecutive events of the same type for the same file -local change_cache = vim.defaulttable() - -local to_lsp_change_type = { - [watch.FileChangeType.Created] = protocol.FileChangeType.Created, - [watch.FileChangeType.Changed] = protocol.FileChangeType.Changed, - [watch.FileChangeType.Deleted] = protocol.FileChangeType.Deleted, -} - ---- Registers the workspace/didChangeWatchedFiles capability dynamically. ---- ----@param reg table LSP Registration object. ----@param ctx table Context from the |lsp-handler|. -function M.register(reg, ctx) - local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) - for _, w in ipairs(reg.registerOptions.watchers) do - local glob_patterns = {} - if type(w.globPattern) == 'string' then - for _, folder in ipairs(client.workspace_folders) do - table.insert(glob_patterns, { baseUri = folder.uri, pattern = w.globPattern }) - end - else - table.insert(glob_patterns, w.globPattern) - end - for _, glob_pattern in ipairs(glob_patterns) do - local pattern = parse(glob_pattern.pattern) - local base_dir = nil - if type(glob_pattern.baseUri) == 'string' then - base_dir = glob_pattern.baseUri - elseif type(glob_pattern.baseUri) == 'table' then - base_dir = glob_pattern.baseUri.uri - end - assert(base_dir, "couldn't identify root of watch") - base_dir = vim.uri_to_fname(base_dir) - local kind = w.kind - or protocol.WatchKind.Create + protocol.WatchKind.Change + protocol.WatchKind.Delete - - table.insert( - cancels[client_id][reg.id], - M._watchfunc(base_dir, { uvflags = { recursive = true } }, function(fullpath, change_type) - change_type = to_lsp_change_type[change_type] - -- e.g. match kind with Delete bit (0b0100) to Delete change_type (3) - local kind_mask = bit.lshift(1, change_type - 1) - local change_type_match = bit.band(kind, kind_mask) == kind_mask - if not M._match(pattern, fullpath) or not change_type_match then - return - end - - local change = { - uri = vim.uri_from_fname(fullpath), - type = change_type, - } - - local last_type = change_cache[client_id][change.uri] - if last_type ~= change.type then - change_queues[client_id] = change_queues[client_id] or {} - table.insert(change_queues[client_id], change) - change_cache[client_id][change.uri] = change.type - end - - if not queue_timers[client_id] then - queue_timers[client_id] = vim.defer_fn(function() - client.notify('workspace/didChangeWatchedFiles', { - changes = change_queues[client_id], - }) - queue_timers[client_id] = nil - change_queues[client_id] = nil - change_cache[client_id] = nil - end, queue_timeout_ms) - end - end) - ) - end - end -end - ---- Unregisters the workspace/didChangeWatchedFiles capability dynamically. ---- ----@param unreg table LSP Unregistration object. ----@param ctx table Context from the |lsp-handler|. -function M.unregister(unreg, ctx) - local client_id = ctx.client_id - local client_cancels = cancels[client_id] - local reg_cancels = client_cancels[unreg.id] - while #reg_cancels > 0 do - table.remove(reg_cancels)() - end - client_cancels[unreg.id] = nil - if not next(cancels[client_id]) then - cancels[client_id] = nil - end -end - -return M diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index ee5b63d260..5096100a60 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -117,35 +117,15 @@ M['window/showMessageRequest'] = function(_, result) end --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability -M['client/registerCapability'] = function(_, result, ctx) - local log_unsupported = false - for _, reg in ipairs(result.registrations) do - if reg.method == 'workspace/didChangeWatchedFiles' then - require('vim.lsp._watchfiles').register(reg, ctx) - else - log_unsupported = true - end - end - if log_unsupported then - local client_id = ctx.client_id - local warning_tpl = 'The language server %s triggers a registerCapability ' - .. 'handler despite dynamicRegistration set to false. ' - .. 'Report upstream, this warning is harmless' - local client = vim.lsp.get_client_by_id(client_id) - local client_name = client and client.name or string.format('id=%d', client_id) - local warning = string.format(warning_tpl, client_name) - log.warn(warning) - end - return vim.NIL -end - ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability -M['client/unregisterCapability'] = function(_, result, ctx) - for _, unreg in ipairs(result.unregisterations) do - if unreg.method == 'workspace/didChangeWatchedFiles' then - require('vim.lsp._watchfiles').unregister(unreg, ctx) - end - end +M['client/registerCapability'] = function(_, _, ctx) + local client_id = ctx.client_id + local warning_tpl = 'The language server %s triggers a registerCapability ' + .. 'handler despite dynamicRegistration set to false. ' + .. 'Report upstream, this warning is harmless' + local client = vim.lsp.get_client_by_id(client_id) + local client_name = client and client.name or string.format('id=%d', client_id) + local warning = string.format(warning_tpl, client_name) + log.warn(warning) return vim.NIL end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index df1ab26667..12345b6c8c 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -28,10 +28,6 @@ end ---@class lsp.MessageActionItem ---@field title string ----@class lsp.FileEvent ----@field uri string ----@field type lsp.FileChangeType - local constants = { DiagnosticSeverity = { -- Reports an error. @@ -64,7 +60,6 @@ local constants = { }, -- The file event type. - ---@enum lsp.FileChangeType FileChangeType = { -- The file got created. Created = 1, @@ -846,10 +841,6 @@ function protocol.make_client_capabilities() semanticTokens = { refreshSupport = true, }, - didChangeWatchedFiles = { - dynamicRegistration = true, - relativePatternSupport = true, - }, }, experimental = nil, window = { -- cgit From c1514d7e6762ed62dee027ecc29bafd4aae2206e Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 25 Feb 2023 18:47:05 +0100 Subject: fix(lsp): fix some type annotations (#22397) --- runtime/doc/lsp.txt | 37 ++++++++------- runtime/lua/vim/lsp.lua | 97 +++++++++++++++++++--------------------- runtime/lua/vim/lsp/protocol.lua | 9 +--- runtime/lua/vim/lsp/rpc.lua | 8 ++-- runtime/lua/vim/lsp/types.lua | 20 +++++++++ 5 files changed, 92 insertions(+), 79 deletions(-) create mode 100644 runtime/lua/vim/lsp/types.lua (limited to 'runtime') diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 215515a2d9..3b5a434eff 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -569,7 +569,7 @@ buf_notify({bufnr}, {method}, {params}) *vim.lsp.buf_notify()* • {params} (any) Arguments to send to the server Return: ~ - true if any client returns true; false otherwise + (boolean) success true if any client returns true; false otherwise *vim.lsp.buf_request_all()* buf_request_all({bufnr}, {method}, {params}, {callback}) @@ -582,11 +582,13 @@ buf_request_all({bufnr}, {method}, {params}, {callback}) • {method} (string) LSP method name • {params} (table|nil) Parameters to send to the server • {callback} (function) The callback to call when all requests are - finished. + finished. Unlike `buf_request`, this will collect all the + responses from each server instead of handling them. A map + of client_id:request_result will be provided to the + callback Return: ~ - (function) A function that will cancel all requests which is the same - as the one returned from `buf_request`. + fun() cancel A function that will cancel all requests *vim.lsp.buf_request_sync()* buf_request_sync({bufnr}, {method}, {params}, {timeout_ms}) @@ -604,8 +606,9 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms}) result. Defaults to 1000 Return: ~ - Map of client_id:request_result. On timeout, cancel or error, returns - `(nil, err)` where `err` is a string describing the failure reason. + table|nil result, string|nil err Map of + client_id:request_result. On timeout, cancel or error, returns `(nil, + err)` where `err` is a string describing the failure reason. client() *vim.lsp.client* LSP client object. You can get an active client object via @@ -671,7 +674,7 @@ client_is_stopped({client_id}) *vim.lsp.client_is_stopped()* • {client_id} (number) Return: ~ - true if client is stopped, false otherwise. + (boolean) stopped true if client is stopped, false otherwise. *vim.lsp.for_each_buffer_client()* for_each_buffer_client({bufnr}, {fn}) @@ -722,10 +725,10 @@ get_buffers_by_client_id({client_id}) Returns list of buffers attached to client_id. Parameters: ~ - • {client_id} (number) client id + • {client_id} (integer) client id Return: ~ - (list) of buffer ids + integer[] buffers list of buffer ids get_client_by_id({client_id}) *vim.lsp.get_client_by_id()* Gets a client by id, or nil if the id is invalid. The returned client may @@ -741,7 +744,7 @@ get_log_path() *vim.lsp.get_log_path()* Gets the path of the logfile used by the LSP client. Return: ~ - (String) Path to logfile. + (string) path to log file omnifunc({findstart}, {base}) *vim.lsp.omnifunc()* Implements 'omnifunc' compatible LSP completion. @@ -946,9 +949,9 @@ start_client({config}) *vim.lsp.start_client()* initialization. Return: ~ - Client id. |vim.lsp.get_client_by_id()| Note: client may not be fully - initialized. Use `on_init` to do any actions once the client has been - initialized. + (integer|nil) client_id. |vim.lsp.get_client_by_id()| Note: client may + not be fully initialized. Use `on_init` to do any actions once the + client has been initialized. stop_client({client_id}, {force}) *vim.lsp.stop_client()* Stops a client(s). @@ -979,7 +982,7 @@ tagfunc({...}) *vim.lsp.tagfunc()* • {flags} (string) See |tag-function| Return: ~ - A list of matching tags + table[] tags A list of matching tags with({handler}, {override_config}) *vim.lsp.with()* Function to manage overriding defaults for LSP handlers. @@ -1943,13 +1946,13 @@ request({method}, {params}, {callback}, {notify_reply_callback}) • {method} (string) The invoked LSP method • {params} (table|nil) Parameters for the invoked LSP method - • {callback} (function) Callback to invoke + • {callback} fun(err: lsp.ResponseError | nil, result: any) Callback to invoke • {notify_reply_callback} (function|nil) Callback to invoke as soon as a request is no longer pending Return: ~ - (bool, number) `(true, message_id)` if request could be sent, `false` - if not + (boolean) success, integer|nil request_id true, message_id if request + could be sent, `false` if not *vim.lsp.rpc.rpc_response_error()* rpc_response_error({code}, {message}, {data}) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 206c7c9b7e..d215b4c47e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -67,7 +67,7 @@ lsp._request_name_to_capability = { ---@private --- Concatenates and writes a list of strings to the Vim error buffer. --- ----@param {...} table[] List to write to the buffer +---@param ... string List to write to the buffer local function err_message(...) nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) nvim_command('redraw') @@ -76,9 +76,8 @@ end ---@private --- Returns the buffer number for the given {bufnr}. --- ----@param bufnr (number|nil) Buffer number to resolve. Defaults to the current ----buffer if not given. ----@returns bufnr (number) Number of requested buffer +---@param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer +---@return integer bufnr local function resolve_bufnr(bufnr) validate({ bufnr = { bufnr, 'n', true } }) if bufnr == nil or bufnr == 0 then @@ -104,7 +103,7 @@ end --- Checks whether a given path is a directory. --- ---@param filename (string) path to check ----@returns true if {filename} exists and is a directory, false otherwise +---@return boolean # true if {filename} exists and is a directory, false otherwise local function is_dir(filename) validate({ filename = { filename, 's' } }) local stat = uv.fs_stat(filename) @@ -133,7 +132,7 @@ local format_line_ending = { ---@private ---@param bufnr (number) ----@returns (string) +---@return string local function buf_get_line_ending(bufnr) return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n' end @@ -142,7 +141,7 @@ local client_index = 0 ---@private --- Returns a new, unused client id. --- ----@returns (number) client id +---@return integer client_id local function next_client_id() client_index = client_index + 1 return client_index @@ -197,7 +196,7 @@ lsp.client_errors = tbl_extend( --- Normalizes {encoding} to valid LSP encoding names. --- ---@param encoding (string) Encoding to normalize ----@returns (string) normalized encoding name +---@return string # normalized encoding name local function validate_encoding(encoding) validate({ encoding = { encoding, 's' }, @@ -215,9 +214,8 @@ end --- Parses a command invocation into the command itself and its args. If there --- are no arguments, an empty table is returned as the second argument. --- ----@param input (List) ----@returns (string) the command ----@returns (list of strings) its arguments +---@param input string[] +---@return string command, string[] args #the command and arguments function lsp._cmd_parts(input) validate({ cmd = { @@ -244,9 +242,9 @@ end ---@private --- Augments a validator function with support for optional (nil) values. --- ----@param fn (fun(v)) The original validator function; should return a +---@param fn (fun(v): boolean) The original validator function; should return a ---bool. ----@returns (fun(v)) The augmented function. Also returns true if {v} is +---@return fun(v): boolean # The augmented function. Also returns true if {v} is ---`nil`. local function optional_validator(fn) return function(v) @@ -258,10 +256,8 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- ---@param config (table) ----@returns (table) "Cleaned" config, containing only the command, its +---@return table config Cleaned config, containing the command, its ---arguments, and a valid encoding. ---- ----@see |vim.lsp.start_client()| local function validate_client_config(config) validate({ config = { config, 't' }, @@ -314,7 +310,7 @@ end --- Returns full text of buffer {bufnr} as a string. --- ---@param bufnr (number) Buffer handle, or 0 for current. ----@returns Buffer text as string. +---@return string # Buffer text as string. local function buf_get_full_text(bufnr) local line_ending = buf_get_line_ending(bufnr) local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) @@ -331,7 +327,7 @@ end --- even if it has side effects. --- ---@param fn (function) Function to run ----@returns (function) Memoized function +---@return function fn Memoized function local function once(fn) local value local ran = false @@ -373,7 +369,7 @@ do --- @field lines string[] snapshot of buffer lines from last didChange --- @field lines_tmp string[] --- @field pending_changes table[] List of debounced changes in incremental sync mode - --- @field timer nil|userdata uv_timer + --- @field timer nil|uv.uv_timer_t uv_timer --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet --- @field refs number how many clients are using this group @@ -648,7 +644,7 @@ do if debounce == 0 then send_changes(bufnr, group.sync_kind, state, buf_state) else - local timer = uv.new_timer() + local timer = assert(uv.new_timer(), 'Must be able to create timer') buf_state.timer = timer timer:start( debounce, @@ -1006,7 +1002,7 @@ end --- server will base its workspaceFolders, rootUri, and rootPath --- on initialization. --- ----@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be +---@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) @@ -1037,7 +1033,7 @@ function lsp.start_client(config) --- Returns the default handler if the user hasn't set a custom one. --- ---@param method (string) LSP method name - ---@returns (fn) The handler for the given method, if defined, or the default from |vim.lsp.handlers| + ---@return function|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) return handlers[method] or default_handlers[method] end @@ -1343,11 +1339,11 @@ function lsp.start_client(config) --- This is a thin wrapper around {client.rpc.request} with some additional --- checks for capabilities and handler availability. --- - ---@param method (string) LSP method name. - ---@param params (table) LSP request params. - ---@param handler (function|nil) Response |lsp-handler| for this method. - ---@param bufnr (number) Buffer handle (0 for current). - ---@returns ({status}, [request_id]): {status} is a bool indicating + ---@param method string LSP method name. + ---@param params table LSP request params. + ---@param handler lsp-handler|nil Response |lsp-handler| for this method. + ---@param bufnr integer Buffer handle (0 for current). + ---@return boolean status, integer|nil request_id {status} is a bool indicating ---whether the request was successful. If it is `false`, then it will ---always be `false` (the client has shutdown). If it was ---successful, then it will return {request_id} as the @@ -1395,10 +1391,11 @@ function lsp.start_client(config) ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for --- a result. Defaults to 1000 ---@param bufnr (number) Buffer handle (0 for current). - ---@returns { err=err, result=result }, a dictionary, where `err` and `result` come from the |lsp-handler|. - ---On timeout, cancel or error, returns `(nil, err)` where `err` is a - ---string describing the failure reason. If the request was unsuccessful - ---returns `nil`. + ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where + --- `err` and `result` come from the |lsp-handler|. + --- On timeout, cancel or error, returns `(nil, err)` where `err` is a + --- string describing the failure reason. If the request was unsuccessful + --- returns `nil`. ---@see |vim.lsp.buf_request_sync()| function client.request_sync(method, params, timeout_ms, bufnr) local request_result = nil @@ -1429,7 +1426,7 @@ function lsp.start_client(config) --- ---@param method string LSP method name. ---@param params table|nil LSP request params. - ---@returns {status} (bool) true if the notification was successful. + ---@return boolean status true if the notification was successful. ---If it is false, then it will always be false ---(the client has shutdown). function client.notify(method, params) @@ -1443,7 +1440,7 @@ function lsp.start_client(config) --- Cancels a request with a given request id. --- ---@param id (number) id of request to cancel - ---@returns true if any client returns true; false otherwise + ---@return boolean status true if notification was successful. false otherwise ---@see |vim.lsp.client.notify()| function client.cancel_request(id) validate({ id = { id, 'n' } }) @@ -1489,7 +1486,7 @@ function lsp.start_client(config) ---@private --- Checks whether a client is stopped. --- - ---@returns (bool) true if client is stopped or in the process of being + ---@return boolean # true if client is stopped or in the process of being ---stopped; false otherwise function client.is_stopped() return rpc.is_closing() @@ -1497,7 +1494,7 @@ function lsp.start_client(config) ---@private --- Runs the on_attach function from the client's config if it was defined. - ---@param bufnr (number) Buffer number + ---@param bufnr integer Buffer number function client._on_attach(bufnr) text_document_did_open_handler(bufnr, client) @@ -1771,8 +1768,8 @@ end --- Returns list of buffers attached to client_id. --- ----@param client_id number client id ----@returns list of buffer ids +---@param client_id integer client id +---@return integer[] buffers list of buffer ids function lsp.get_buffers_by_client_id(client_id) local client = lsp.get_client_by_id(client_id) return client and vim.tbl_keys(client.attached_buffers) or {} @@ -1906,7 +1903,7 @@ api.nvim_create_autocmd('VimLeavePre', { ---@param handler function|nil See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| --- ----@returns 2-tuple: +---@return table, fun() 2-tuple: --- - Map of client-id:request-id pairs for all successful requests. --- - Function which can be used to cancel all the requests. You could instead --- iterate all clients and call their `cancel_request()` methods. @@ -1964,10 +1961,10 @@ end ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ---@param callback (function) The callback to call when all requests are finished. --- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. --- A map of client_id:request_result will be provided to the callback --- ----@returns (function) A function that will cancel all requests which is the same as the one returned from `buf_request`. +--- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. +--- A map of client_id:request_result will be provided to the callback +--- +---@return fun() cancel A function that will cancel all requests function lsp.buf_request_all(bufnr, method, params, callback) local request_results = {} local result_count = 0 @@ -2008,9 +2005,9 @@ end ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for a --- result. Defaults to 1000 --- ----@returns Map of client_id:request_result. On timeout, cancel or error, ---- returns `(nil, err)` where `err` is a string describing the failure ---- reason. +---@return table|nil result, string|nil err Map of client_id:request_result. +--- On timeout, cancel or error, returns `(nil, err)` where `err` is a string describing +--- the failure reason. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) local request_results @@ -2035,7 +2032,7 @@ end ---@param method (string) Name of the request method ---@param params (any) Arguments to send to the server --- ----@returns true if any client returns true; false otherwise +---@return boolean success true if any client returns true; false otherwise function lsp.buf_notify(bufnr, method, params) validate({ bufnr = { bufnr, 'n', true }, @@ -2172,7 +2169,7 @@ function lsp.formatexpr(opts) for _, client in pairs(lsp.get_active_clients({ bufnr = bufnr })) do if client.supports_method('textDocument/rangeFormatting') then local params = util.make_formatting_params() - local end_line = vim.fn.getline(end_lnum) + local end_line = vim.fn.getline(end_lnum) --[[@as string]] local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding) params.range = { start = { @@ -2207,7 +2204,7 @@ end ---@param pattern string Pattern used to find a workspace symbol ---@param flags string See |tag-function| --- ----@returns A list of matching tags +---@return table[] tags A list of matching tags function lsp.tagfunc(...) return require('vim.lsp.tagfunc')(...) end @@ -2215,7 +2212,7 @@ end ---Checks whether a client is stopped. --- ---@param client_id (number) ----@returns true if client is stopped, false otherwise. +---@return boolean stopped true if client is stopped, false otherwise. function lsp.client_is_stopped(client_id) return active_clients[client_id] == nil end @@ -2262,7 +2259,7 @@ function lsp.set_log_level(level) end --- Gets the path of the logfile used by the LSP client. ----@returns (String) Path to logfile. +---@return string path to log file function lsp.get_log_path() return log.get_filename() end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 12345b6c8c..41dfc9e00e 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -20,14 +20,6 @@ function transform_schema_to_table() end --]=] ----@class lsp.ShowMessageRequestParams ----@field type lsp.MessageType ----@field message string ----@field actions nil|lsp.MessageActionItem[] - ----@class lsp.MessageActionItem ----@field title string - local constants = { DiagnosticSeverity = { -- Reports an error. @@ -60,6 +52,7 @@ local constants = { }, -- The file event type. + ---@enum lsp.FileChangeType FileChangeType = { -- The file got created. Created = 1, diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index f1492601ff..aa833deb99 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -319,9 +319,9 @@ end --- ---@param method (string) The invoked LSP method ---@param params (table|nil) Parameters for the invoked LSP method ----@param callback (function) Callback to invoke +---@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending ----@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not +---@return boolean success, integer|nil request_id true, request_id if request could be sent, `false` if not function Client:request(method, params, callback, notify_reply_callback) validate({ callback = { callback, 'f' }, @@ -538,9 +538,9 @@ local function public_client(client) --- ---@param method (string) The invoked LSP method ---@param params (table|nil) Parameters for the invoked LSP method - ---@param callback (function) Callback to invoke + ---@param callback fun(err: lsp.ResponseError | nil, result: any) Callback to invoke ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending - ---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not + ---@return boolean success, integer|nil request_id true, message_id if request could be sent, `false` if not function result.request(method, params, callback, notify_reply_callback) return client:request(method, params, callback, notify_reply_callback) end diff --git a/runtime/lua/vim/lsp/types.lua b/runtime/lua/vim/lsp/types.lua new file mode 100644 index 0000000000..1aea6841ee --- /dev/null +++ b/runtime/lua/vim/lsp/types.lua @@ -0,0 +1,20 @@ +---@meta + +---@alias lsp-handler fun(err: lsp.ResponseError|nil, result: any, context: table, config: table|nil) + +---@class lsp.ResponseError +---@field code integer +---@field message string +---@field data string|number|boolean|table[]|table|nil + +---@class lsp.ShowMessageRequestParams +---@field type lsp.MessageType +---@field message string +---@field actions nil|lsp.MessageActionItem[] + +---@class lsp.MessageActionItem +---@field title string + +---@class lsp.FileEvent +---@field uri string +---@field type lsp.FileChangeType -- cgit From 774e59f3f9bf50c8350857c6722bb58df2dd940a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 26 Feb 2023 16:53:33 +0000 Subject: feat(treesitter): expand the API --- runtime/doc/news.txt | 8 ++++++++ runtime/doc/treesitter.txt | 25 ++++++++++++++++++++++--- runtime/lua/vim/treesitter/_meta.lua | 8 +++++++- 3 files changed, 37 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 23bb6d4343..c5261b739d 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -171,6 +171,14 @@ The following new APIs or features were added. • |vim.treesitter.foldexpr()| can be used for 'foldexpr' to use treesitter for folding. +• Expanded the TSNode API with: + - |TSNode:tree()| + - |TSNode:has_changes()| + - |TSNode:extra()| + - |TSNode:equal()| + + Additionally |TSNode:range()| now takes an optional {include_bytes} argument. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 76cde91920..fdea84282f 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -136,9 +136,16 @@ TSNode:end_() *TSNode:end_()* Get the node's end position. Return three values: the row, column and total byte count (all zero-based). -TSNode:range() *TSNode:range()* - Get the range of the node. Return four values: the row, column of the - start position, then the row, column of the end position. +TSNode:range({include_bytes}) *TSNode:range()* + Get the range of the node. + + Return four or six values: + - start row + - start column + - start byte (if {include_bytes} is `true`) + - end row + - end column + - end byte (if {include_bytes} is `true`) TSNode:type() *TSNode:type()* Get the node's type as a string. @@ -155,6 +162,13 @@ TSNode:missing() *TSNode:missing()* Check if the node is missing. Missing nodes are inserted by the parser in order to recover from certain kinds of syntax errors. +TSNode:extra() *TSNode:extra()* + Check if the node is extra. Extra nodes represent things like comments, + which are not required by the grammar but can appear anywhere. + +TSNode:has_changes() *TSNode:has_changes()* + Check if a syntax node has been edited. + TSNode:has_error() *TSNode:has_error()* Check if the node is a syntax error or contains any syntax errors. @@ -171,6 +185,8 @@ TSNode:id() *TSNode:id()* Note: The `id` is not guaranteed to be unique for nodes from different trees. +TSNode:tree() *TSNode:tree()* + Get the |TSTree| of the node. *TSNode:descendant_for_range()* TSNode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest node within this node that spans the given range of (row, @@ -180,6 +196,9 @@ TSNode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) TSNode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest named node within this node that spans the given range of (row, column) positions + *TSNode:equal()* +TSNode:equal({node}) + Check if {node} refers to the same node within the same tree. ============================================================================== TREESITTER QUERIES *treesitter-query* diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua index 87b4560798..731a5ebf9f 100644 --- a/runtime/lua/vim/treesitter/_meta.lua +++ b/runtime/lua/vim/treesitter/_meta.lua @@ -2,6 +2,7 @@ ---@class TSNode ---@field id fun(self: TSNode): integer +---@field tree fun(self: TSNode): TSTree ---@field range fun(self: TSNode): integer, integer, integer, integer ---@field start fun(self: TSNode): integer, integer, integer ---@field end_ fun(self: TSNode): integer, integer, integer @@ -9,6 +10,7 @@ ---@field symbol fun(self: TSNode): integer ---@field named fun(self: TSNode): boolean ---@field missing fun(self: TSNode): boolean +---@field extra fun(self: TSNode): boolean ---@field child_count fun(self: TSNode): integer ---@field named_child_count fun(self: TSNode): integer ---@field child fun(self: TSNode, integer): TSNode @@ -21,7 +23,8 @@ ---@field next_named_sibling fun(self: TSNode): TSNode ---@field prev_named_sibling fun(self: TSNode): TSNode ---@field named_children fun(self: TSNode): TSNode[] ----@field has_error fun(self: TSNode): boolean +---@field has_changes fun(self: TSNode): boolean +---@field equal fun(self: TSNode, other: TSNode): boolean ---@field iter_children fun(self: TSNode): fun(): TSNode, string local TSNode = {} @@ -41,8 +44,11 @@ function TSNode:_rawquery(query, captures, start, end_) end ---@class TSParser ---@field parse fun(self: TSParser, tree, source: integer|string): TSTree, integer[] +---@field reset fun(self: TSParser) ---@field included_ranges fun(self: TSParser): integer[] ---@field set_included_ranges fun(self: TSParser, ranges: integer[][]) +---@field set_timeout fun(self: TSParser, timeout: integer) +---@field timeout fun(self: TSParser): integer ---@class TSTree ---@field root fun(self: TSTree): TSNode -- cgit From 0972d7a12468d6914a70e453af85c307b167c55b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:13:12 +0800 Subject: vim-patch:9.0.0196: finding value in list may require a for loop Problem: Finding value in list may require a for loop. Solution: Add indexof(). (Yegappan Lakshmanan, closes vim/vim#10903) https://github.com/vim/vim/commit/b218655d5a485f5b193fb18d7240837d42b89812 Co-authored-by: Yegappan Lakshmanan --- runtime/doc/builtin.txt | 48 +++++++++++++++++++++++++++++++++++++++++++++++- runtime/doc/usr_41.txt | 6 ++++-- 2 files changed, 51 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 5f279ed09c..1168d7ff1d 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -255,6 +255,8 @@ iconv({expr}, {from}, {to}) String convert encoding of {expr} indent({lnum}) Number indent of line {lnum} index({object}, {expr} [, {start} [, {ic}]]) Number index in {object} where {expr} appears +indexof({object}, {expr} [, {opts}]]) + Number index in {object} where {expr} is true input({prompt} [, {text} [, {completion}]]) String get input from the user inputlist({textlist}) Number let the user pick from a choice list @@ -4084,19 +4086,25 @@ indent({lnum}) The result is a Number, which is indent of line {lnum} in the GetLnum()->indent() index({object}, {expr} [, {start} [, {ic}]]) *index()* + Find {expr} in {object} and return its index. See + |filterof()| for using a lambda to select the item. + If {object} is a |List| return the lowest index where the item has a value equal to {expr}. There is no automatic conversion, so the String "4" is different from the Number 4. And the Number 4 is different from the Float 4.0. The value - of 'ignorecase' is not used here, case always matters. + of 'ignorecase' is not used here, case matters as indicated by + the {ic} argument. If {object} is a |Blob| return the lowest index where the byte value is equal to {expr}. If {start} is given then start looking at the item with index {start} (may be negative for an item relative to the end). + When {ic} is given and it is |TRUE|, ignore case. Otherwise case must match. + -1 is returned when {expr} is not found in {object}. Example: > :let idx = index(words, "the") @@ -4105,6 +4113,44 @@ index({object}, {expr} [, {start} [, {ic}]]) *index()* < Can also be used as a |method|: > GetObject()->index(what) +indexof({object}, {expr} [, {opt}]) *indexof()* + {object} must be a |List| or a |Blob|. + If {object} is a |List|, evaluate {expr} for each item in the + List until the expression returns v:true and return the index + of this item. + + If {object} is a |Blob| evaluate {expr} for each byte in the + Blob until the expression returns v:true and return the index + of this byte. + + {expr} must be a |string| or |Funcref|. + + If {expr} is a |string|: If {object} is a |List|, inside + {expr} |v:key| has the index of the current List item and + |v:val| has the value of the item. If {object} is a |Blob|, + inside {expr} |v:key| has the index of the current byte and + |v:val| has the byte value. + + If {expr} is a |Funcref| it must take two arguments: + 1. the key or the index of the current item. + 2. the value of the current item. + The function must return |TRUE| if the item is found and the + search should stop. + + The optional argument {opt} is a Dict and supports the + following items: + start start evaluating {expr} at the item with index + {start} (may be negative for an item relative + to the end). + Returns -1 when {expr} evaluates to v:false for all the items. + Example: > + :let l = [#{n: 10}, #{n: 20}, #{n: 30]] + :let idx = indexof(l, "v:val.n == 20") + :let idx = indexof(l, {i, v -> v.n == 30}) + +< Can also be used as a |method|: > + mylist->indexof(expr) + input({prompt} [, {text} [, {completion}]]) *input()* input({opts}) The result is a String, which is whatever the user typed on diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 27c5927cf9..77b1795a57 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -657,14 +657,16 @@ List manipulation: *list-functions* map() change each List item reduce() reduce a List to a value sort() sort a List - reverse() reverse the order of a List + reverse() reverse the order of a List or Blob uniq() remove copies of repeated adjacent items split() split a String into a List join() join List items into a String range() return a List with a sequence of numbers string() String representation of a List call() call a function with List as arguments - index() index of a value in a List + index() index of a value in a List or Blob + indexof() index in a List or Blob where an expression + evaluates to true max() maximum value in a List min() minimum value in a List count() count number of times a value appears in a List -- cgit From 13da3d469ae10201de00ae89277c53c40342f4df Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:50:35 +0800 Subject: vim-patch:partial:9.0.0202: code and help for indexof() is not ideal Problem: Code and help for indexof() is not ideal. Solution: Refactor the code, improve the help. (Yegappan Lakshmanan, closes vim/vim#10908) https://github.com/vim/vim/commit/3fbf6cd355de2212e9227f57d545592aae3f688f Skip CHECK_LIST_MATERIALIZE and set_vim_var_type(). Use tv_list_uidx() instead of lv_idx. Co-authored-by: Yegappan Lakshmanan --- runtime/doc/builtin.txt | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 1168d7ff1d..35f1b7cd6f 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -4087,7 +4087,7 @@ indent({lnum}) The result is a Number, which is indent of line {lnum} in the index({object}, {expr} [, {start} [, {ic}]]) *index()* Find {expr} in {object} and return its index. See - |filterof()| for using a lambda to select the item. + |indexof()| for using a lambda to select the item. If {object} is a |List| return the lowest index where the item has a value equal to {expr}. There is no automatic @@ -4113,15 +4113,17 @@ index({object}, {expr} [, {start} [, {ic}]]) *index()* < Can also be used as a |method|: > GetObject()->index(what) -indexof({object}, {expr} [, {opt}]) *indexof()* - {object} must be a |List| or a |Blob|. +indexof({object}, {expr} [, {opts}]) *indexof()* + Returns the index of an item in {object} where {expr} is + v:true. {object} must be a |List| or a |Blob|. + If {object} is a |List|, evaluate {expr} for each item in the - List until the expression returns v:true and return the index - of this item. + List until the expression is v:true and return the index of + this item. If {object} is a |Blob| evaluate {expr} for each byte in the - Blob until the expression returns v:true and return the index - of this byte. + Blob until the expression is v:true and return the index of + this byte. {expr} must be a |string| or |Funcref|. @@ -4137,16 +4139,17 @@ indexof({object}, {expr} [, {opt}]) *indexof()* The function must return |TRUE| if the item is found and the search should stop. - The optional argument {opt} is a Dict and supports the + The optional argument {opts} is a Dict and supports the following items: - start start evaluating {expr} at the item with index - {start} (may be negative for an item relative - to the end). + startidx start evaluating {expr} at the item with this + index; may be negative for an item relative to + the end Returns -1 when {expr} evaluates to v:false for all the items. Example: > - :let l = [#{n: 10}, #{n: 20}, #{n: 30]] - :let idx = indexof(l, "v:val.n == 20") - :let idx = indexof(l, {i, v -> v.n == 30}) + :let l = [#{n: 10}, #{n: 20}, #{n: 30}] + :echo indexof(l, "v:val.n == 20") + :echo indexof(l, {i, v -> v.n == 30}) + :echo indexof(l, "v:val.n == 20", #{startidx: 1}) < Can also be used as a |method|: > mylist->indexof(expr) -- cgit From 2c9fbe34b20266ef5ab54f6ed14fb38eef60430d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Feb 2023 10:10:42 +0800 Subject: vim-patch:8.2.2336: Vim9: not possible to extend dictionary with different type (#22425) Problem: Vim9: it is not possible to extend a dictionary with different item types. Solution: Add extendnew(). (closes vim/vim#7666) https://github.com/vim/vim/commit/b0e6b513648db7035046613431a4aa9d71ef4653 Co-authored-by: Bram Moolenaar --- runtime/doc/builtin.txt | 11 +++++++++++ runtime/doc/usr_41.txt | 2 ++ 2 files changed, 13 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 35f1b7cd6f..3ff4e47a45 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -138,6 +138,9 @@ expandcmd({string} [, {options}]) String expand {string} like with `:edit` extend({expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} +extendnew({expr1}, {expr2} [, {expr3}]) + List/Dict like |extend()| but creates a new + List or Dictionary feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer filereadable({file}) Number |TRUE| if {file} is a readable file filewritable({file}) Number |TRUE| if {file} is a writable file @@ -2119,6 +2122,14 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()* Can also be used as a |method|: > mylist->extend(otherlist) + +extendnew({expr1}, {expr2} [, {expr3}]) *extendnew()* + Like |extend()| but instead of adding items to {expr1} a new + List or Dictionary is created and returned. {expr1} remains + unchanged. Items can still be changed by {expr2}, if you + don't want that use |deepcopy()| first. + + feedkeys({string} [, {mode}]) *feedkeys()* Characters in {string} are queued for processing as if they come from a mapping or were typed by the user. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 77b1795a57..0f2cfdd2ac 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -650,6 +650,7 @@ List manipulation: *list-functions* insert() insert an item somewhere in a List add() append an item to a List extend() append a List to a List + extendnew() make a new List and append items remove() remove one or more items from a List copy() make a shallow copy of a List deepcopy() make a full copy of a List @@ -681,6 +682,7 @@ Dictionary manipulation: *dict-functions* empty() check if Dictionary is empty remove() remove an entry from a Dictionary extend() add entries from one Dictionary to another + extendnew() make a new Dictionary and append items filter() remove selected entries from a Dictionary map() change each Dictionary entry keys() get List of Dictionary keys -- cgit From da56f06037c26180021c1e3b73a77fc990f0c1e3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 27 Feb 2023 10:49:19 +0000 Subject: fix(treesitter): remove virtual text from playground Implement the range and lang annotations as comments instead --- runtime/lua/vim/treesitter/playground.lua | 46 +++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua index 001bc2d5bf..fd5b687195 100644 --- a/runtime/lua/vim/treesitter/playground.lua +++ b/runtime/lua/vim/treesitter/playground.lua @@ -138,6 +138,19 @@ end local decor_ns = api.nvim_create_namespace('ts.playground') +---@private +---@param lnum integer +---@param col integer +---@param end_lnum integer +---@param end_col integer +---@return string +local function get_range_str(lnum, col, end_col, end_lnum) + if lnum == end_lnum then + return string.format('[%d:%d-%d]', lnum + 1, col + 1, end_col) + end + return string.format('[%d:%d-%d:%d]', lnum + 1, col + 1, end_lnum + 1, end_col) +end + --- Write the contents of this Playground into {bufnr}. --- ---@param bufnr number Buffer number to write into. @@ -145,26 +158,31 @@ local decor_ns = api.nvim_create_namespace('ts.playground') function TSPlayground:draw(bufnr) vim.bo[bufnr].modifiable = true local lines = {} ---@type string[] + local lang_hl_marks = {} ---@type table[] + for _, item in self:iter() do - lines[#lines + 1] = string.rep(' ', item.depth) .. item.text + local range_str = get_range_str(item.lnum, item.col, item.end_lnum, item.end_col) + local lang_str = self.opts.lang and string.format(' %s', item.lang) or '' + local line = string.rep(' ', item.depth) .. item.text .. '; ' .. range_str .. lang_str + + if self.opts.lang then + lang_hl_marks[#lang_hl_marks + 1] = { + col = #line - #lang_str, + end_col = #line, + } + end + + lines[#lines + 1] = line end + api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) api.nvim_buf_clear_namespace(bufnr, decor_ns, 0, -1) - for i, item in self:iter() do - local range_str - if item.lnum == item.end_lnum then - range_str = string.format('[%d:%d-%d]', item.lnum + 1, item.col + 1, item.end_col) - else - range_str = - string.format('[%d:%d-%d:%d]', item.lnum + 1, item.col + 1, item.end_lnum + 1, item.end_col) - end - - local lang_str = self.opts.lang and string.format(' %s', item.lang) or '' - - api.nvim_buf_set_extmark(bufnr, decor_ns, i - 1, 0, { - virt_text = { { range_str, 'Comment' }, { lang_str, 'Title' } }, + for i, m in ipairs(lang_hl_marks) do + api.nvim_buf_set_extmark(bufnr, decor_ns, i - 1, m.col, { + hl_group = 'Title', + end_col = m.end_col, }) end -- cgit From 5aa37e20e0e6cbabf82c5cf1d35c6f5e6e48f099 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 27 Feb 2023 15:01:09 +0000 Subject: fix(treesitter): ipairs -> pairs Fixes: https://github.com/nvim-treesitter/nvim-treesitter/issues/4349 --- runtime/lua/vim/treesitter/languagetree.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 7ec7bbfa12..43fb866896 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -467,7 +467,7 @@ function LanguageTree:_get_injections() -- Generate a map by lang of node lists. -- Each list is a set of ranges that should be parsed together. - for _, lang_map in ipairs(injections) do + for _, lang_map in pairs(injections) do for lang, patterns in pairs(lang_map) do if not result[lang] then result[lang] = {} -- cgit From f64098a2df774c79dd454f63ac491570cdcaf2b2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 27 Feb 2023 15:33:18 +0000 Subject: fix(treesitter): fixup for health --- runtime/lua/vim/treesitter/health.lua | 22 ++++++++++------------ runtime/lua/vim/treesitter/language.lua | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 1abcdd0b31..fd1188fde4 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -2,28 +2,26 @@ local M = {} local ts = vim.treesitter local health = require('vim.health') ---- Lists the parsers currently installed ---- ----@return string[] list of parser files -function M.list_parsers() - return vim.api.nvim_get_runtime_file('parser/*', true) -end - --- Performs a healthcheck for treesitter integration function M.check() - local parsers = M.list_parsers() + local parsers = vim.api.nvim_get_runtime_file('parser/*', true) health.report_info(string.format('Nvim runtime ABI version: %d', ts.language_version)) for _, parser in pairs(parsers) do local parsername = vim.fn.fnamemodify(parser, ':t:r') - local is_loadable, ret = pcall(ts.language.add, parsername) + local is_loadable, err_or_nil = pcall(ts.language.add, parsername) - if not is_loadable or not ret then + if not is_loadable then health.report_error( - string.format('Parser "%s" failed to load (path: %s): %s', parsername, parser, ret or '?') + string.format( + 'Parser "%s" failed to load (path: %s): %s', + parsername, + parser, + err_or_nil or '?' + ) ) - elseif ret then + else local lang = ts.language.inspect_language(parsername) health.report_ok( string.format('Parser: %-10s ABI: %d, path: %s', parsername, lang._abi_version, parser) diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 0796383bf5..5bcc786e88 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -63,7 +63,7 @@ function M.add(lang, opts) M.register(lang, filetype or lang) if vim._ts_has_language(lang) then - return true + return end if path == nil then -- cgit From 7f424e2b65779c59fc0cac3cc7508ba2ec07f200 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 23 Feb 2023 18:29:36 +0100 Subject: feat(api): more fields in nvim_list_uis Problem: nvim_list_uis does not report all ":help ui-option" fields. Solution: Store ":help ui-option" fields on the `UI` object and update ui_array. --- runtime/doc/builtin.txt | 1 + runtime/doc/news.txt | 2 ++ runtime/doc/ui.txt | 5 ++--- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 3ff4e47a45..8cde2f8fb0 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -3868,6 +3868,7 @@ has({feature}) Returns 1 if {feature} is supported, 0 otherwise. The clipboard |clipboard| provider is available. fname_case Case in file names matters (for Darwin and MS-Windows this is not present). + gui_running Nvim has a GUI. iconv Can use |iconv()| for conversion. linux Linux system. mac MacOS system. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index c5261b739d..4c9cbf9189 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -179,6 +179,8 @@ The following new APIs or features were added. Additionally |TSNode:range()| now takes an optional {include_bytes} argument. +• |nvim_list_uis()| reports all |ui-option| fields. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index bb567e021e..e706e36374 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -53,9 +53,8 @@ with these (optional) keys: - `term_name` Sets the name of the terminal 'term'. - `term_colors` Sets the number of supported colors 't_Co'. - `term_background` Sets the default value of 'background'. -- `stdin_fd` Read buffer from `fd` as if it was a stdin pipe. - This option can only used by |--embed| ui on startup. - See |ui-startup-stdin|. +- `stdin_fd` Read buffer 1 from this fd as if it were stdin |--|. + Only from |--embed| UI on startup. |ui-startup-stdin| - `stdin_tty` Tells if `stdin` is a `tty` or not. - `stdout_tty` Tells if `stdout` is a `tty` or not. -- cgit From ce597235a26839826de88ecd8b949ec54c310fbd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 27 Feb 2023 16:31:05 +0100 Subject: feat(ui): restore has('gui_running') Problem: has('gui_running') is still common in the wild and our answer has changed over time, causing frustration. https://github.com/vimpostor/vim-tpipeline/commit/95a6ccbe9f33bc42dd4cee45731d8bc3fbcd92d1 Solution: Use stdin_tty/stdout_tty to decide if a UI is (not) a GUI. --- runtime/doc/news.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 4c9cbf9189..90e17d3678 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -181,6 +181,9 @@ The following new APIs or features were added. • |nvim_list_uis()| reports all |ui-option| fields. +• Vim's `has('gui_running')` is now supported as a way for plugins to check if + a GUI (not the |TUI|) is attached to Nvim. |has()| + ============================================================================== CHANGED FEATURES *news-changes* -- cgit From 2a8e6a2f1a8e047a8efd84764d9a332bbd6ae96d Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Mon, 27 Feb 2023 15:08:31 -0500 Subject: vim-patch:9.0.1360: Cue files are not recognized (#22439) Problem: Cue files are not recognized. Solution: Add patterns for Cue files. (Amaan Qureshi, closes vim/vim#12067) https://github.com/vim/vim/commit/80c5b2c0f78b24e52c73bb162dda3ad85acd7e82 --- runtime/lua/vim/filetype.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index a4e078fd04..256c053801 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -276,6 +276,7 @@ local extension = { feature = 'cucumber', cuh = 'cuda', cu = 'cuda', + cue = 'cue', pld = 'cupl', si = 'cuplsim', cyn = 'cynpp', -- cgit From f89e3497c88f59916e3bce2e902be9b0f8bf15ba Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 27 Feb 2023 14:19:41 -0600 Subject: docs(lsp): update cmd_env description (#22438) --- runtime/doc/lsp.txt | 7 +++---- runtime/lua/vim/lsp.lua | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 3b5a434eff..7e46698614 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -851,11 +851,10 @@ start_client({config}) *vim.lsp.start_client()* • cmd_cwd: (string, default=|getcwd()|) Directory to launch the `cmd` process. Not related to `root_dir`. • cmd_env: (table) Environment flags to pass to the LSP on - spawn. Can be specified using keys like a map or as a list - with `k=v` pairs or both. Non-string values are coerced to string. - Example: > + spawn. Must be specified using a map-like table. + Non-string values are coerced to string. Example: > - { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; } + { PORT = 8080; HOST = "0.0.0.0"; } < • detached: (boolean, default true) Daemonize the server process so that it runs in a separate process group from diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index d215b4c47e..61a06ff7a7 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -908,11 +908,11 @@ end --- the `cmd` process. Not related to `root_dir`. --- --- - cmd_env: (table) Environment flags to pass to the LSP on ---- spawn. Can be specified using keys like a map or as a list with `k=v` ---- pairs or both. Non-string values are coerced to string. +--- spawn. Must be specified using a map-like table. +--- Non-string values are coerced to string. --- Example: ---
----                   { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+---                   { PORT = 8080; HOST = "0.0.0.0"; }
 ---       
--- --- - detached: (boolean, default true) Daemonize the server process so that it runs in a -- cgit From fb2ead6cf3ef2d5a60af5dbe9cd1443a07296beb Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 27 Feb 2023 22:17:12 +0000 Subject: docs(usr): make usr_05.txt more coherent with Nvim changes (#22428) - Make section 05.2 more coherent. - Remove explanation of options that are already default. --- runtime/doc/usr_05.txt | 80 ++++++++------------------------------------------ 1 file changed, 13 insertions(+), 67 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt index d8fb2acedb..00b4f9eed4 100644 --- a/runtime/doc/usr_05.txt +++ b/runtime/doc/usr_05.txt @@ -10,7 +10,7 @@ make Vim start with options set to different values. Add plugins to extend Vim's capabilities. Or define your own macros. |05.1| The vimrc file -|05.2| The example vimrc file explained +|05.2| Example vimrc contents |05.3| Simple mappings |05.4| Adding a package |05.5| Adding a plugin @@ -27,10 +27,10 @@ Table of contents: |usr_toc.txt| You probably got tired of typing commands that you use very often. To start Vim with all your favorite option settings and mappings, you write them in -what is called the init.vim file. Vim executes the commands in this file when +what is called the init.vim file. Vim executes the commands in this file when it starts up. -If you already have a init.vim file (e.g., when your sysadmin has one setup +If you already have a init.vim file (e.g., when your sysadmin has one setup for you), you can edit it this way: > :edit $MYVIMRC @@ -56,80 +56,32 @@ This chapter only explains the most basic items. For more information on how to write a Vim script file: |usr_41.txt|. ============================================================================== -*05.2* The example vimrc file explained *vimrc_example.vim* +*05.2* Example vimrc contents *vimrc_example.vim* In the first chapter was explained how to create a vimrc file. > :exe 'edit' stdpath('config').'/init.vim' -In this section we will explain the various commands used in this file. This -will give you hints about how to set up your own preferences. Not everything -will be explained though. Use the ":help" command to find out more. - -> - set backspace=indent,eol,start - -This specifies where in Insert mode the is allowed to delete the -character in front of the cursor. The three items, separated by commas, tell -Vim to delete the white space at the start of the line, a line break and the -character before where Insert mode started. -> - - set autoindent - -This makes Vim use the indent of the previous line for a newly created line. -Thus there is the same amount of white space before the new line. For example -when pressing in Insert mode, and when using the "o" command to open a -new line. +In this section we will explain the various commands that can be specified in +this file. This will give you hints about how to set up your own preferences. +Not everything will be explained though. Use the ":help" command to find out +more. > - set backup This tells Vim to keep a backup copy of a file when overwriting it. The backup file will have the same name as the original file with "~" added. See |07.4| > - set history=50 - +< Keep 50 commands and 50 search patterns in the history. Use another number if you want to remember fewer or more lines. -> - - set ruler - -Always display the current cursor position in the lower right corner of the -Vim window. - -> - set showcmd - -Display an incomplete command in the lower right corner of the Vim window, -left of the ruler. For example, when you type "2f", Vim is waiting for you to -type the character to find and "2f" is displayed. When you press "w" next, -the "2fw" command is executed and the displayed "2f" is removed. -> - +-------------------------------------------------+ - |text in the Vim window | - |~ | - |~ | - |-- VISUAL -- 2f 43,8 17% | - +-------------------------------------------------+ - ^^^^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^ - 'showmode' 'showcmd' 'ruler' - -> - set incsearch -< -Display matches for a search pattern while you type. - > map Q gq This defines a key mapping. More about that in the next section. This -defines the "Q" command to do formatting with the "gq" operator. This is how -it worked before Vim 5.0. Otherwise the "Q" command repeats the last recorded -register. - +defines the "Q" command to do formatting with the "gq" operator. Otherwise the +"Q" command repeats the last recorded register. > vnoremap _g y:exe "grep /" .. escape(@", '\\/') .. "/ *.c *.h" @@ -138,14 +90,8 @@ This is a complicated mapping. You can see that mappings can be used to do quite complicated things. Still, it is just a sequence of commands that are executed like you typed them. + *vimrc-filetype* > - set hlsearch - -This option tells Vim to highlight matches with the last used search pattern. -The "if" command is very useful to set options only when some condition is -met. More about that in |usr_41.txt|. - - *vimrc-filetype* > filetype plugin indent on This switches on three very clever mechanisms: @@ -342,7 +288,7 @@ That's all! Now you can use the commands defined in this plugin. Instead of putting plugins directly into the plugin/ directory, you may better organize them by putting them into subdirectories under plugin/. -As an example, consider using "~/.local/share/nvim/site/plugin/perl/*.vim" for +As an example, consider using "~/.local/share/nvim/site/plugin/perl/*.vim" for all your Perl plugins. -- cgit From 66c384d4e806a5e8de53bc57a05f0ddd8c8a9d1c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 28 Feb 2023 09:34:27 +0100 Subject: vim-patch:partial:dd60c365cd26 (#22437) vim-patch:partial:dd60c365cd26 Update runtime files https://github.com/vim/vim/commit/dd60c365cd2630794be84d63c4fe287124a30b97 Co-authored-by: Bram Moolenaar Skip: eval.txt, repeat.txt (needs `getscriptinfo()`) --- runtime/autoload/python.vim | 9 +- runtime/doc/builtin.txt | 5 +- runtime/doc/change.txt | 6 +- runtime/doc/map.txt | 6 +- runtime/doc/sign.txt | 12 +- runtime/doc/syntax.txt | 20 ++- runtime/ftplugin/quarto.vim | 1 + runtime/ftplugin/r.vim | 4 +- runtime/ftplugin/rhelp.vim | 4 +- runtime/ftplugin/rmd.vim | 21 ++- runtime/ftplugin/rnoweb.vim | 21 ++- runtime/ftplugin/rrst.vim | 4 +- runtime/indent/quarto.vim | 1 + runtime/indent/r.vim | 14 +- runtime/indent/rhelp.vim | 4 +- runtime/indent/rmd.vim | 6 +- runtime/indent/rnoweb.vim | 4 +- runtime/indent/rrst.vim | 4 +- runtime/plugin/matchparen.vim | 5 +- runtime/syntax/python.vim | 20 ++- runtime/syntax/python2.vim | 345 ++++++++++++++++++++++++++++++++++++++++++ runtime/syntax/quarto.vim | 17 +++ runtime/syntax/r.vim | 48 +++--- runtime/syntax/rmd.vim | 209 ++++++++++++++----------- runtime/syntax/sh.vim | 11 +- 25 files changed, 635 insertions(+), 166 deletions(-) create mode 100644 runtime/ftplugin/quarto.vim create mode 100644 runtime/indent/quarto.vim create mode 100644 runtime/syntax/python2.vim create mode 100644 runtime/syntax/quarto.vim (limited to 'runtime') diff --git a/runtime/autoload/python.vim b/runtime/autoload/python.vim index 1eaad09ef5..d5f4862363 100644 --- a/runtime/autoload/python.vim +++ b/runtime/autoload/python.vim @@ -22,8 +22,7 @@ let s:maxoff = 50 " maximum number of lines to look backwards for () function s:SearchBracket(fromlnum, flags) return searchpairpos('[[({]', '', '[])}]', a:flags, \ {-> synstack('.', col('.')) - \ ->map({_, id -> id->synIDattr('name')}) - \ ->match('\%(Comment\|Todo\|String\)$') >= 0}, + \ ->indexof({_, id -> synIDattr(id, 'name') =~ '\%(Comment\|Todo\|String\)$'}) >= 0}, \ [0, a:fromlnum - s:maxoff]->max(), g:python_indent.searchpair_timeout) endfunction @@ -157,15 +156,13 @@ function python#GetIndent(lnum, ...) " the start of the comment. synID() is slow, a linear search would take " too long on a long line. if synstack(plnum, pline_len) - \ ->map({_, id -> id->synIDattr('name')}) - \ ->match('\%(Comment\|Todo\)$') >= 0 + \ ->indexof({_, id -> synIDattr(id, 'name') =~ '\%(Comment\|Todo\)$'}) >= 0 let min = 1 let max = pline_len while min < max let col = (min + max) / 2 if synstack(plnum, col) - \ ->map({_, id -> id->synIDattr('name')}) - \ ->match('\%(Comment\|Todo\)$') >= 0 + \ ->indexof({_, id -> synIDattr(id, 'name') =~ '\%(Comment\|Todo\)$'}) >= 0 let max = col else let min = col + 1 diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 3ff4e47a45..b74e30db09 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2126,8 +2126,7 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()* extendnew({expr1}, {expr2} [, {expr3}]) *extendnew()* Like |extend()| but instead of adding items to {expr1} a new List or Dictionary is created and returned. {expr1} remains - unchanged. Items can still be changed by {expr2}, if you - don't want that use |deepcopy()| first. + unchanged. feedkeys({string} [, {mode}]) *feedkeys()* @@ -8725,6 +8724,8 @@ timer_start({time}, {callback} [, {options}]) {time} is the waiting time in milliseconds. This is the minimum time before invoking the callback. When the system is busy or Vim is not waiting for input the time will be longer. + Zero can be used to execute the callback when Vim is back in + the main loop. {callback} is the function to call. It can be the name of a function or a |Funcref|. It is called with one argument, which diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 990ba3d8fd..2cebd8abdd 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -276,7 +276,9 @@ gr{char} Replace the virtual characters under the cursor with {char}. This replaces in screen space, not file space. See |gR| and |Virtual-Replace-mode| for more details. As with |r| a count may be given. - {char} can be entered like with |r|. + {char} can be entered like with |r|, but characters + that have a special meaning in Insert mode, such as + most CTRL-keys, cannot be used. *digraph-arg* The argument for Normal mode commands like |r| and |t| is a single character. @@ -976,7 +978,7 @@ inside of strings can change! Also see 'softtabstop' option. > < to display registers '1' and 'a'. Spaces are allowed in {arg}. - *:di* *:display* + *:di* *:dis* *:display* :di[splay] [arg] Same as :registers. *y* *yank* diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index ad0570e9f7..3a5223fa3a 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1205,12 +1205,14 @@ functions used in one script use the same name as in other scripts. To avoid this, they can be made local to the script. ** ** *E81* -The string "" can be used in a mapping or menu. +The string "" can be used in a mapping or menu. This is useful if you +have a script-local function that you want to call from a mapping in the same +script. When executing the map command, Vim will replace "" with the special key code , followed by a number that's unique for the script, and an underscore. Example: > :map Add -could define a mapping "23_Add". +would define a mapping "23_Add". When defining a function in a script, "s:" can be prepended to the name to make it local to the script. But when a mapping is executed from outside of diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 53ef03eb63..162bdaed7b 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -595,23 +595,23 @@ sign_placelist({list}) |sign_place()| function. The {list} argument specifies the List of signs to place. Each list item is a dict with the following sign attributes: - buffer buffer name or number. For the accepted + buffer Buffer name or number. For the accepted values, see |bufname()|. - group sign group. {group} functions as a namespace + group Sign group. {group} functions as a namespace for {id}, thus two groups can use the same IDs. If not specified or set to an empty string, then the global group is used. See |sign-group| for more information. - id sign identifier. If not specified or zero, + id Sign identifier. If not specified or zero, then a new unique identifier is allocated. Otherwise the specified number is used. See |sign-identifier| for more information. - lnum line number in the buffer where the sign is to + lnum Line number in the buffer where the sign is to be placed. For the accepted values, see |line()|. - name name of the sign to place. See |sign_define()| + name Name of the sign to place. See |sign_define()| for more information. - priority priority of the sign. When multiple signs are + priority Priority of the sign. When multiple signs are placed on a line, the sign with the highest priority is used. If not specified, the default value of 10 is used. See diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 7102e93f0a..68d059be82 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -2756,17 +2756,25 @@ For highlighted doctests and code inside: > :let python_no_doctest_highlight = 1 or > :let python_no_doctest_code_highlight = 1 -(first option implies second one). +The first option implies the second one. For highlighted trailing whitespace and mix of spaces and tabs: > :let python_space_error_highlight = 1 -If you want all possible Python highlighting (the same as setting the -preceding last option and unsetting all other ones): > +If you want all possible Python highlighting: > :let python_highlight_all = 1 +This has the same effect as setting python_space_error_highlight and +unsetting all the other ones. + +If you use Python 2 or straddling code (Python 2 and 3 compatible), +you can enforce the use of an older syntax file with support for +Python 2 and up to Python 3.5. > + : let python_use_python2_syntax = 1 +This option will exclude all modern Python 3.6 or higher features. + +Note: Only existence of these options matters, not their value. + You can replace 1 above with anything. -Note: Only existence of these options matter, not their value. You can replace - 1 above with anything. QUAKE *quake.vim* *ft-quake-syntax* @@ -5179,7 +5187,7 @@ Conceal Placeholder characters substituted for concealed *hl-CurSearch* CurSearch Used for highlighting a search pattern under the cursor (see 'hlsearch'). - *hl-Cursor* + *hl-Cursor* *hl-lCursor* Cursor Character under the cursor. lCursor Character under the cursor when |language-mapping| is used (see 'guicursor'). diff --git a/runtime/ftplugin/quarto.vim b/runtime/ftplugin/quarto.vim new file mode 100644 index 0000000000..a76bcc2c7e --- /dev/null +++ b/runtime/ftplugin/quarto.vim @@ -0,0 +1 @@ +runtime ftplugin/rmd.vim diff --git a/runtime/ftplugin/r.vim b/runtime/ftplugin/r.vim index a78afa2e7e..28966368cb 100644 --- a/runtime/ftplugin/r.vim +++ b/runtime/ftplugin/r.vim @@ -2,7 +2,7 @@ " Language: R " Maintainer: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Aug 15, 2020 11:37AM +" Last Change: Sun Apr 24, 2022 09:14AM " Only do this when not yet done for this buffer if exists("b:did_ftplugin") @@ -22,7 +22,7 @@ setlocal comments=:#',:###,:##,:# if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") let b:browsefilter = "R Source Files (*.R)\t*.R\n" . - \ "Files that include R (*.Rnw *.Rd *.Rmd *.Rrst)\t*.Rnw;*.Rd;*.Rmd;*.Rrst\n" . + \ "Files that include R (*.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" . \ "All Files (*.*)\t*.*\n" endif diff --git a/runtime/ftplugin/rhelp.vim b/runtime/ftplugin/rhelp.vim index d0b546d62d..2fde4875c6 100644 --- a/runtime/ftplugin/rhelp.vim +++ b/runtime/ftplugin/rhelp.vim @@ -2,7 +2,7 @@ " Language: R help file " Maintainer: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Aug 15, 2020 12:01PM +" Last Change: Sun Apr 24, 2022 09:12AM " Only do this when not yet done for this buffer if exists("b:did_ftplugin") @@ -18,7 +18,7 @@ set cpo&vim setlocal iskeyword=@,48-57,_,. if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") - let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst\n" . + let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" . \ "All Files (*.*)\t*.*\n" endif diff --git a/runtime/ftplugin/rmd.vim b/runtime/ftplugin/rmd.vim index 2ee72ffc6c..355b88f04a 100644 --- a/runtime/ftplugin/rmd.vim +++ b/runtime/ftplugin/rmd.vim @@ -2,7 +2,7 @@ " Language: R Markdown file " Maintainer: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Aug 15, 2020 12:03PM +" Last Change: Sun Apr 24, 2022 09:12AM " Original work by Alex Zvoleff (adjusted from R help for rmd by Michel Kuhlmann) " Only do this when not yet done for this buffer @@ -32,13 +32,24 @@ function! FormatRmd() return 1 endfunction -" If you do not want 'comments' dynamically defined, put in your vimrc: -" let g:rmd_dynamic_comments = 0 +function! SetRmdCommentStr() + if (search("^[ \t]*```[ ]*{r", "bncW") > search("^[ \t]*```$", "bncW")) || ((search('^---$', 'Wn') || search('^\.\.\.$', 'Wn')) && search('^---$', 'bnW')) + set commentstring=#\ %s + else + set commentstring= + endif +endfunction + +" If you do not want both 'comments' and 'commentstring' dynamically defined, +" put in your vimrc: let g:rmd_dynamic_comments = 0 if !exists("g:rmd_dynamic_comments") || (exists("g:rmd_dynamic_comments") && g:rmd_dynamic_comments == 1) setlocal formatexpr=FormatRmd() + augroup RmdCStr + autocmd! + autocmd CursorMoved call SetRmdCommentStr() + augroup END endif - " Enables pandoc if it is installed unlet! b:did_ftplugin runtime ftplugin/pandoc.vim @@ -47,7 +58,7 @@ runtime ftplugin/pandoc.vim let b:did_ftplugin = 1 if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") - let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst\n" . + let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" . \ "All Files (*.*)\t*.*\n" endif diff --git a/runtime/ftplugin/rnoweb.vim b/runtime/ftplugin/rnoweb.vim index dc5f1b5e06..cf1c0922c0 100644 --- a/runtime/ftplugin/rnoweb.vim +++ b/runtime/ftplugin/rnoweb.vim @@ -2,7 +2,7 @@ " Language: Rnoweb " Maintainer: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Aug 15, 2020 12:02PM +" Last Change: Sun Apr 24, 2022 09:13AM " Only do this when not yet done for this buffer if exists("b:did_ftplugin") @@ -25,10 +25,27 @@ setlocal suffixesadd=.bib,.tex setlocal comments=b:%,b:#,b:##,b:###,b:#' if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") - let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst\n" . + let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" . \ "All Files (*.*)\t*.*\n" endif +function! SetRnwCommentStr() + if (search("^\s*<<.*>>=", "bncW") > search("^@", "bncW")) + set commentstring=#\ %s + else + set commentstring=%\ %s + endif +endfunction + +" If you do not want both 'comments' and 'commentstring' dynamically defined, +" put in your vimrc: let g:rnw_dynamic_comments = 0 +if !exists("g:rnw_dynamic_comments") || (exists("g:rnw_dynamic_comments") && g:rnw_dynamic_comments == 1) + augroup RnwCStr + autocmd! + autocmd CursorMoved call SetRnwCommentStr() + augroup END +endif + if exists('b:undo_ftplugin') let b:undo_ftplugin .= " | setl isk< sua< com< | unlet! b:browsefilter" else diff --git a/runtime/ftplugin/rrst.vim b/runtime/ftplugin/rrst.vim index a56fd6478e..19c67c4cc2 100644 --- a/runtime/ftplugin/rrst.vim +++ b/runtime/ftplugin/rrst.vim @@ -2,7 +2,7 @@ " Language: reStructuredText documentation format with R code " Maintainer: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sat Aug 15, 2020 12:02PM +" Last Change: Sun Apr 24, 2022 09:13AM " Original work by Alex Zvoleff " Only do this when not yet done for this buffer @@ -38,7 +38,7 @@ if !exists("g:rrst_dynamic_comments") || (exists("g:rrst_dynamic_comments") && g endif if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") - let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst\n" . + let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" . \ "All Files (*.*)\t*.*\n" endif diff --git a/runtime/indent/quarto.vim b/runtime/indent/quarto.vim new file mode 100644 index 0000000000..586d232d2b --- /dev/null +++ b/runtime/indent/quarto.vim @@ -0,0 +1 @@ +runtime indent/rmd.vim diff --git a/runtime/indent/r.vim b/runtime/indent/r.vim index ca85a2e62d..293dd98175 100644 --- a/runtime/indent/r.vim +++ b/runtime/indent/r.vim @@ -2,7 +2,7 @@ " Language: R " Author: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sun Aug 19, 2018 09:13PM +" Last Change: Wed Oct 26, 2022 12:04PM " Only load this indent file when no other was loaded. @@ -14,6 +14,8 @@ let b:did_indent = 1 setlocal indentkeys=0{,0},:,!^F,o,O,e setlocal indentexpr=GetRIndent() +let b:undo_indent = "setl inde< indk<" + " Only define the function once. if exists("*GetRIndent") finish @@ -28,7 +30,7 @@ let g:r_indent_ess_comments = get(g:, 'r_indent_ess_comments', 0) let g:r_indent_comment_column = get(g:, 'r_indent_comment_column', 40) let g:r_indent_ess_compatible = get(g:, 'r_indent_ess_compatible', 0) let g:r_indent_op_pattern = get(g:, 'r_indent_op_pattern', - \ '\(&\||\|+\|-\|\*\|/\|=\|\~\|%\|->\)\s*$') + \ '\(&\||\|+\|-\|\*\|/\|=\|\~\|%\|->\||>\)\s*$') function s:RDelete_quotes(line) let i = 0 @@ -359,17 +361,19 @@ function GetRIndent() let olnum = s:Get_prev_line(lnum) let oline = getline(olnum) if olnum > 0 - if line =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 - if oline =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 + if substitute(line, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 + if substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 return indent(lnum) else return indent(lnum) + shiftwidth() endif else - if oline =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 + if substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 return indent(lnum) - shiftwidth() endif endif + elseif substitute(line, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0 + return indent(lnum) + shiftwidth() endif let post_fun = 0 diff --git a/runtime/indent/rhelp.vim b/runtime/indent/rhelp.vim index cf69ae3392..2b9d49b915 100644 --- a/runtime/indent/rhelp.vim +++ b/runtime/indent/rhelp.vim @@ -2,7 +2,7 @@ " Language: R Documentation (Help), *.Rd " Author: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Tue Apr 07, 2015 04:38PM +" Last Change: Feb 25, 2023 " Only load this indent file when no other was loaded. @@ -20,6 +20,8 @@ setlocal nolisp setlocal indentkeys=0{,0},:,!^F,o,O,e setlocal indentexpr=GetCorrectRHelpIndent() +let b:undo_indent = "setl ai< cin< inde< indk< lisp< si<" + " Only define the functions once. if exists("*GetRHelpIndent") finish diff --git a/runtime/indent/rmd.vim b/runtime/indent/rmd.vim index 8fd57257fa..a043b0c994 100644 --- a/runtime/indent/rmd.vim +++ b/runtime/indent/rmd.vim @@ -2,7 +2,7 @@ " Language: Rmd " Author: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sun Mar 28, 2021 08:05PM +" Last Change: Wed Nov 09, 2022 09:44PM " Only load this indent file when no other was loaded. @@ -16,6 +16,8 @@ let b:did_indent = 1 setlocal indentkeys=0{,0},<:>,!^F,o,O,e setlocal indentexpr=GetRmdIndent() +let b:undo_indent = "setl inde< indk<" + if exists("*GetRmdIndent") finish endif @@ -47,6 +49,8 @@ function s:GetMdIndent() return indent(v:lnum - 1) + 2 elseif pline =~ '^\s*\d\+\.\s\+' return indent(v:lnum - 1) + 3 + elseif pline =~ '^\[\^\S\+\]: ' + return indent(v:lnum - 1) + shiftwidth() endif return indent(prevnonblank(v:lnum - 1)) endfunction diff --git a/runtime/indent/rnoweb.vim b/runtime/indent/rnoweb.vim index 73966868b8..33bc103d18 100644 --- a/runtime/indent/rnoweb.vim +++ b/runtime/indent/rnoweb.vim @@ -2,7 +2,7 @@ " Language: Rnoweb " Author: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Fri Apr 15, 2016 10:58PM +" Last Change: Feb 25, 2023 " Only load this indent file when no other was loaded. @@ -29,6 +29,8 @@ let b:did_indent = 1 setlocal indentkeys=0{,0},!^F,o,O,e,},=\bibitem,=\item setlocal indentexpr=GetRnowebIndent() +let b:undo_indent = "setl inde< indk<" + if exists("*GetRnowebIndent") finish endif diff --git a/runtime/indent/rrst.vim b/runtime/indent/rrst.vim index f3ee53e7fb..585c5e6654 100644 --- a/runtime/indent/rrst.vim +++ b/runtime/indent/rrst.vim @@ -2,7 +2,7 @@ " Language: Rrst " Author: Jakson Alves de Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Tue Apr 07, 2015 04:38PM +" Last Change: Feb 25, 2023 " Only load this indent file when no other was loaded. @@ -16,6 +16,8 @@ let b:did_indent = 1 setlocal indentkeys=0{,0},:,!^F,o,O,e setlocal indentexpr=GetRrstIndent() +let b:undo_indent = "setl inde< indk<" + if exists("*GetRrstIndent") finish endif diff --git a/runtime/plugin/matchparen.vim b/runtime/plugin/matchparen.vim index 3982489b92..e19b283228 100644 --- a/runtime/plugin/matchparen.vim +++ b/runtime/plugin/matchparen.vim @@ -108,8 +108,9 @@ func s:Highlight_Matching_Pair() " searchpairpos()'s skip argument. " We match "escape" for special items, such as lispEscapeSpecial, and " match "symbol" for lispBarSymbol. - let s_skip = '!empty(filter(map(synstack(line("."), col(".")), ''synIDattr(v:val, "name")''), ' . - \ '''v:val =~? "string\\|character\\|singlequote\\|escape\\|symbol\\|comment"''))' + let s_skip = 'synstack(".", col("."))' + \ . '->indexof({_, id -> synIDattr(id, "name") =~? ' + \ . '"string\\|character\\|singlequote\\|escape\\|symbol\\|comment"}) >= 0' " If executing the expression determines that the cursor is currently in " one of the syntax types, then we want searchpairpos() to find the pair " within those syntax types (i.e., not skip). Otherwise, the cursor is diff --git a/runtime/syntax/python.vim b/runtime/syntax/python.vim index ef4da1b448..831fb92f4c 100644 --- a/runtime/syntax/python.vim +++ b/runtime/syntax/python.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Python " Maintainer: Zvezdan Petkovic -" Last Change: 2022 Jun 28 +" Last Change: 2023 Feb 26 " Credits: Neil Schemenauer " Dmitry Vasiliev " @@ -35,12 +35,26 @@ " " let python_highlight_all = 1 " +" The use of Python 2 compatible syntax highlighting can be enforced. +" The straddling code (Python 2 and 3 compatible), up to Python 3.5, +" will be also supported. +" +" let python_use_python2_syntax = 1 +" +" This option will exclude all modern Python 3.6 or higher features. +" " quit when a syntax file was already loaded. if exists("b:current_syntax") finish endif +" Use of Python 2 and 3.5 or lower requested. +if exists("python_use_python2_syntax") + runtime! syntax/python2.vim + finish +endif + " We need nocompatible mode in order to continue lines with backslashes. " Original setting will be restored. let s:cpo_save = &cpo @@ -91,8 +105,8 @@ syn keyword pythonInclude from import syn keyword pythonAsync async await " Soft keywords -" These keywords do not mean anything unless used in the right context -" See https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords +" These keywords do not mean anything unless used in the right context. +" See https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords " for more on this. syn match pythonConditional "^\s*\zscase\%(\s\+.*:.*$\)\@=" syn match pythonConditional "^\s*\zsmatch\%(\s\+.*:\s*\%(#.*\)\=$\)\@=" diff --git a/runtime/syntax/python2.vim b/runtime/syntax/python2.vim new file mode 100644 index 0000000000..3b30eabbae --- /dev/null +++ b/runtime/syntax/python2.vim @@ -0,0 +1,345 @@ +" Vim syntax file +" Language: Python 2 +" Maintainer: Zvezdan Petkovic +" Last Change: 2016 Oct 29 +" Credits: Neil Schemenauer +" Dmitry Vasiliev +" +" This version is a major rewrite by Zvezdan Petkovic. +" +" - introduced highlighting of doctests +" - updated keywords, built-ins, and exceptions +" - corrected regular expressions for +" +" * functions +" * decorators +" * strings +" * escapes +" * numbers +" * space error +" +" - corrected synchronization +" - more highlighting is ON by default, except +" - space error highlighting is OFF by default +" +" Optional highlighting can be controlled using these variables. +" +" let python_no_builtin_highlight = 1 +" let python_no_doctest_code_highlight = 1 +" let python_no_doctest_highlight = 1 +" let python_no_exception_highlight = 1 +" let python_no_number_highlight = 1 +" let python_space_error_highlight = 1 +" +" All the options above can be switched on together. +" +" let python_highlight_all = 1 +" +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" NOTE: This file is a copy of the last commit of runtime/syntax/python.vim +" that still supported Python 2. There is support for Python 3, up to 3.5, +" and it was kept in the file as is, because it supports the straddling code +" (Python 2 and 3 compatible) better. +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +" quit when a syntax file was already loaded. +if exists("b:current_syntax") + finish +endif + +" We need nocompatible mode in order to continue lines with backslashes. +" Original setting will be restored. +let s:cpo_save = &cpo +set cpo&vim + +if exists("python_no_doctest_highlight") + let python_no_doctest_code_highlight = 1 +endif + +if exists("python_highlight_all") + if exists("python_no_builtin_highlight") + unlet python_no_builtin_highlight + endif + if exists("python_no_doctest_code_highlight") + unlet python_no_doctest_code_highlight + endif + if exists("python_no_doctest_highlight") + unlet python_no_doctest_highlight + endif + if exists("python_no_exception_highlight") + unlet python_no_exception_highlight + endif + if exists("python_no_number_highlight") + unlet python_no_number_highlight + endif + let python_space_error_highlight = 1 +endif + +" Keep Python keywords in alphabetical order inside groups for easy +" comparison with the table in the 'Python Language Reference' +" https://docs.python.org/2/reference/lexical_analysis.html#keywords, +" https://docs.python.org/3/reference/lexical_analysis.html#keywords. +" Groups are in the order presented in NAMING CONVENTIONS in syntax.txt. +" Exceptions come last at the end of each group (class and def below). +" +" Keywords 'with' and 'as' are new in Python 2.6 +" (use 'from __future__ import with_statement' in Python 2.5). +" +" Some compromises had to be made to support both Python 3 and 2. +" We include Python 3 features, but when a definition is duplicated, +" the last definition takes precedence. +" +" - 'False', 'None', and 'True' are keywords in Python 3 but they are +" built-ins in 2 and will be highlighted as built-ins below. +" - 'exec' is a built-in in Python 3 and will be highlighted as +" built-in below. +" - 'nonlocal' is a keyword in Python 3 and will be highlighted. +" - 'print' is a built-in in Python 3 and will be highlighted as +" built-in below (use 'from __future__ import print_function' in 2) +" - async and await were added in Python 3.5 and are soft keywords. +" +syn keyword pythonStatement False None True +syn keyword pythonStatement as assert break continue del exec global +syn keyword pythonStatement lambda nonlocal pass print return with yield +syn keyword pythonStatement class def nextgroup=pythonFunction skipwhite +syn keyword pythonConditional elif else if +syn keyword pythonRepeat for while +syn keyword pythonOperator and in is not or +syn keyword pythonException except finally raise try +syn keyword pythonInclude from import +syn keyword pythonAsync async await + +" Decorators (new in Python 2.4) +" A dot must be allowed because of @MyClass.myfunc decorators. +syn match pythonDecorator "@" display contained +syn match pythonDecoratorName "@\s*\h\%(\w\|\.\)*" display contains=pythonDecorator + +" Python 3.5 introduced the use of the same symbol for matrix multiplication: +" https://www.python.org/dev/peps/pep-0465/. We now have to exclude the +" symbol from highlighting when used in that context. +" Single line multiplication. +syn match pythonMatrixMultiply + \ "\%(\w\|[])]\)\s*@" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent +" Multiplication continued on the next line after backslash. +syn match pythonMatrixMultiply + \ "[^\\]\\\s*\n\%(\s*\.\.\.\s\)\=\s\+@" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent +" Multiplication in a parenthesized expression over multiple lines with @ at +" the start of each continued line; very similar to decorators and complex. +syn match pythonMatrixMultiply + \ "^\s*\%(\%(>>>\|\.\.\.\)\s\+\)\=\zs\%(\h\|\%(\h\|[[(]\).\{-}\%(\w\|[])]\)\)\s*\n\%(\s*\.\.\.\s\)\=\s\+@\%(.\{-}\n\%(\s*\.\.\.\s\)\=\s\+@\)*" + \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue + \ transparent + +syn match pythonFunction "\h\w*" display contained + +syn match pythonComment "#.*$" contains=pythonTodo,@Spell +syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained + +" Triple-quoted strings can contain doctests. +syn region pythonString matchgroup=pythonQuotes + \ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1" + \ contains=pythonEscape,@Spell +syn region pythonString matchgroup=pythonTripleQuotes + \ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend + \ contains=pythonEscape,pythonSpaceError,pythonDoctest,@Spell +syn region pythonRawString matchgroup=pythonQuotes + \ start=+[uU]\=[rR]\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1" + \ contains=@Spell +syn region pythonRawString matchgroup=pythonTripleQuotes + \ start=+[uU]\=[rR]\z('''\|"""\)+ end="\z1" keepend + \ contains=pythonSpaceError,pythonDoctest,@Spell + +syn match pythonEscape +\\[abfnrtv'"\\]+ contained +syn match pythonEscape "\\\o\{1,3}" contained +syn match pythonEscape "\\x\x\{2}" contained +syn match pythonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained +" Python allows case-insensitive Unicode IDs: http://www.unicode.org/charts/ +syn match pythonEscape "\\N{\a\+\%(\s\a\+\)*}" contained +syn match pythonEscape "\\$" + +" It is very important to understand all details before changing the +" regular expressions below or their order. +" The word boundaries are *not* the floating-point number boundaries +" because of a possible leading or trailing decimal point. +" The expressions below ensure that all valid number literals are +" highlighted, and invalid number literals are not. For example, +" +" - a decimal point in '4.' at the end of a line is highlighted, +" - a second dot in 1.0.0 is not highlighted, +" - 08 is not highlighted, +" - 08e0 or 08j are highlighted, +" +" and so on, as specified in the 'Python Language Reference'. +" https://docs.python.org/2/reference/lexical_analysis.html#numeric-literals +" https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals +if !exists("python_no_number_highlight") + " numbers (including longs and complex) + syn match pythonNumber "\<0[oO]\=\o\+[Ll]\=\>" + syn match pythonNumber "\<0[xX]\x\+[Ll]\=\>" + syn match pythonNumber "\<0[bB][01]\+[Ll]\=\>" + syn match pythonNumber "\<\%([1-9]\d*\|0\)[Ll]\=\>" + syn match pythonNumber "\<\d\+[jJ]\>" + syn match pythonNumber "\<\d\+[eE][+-]\=\d\+[jJ]\=\>" + syn match pythonNumber + \ "\<\d\+\.\%([eE][+-]\=\d\+\)\=[jJ]\=\%(\W\|$\)\@=" + syn match pythonNumber + \ "\%(^\|\W\)\zs\d*\.\d\+\%([eE][+-]\=\d\+\)\=[jJ]\=\>" +endif + +" Group the built-ins in the order in the 'Python Library Reference' for +" easier comparison. +" https://docs.python.org/2/library/constants.html +" https://docs.python.org/3/library/constants.html +" http://docs.python.org/2/library/functions.html +" http://docs.python.org/3/library/functions.html +" http://docs.python.org/2/library/functions.html#non-essential-built-in-functions +" http://docs.python.org/3/library/functions.html#non-essential-built-in-functions +" Python built-in functions are in alphabetical order. +if !exists("python_no_builtin_highlight") + " built-in constants + " 'False', 'True', and 'None' are also reserved words in Python 3 + syn keyword pythonBuiltin False True None + syn keyword pythonBuiltin NotImplemented Ellipsis __debug__ + " built-in functions + syn keyword pythonBuiltin abs all any bin bool bytearray callable chr + syn keyword pythonBuiltin classmethod compile complex delattr dict dir + syn keyword pythonBuiltin divmod enumerate eval filter float format + syn keyword pythonBuiltin frozenset getattr globals hasattr hash + syn keyword pythonBuiltin help hex id input int isinstance + syn keyword pythonBuiltin issubclass iter len list locals map max + syn keyword pythonBuiltin memoryview min next object oct open ord pow + syn keyword pythonBuiltin print property range repr reversed round set + syn keyword pythonBuiltin setattr slice sorted staticmethod str + syn keyword pythonBuiltin sum super tuple type vars zip __import__ + " Python 2 only + syn keyword pythonBuiltin basestring cmp execfile file + syn keyword pythonBuiltin long raw_input reduce reload unichr + syn keyword pythonBuiltin unicode xrange + " Python 3 only + syn keyword pythonBuiltin ascii bytes exec + " non-essential built-in functions; Python 2 only + syn keyword pythonBuiltin apply buffer coerce intern + " avoid highlighting attributes as builtins + syn match pythonAttribute /\.\h\w*/hs=s+1 + \ contains=ALLBUT,pythonBuiltin,pythonFunction,pythonAsync + \ transparent +endif + +" From the 'Python Library Reference' class hierarchy at the bottom. +" http://docs.python.org/2/library/exceptions.html +" http://docs.python.org/3/library/exceptions.html +if !exists("python_no_exception_highlight") + " builtin base exceptions (used mostly as base classes for other exceptions) + syn keyword pythonExceptions BaseException Exception + syn keyword pythonExceptions ArithmeticError BufferError + syn keyword pythonExceptions LookupError + " builtin base exceptions removed in Python 3 + syn keyword pythonExceptions EnvironmentError StandardError + " builtin exceptions (actually raised) + syn keyword pythonExceptions AssertionError AttributeError + syn keyword pythonExceptions EOFError FloatingPointError GeneratorExit + syn keyword pythonExceptions ImportError IndentationError + syn keyword pythonExceptions IndexError KeyError KeyboardInterrupt + syn keyword pythonExceptions MemoryError NameError NotImplementedError + syn keyword pythonExceptions OSError OverflowError ReferenceError + syn keyword pythonExceptions RuntimeError StopIteration SyntaxError + syn keyword pythonExceptions SystemError SystemExit TabError TypeError + syn keyword pythonExceptions UnboundLocalError UnicodeError + syn keyword pythonExceptions UnicodeDecodeError UnicodeEncodeError + syn keyword pythonExceptions UnicodeTranslateError ValueError + syn keyword pythonExceptions ZeroDivisionError + " builtin OS exceptions in Python 3 + syn keyword pythonExceptions BlockingIOError BrokenPipeError + syn keyword pythonExceptions ChildProcessError ConnectionAbortedError + syn keyword pythonExceptions ConnectionError ConnectionRefusedError + syn keyword pythonExceptions ConnectionResetError FileExistsError + syn keyword pythonExceptions FileNotFoundError InterruptedError + syn keyword pythonExceptions IsADirectoryError NotADirectoryError + syn keyword pythonExceptions PermissionError ProcessLookupError + syn keyword pythonExceptions RecursionError StopAsyncIteration + syn keyword pythonExceptions TimeoutError + " builtin exceptions deprecated/removed in Python 3 + syn keyword pythonExceptions IOError VMSError WindowsError + " builtin warnings + syn keyword pythonExceptions BytesWarning DeprecationWarning FutureWarning + syn keyword pythonExceptions ImportWarning PendingDeprecationWarning + syn keyword pythonExceptions RuntimeWarning SyntaxWarning UnicodeWarning + syn keyword pythonExceptions UserWarning Warning + " builtin warnings in Python 3 + syn keyword pythonExceptions ResourceWarning +endif + +if exists("python_space_error_highlight") + " trailing whitespace + syn match pythonSpaceError display excludenl "\s\+$" + " mixed tabs and spaces + syn match pythonSpaceError display " \+\t" + syn match pythonSpaceError display "\t\+ " +endif + +" Do not spell doctests inside strings. +" Notice that the end of a string, either ''', or """, will end the contained +" doctest too. Thus, we do *not* need to have it as an end pattern. +if !exists("python_no_doctest_highlight") + if !exists("python_no_doctest_code_highlight") + syn region pythonDoctest + \ start="^\s*>>>\s" end="^\s*$" + \ contained contains=ALLBUT,pythonDoctest,pythonFunction,@Spell + syn region pythonDoctestValue + \ start=+^\s*\%(>>>\s\|\.\.\.\s\|"""\|'''\)\@!\S\++ end="$" + \ contained + else + syn region pythonDoctest + \ start="^\s*>>>" end="^\s*$" + \ contained contains=@NoSpell + endif +endif + +" Sync at the beginning of class, function, or method definition. +syn sync match pythonSync grouphere NONE "^\%(def\|class\)\s\+\h\w*\s*[(:]" + +" The default highlight links. Can be overridden later. +hi def link pythonStatement Statement +hi def link pythonConditional Conditional +hi def link pythonRepeat Repeat +hi def link pythonOperator Operator +hi def link pythonException Exception +hi def link pythonInclude Include +hi def link pythonAsync Statement +hi def link pythonDecorator Define +hi def link pythonDecoratorName Function +hi def link pythonFunction Function +hi def link pythonComment Comment +hi def link pythonTodo Todo +hi def link pythonString String +hi def link pythonRawString String +hi def link pythonQuotes String +hi def link pythonTripleQuotes pythonQuotes +hi def link pythonEscape Special +if !exists("python_no_number_highlight") + hi def link pythonNumber Number +endif +if !exists("python_no_builtin_highlight") + hi def link pythonBuiltin Function +endif +if !exists("python_no_exception_highlight") + hi def link pythonExceptions Structure +endif +if exists("python_space_error_highlight") + hi def link pythonSpaceError Error +endif +if !exists("python_no_doctest_highlight") + hi def link pythonDoctest Special + hi def link pythonDoctestValue Define +endif + +let b:current_syntax = "python" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 noet: diff --git a/runtime/syntax/quarto.vim b/runtime/syntax/quarto.vim new file mode 100644 index 0000000000..d5d4ee257d --- /dev/null +++ b/runtime/syntax/quarto.vim @@ -0,0 +1,17 @@ +" Language: Quarto (Markdown with chunks of R, Python and other languages) +" Provisory Maintainer: Jakson Aquino +" Homepage: https://github.com/jalvesaq/R-Vim-runtime +" Last Change: Fri Feb 24, 2023 08:26AM +" +" The developers of tools for Quarto maintain Vim runtime files in their +" Github repository and, if required, I will hand over the maintenance of +" this script for them. + +runtime syntax/rmd.vim + +syn match quartoShortarg /\S\+/ contained +syn keyword quartoShortkey var meta env pagebreak video include contained +syn region quartoShortcode matchgroup=PreProc start='{{< ' end=' >}}' contains=quartoShortkey,quartoShortarg transparent keepend + +hi def link quartoShortkey Include +hi def link quartoShortarg String diff --git a/runtime/syntax/r.vim b/runtime/syntax/r.vim index a8100cfded..9b3754ae23 100644 --- a/runtime/syntax/r.vim +++ b/runtime/syntax/r.vim @@ -5,7 +5,7 @@ " Tom Payne " Contributor: Johannes Ranke " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Sun Mar 28, 2021 01:47PM +" Last Change: Thu Nov 17, 2022 10:13PM " Filenames: *.R *.r *.Rhistory *.Rt " " NOTE: The highlighting of R functions might be defined in @@ -65,41 +65,35 @@ if g:r_syntax_hl_roxygen " roxygen line containing only a roxygen comment marker, optionally followed " by whitespace is called an empty roxygen line. + syn match rOCommentKey "^\s*#\{1,2}'" contained + syn region rOExamples start="^\s*#\{1,2}' @examples.*"rs=e+1,hs=e+1 end="^\(#\{1,2}' @.*\)\@=" end="^\(#\{1,2}'\)\@!" contained contains=rOTag fold + + " R6 classes may contain roxygen lines independent of roxygen blocks + syn region rOR6Class start=/R6Class(/ end=/)/ transparent contains=ALLBUT,rError,rBraceError,rCurlyError fold + syn match rOR6Block "#\{1,2}'.*" contains=rOTag,rOExamples,@Spell containedin=rOR6Class contained + syn match rOR6Block "^\s*#\{1,2}'.*" contains=rOTag,rOExamples,@Spell containedin=rOR6Class contained + " First we match all roxygen blocks as containing only a title. In case an " empty roxygen line ending the title or a tag is found, this will be " overridden later by the definitions of rOBlock. - syn match rOTitleBlock "\%^\(\s*#\{1,2}' .*\n\)\{1,}" contains=rOCommentKey,rOTitleTag - syn match rOTitleBlock "^\s*\n\(\s*#\{1,2}' .*\n\)\{1,}" contains=rOCommentKey,rOTitleTag + syn match rOTitleBlock "\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{1,}" contains=rOCommentKey,rOTitleTag " A title as part of a block is always at the beginning of the block, i.e. " either at the start of a file or after a completely empty line. - syn match rOTitle "\%^\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" contained contains=rOCommentKey,rOTitleTag - syn match rOTitle "^\s*\n\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" contained contains=rOCommentKey,rOTitleTag + syn match rOTitle "\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" contained contains=rOCommentKey,rOTitleTag syn match rOTitleTag contained "@title" " When a roxygen block has a title and additional content, the title " consists of one or more roxygen lines (as little as possible are matched), " followed either by an empty roxygen line - syn region rOBlock start="\%^\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold - syn region rOBlock start="^\s*\n\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold + syn region rOBlock start="\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*$" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold " or by a roxygen tag (we match everything starting with @ but not @@ which is used as escape sequence for a literal @). - syn region rOBlock start="\%^\(\s*#\{1,2}' .*\n\)\{-}\s*#\{1,2}' @\(@\)\@!" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold - syn region rOBlock start="^\s*\n\(\s*#\{1,2}' .*\n\)\{-}\s*#\{1,2}' @\(@\)\@!" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold + syn region rOBlock start="\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{-}\s*#\{1,2}' @\(@\)\@!" end="^\s*\(#\{1,2}'\)\@!" contains=rOTitle,rOTag,rOExamples,@Spell keepend fold " If a block contains an @rdname, @describeIn tag, it may have paragraph breaks, but does not have a title - syn region rOBlockNoTitle start="\%^\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @rdname" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold - syn region rOBlockNoTitle start="^\s*\n\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @rdname" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold - syn region rOBlockNoTitle start="\%^\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @describeIn" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold - syn region rOBlockNoTitle start="^\s*\n\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @describeIn" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold - - syn match rOCommentKey "^\s*#\{1,2}'" contained - syn region rOExamples start="^\s*#\{1,2}' @examples.*"rs=e+1,hs=e+1 end="^\(#\{1,2}' @.*\)\@=" end="^\(#\{1,2}'\)\@!" contained contains=rOTag fold - - " R6 classes may contain roxygen lines independent of roxygen blocks - syn region rOR6Class start=/R6Class(/ end=/)/ transparent contains=ALLBUT,rError,rBraceError,rCurlyError fold - syn match rOR6Block "#\{1,2}'.*" contains=rOTag,rOExamples,@Spell containedin=rOR6Class contained - syn match rOR6Block "^\s*#\{1,2}'.*" contains=rOTag,rOExamples,@Spell containedin=rOR6Class contained + syn region rOBlockNoTitle start="\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @rdname" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold + syn region rOBlockNoTitle start="\(\%^\|^\s*\n\)\@<=\(\s*#\{1,2}' .*\n\)\{-1,}\s*#\{1,2}'\s*\n\(\s*#\{1,2}'.*\n\)\{-}\s*#\{1,2}' @describeIn" end="^\s*\(#\{1,2}'\)\@!" contains=rOTag,rOExamples,@Spell keepend fold " rOTag list originally generated from the lists that were available in " https://github.com/klutometis/roxygen/R/rd.R and @@ -245,14 +239,15 @@ syn match rOperator "&" syn match rOperator '-' syn match rOperator '\*' syn match rOperator '+' -if &filetype != "rmd" && &filetype != "rrst" - syn match rOperator "[|!<>^~/:]" -else +if &filetype == "quarto" || &filetype == "rmd" || &filetype == "rrst" syn match rOperator "[|!<>^~`/:]" +else + syn match rOperator "[|!<>^~/:]" endif syn match rOperator "%\{2}\|%\S\{-}%" syn match rOperator '\([!><]\)\@<==' syn match rOperator '==' +syn match rOperator '|>' syn match rOpError '\*\{3}' syn match rOpError '//' syn match rOpError '&&&' @@ -318,10 +313,13 @@ if &filetype == "rhelp" endif " Type +syn match rType "\\" syn keyword rType array category character complex double function integer list logical matrix numeric vector data.frame " Name of object with spaces -if &filetype != "rmd" && &filetype != "rrst" +if &filetype == "rmd" || &filetype == "rrst" || &filetype == "quarto" + syn region rNameWSpace start="`" end="`" contains=rSpaceFun containedin=rmdrChunk +else syn region rNameWSpace start="`" end="`" contains=rSpaceFun endif diff --git a/runtime/syntax/rmd.vim b/runtime/syntax/rmd.vim index cccd4110f5..f849af97d2 100644 --- a/runtime/syntax/rmd.vim +++ b/runtime/syntax/rmd.vim @@ -1,7 +1,7 @@ -" markdown Text with R statements -" Language: markdown with R code chunks +" Language: Markdown with chunks of R, Python and other languages +" Maintainer: Jakson Aquino " Homepage: https://github.com/jalvesaq/R-Vim-runtime -" Last Change: Wed Apr 21, 2021 09:55AM +" Last Change: Fri Feb 24, 2023 08:28AM " " For highlighting pandoc extensions to markdown like citations and TeX and " many other advanced features like folding of markdown sections, it is @@ -13,63 +13,120 @@ if exists("b:current_syntax") finish endif +let s:cpo_save = &cpo +set cpo&vim + " Highlight the header of the chunks as R code let g:rmd_syn_hl_chunk = get(g:, 'rmd_syn_hl_chunk', 0) " Pandoc-syntax has more features, but it is slower. " https://github.com/vim-pandoc/vim-pandoc-syntax -let g:pandoc#syntax#codeblocks#embeds#langs = get(g:, 'pandoc#syntax#codeblocks#embeds#langs', ['r']) + +" Don't waste time loading syntax that will be discarded: +let s:save_pandoc_lngs = get(g:, 'pandoc#syntax#codeblocks#embeds#langs', []) +let g:pandoc#syntax#codeblocks#embeds#langs = [] + +" Step_1: Source pandoc.vim if it is installed: runtime syntax/pandoc.vim if exists("b:current_syntax") + if hlexists('pandocDelimitedCodeBlock') + syn clear pandocDelimitedCodeBlock + endif + + if len(s:save_pandoc_lngs) > 0 && !exists('g:rmd_fenced_languages') + let g:rmd_fenced_languages = deepcopy(s:save_pandoc_lngs) + endif + " Recognize inline R code - syn region rmdrInline matchgroup=rmdInlineDelim start="`r " end="`" contains=@R containedin=pandocLaTeXRegion,yamlFlowString keepend - hi def link rmdInlineDelim Delimiter - - " Fix recognition of language chunks (code adapted from pandoc, 2021-03-28) - " Knitr requires braces in the block's header - for s:lng in g:pandoc#syntax#codeblocks#embeds#langs - let s:nm = matchstr(s:lng, '^[^=]*') - exe 'syn clear pandocDelimitedCodeBlock_'.s:nm - exe 'syn clear pandocDelimitedCodeBlockinBlockQuote_'.s:nm - if g:rmd_syn_hl_chunk - exe 'syn region rmd'.s:nm.'ChunkDelim matchgroup=rmdCodeDelim start="^\s*```\s*{\s*'.s:nm.'\>" matchgroup=rmdCodeDelim end="}$" keepend containedin=rmd'.s:nm.'Chunk contains=@R' - exe 'syn region rmd'.s:nm.'Chunk start="^\s*```\s*{\s*'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=rmd'.s:nm.'ChunkDelim,@'.toupper(s:nm) + syn region rmdrInline matchgroup=rmdInlineDelim start="`r " end="`" contains=@Rmdr containedin=pandocLaTeXRegion,yamlFlowString keepend +else + " Step_2: Source markdown.vim if pandoc.vim is not installed + + " Configuration if not using pandoc syntax: + " Add syntax highlighting of YAML header + let g:rmd_syn_hl_yaml = get(g:, 'rmd_syn_hl_yaml', 1) + " Add syntax highlighting of citation keys + let g:rmd_syn_hl_citations = get(g:, 'rmd_syn_hl_citations', 1) + + " R chunks will not be highlighted by syntax/markdown because their headers + " follow a non standard pattern: "```{lang" instead of "^```lang". + " Make a copy of g:markdown_fenced_languages to highlight the chunks later: + if exists('g:markdown_fenced_languages') && !exists('g:rmd_fenced_languages') + let g:rmd_fenced_languages = deepcopy(g:markdown_fenced_languages) + endif + + if exists('g:markdown_fenced_languages') && len(g:markdown_fenced_languages) > 0 + let s:save_mfl = deepcopy(g:markdown_fenced_languages) + endif + " Don't waste time loading syntax that will be discarded: + let g:markdown_fenced_languages = [] + runtime syntax/markdown.vim + if exists('s:save_mfl') > 0 + let g:markdown_fenced_languages = deepcopy(s:save_mfl) + unlet s:save_mfl + endif + syn region rmdrInline matchgroup=rmdInlineDelim start="`r " end="`" contains=@Rmdr keepend + + " Step_2a: Add highlighting for both YAML and citations which are pandoc + " specific, but also used in Rmd files + + " You don't need this if either your markdown/syntax.vim already highlights + " the YAML header or you are writing standard markdown + if g:rmd_syn_hl_yaml + " Basic highlighting of YAML header + syn match rmdYamlFieldTtl /^\s*\zs\w\%(-\|\w\)*\ze:/ contained + syn match rmdYamlFieldTtl /^\s*-\s*\zs\w\%(-\|\w\)*\ze:/ contained + syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start='"' skip='\\"' end='"' contains=yamlEscape,rmdrInline contained + syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start="'" skip="''" end="'" contains=yamlSingleEscape,rmdrInline contained + syn match yamlEscape contained '\\\%([\\"abefnrtv\^0_ NLP\n]\|x\x\x\|u\x\{4}\|U\x\{8}\)' + syn match yamlSingleEscape contained "''" + syn match yamlComment /#.*/ contained + " A second colon is a syntax error, unles within a string or following !expr + syn match yamlColonError /:\s*[^'^"^!]*:/ contained + if &filetype == 'quarto' + syn region pandocYAMLHeader matchgroup=rmdYamlBlockDelim start=/\%(\%^\|\_^\s*\n\)\@<=\_^-\{3}\ze\n.\+/ end=/^---$/ keepend contains=rmdYamlFieldTtl,yamlFlowString,yamlComment,yamlColonError else - exe 'syn region rmd'.s:nm.'Chunk matchgroup=rmdCodeDelim start="^\s*```\s*{\s*'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=@'.toupper(s:nm) + syn region pandocYAMLHeader matchgroup=rmdYamlBlockDelim start=/\%(\%^\|\_^\s*\n\)\@<=\_^-\{3}\ze\n.\+/ end=/^\([-.]\)\1\{2}$/ keepend contains=rmdYamlFieldTtl,yamlFlowString,yamlComment,yamlColonError endif - endfor - unlet s:lng - unlet s:nm - hi def link rmdInlineDelim Delimiter - hi def link rmdCodeDelim Delimiter - let b:current_syntax = "rmd" - finish -endif - -" Configuration if not using pandoc syntax: -" Add syntax highlighting of YAML header -let g:rmd_syn_hl_yaml = get(g:, 'rmd_syn_hl_yaml', 1) -" Add syntax highlighting of citation keys -let g:rmd_syn_hl_citations = get(g:, 'rmd_syn_hl_citations', 1) - -let s:cpo_save = &cpo -set cpo&vim + hi def link rmdYamlBlockDelim Delimiter + hi def link rmdYamlFieldTtl Identifier + hi def link yamlFlowString String + hi def link yamlComment Comment + hi def link yamlColonError Error + endif -" R chunks will not be highlighted by syntax/markdown because their headers -" follow a non standard pattern: "```{lang" instead of "^```lang". -" Make a copy of g:markdown_fenced_languages to highlight the chunks later: -if exists('g:markdown_fenced_languages') - if !exists('g:rmd_fenced_languages') - let g:rmd_fenced_languages = deepcopy(g:markdown_fenced_languages) - let g:markdown_fenced_languages = [] + " You don't need this if either your markdown/syntax.vim already highlights + " citations or you are writing standard markdown + if g:rmd_syn_hl_citations + " From vim-pandoc-syntax + " parenthetical citations + syn match pandocPCite /\^\@~\/]*.\{-}\]/ contains=pandocEmphasis,pandocStrong,pandocLatex,pandocCiteKey,@Spell,pandocAmpersandEscape display + " in-text citations with location + syn match pandocICite /@[[:alnum:]_][[:alnum:]à-öø-ÿÀ-ÖØ-ß_:.#$%&\-+?<>~\/]*\s\[.\{-1,}\]/ contains=pandocCiteKey,@Spell display + " cite keys + syn match pandocCiteKey /\(-\=@[[:alnum:]_][[:alnum:]à-öø-ÿÀ-ÖØ-ß_:.#$%&\-+?<>~\/]*\)/ containedin=pandocPCite,pandocICite contains=@NoSpell display + syn match pandocCiteAnchor /[-@]/ contained containedin=pandocCiteKey display + syn match pandocCiteLocator /[\[\]]/ contained containedin=pandocPCite,pandocICite + hi def link pandocPCite Operator + hi def link pandocICite Operator + hi def link pandocCiteKey Label + hi def link pandocCiteAnchor Operator + hi def link pandocCiteLocator Operator endif -else - let g:rmd_fenced_languages = ['r'] endif -runtime syntax/markdown.vim +" Step_3: Highlight code blocks. + +syn region rmdCodeBlock matchgroup=rmdCodeDelim start="^\s*```\s*{.*}$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend +syn region rmdCodeBlock matchgroup=rmdCodeDelim start="^\s*```.+$" matchgroup=rmdCodeDelim end="^```$" keepend +hi link rmdCodeBlock Special " Now highlight chunks: +syn region knitrBodyOptions start='^#| ' end='$' contained containedin=rComment,pythonComment contains=knitrBodyVar,knitrBodyValue transparent +syn match knitrBodyValue ': \zs.*\ze$' keepend contained containedin=knitrBodyOptions +syn match knitrBodyVar '| \zs\S\{-}\ze:' contained containedin=knitrBodyOptions + +let g:rmd_fenced_languages = get(g:, 'rmd_fenced_languages', ['r']) for s:type in g:rmd_fenced_languages if s:type =~ '=' let s:ft = substitute(s:type, '.*=', '', '') @@ -81,58 +138,40 @@ for s:type in g:rmd_fenced_languages unlet! b:current_syntax exe 'syn include @Rmd'.s:nm.' syntax/'.s:ft.'.vim' if g:rmd_syn_hl_chunk - exe 'syn region rmd'.s:nm.'ChunkDelim matchgroup=rmdCodeDelim start="^\s*```\s*{\s*'.s:nm.'\>" matchgroup=rmdCodeDelim end="}$" keepend containedin=rmd'.s:nm.'Chunk contains=@Rmdr' - exe 'syn region rmd'.s:nm.'Chunk start="^\s*```\s*{\s*'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=rmd'.s:nm.'ChunkDelim,@Rmd'.s:nm + exe 'syn match knitrChunkDelim /```\s*{\s*'.s:nm.'/ contained containedin=knitrChunkBrace contains=knitrChunkLabel' + exe 'syn match knitrChunkLabelDelim /```\s*{\s*'.s:nm.',\=\s*[-[:alnum:]]\{-1,}[,}]/ contained containedin=knitrChunkBrace' + syn match knitrChunkDelim /}\s*$/ contained containedin=knitrChunkBrace + exe 'syn match knitrChunkBrace /```\s*{\s*'.s:nm.'.*$/ contained containedin=rmd'.s:nm.'Chunk contains=knitrChunkDelim,knitrChunkLabelDelim,@Rmd'.s:nm + exe 'syn region rmd'.s:nm.'Chunk start="^\s*```\s*{\s*=\?'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=knitrChunkBrace,@Rmd'.s:nm + + hi link knitrChunkLabel Identifier + hi link knitrChunkDelim rmdCodeDelim + hi link knitrChunkLabelDelim rmdCodeDelim else - exe 'syn region rmd'.s:nm.'Chunk matchgroup=rmdCodeDelim start="^\s*```\s*{\s*'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=@Rmd'.s:nm + exe 'syn region rmd'.s:nm.'Chunk matchgroup=rmdCodeDelim start="^\s*```\s*{\s*=\?'.s:nm.'\>.*$" matchgroup=rmdCodeDelim end="^\s*```\ze\s*$" keepend contains=@Rmd'.s:nm endif endfor unlet! s:type -" Recognize inline R code -syn region rmdrInline matchgroup=rmdInlineDelim start="`r " end="`" contains=@Rmdr keepend +" Step_4: Highlight code recognized by pandoc but not defined in pandoc.vim yet: +syn match pandocDivBegin '^:::\+ {.\{-}}' contains=pandocHeaderAttr +syn match pandocDivEnd '^:::\+$' +hi def link knitrBodyVar PreProc +hi def link knitrBodyValue Constant +hi def link knitrBodyOptions rComment +hi def link pandocDivBegin Delimiter +hi def link pandocDivEnd Delimiter hi def link rmdInlineDelim Delimiter hi def link rmdCodeDelim Delimiter -" You don't need this if either your markdown/syntax.vim already highlights -" the YAML header or you are writing standard markdown -if g:rmd_syn_hl_yaml - " Minimum highlighting of yaml header - syn match rmdYamlFieldTtl /^\s*\zs\w*\ze:/ contained - syn match rmdYamlFieldTtl /^\s*-\s*\zs\w*\ze:/ contained - syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start='"' skip='\\"' end='"' contains=yamlEscape,rmdrInline contained - syn region yamlFlowString matchgroup=yamlFlowStringDelimiter start="'" skip="''" end="'" contains=yamlSingleEscape,rmdrInline contained - syn match yamlEscape contained '\\\%([\\"abefnrtv\^0_ NLP\n]\|x\x\x\|u\x\{4}\|U\x\{8}\)' - syn match yamlSingleEscape contained "''" - syn region pandocYAMLHeader matchgroup=rmdYamlBlockDelim start=/\%(\%^\|\_^\s*\n\)\@<=\_^-\{3}\ze\n.\+/ end=/^\([-.]\)\1\{2}$/ keepend contains=rmdYamlFieldTtl,yamlFlowString - hi def link rmdYamlBlockDelim Delimiter - hi def link rmdYamlFieldTtl Identifier - hi def link yamlFlowString String -endif - -" You don't need this if either your markdown/syntax.vim already highlights -" citations or you are writing standard markdown -if g:rmd_syn_hl_citations - " From vim-pandoc-syntax - " parenthetical citations - syn match pandocPCite /\^\@~\/]*.\{-}\]/ contains=pandocEmphasis,pandocStrong,pandocLatex,pandocCiteKey,@Spell,pandocAmpersandEscape display - " in-text citations with location - syn match pandocICite /@[[:alnum:]_][[:alnum:]à-öø-ÿÀ-ÖØ-ß_:.#$%&\-+?<>~\/]*\s\[.\{-1,}\]/ contains=pandocCiteKey,@Spell display - " cite keys - syn match pandocCiteKey /\(-\=@[[:alnum:]_][[:alnum:]à-öø-ÿÀ-ÖØ-ß_:.#$%&\-+?<>~\/]*\)/ containedin=pandocPCite,pandocICite contains=@NoSpell display - syn match pandocCiteAnchor /[-@]/ contained containedin=pandocCiteKey display - syn match pandocCiteLocator /[\[\]]/ contained containedin=pandocPCite,pandocICite - hi def link pandocPCite Operator - hi def link pandocICite Operator - hi def link pandocCiteKey Label - hi def link pandocCiteAnchor Operator - hi def link pandocCiteLocator Operator +if len(s:save_pandoc_lngs) + let g:pandoc#syntax#codeblocks#embeds#langs = s:save_pandoc_lngs endif - -let b:current_syntax = "rmd" - +unlet s:save_pandoc_lngs let &cpo = s:cpo_save unlet s:cpo_save +let b:current_syntax = "rmd" + " vim: ts=8 sw=2 diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim index 13d74dbc17..f455f19c93 100644 --- a/runtime/syntax/sh.vim +++ b/runtime/syntax/sh.vim @@ -2,8 +2,8 @@ " Language: shell (sh) Korn shell (ksh) bash (sh) " Maintainer: Charles E. Campbell " Previous Maintainer: Lennart Schultz -" Last Change: Dec 20, 2022 -" Version: 205 +" Last Change: Feb 11, 2023 +" Version: 207 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH " For options and settings, please use: :help ft-sh-syntax " This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras @@ -166,7 +166,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") syn cluster shLoopoList add=shForPP endif syn cluster shPPSLeftList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable -syn cluster shPPSRightList contains=shComment,shDeref,shDerefSimple,shEscape,shPosnParm +syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm syn cluster shSubShList contains=@shCommandSubList,shCommandSubBQ,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator syn cluster shTestList contains=shArithmetic,shCharClass,shCommandSub,shCommandSubBQ,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr syn cluster shNoZSList contains=shSpecialNoZS @@ -335,7 +335,7 @@ syn match shEscape contained '\%(^\)\@!\%(\\\\\)*\\.' nextgroup=shComment " systems too, however, so the following syntax will flag $(..) as " an Error under /bin/sh. By consensus of vimdev'ers! if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix") - syn region shCommandSub matchgroup=shCmdSubRegion start="\$(\ze[^(]\|$" skip='\\\\\|\\.' end=")" contains=@shCommandSubList + syn region shCommandSub matchgroup=shCmdSubRegion start="\$(\ze[^(]" skip='\\\\\|\\.' end=")" contains=@shCommandSubList syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList syn match shSkipInitWS contained "^\s\+" @@ -503,7 +503,6 @@ endif " ksh: ${.sh.*} variables: {{{1 " ======================================== if exists("b:is_kornshell") -" syn match shDerefVar contained "[.]*" nextgroup=@shDerefVarList syn match shDerefVar contained "\.\+" nextgroup=@shDerefVarList endif @@ -548,6 +547,7 @@ syn region shDerefVarArray contained matchgroup=shDeref start="\[" end="]" co " bash : ${parameter,pattern} Case modification " bash : ${parameter,,pattern} Case modification " bash : ${@:start:qty} display command line arguments from start to start+qty-1 (inferred) +" bash : ${parameter@operator} transforms parameter (operator∈[uULqEPARa]) syn cluster shDerefPatternList contains=shDerefPattern,shDerefString if !exists("g:sh_no_error") syn match shDerefOpError contained ":[[:punct:]]" @@ -563,6 +563,7 @@ if exists("b:is_bash") || exists("b:is_kornshell") || exists("b:is_posix") endif if exists("b:is_bash") syn match shDerefOp contained "[,^]\{1,2}" nextgroup=@shDerefPatternList + syn match shDerefOp contained "@[uULQEPAKa]" endif syn region shDerefString contained matchgroup=shDerefDelim start=+\%(\\\)\@ Date: Tue, 28 Feb 2023 12:12:08 +0100 Subject: fix(inspect): alwasy resolve full treesitter lang hl groups --- runtime/lua/vim/_inspector.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index f46a525910..bb6608421b 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -69,7 +69,7 @@ function vim.inspect_pos(bufnr, row, col, filter) -- treesitter if filter.treesitter then for _, capture in pairs(vim.treesitter.get_captures_at_pos(bufnr, row, col)) do - capture.hl_group = '@' .. capture.capture + capture.hl_group = '@' .. capture.capture .. '.' .. capture.lang table.insert(results.treesitter, resolve_hl(capture)) end end -- cgit From bfa0bc7df0ca527fcec49dbd2055f1bac438663e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:04:32 +0800 Subject: vim-patch:9.0.0795: readblob() always reads the whole file Problem: readblob() always reads the whole file. Solution: Add arguments to read part of the file. (Ken Takata, closes vim/vim#11402) https://github.com/vim/vim/commit/11df3aeee548b959ccd4b9a4d3c44651eab6b3ce Remove trailing whitespace in test as done in patch 9.0.1257. Move the help for rand() before range(). Co-authored-by: K.Takata --- runtime/doc/builtin.txt | 53 ++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index ed8c78ef2f..113703680f 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -359,7 +359,8 @@ pyxeval({expr}) any evaluate |python_x| expression rand([{expr}]) Number get pseudo-random number range({expr} [, {max} [, {stride}]]) List items from {expr} to {max} -readblob({fname}) Blob read a |Blob| from {fname} +readblob({fname} [, {offset} [, {size}]]) + Blob read a |Blob| from {fname} readdir({dir} [, {expr}]) List file names in {dir} selected by {expr} readfile({fname} [, {type} [, {max}]]) List get list of lines from file {fname} @@ -6110,6 +6111,25 @@ pyxeval({expr}) *pyxeval()* Can also be used as a |method|: > GetExpr()->pyxeval() < +rand([{expr}]) *rand()* + Return a pseudo-random Number generated with an xoshiro128** + algorithm using seed {expr}. The returned number is 32 bits, + also on 64 bits systems, for consistency. + {expr} can be initialized by |srand()| and will be updated by + rand(). If {expr} is omitted, an internal seed value is used + and updated. + Returns -1 if {expr} is invalid. + + Examples: > + :echo rand() + :let seed = srand() + :echo rand(seed) + :echo rand(seed) % 16 " random number 0 - 15 +< + Can also be used as a |method|: > + seed->rand() +< + *E726* *E727* range({expr} [, {max} [, {stride}]]) *range()* Returns a |List| with Numbers: @@ -6132,29 +6152,22 @@ range({expr} [, {max} [, {stride}]]) *range()* Can also be used as a |method|: > GetExpr()->range() < -rand([{expr}]) *rand()* - Return a pseudo-random Number generated with an xoshiro128** - algorithm using seed {expr}. The returned number is 32 bits, - also on 64 bits systems, for consistency. - {expr} can be initialized by |srand()| and will be updated by - rand(). If {expr} is omitted, an internal seed value is used - and updated. - Returns -1 if {expr} is invalid. - - Examples: > - :echo rand() - :let seed = srand() - :echo rand(seed) - :echo rand(seed) % 16 " random number 0 - 15 -< - Can also be used as a |method|: > - seed->rand() -< -readblob({fname}) *readblob()* +readblob({fname} [, {offset} [, {size}]]) *readblob()* Read file {fname} in binary mode and return a |Blob|. + If {offset} is specified, read the file from the specified + offset. If it is a negative value, it is used as an offset + from the end of the file. E.g., to read the last 12 bytes: > + readblob('file.bin', -12) +< If {size} is specified, only the specified size will be read. + E.g. to read the first 100 bytes of a file: > + readblob('file.bin', 0, 100) +< If {size} is -1 or omitted, the whole data starting from + {offset} will be read. When the file can't be opened an error message is given and the result is an empty |Blob|. + When trying to read bytes beyond the end of the file the + result is an empty blob. Also see |readfile()| and |writefile()|. -- cgit From 4bd0611d7b07b56fc5a9e121669a313166ba540f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:23:28 +0800 Subject: vim-patch:9.0.0803: readblob() cannot read from character device Problem: readblob() cannot read from character device. Solution: Use S_ISCHR() to not check the size. (Ken Takata, closes vim/vim#11407) https://github.com/vim/vim/commit/43625762a9751cc6e6e4d8f54fbc8b82d98fb20d S_ISCHR is always defined in Nvim. Co-authored-by: K.Takata --- runtime/doc/builtin.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 113703680f..eab415f495 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6164,7 +6164,12 @@ readblob({fname} [, {offset} [, {size}]]) *readblob()* readblob('file.bin', 0, 100) < If {size} is -1 or omitted, the whole data starting from {offset} will be read. - When the file can't be opened an error message is given and + This can be also used to read the data from a character device + on Unix when {size} is explicitly set. Only if the device + supports seeking {offset} can be used. Otherwise it should be + zero. E.g. to read 10 bytes from a serial console: > + readblob('/dev/ttyS0', 0, 10) +< When the file can't be opened an error message is given and the result is an empty |Blob|. When trying to read bytes beyond the end of the file the result is an empty blob. -- cgit From 7aad75e293e3a01e292308ca2058e35083b83280 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:29:59 +0800 Subject: vim-patch:9.0.0810: readblob() returns empty when trying to read too much Problem: readblob() returns empty when trying to read too much. Solution: Return what is available. https://github.com/vim/vim/commit/5b2a3d77d320d76f12b1666938a9d58c2a848205 Co-authored-by: Bram Moolenaar --- runtime/doc/builtin.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index eab415f495..568b73ddfa 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6171,8 +6171,10 @@ readblob({fname} [, {offset} [, {size}]]) *readblob()* readblob('/dev/ttyS0', 0, 10) < When the file can't be opened an error message is given and the result is an empty |Blob|. - When trying to read bytes beyond the end of the file the - result is an empty blob. + When the offset is beyond the end of the file the result is an + empty blob. + When trying to read more bytes than are available the result + is truncated. Also see |readfile()| and |writefile()|. -- cgit From 7e19cabeb192d2e7f20d7bb965a3f62e1543d2ac Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 28 Feb 2023 12:38:33 +0100 Subject: perf(lsp): only redraw the windows containing LSP tokens redraw! redraws the entire screen instead of just the windows with the buffer which were actually changed. I considered trying to calculating the range for the delta but it looks tricky. Could a follow-up. --- runtime/lua/vim/lsp/semantic_tokens.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 00b4757ea9..24b5c6c24e 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -334,7 +334,8 @@ function STHighlighter:process_response(response, client, version) current_result.highlights = tokens_to_ranges(tokens, self.bufnr, client) current_result.namespace_cleared = false - api.nvim_command('redraw!') + -- redraw all windows displaying buffer + api.nvim__buf_redraw_range(self.bufnr, 0, -1) end --- on_win handler for the decoration provider (see |nvim_set_decoration_provider|) -- cgit From f6b9791212e86bac3e8128035dec2bfc5016927f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:18:52 +0800 Subject: vim-patch:8.2.3438: cannot manipulate blobs Problem: Cannot manipulate blobs. Solution: Add blob2list() and list2blob(). (Yegappan Lakshmanan, closes vim/vim#8868) https://github.com/vim/vim/commit/5dfe467432638fac2e0156a2f9cd0d9eb569fb39 Co-authored-by: Yegappan Lakshmanan --- runtime/doc/builtin.txt | 28 +++++++++++++++++++++++++++- runtime/doc/usr_41.txt | 6 ++++++ 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 568b73ddfa..b194a104f7 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -55,6 +55,7 @@ assert_report({msg}) Number report a test failure assert_true({actual} [, {msg}]) Number assert {actual} is true atan({expr}) Float arc tangent of {expr} atan2({expr1}, {expr2}) Float arc tangent of {expr1} / {expr2} +blob2list({blob}) List convert {blob} into a list of numbers browse({save}, {title}, {initdir}, {default}) String put up a file requester browsedir({title}, {initdir}) String put up a directory requester @@ -296,7 +297,8 @@ libcallnr({lib}, {func}, {arg}) Number idem, but return a Number line({expr} [, {winid}]) Number line nr of cursor, last line or mark line2byte({lnum}) Number byte count of line {lnum} lispindent({lnum}) Number Lisp indent for line {lnum} -list2str({list} [, {utf8}]) String turn numbers in {list} into a String +list2blob({list}) Blob turn {list} of numbers into a Blob +list2str({list} [, {utf8}]) String turn {list} of numbers into a String localtime() Number current time log({expr}) Float natural logarithm (base e) of {expr} log10({expr}) Float logarithm of Float {expr} to base 10 @@ -777,6 +779,17 @@ atan2({expr1}, {expr2}) *atan2()* Can also be used as a |method|: > Compute()->atan2(1) +blob2list({blob}) *blob2list()* + Return a List containing the number value of each byte in Blob + {blob}. Examples: > + blob2list(0z0102.0304) returns [1, 2, 3, 4] + blob2list(0z) returns [] +< Returns an empty List on error. |list2blob()| does the + opposite. + + Can also be used as a |method|: > + GetBlob()->blob2list() +< *browse()* browse({save}, {title}, {initdir}, {default}) Put up a file requester. This only works when "has("browse")" @@ -4768,6 +4781,19 @@ lispindent({lnum}) *lispindent()* Can also be used as a |method|: > GetLnum()->lispindent() +list2blob({list}) *list2blob()* + Return a Blob concatenating all the number values in {list}. + Examples: > + list2blob([1, 2, 3, 4]) returns 0z01020304 + list2blob([]) returns 0z +< Returns an empty Blob on error. If one of the numbers is + negative or more than 255 error *E1239* is given. + + |blob2list()| does the opposite. + + Can also be used as a |method|: > + GetList()->list2blob() + list2str({list} [, {utf8}]) *list2str()* Convert each number in {list} to a character string can concatenate them all. Examples: > diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 0f2cfdd2ac..ed16f837cf 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -721,6 +721,10 @@ Floating point computation: *float-functions* isinf() check for infinity isnan() check for not a number +Blob manipulation: *blob-functions* + blob2list() get a list of numbers from a blob + list2blob() get a blob from a list of numbers + Other computation: *bitwise-function* and() bitwise AND invert() bitwise invert @@ -1321,6 +1325,8 @@ is a List with arguments. Function references are most useful in combination with a Dictionary, as is explained in the next section. +More information about defining your own functions here: |user-functions|. + ============================================================================== *41.8* Lists and Dictionaries -- cgit From ccac34af766bee70d4f2a3cd69b54977849f567d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:38:16 +0800 Subject: vim-patch:8.2.3446: not enough tests for empty string arguments Problem: Not enough tests for empty string arguments. Solution: Add tests, fix type check. (Yegappan Lakshmanan, closes vim/vim#8881) https://github.com/vim/vim/commit/820d5525cae707f39571c6abc2aa6a9e66ed171e Co-authored-by: Yegappan Lakshmanan --- runtime/doc/sign.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime') diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 162bdaed7b..9f469767a2 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -525,6 +525,7 @@ sign_jump({id}, {group}, {buf}) {buf} and position the cursor at sign {id} in group {group}. This is similar to the |:sign-jump| command. + If {group} is an empty string, then the global group is used. For the use of {buf}, see |bufname()|. Returns the line number of the sign. Returns -1 if the -- cgit From 278aeee3aed753d1084597378e653395bd472c42 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 21:07:56 +0800 Subject: vim-patch:9.0.0430: cannot use repeat() with a blob Problem: Cannot use repeat() with a blob. Solution: Implement blob repeat. (closes vim/vim#11090) https://github.com/vim/vim/commit/375141e1f80dced9be738568a3418f65813f4a2f Co-authored-by: Bakudankun --- runtime/doc/builtin.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index b194a104f7..7fab2ac6ff 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -380,7 +380,8 @@ remove({blob}, {idx} [, {end}]) Number/Blob remove bytes {idx}-{end} from {blob} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} -repeat({expr}, {count}) String repeat {expr} {count} times +repeat({expr}, {count}) List/Blob/String + repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} @@ -6420,8 +6421,8 @@ repeat({expr}, {count}) *repeat()* result. Example: > :let separator = repeat('-', 80) < When {count} is zero or negative the result is empty. - When {expr} is a |List| the result is {expr} concatenated - {count} times. Example: > + When {expr} is a |List| or a |Blob| the result is {expr} + concatenated {count} times. Example: > :let longlist = repeat(['a', 'b'], 3) < Results in ['a', 'b', 'a', 'b', 'a', 'b']. -- cgit From cf07f2baabd3a1a072102e0cacb6d70509ada044 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 12:29:20 +0100 Subject: feat(edit)!: remove old c implementation of hebrew keymap This feature has long been obsolete. The 'keymap' option can be used to support language keymaps, including hebrew and hebrewp (phonetic mapping). There is no need to keep the old c code with hardcoded keymaps for some languages. --- runtime/doc/hebrew.txt | 19 ++++++------------- runtime/doc/insert.txt | 8 ++++---- runtime/doc/news.txt | 2 ++ runtime/doc/options.txt | 24 ------------------------ runtime/doc/starting.txt | 2 +- runtime/doc/vim_diff.txt | 4 ++++ 6 files changed, 17 insertions(+), 42 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/hebrew.txt b/runtime/doc/hebrew.txt index 76266d777f..e38385e13a 100644 --- a/runtime/doc/hebrew.txt +++ b/runtime/doc/hebrew.txt @@ -30,17 +30,10 @@ Details + 'rightleft' ('rl') sets window orientation to right-to-left. This means that the logical text 'ABC' will be displayed as 'CBA', and will start drawing at the right edge of the window, not the left edge. - + 'hkmap' ('hk') sets keyboard mapping to Hebrew, in insert/replace modes. - + 'aleph' ('al'), numeric, holds the decimal code of Aleph, for keyboard - mapping. - + 'hkmapp' ('hkp') sets keyboard mapping to "phonetic hebrew" - - NOTE: these three ('hkmap', 'hkmapp' and 'aleph') are obsolete. You should - use ":set keymap=hebrewp" instead. - - + 'delcombine' ('deco'), boolean, if editing UTF-8 encoded Hebrew, allows - one to remove the niqud or te`amim by pressing 'x' on a character (with - associated niqud). + + 'keymap' ('kmp') sets keyboard mapping. use values "hebrew" or "heprewp" + (the latter option enables phonetic mapping) + + 'delcombine' ('deco'), boolean, allows one to remove the niqud or + te`amim by pressing 'x' on a character (with associated niqud). + 'rightleftcmd' ('rlc') makes the command-prompt for searches show up on the right side. It only takes effect if the window is 'rightleft'. @@ -62,10 +55,10 @@ Details + CTRL-_ in insert/replace modes toggles 'revins' and 'hkmap' as follows: - When in rightleft window, 'revins' and 'nohkmap' are toggled, since + When in rightleft window, 'revins' is toggled, since English will likely be inserted in this case. - When in norightleft window, 'revins' 'hkmap' are toggled, since Hebrew + When in norightleft window, 'revins' is toggled, since Hebrew will likely be inserted in this case. CTRL-_ moves the cursor to the end of the typed text. diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 84aee43af4..49aa2a79a4 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -221,11 +221,11 @@ CTRL-Y Insert the character which is above the cursor. able to copy characters from a long line. *i_CTRL-_* -CTRL-_ Switch between languages, as follows: - - When in a rightleft window, revins and nohkmap are toggled, +CTRL-_ Switch between insert direction, by toggling 'revins', as follows: + - When in a rightleft window, 'revins' is toggled, since English will likely be inserted in this case. - - When in a norightleft window, revins and hkmap are toggled, - since Hebrew will likely be inserted in this case. + - When in a norightleft window, 'revins' is toggled, + since a rightleft language will likely be inserted in this case. CTRL-_ moves the cursor to the end of the typed text. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index c5261b739d..86a81e0c95 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -211,6 +211,8 @@ The following deprecated functions or APIs were removed. changes need to be contributed there first.) See https://github.com/neovim/neovim/pull/20674. +- 'hkmap', 'hkmapp' and 'aleph' options were removed. Use 'keymap' option instead. + ============================================================================== DEPRECATIONS *news-deprecations* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f44b6f28e3..6c5b168402 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -575,16 +575,6 @@ supported use something like this: > *E355* A jump table for the options with a short description can be found at |Q_op|. - *'aleph'* *'al'* *aleph* *Aleph* -'aleph' 'al' number (default 224) - global - The ASCII code for the first letter of the Hebrew alphabet. The - routine that maps the keyboard in Hebrew mode, both in Insert mode - (when hkmap is set) and on the command-line (when hitting CTRL-_) - outputs the Hebrew characters in the range [aleph..aleph+26]. - aleph=128 applies to PC code, and aleph=224 applies to ISO 8859-8. - See |rileft.txt|. - *'allowrevins'* *'ari'* *'noallowrevins'* *'noari'* 'allowrevins' 'ari' boolean (default off) global @@ -3195,20 +3185,6 @@ A jump table for the options with a short description can be found at |Q_op|. each of these histories (see |cmdline-editing|). The maximum value is 10000. - *'hkmap'* *'hk'* *'nohkmap'* *'nohk'* -'hkmap' 'hk' boolean (default off) - global - When on, the keyboard is mapped for the Hebrew character set. - Normally you would set 'allowrevins' and use CTRL-_ in insert mode to - toggle this option. See |rileft.txt|. - - *'hkmapp'* *'hkp'* *'nohkmapp'* *'nohkp'* -'hkmapp' 'hkp' boolean (default off) - global - When on, phonetic keyboard mapping is used. 'hkmap' must also be on. - This is useful if you have a non-Hebrew keyboard. - See |rileft.txt|. - *'hlsearch'* *'hls'* *'nohlsearch'* *'nohls'* 'hlsearch' 'hls' boolean (default on) global diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index a8a149def8..8c9ec7df9c 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -258,7 +258,7 @@ argument. -A Arabic mode. Sets the 'arabic' option on. *-H* --H Hebrew mode. Sets the 'hkmap' and 'rightleft' options on. +-H Hebrew mode. Sets the 'rightleft' option on and 'keymap' to "hebrew" *-V* *verbose* -V[N] Verbose. Sets the 'verbose' option to [N] (default: 10). diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 79808eccc9..5efe094226 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -594,6 +594,7 @@ Highlight groups: < Options: + *'aleph'* *'al'* antialias *'balloondelay'* *'bdlay'* *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'* @@ -617,6 +618,9 @@ Options: *'guifontset'* *'gfs'* (Use 'guifont' instead.) *'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.) 'highlight' (Names of builtin |highlight-groups| cannot be changed.) + *'hkmap'* *'hk'* use `set keymap=hebrew` instead. + *'hkmapp'* *'hkp'* use `set keymap=hebrewp` instead. + *'imactivatefunc'* *'imaf'* *'imactivatekey'* *'imak'* *'imstatusfunc'* *'imsf'* -- cgit From 96d3616a531b2626e3ab9b4fa2c5dea03a927717 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Wed, 1 Mar 2023 11:35:16 +0100 Subject: fix(lsp): callHierarchy methods also require the callHierarchyProvider (#22427) --- runtime/lua/vim/lsp.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 61a06ff7a7..fed56ff846 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -46,6 +46,8 @@ lsp._request_name_to_capability = { ['textDocument/typeDefinition'] = { 'typeDefinitionProvider' }, ['textDocument/documentSymbol'] = { 'documentSymbolProvider' }, ['textDocument/prepareCallHierarchy'] = { 'callHierarchyProvider' }, + ['callHierarchy/incomingCalls'] = { 'callHierarchyProvider' }, + ['callHierarchy/outgoingCalls'] = { 'callHierarchyProvider' }, ['textDocument/rename'] = { 'renameProvider' }, ['textDocument/prepareRename'] = { 'renameProvider', 'prepareProvider' }, ['textDocument/codeAction'] = { 'codeActionProvider' }, -- cgit From 896d672736b32a8f4a4fa51844b44f266dcdcc6c Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Wed, 1 Mar 2023 15:33:13 +0100 Subject: fix(lsp): use buffer scheme for files not stored on disk (#22407) Sending `didOpen` with a `file` scheme causes problems with some language servers because they expect the file to exist on disk. See https://github.com/microsoft/language-server-protocol/pull/1679 --- runtime/lua/vim/lsp.lua | 54 ++++++++++++++++++++++++++++++++++---------- runtime/lua/vim/lsp/util.lua | 9 ++++++-- 2 files changed, 49 insertions(+), 14 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index fed56ff846..a6d550f48f 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -367,7 +367,7 @@ do --- @field offset_encoding "utf-8"|"utf-16"|"utf-32" --- --- @class CTBufferState - --- @field name string name of the buffer + --- @field uri string uri of the buffer --- @field lines string[] snapshot of buffer lines from last didChange --- @field lines_tmp string[] --- @field pending_changes table[] List of debounced changes in incremental sync mode @@ -486,8 +486,12 @@ do if buf_state then buf_state.refs = buf_state.refs + 1 else + local uri = vim.uri_from_bufnr(bufnr) + if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then + uri = uri:gsub('^file://', 'buffer://') + end buf_state = { - name = api.nvim_buf_get_name(bufnr), + uri = uri, lines = {}, lines_tmp = {}, pending_changes = {}, @@ -502,12 +506,26 @@ do end ---@private - function changetracking._get_and_set_name(client, bufnr, name) + ---@param client table + ---@param bufnr integer + ---@return string uri + function changetracking._get_uri(client, bufnr) local state = state_by_group[get_group(client)] or {} local buf_state = (state.buffers or {})[bufnr] - local old_name = buf_state.name - buf_state.name = name - return old_name + return assert(buf_state.uri, 'Must have an URI set') + end + + ---@private + ---@param client table + ---@param bufnr integer + ---@param uri string + ---@return string uri + function changetracking._get_and_set_uri(client, bufnr, uri) + local state = state_by_group[get_group(client)] or {} + local buf_state = (state.buffers or {})[bufnr] + local old_uri = buf_state.uri + buf_state.uri = uri + return old_uri end ---@private @@ -594,7 +612,7 @@ do { text = buf_get_full_text(bufnr) }, } end - local uri = vim.uri_from_bufnr(bufnr) + local uri = buf_state.uri for _, client in pairs(state.clients) do if not client.is_stopped() and lsp.buf_is_attached(bufnr, client.id) then client.notify('textDocument/didChange', { @@ -707,11 +725,14 @@ local function text_document_did_open_handler(bufnr, client) return end local filetype = nvim_buf_get_option(bufnr, 'filetype') - + local uri = vim.uri_from_bufnr(bufnr) + if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then + uri = uri:gsub('^file://', 'buffer://') + end local params = { textDocument = { version = 0, - uri = vim.uri_from_bufnr(bufnr), + uri = uri, languageId = client.config.get_language_id(bufnr, filetype), text = buf_get_full_text(bufnr), }, @@ -1560,8 +1581,13 @@ local function text_document_did_save_handler(bufnr) local text = once(buf_get_full_text) for_each_buffer_client(bufnr, function(client) local name = api.nvim_buf_get_name(bufnr) - local old_name = changetracking._get_and_set_name(client, bufnr, name) - if old_name and name ~= old_name then + local old_uri = changetracking._get_and_set_uri(client, bufnr, uri) + if old_uri and name ~= old_uri then + client.notify('textDocument/didClose', { + textDocument = { + uri = old_uri, + }, + }) client.notify('textDocument/didOpen', { textDocument = { version = 0, @@ -1664,8 +1690,12 @@ function lsp.buf_attach_client(bufnr, client_id) end) end, on_detach = function() - local params = { textDocument = { uri = uri } } for_each_buffer_client(bufnr, function(client, _) + local params = { + textDocument = { + uri = changetracking._get_uri(client, bufnr), + }, + } changetracking.reset_buf(client, bufnr) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then client.notify('textDocument/didClose', params) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 4beb4fc367..554e26022c 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -2032,7 +2032,12 @@ end ---@returns `TextDocumentIdentifier` ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier function M.make_text_document_params(bufnr) - return { uri = vim.uri_from_bufnr(bufnr or 0) } + bufnr = bufnr or 0 + local uri = vim.uri_from_bufnr(bufnr) + if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then + uri = uri:gsub('^file://', 'buffer://') + end + return { uri = uri } end --- Create the workspace params @@ -2065,7 +2070,7 @@ function M.make_formatting_params(options) insertSpaces = vim.bo.expandtab, }) return { - textDocument = { uri = vim.uri_from_bufnr(0) }, + textDocument = M.make_text_document_params(0), options = options, } end -- cgit From 014981c9006f9b96b8045e609dc27f4a84da5263 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 1 Mar 2023 09:47:56 -0700 Subject: fix(lsp): only fire LspDetach for attached buffers (#22468) If the LSP server fails to start then the client never initializes and thus never calls its on_attach function and an LspAttach event is never fired. However, the on_exit function still fires a LspDetach event, so user autocommands that attempt to "clean up" in LspDetach may run into problems if they assume that the buffer was already attached. The solution is to only fire an LspDetach event if the buffer was already attached in the first place. --- runtime/lua/vim/lsp.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a6d550f48f..a56e141c29 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1155,14 +1155,19 @@ function lsp.start_client(config) pcall(config.on_exit, code, signal, client_id) end + local client = active_clients[client_id] and active_clients[client_id] + or uninitialized_clients[client_id] + for bufnr, client_ids in pairs(all_buffer_active_clients) do if client_ids[client_id] then vim.schedule(function() - nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) + if client and client.attached_buffers[bufnr] then + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + end local namespace = vim.lsp.diagnostic.get_namespace(client_id) vim.diagnostic.reset(namespace, bufnr) @@ -1178,8 +1183,6 @@ function lsp.start_client(config) -- Schedule the deletion of the client object so that it exists in the execution of LspDetach -- autocommands vim.schedule(function() - local client = active_clients[client_id] and active_clients[client_id] - or uninitialized_clients[client_id] active_clients[client_id] = nil uninitialized_clients[client_id] = nil -- cgit From bc15b075d14c85098d674a2466d2386e08b0005f Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 1 Mar 2023 10:51:22 -0600 Subject: feat(vim.fs): pass path to find() predicate, lazy evaluate #22378 Problem: No easy way to find files under certain directories (ex: grab all files under `test/`) or exclude the content of certain paths (ex. `build/`, `.git/`) Solution: Pass the full `path` as an arg to the predicate. --- runtime/doc/lua.txt | 35 ++++++++++++++++++++++++++++++----- runtime/lua/vim/fs.lua | 35 +++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 11 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 8ae1c6dc40..e3e0665025 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -2359,12 +2359,37 @@ find({names}, {opts}) *vim.fs.find()* The search can be narrowed to find only files or only directories by specifying {type} to be "file" or "directory", respectively. + Examples: >lua + + -- location of Cargo.toml from the current buffer's path + local cargo = vim.fs.find('Cargo.toml', { + upward = true, + stop = vim.loop.os_homedir(), + path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)), + }) + + -- list all test directories under the runtime directory + local test_dirs = vim.fs.find( + {'test', 'tst', 'testdir'}, + {limit = math.huge, type = 'directory', path = './runtime/'} + ) + + -- get all files ending with .cpp or .hpp inside lib/ + local cpp_hpp = vim.fs.find(function(name, path) + return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$') + end, {limit = math.huge, type = 'file'}) +< + Parameters: ~ - • {names} (string|table|fun(name: string): boolean) Names of the files - and directories to find. Must be base names, paths and globs - are not supported. The function is called per file and - directory within the traversed directories to test if they - match {names}. + • {names} (string|table|fun(name: string, path: string): boolean) Names + of the files and directories to find. Must be base names, + paths and globs are not supported when {names} is a string or + a table. If {names} is a function, it is called for each + traversed file and directory with args: + • name: base name of the current item + • path: full path of the current item The function should + return `true` if the given file or directory is considered + a match. • {opts} (table) Optional keyword arguments: • path (string): Path to begin searching from. If omitted, the |current-directory| is used. diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index a0d2c4c339..2c3fc64d57 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -144,11 +144,34 @@ end --- The search can be narrowed to find only files or only directories by --- specifying {type} to be "file" or "directory", respectively. --- ----@param names (string|table|fun(name: string): boolean) Names of the files +--- Examples: +---
lua
+--- -- location of Cargo.toml from the current buffer's path
+--- local cargo = vim.fs.find('Cargo.toml', {
+---   upward = true,
+---   stop = vim.loop.os_homedir(),
+---   path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
+--- })
+---
+--- -- list all test directories under the runtime directory
+--- local test_dirs = vim.fs.find(
+---   {'test', 'tst', 'testdir'},
+---   {limit = math.huge, type = 'directory', path = './runtime/'}
+--- )
+---
+--- -- get all files ending with .cpp or .hpp inside lib/
+--- local cpp_hpp = vim.fs.find(function(name, path)
+---   return name:match('.*%.[ch]pp$') and path:match('[/\\\\]lib$')
+--- end, {limit = math.huge, type = 'file'})
+--- 
+--- +---@param names (string|table|fun(name: string, path: string): boolean) Names of the files --- and directories to find. ---- Must be base names, paths and globs are not supported. ---- The function is called per file and directory within the ---- traversed directories to test if they match {names}. +--- Must be base names, paths and globs are not supported when {names} is a string or a table. +--- If {names} is a function, it is called for each traversed file and directory with args: +--- - name: base name of the current item +--- - path: full path of the current item +--- The function should return `true` if the given file or directory is considered a match. --- ---@param opts (table) Optional keyword arguments: --- - path (string): Path to begin searching from. If @@ -201,7 +224,7 @@ function M.find(names, opts) test = function(p) local t = {} for name, type in M.dir(p) do - if names(name) and (not opts.type or opts.type == type) then + if (not opts.type or opts.type == type) and names(name, p) then table.insert(t, join_paths(p, name)) end end @@ -250,7 +273,7 @@ function M.find(names, opts) for other, type_ in M.dir(dir) do local f = join_paths(dir, other) if type(names) == 'function' then - if names(other) and (not opts.type or opts.type == type_) then + if (not opts.type or opts.type == type_) and names(other, dir) then if add(f) then return matches end -- cgit From b0b4c310973c2b419350e3c05c772596b1c334e9 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 2 Mar 2023 10:01:42 -0500 Subject: refactor: rename show_tree => inspect_tree #22474 Problem: "show" is potentially a new verb that we can avoid (there is already "open" and "echo"). Even if we can't avoid it, the behavior of `show_tree` fits well in the "inspect" family of functions: a way for users to introspect/reflect on the state of Nvim. Existing "inspect" functions: vim.inspect() vim.inspect_pos() vim.treesitter.inspect_language() nvim__inspect_cell Solution: Rename `show_tree` to `inspect_tree`. --- runtime/doc/news.txt | 2 +- runtime/doc/treesitter.txt | 50 +++++++++++++++++++++--------------------- runtime/lua/vim/treesitter.lua | 8 ++++++- 3 files changed, 33 insertions(+), 27 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 919f8ceaee..226444ccb5 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -89,7 +89,7 @@ The following new APIs or features were added. See |lsp-semantic_tokens| for more information. -• |vim.treesitter.show_tree()| opens a split window showing a text +• |vim.treesitter.inspect_tree()| opens a split window showing a text representation of the nodes in a language tree for the current buffer. • Added support for the `willSave` and `willSaveWaitUntil` capabilities to the diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index fdea84282f..b75e879424 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -595,6 +595,31 @@ get_string_parser({str}, {lang}, {opts}) Return: ~ |LanguageTree| object to use for parsing +inspect_tree({opts}) *vim.treesitter.inspect_tree()* + Open a window that displays a textual representation of the nodes in the + language tree. + + While in the window, press "a" to toggle display of anonymous nodes, "I" + to toggle the display of the source language of each node, and press + to jump to the node under the cursor in the source buffer. + + Parameters: ~ + • {opts} (table|nil) Optional options table with the following possible + keys: + • lang (string|nil): The language of the source buffer. If + omitted, the filetype of the source buffer is used. + • bufnr (integer|nil): Buffer to draw the tree into. If + omitted, a new buffer is created. + • winid (integer|nil): Window id to display the tree buffer + in. If omitted, a new window is created with {command}. + • command (string|nil): Vimscript command to create the + window. Default value is "topleft 60vnew". Only used when + {winid} is nil. + • title (string|fun(bufnr:integer):string|nil): Title of the + window. If a function, it accepts the buffer number of the + source buffer as its only argument and should return a + string. + is_ancestor({dest}, {source}) *vim.treesitter.is_ancestor()* Determines whether a node is the ancestor of another @@ -627,31 +652,6 @@ node_contains({node}, {range}) *vim.treesitter.node_contains()* Return: ~ (boolean) True if the {node} contains the {range} -show_tree({opts}) *vim.treesitter.show_tree()* - Open a window that displays a textual representation of the nodes in the - language tree. - - While in the window, press "a" to toggle display of anonymous nodes, "I" - to toggle the display of the source language of each node, and press - to jump to the node under the cursor in the source buffer. - - Parameters: ~ - • {opts} (table|nil) Optional options table with the following possible - keys: - • lang (string|nil): The language of the source buffer. If - omitted, the filetype of the source buffer is used. - • bufnr (integer|nil): Buffer to draw the tree into. If - omitted, a new buffer is created. - • winid (integer|nil): Window id to display the tree buffer - in. If omitted, a new window is created with {command}. - • command (string|nil): Vimscript command to create the - window. Default value is "topleft 60vnew". Only used when - {winid} is nil. - • title (string|fun(bufnr:integer):string|nil): Title of the - window. If a function, it accepts the buffer number of the - source buffer as its only argument and should return a - string. - start({bufnr}, {lang}) *vim.treesitter.start()* Starts treesitter highlighting for a buffer diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index fead7b7b1b..412140b757 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -436,7 +436,7 @@ end --- - title (string|fun(bufnr:integer):string|nil): Title of the window. If a --- function, it accepts the buffer number of the source buffer as its only --- argument and should return a string. -function M.show_tree(opts) +function M.inspect_tree(opts) vim.validate({ opts = { opts, 't', true }, }) @@ -622,6 +622,12 @@ function M.show_tree(opts) }) end +---@deprecated +---@private +function M.show_tree() + vim.deprecate('show_tree', 'inspect_tree', '0.9', nil, false) +end + --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': ---
lua
 --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
-- 
cgit 


From f449121764c19cebda7b8b2c970b76bc8121bae7 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Thu, 2 Mar 2023 18:03:11 +0100
Subject: feat(treesitter): add :InspectTree command (#22477)

---
 runtime/doc/news.txt           | 5 +++--
 runtime/doc/treesitter.txt     | 2 ++
 runtime/lua/vim/treesitter.lua | 2 ++
 runtime/plugin/nvim.lua        | 4 ++++
 4 files changed, 11 insertions(+), 2 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 226444ccb5..0ffd335520 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -89,8 +89,9 @@ The following new APIs or features were added.
 
   See |lsp-semantic_tokens| for more information.
 
-• |vim.treesitter.inspect_tree()| opens a split window showing a text
-  representation of the nodes in a language tree for the current buffer.
+• |vim.treesitter.inspect_tree()| and |:InspectTree| opens a split window
+  showing a text representation of the nodes in a language tree for the current
+  buffer.
 
 • Added support for the `willSave` and `willSaveWaitUntil` capabilities to the
   LSP client. `willSaveWaitUntil` allows a server to modify a document before it
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index b75e879424..5ac24de70a 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -603,6 +603,8 @@ inspect_tree({opts})                           *vim.treesitter.inspect_tree()*
     to toggle the display of the source language of each node, and press
      to jump to the node under the cursor in the source buffer.
 
+    Can also be shown with `:InspectTree`.                      *:InspectTree*
+
     Parameters: ~
       • {opts}  (table|nil) Optional options table with the following possible
                 keys:
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 412140b757..09e3814a17 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -424,6 +424,8 @@ end
 --- display of the source language of each node, and press  to jump to the node under the
 --- cursor in the source buffer.
 ---
+--- Can also be shown with `:InspectTree`. *:InspectTree*
+---
 ---@param opts table|nil Optional options table with the following possible keys:
 ---                      - lang (string|nil): The language of the source buffer. If omitted, the
 ---                        filetype of the source buffer is used.
diff --git a/runtime/plugin/nvim.lua b/runtime/plugin/nvim.lua
index 815886f896..762e9519db 100644
--- a/runtime/plugin/nvim.lua
+++ b/runtime/plugin/nvim.lua
@@ -5,3 +5,7 @@ vim.api.nvim_create_user_command('Inspect', function(cmd)
     vim.show_pos()
   end
 end, { desc = 'Inspect highlights and extmarks at the cursor', bang = true })
+
+vim.api.nvim_create_user_command('InspectTree', function()
+  vim.treesitter.inspect_tree()
+end, { desc = 'Inspect treesitter language tree for buffer' })
-- 
cgit 


From 2eeafc43c43697d18d5634f8f81bf9e60a880e17 Mon Sep 17 00:00:00 2001
From: Gregory Anders 
Date: Thu, 2 Mar 2023 14:06:11 -0700
Subject: fix(treesitter): maintain cursor position when toggling anonymous
 nodes

When toggling anonymous nodes in the :InspectTree window, keep the
cursor fixed relative to the node within the tree. This prevents the
cursor from jumping.
---
 runtime/lua/vim/treesitter.lua | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

(limited to 'runtime')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 09e3814a17..b2909f2154 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -506,8 +506,26 @@ function M.inspect_tree(opts)
   a.nvim_buf_set_keymap(b, 'n', 'a', '', {
     desc = 'Toggle anonymous nodes',
     callback = function()
+      local row, col = unpack(a.nvim_win_get_cursor(w))
+      local curnode = pg:get(row)
+      while curnode and not curnode.named do
+        row = row - 1
+        curnode = pg:get(row)
+      end
+
       pg.opts.anon = not pg.opts.anon
       pg:draw(b)
+
+      if not curnode then
+        return
+      end
+
+      local id = curnode.id
+      for i, node in pg:iter() do
+        if node.id == id then
+          a.nvim_win_set_cursor(w, { i, col })
+        end
+      end
     end,
   })
   a.nvim_buf_set_keymap(b, 'n', 'I', '', {
-- 
cgit 


From 86ff239240e955ef6da95bc9c8814cfd4492f5aa Mon Sep 17 00:00:00 2001
From: Gregory Anders 
Date: Thu, 2 Mar 2023 14:15:18 -0700
Subject: refactor(treesitter): use string.format to create lines

---
 runtime/lua/vim/treesitter/playground.lua | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua
index fd5b687195..992433961f 100644
--- a/runtime/lua/vim/treesitter/playground.lua
+++ b/runtime/lua/vim/treesitter/playground.lua
@@ -146,9 +146,9 @@ local decor_ns = api.nvim_create_namespace('ts.playground')
 ---@return string
 local function get_range_str(lnum, col, end_col, end_lnum)
   if lnum == end_lnum then
-    return string.format('[%d:%d-%d]', lnum + 1, col + 1, end_col)
+    return string.format('[%d:%d - %d]', lnum + 1, col + 1, end_col)
   end
-  return string.format('[%d:%d-%d:%d]', lnum + 1, col + 1, end_lnum + 1, end_col)
+  return string.format('[%d:%d - %d:%d]', lnum + 1, col + 1, end_lnum + 1, end_col)
 end
 
 --- Write the contents of this Playground into {bufnr}.
@@ -163,7 +163,8 @@ function TSPlayground:draw(bufnr)
   for _, item in self:iter() do
     local range_str = get_range_str(item.lnum, item.col, item.end_lnum, item.end_col)
     local lang_str = self.opts.lang and string.format(' %s', item.lang) or ''
-    local line = string.rep(' ', item.depth) .. item.text .. '; ' .. range_str .. lang_str
+    local line =
+      string.format('%s%s ; %s%s', string.rep(' ', item.depth), item.text, range_str, lang_str)
 
     if self.opts.lang then
       lang_hl_marks[#lang_hl_marks + 1] = {
-- 
cgit 


From fdb6b4d2e729211f0526ce75c6a3fcc636859bfd Mon Sep 17 00:00:00 2001
From: Amaan Qureshi 
Date: Thu, 2 Mar 2023 17:29:03 -0500
Subject: vim-patch:9.0.1368: Bass files are not recognized (#22485)

Problem:    Bass files are not recognized.
Solution:   Add patterns for Bass files. (Amaan Qureshi, closes vim/vim#12088)

https://github.com/vim/vim/commit/4ed914b18a47192f79f342bea5e8f59e120d5260
---
 runtime/lua/vim/filetype.lua | 1 +
 1 file changed, 1 insertion(+)

(limited to 'runtime')

diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 256c053801..8911eafc71 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -156,6 +156,7 @@ local extension = {
   bas = function(path, bufnr)
     return require('vim.filetype.detect').bas(bufnr)
   end,
+  bass = 'bass',
   bi = function(path, bufnr)
     return require('vim.filetype.detect').bas(bufnr)
   end,
-- 
cgit 


From 6d4f48182131c36d57589eefd4cefe3c70256d04 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Fri, 3 Mar 2023 09:44:02 +0000
Subject: fix(treesitter): disallow empty filetypes

Fixes #22473
---
 runtime/lua/vim/treesitter.lua          |  3 ++-
 runtime/lua/vim/treesitter/language.lua | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 09e3814a17..f80da433b1 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -47,7 +47,8 @@ function M._create_parser(bufnr, lang, opts)
 
   vim.fn.bufload(bufnr)
 
-  language.add(lang, { filetype = vim.bo[bufnr].filetype })
+  local ft = vim.bo[bufnr].filetype
+  language.add(lang, { filetype = ft ~= '' and ft or nil })
 
   local self = LanguageTree.new(bufnr, lang, opts)
 
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 5bcc786e88..5f34d9cd56 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -60,6 +60,16 @@ function M.add(lang, opts)
     filetype = { filetype, { 'string', 'table' }, true },
   })
 
+  if filetype == '' then
+    error(string.format("'%s' is not a valid filetype", filetype))
+  elseif type(filetype) == 'table' then
+    for _, f in ipairs(filetype) do
+      if f == '' then
+        error(string.format("'%s' is not a valid filetype", filetype))
+      end
+    end
+  end
+
   M.register(lang, filetype or lang)
 
   if vim._ts_has_language(lang) then
-- 
cgit 


From f0a2ffab2923202f4454860ba1a7c7bd0e035ed2 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Fri, 3 Mar 2023 20:05:59 +0900
Subject: fix(treesitter): typos in _range.lua

fix(treesitter): typos _range.lua
---
 runtime/lua/vim/treesitter/_range.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua
index b87542c20f..8decd3a1fd 100644
--- a/runtime/lua/vim/treesitter/_range.lua
+++ b/runtime/lua/vim/treesitter/_range.lua
@@ -61,7 +61,7 @@ function M.intercepts(r1, r2)
   local off_1 = #r1 == 6 and 1 or 0
   local off_2 = #r1 == 6 and 1 or 0
 
-  local srow_1, scol_1, erow_1, ecol_1 = r1[1], r2[2], r1[3 + off_1], r1[4 + off_1]
+  local srow_1, scol_1, erow_1, ecol_1 = r1[1], r1[2], r1[3 + off_1], r1[4 + off_1]
   local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2]
 
   -- r1 is above r2
@@ -85,7 +85,7 @@ function M.contains(r1, r2)
   local off_1 = #r1 == 6 and 1 or 0
   local off_2 = #r1 == 6 and 1 or 0
 
-  local srow_1, scol_1, erow_1, ecol_1 = r1[1], r2[2], r1[3 + off_1], r1[4 + off_1]
+  local srow_1, scol_1, erow_1, ecol_1 = r1[1], r1[2], r1[3 + off_1], r1[4 + off_1]
   local srow_2, scol_2, erow_2, ecol_2 = r2[1], r2[2], r2[3 + off_2], r2[4 + off_2]
 
   -- start doesn't fit
-- 
cgit 


From 98e051783c26239a47c5cd643e9aea7146b097bd Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Fri, 3 Mar 2023 14:27:30 +0100
Subject: feat(treesitter): bundle query parser and queries (#22483)

skip injections for now
---
 runtime/queries/lua/injections.scm   |  8 ++++----
 runtime/queries/query/folds.scm      |  6 ++++++
 runtime/queries/query/highlights.scm | 34 ++++++++++++++++++++++++++++++++++
 runtime/queries/vim/injections.scm   |  4 ++--
 4 files changed, 46 insertions(+), 6 deletions(-)
 create mode 100644 runtime/queries/query/folds.scm
 create mode 100644 runtime/queries/query/highlights.scm

(limited to 'runtime')

diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm
index 0e67329139..69acbbbe9f 100644
--- a/runtime/queries/lua/injections.scm
+++ b/runtime/queries/lua/injections.scm
@@ -11,10 +11,10 @@
   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"))
+((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"))
diff --git a/runtime/queries/query/folds.scm b/runtime/queries/query/folds.scm
new file mode 100644
index 0000000000..47dd965126
--- /dev/null
+++ b/runtime/queries/query/folds.scm
@@ -0,0 +1,6 @@
+[
+  (named_node)
+  (predicate)
+  (grouping)
+  (list)
+] @fold
diff --git a/runtime/queries/query/highlights.scm b/runtime/queries/query/highlights.scm
new file mode 100644
index 0000000000..ee31a7e7ef
--- /dev/null
+++ b/runtime/queries/query/highlights.scm
@@ -0,0 +1,34 @@
+(string) @string
+(escape_sequence) @string.escape
+(capture (identifier) @type)
+(anonymous_node (identifier) @string)
+(predicate name: (identifier) @function)
+(named_node name: (identifier) @variable)
+(field_definition name: (identifier) @property)
+(negated_field "!" @operator (identifier) @property)
+(comment) @comment @spell
+
+(quantifier) @operator
+(predicate_type) @punctuation.special
+
+"." @operator
+
+[
+  "["
+  "]"
+  "("
+  ")"
+] @punctuation.bracket
+
+":" @punctuation.delimiter
+["@" "#"] @punctuation.special
+"_" @constant
+
+((parameters (identifier) @number)
+ (#match? @number "^[-+]?[0-9]+(.[0-9]+)?$"))
+
+((program . (comment) @include)
+ (#match? @include "^;\ +inherits\ *:"))
+
+((program . (comment) @preproc)
+ (#match? @preproc "^; +extends"))
diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm
index fdd025bfd9..b53643dc1a 100644
--- a/runtime/queries/vim/injections.scm
+++ b/runtime/queries/vim/injections.scm
@@ -24,5 +24,5 @@
     "patchexpr" "pex"
     "charconvert" "ccv"))
 
-(comment) @comment
-(line_continuation_comment) @comment
+; (comment) @comment
+; (line_continuation_comment) @comment
-- 
cgit 


From 8414cfe7f4d8888698343cb54a3f373a28b365db Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Thu, 2 Mar 2023 20:46:59 +0100
Subject: docs: fix vim.treesitter tags

Problem:
Help tags like vim.treesitter.language.add() are confusing because
`vim.treesitter.language` is (thankfully) not a user-facing module.

Solution:
Ignore the "fstem" when generating "treesitter" tags.
---
 runtime/doc/deprecated.txt                  |  2 +-
 runtime/doc/news.txt                        | 10 ++---
 runtime/doc/treesitter.txt                  | 69 ++++++++---------------------
 runtime/lua/vim/treesitter/highlighter.lua  |  4 +-
 runtime/lua/vim/treesitter/languagetree.lua | 20 ++++-----
 runtime/lua/vim/treesitter/query.lua        |  5 +--
 6 files changed, 38 insertions(+), 72 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index 42dfb53e77..3d861b07b3 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -120,7 +120,7 @@ LSP FUNCTIONS
 					or |vim.lsp.buf.format()| instead.
 
 TREESITTER FUNCTIONS
-- *vim.treesitter.language.require_language()*	Use |vim.treesitter.language.add()|
+- *vim.treesitter.language.require_language()*	Use |vim.treesitter.add()|
 						instead.
 - *vim.treesitter.get_node_at_pos()*		Use |vim.treesitter.get_node()|
 						instead.
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 0ffd335520..cda4792c9e 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -162,11 +162,10 @@ The following new APIs or features were added.
 • Treesitter captures can now be transformed by directives. This will allow
   more complicated dynamic language injections.
 
-• |vim.treesitter.query.get_node_text()| now accepts a `metadata` option for
-  writing custom directives using |vim.treesitter.query.add_directive()|.
+• |vim.treesitter.get_node_text()| now accepts a `metadata` option for
+  writing custom directives using |vim.treesitter.add_directive()|.
 
-• |vim.treesitter.language.add()| as a new replacement for
-  `vim.treesitter.language.require_language`.
+• |vim.treesitter.add()| replaces `vim.treesitter.language.require_language`.
 
 • `require'bit'` is now always available |lua-bit|
 
@@ -225,8 +224,7 @@ DEPRECATIONS                                                *news-deprecations*
 The following functions are now deprecated and will be removed in the next
 release.
 
-• `vim.treesitter.language.require_language()` has been deprecated in favour
-  of |vim.treesitter.language.add()|.
+• |vim.treesitter.add()| replaces `vim.treesitter.language.require_language()`
 
 • |vim.treesitter.get_node_at_pos()| and |vim.treesitter.get_node_at_cursor()|
   are both deprecated in favor of |vim.treesitter.get_node()|.
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 5ac24de70a..94a93bdbbb 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -272,9 +272,8 @@ The following predicates are built in:
 Each predicate has a `not-` prefixed predicate that is just the negation of
 the predicate.
 
-Further predicates can be added via |vim.treesitter.query.add_predicate()|.
-Use |vim.treesitter.query.list_predicates()| to list all available
-predicates.
+Further predicates can be added via |vim.treesitter.add_predicate()|.
+Use |vim.treesitter.list_predicates()| to list all available predicates.
 
 
 TREESITTER QUERY DIRECTIVES                            *treesitter-directives*
@@ -316,9 +315,8 @@ The following directives are built in:
             ((identifier) @constant (#offset! @constant 0 1 0 -1))
 <
 
-Further directives can be added via |vim.treesitter.query.add_directive()|.
-Use |vim.treesitter.query.list_directives()| to list all available
-directives.
+Further directives can be added via |vim.treesitter.add_directive()|.
+Use |vim.treesitter.list_directives()| to list all available directives.
 
 
 TREESITTER QUERY MODELINES                          *treesitter-query-modeline*
@@ -690,7 +688,7 @@ stop({bufnr})                                          *vim.treesitter.stop()*
 ==============================================================================
 Lua module: vim.treesitter.language                  *lua-treesitter-language*
 
-add({lang}, {opts})                            *vim.treesitter.language.add()*
+add({lang}, {opts})                                     *vim.treesitter.add()*
     Asserts that a parser for the language {lang} is installed.
 
     Parsers are searched in the `parser` runtime directory, or the provided
@@ -708,14 +706,14 @@ add({lang}, {opts})                            *vim.treesitter.language.add()*
                 • symbol_name (string|nil) Internal symbol name for the
                   language to load
 
-get_lang({filetype})                      *vim.treesitter.language.get_lang()*
+get_lang({filetype})                               *vim.treesitter.get_lang()*
     Parameters: ~
       • {filetype}  (string)
 
     Return: ~
         (string|nil)
 
-inspect_language({lang})          *vim.treesitter.language.inspect_language()*
+inspect_language({lang})                   *vim.treesitter.inspect_language()*
     Inspects the provided language.
 
     Inspecting provides some useful information on the language like node
@@ -727,7 +725,7 @@ inspect_language({lang})          *vim.treesitter.language.inspect_language()*
     Return: ~
         (table)
 
-register({lang}, {filetype})              *vim.treesitter.language.register()*
+register({lang}, {filetype})                       *vim.treesitter.register()*
     Register a lang to be used for a filetype (or list of filetypes).
 
     Parameters: ~
@@ -738,7 +736,7 @@ register({lang}, {filetype})              *vim.treesitter.language.register()*
 ==============================================================================
 Lua module: vim.treesitter.query                        *lua-treesitter-query*
 
-                                        *vim.treesitter.query.add_directive()*
+                                              *vim.treesitter.add_directive()*
 add_directive({name}, {handler}, {force})
     Adds a new directive to be used in queries
 
@@ -760,7 +758,7 @@ add_directive({name}, {handler}, {force})
                      the predicate `{ "#set!", "conceal", "-" }`
       • {force}    (boolean|nil)
 
-                                        *vim.treesitter.query.add_predicate()*
+                                              *vim.treesitter.add_predicate()*
 add_predicate({name}, {handler}, {force})
     Adds a new predicate to be used in queries
 
@@ -768,11 +766,11 @@ add_predicate({name}, {handler}, {force})
       • {name}     (string) Name of the predicate, without leading #
       • {handler}  function(match:table, pattern:string,
                    bufnr:number, predicate:string[])
-                   • see |vim.treesitter.query.add_directive()| for argument
+                   • see |vim.treesitter.add_directive()| for argument
                      meanings
       • {force}    (boolean|nil)
 
-                                        *vim.treesitter.query.get_node_text()*
+                                              *vim.treesitter.get_node_text()*
 get_node_text({node}, {source}, {opts})
     Gets the text corresponding to a given node
 
@@ -785,12 +783,12 @@ get_node_text({node}, {source}, {opts})
                     true)
                   • metadata (table) Metadata of a specific capture. This
                     would be set to `metadata[capture_id]` when using
-                    |vim.treesitter.query.add_directive()|.
+                    |vim.treesitter.add_directive()|.
 
     Return: ~
         (string[]|string|nil)
 
-get_query({lang}, {query_name})             *vim.treesitter.query.get_query()*
+get_query({lang}, {query_name})                   *vim.treesitter.get_query()*
     Returns the runtime query {query_name} for {lang}.
 
     Parameters: ~
@@ -800,7 +798,7 @@ get_query({lang}, {query_name})             *vim.treesitter.query.get_query()*
     Return: ~
         Query|nil Parsed query
 
-                                      *vim.treesitter.query.get_query_files()*
+                                            *vim.treesitter.get_query_files()*
 get_query_files({lang}, {query_name}, {is_included})
     Gets the list of files used to make up a query
 
@@ -814,19 +812,19 @@ get_query_files({lang}, {query_name}, {is_included})
         string[] query_files List of files to load for given query and
         language
 
-list_directives()                     *vim.treesitter.query.list_directives()*
+list_directives()                           *vim.treesitter.list_directives()*
     Lists the currently available directives to use in queries.
 
     Return: ~
         string[] List of supported directives.
 
-list_predicates()                     *vim.treesitter.query.list_predicates()*
+list_predicates()                           *vim.treesitter.list_predicates()*
     Lists the currently available predicates to use in queries.
 
     Return: ~
         string[] List of supported predicates.
 
-parse_query({lang}, {query})              *vim.treesitter.query.parse_query()*
+parse_query({lang}, {query})                    *vim.treesitter.parse_query()*
     Parse {query} as a string. (If the query is in a file, the caller should
     read the contents into a string before calling).
 
@@ -915,8 +913,7 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
         (fun(): integer, table, table): pattern id, match,
         metadata
 
-                                            *vim.treesitter.query.set_query()*
-set_query({lang}, {query_name}, {text})
+set_query({lang}, {query_name}, {text})           *vim.treesitter.set_query()*
     Sets the runtime query named {query_name} for {lang}
 
     This allows users to override any runtime files and/or configuration set
@@ -931,17 +928,6 @@ set_query({lang}, {query_name}, {text})
 ==============================================================================
 Lua module: vim.treesitter.highlighter            *lua-treesitter-highlighter*
 
-new({tree}, {opts})                         *vim.treesitter.highlighter.new()*
-    Creates a new highlighter using
-
-    Parameters: ~
-      • {tree}  |LanguageTree| parser object to use for highlighting
-      • {opts}  (table|nil) Configuration of the highlighter:
-                • queries table overwrite queries used by the highlighter
-
-    Return: ~
-        TSHighlighter Created highlighter object
-
 TSHighlighter:destroy({self})                        *TSHighlighter:destroy()*
     Removes all internal references to the highlighter
 
@@ -1103,21 +1089,4 @@ LanguageTree:trees({self})                              *LanguageTree:trees()*
     Parameters: ~
       • {self}
 
-new({source}, {lang}, {opts})              *vim.treesitter.languagetree.new()*
-    A |LanguageTree| holds the treesitter parser for a given language {lang}
-    used to parse a buffer. As the buffer may contain injected languages, the LanguageTree needs to store parsers for these child languages as well (which in turn
-    may contain child languages themselves, hence the name).
-
-    Parameters: ~
-      • {source}  (integer|string) Buffer or a string of text to parse
-      • {lang}    (string) Root language this tree represents
-      • {opts}    (table|nil) Optional keyword arguments:
-                  • injections table Mapping language to injection query
-                    strings. This is useful for overriding the built-in
-                    runtime file searching for the injection language query
-                    per language.
-
-    Return: ~
-        |LanguageTree| parser object
-
  vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 8adaa4ef2f..e3deaf6ba6 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -58,7 +58,9 @@ function TSHighlighterQuery:query()
   return self._query
 end
 
---- Creates a new highlighter using @param tree
+---@private
+---
+--- Creates a highlighter for `tree`.
 ---
 ---@param tree LanguageTree parser object to use for highlighting
 ---@param opts (table|nil) Configuration of the highlighter:
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 43fb866896..1bc7971eba 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -38,18 +38,16 @@ local LanguageTree = {}
 
 LanguageTree.__index = LanguageTree
 
---- A |LanguageTree| holds the treesitter parser for a given language {lang} used
---- to parse a buffer. As the buffer may contain injected languages, the LanguageTree
---- needs to store parsers for these child languages as well (which in turn may contain
---- child languages themselves, hence the name).
+--- @private
 ---
----@param source (integer|string) Buffer or a string of text to parse
----@param lang string Root language this tree represents
----@param opts (table|nil) Optional keyword arguments:
----             - injections table Mapping language to injection query strings.
----                                This is useful for overriding the built-in
----                                runtime file searching for the injection language
----                                query per language.
+--- |LanguageTree| contains a tree of parsers: the root treesitter parser for {lang} and any
+--- "injected" language parsers, which themselves may inject other languages, recursively.
+---
+---@param source (integer|string) Buffer or text string to parse
+---@param lang string Root language of this tree
+---@param opts (table|nil) Optional arguments:
+---             - injections table Map of language to injection query strings. Overrides the
+---                                built-in runtime file searching for language injections.
 ---@return LanguageTree parser object
 function LanguageTree.new(source, lang, opts)
   language.add(lang)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 13d98a0625..4e9871b59d 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -273,8 +273,7 @@ end
 ---@param opts (table|nil) Optional parameters.
 ---          - concat: (boolean) Concatenate result in a string (default true)
 ---          - metadata (table) Metadata of a specific capture. This would be
----            set to `metadata[capture_id]` when using
----            |vim.treesitter.query.add_directive()|.
+---            set to `metadata[capture_id]` when using |vim.treesitter.add_directive()|.
 ---@return (string[]|string|nil)
 function M.get_node_text(node, source, opts)
   opts = opts or {}
@@ -486,7 +485,7 @@ local directive_handlers = {
 ---
 ---@param name string Name of the predicate, without leading #
 ---@param handler function(match:table, pattern:string, bufnr:number, predicate:string[])
----   - see |vim.treesitter.query.add_directive()| for argument meanings
+---   - see |vim.treesitter.add_directive()| for argument meanings
 ---@param force boolean|nil
 function M.add_predicate(name, handler, force)
   if predicate_handlers[name] and not force then
-- 
cgit 


From bf90ceb5488ea2b41eb53335984f017785aefea9 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Fri, 3 Mar 2023 07:52:57 -0700
Subject: fix(treesitter): break early from loop when match is found (#22499)

Fixup to #22484.
---
 runtime/lua/vim/treesitter.lua | 1 +
 1 file changed, 1 insertion(+)

(limited to 'runtime')

diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index b63247aa2c..ee66ba9f9b 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -525,6 +525,7 @@ function M.inspect_tree(opts)
       for i, node in pg:iter() do
         if node.id == id then
           a.nvim_win_set_cursor(w, { i, col })
+          break
         end
       end
     end,
-- 
cgit 


From a4f443994bb91321b00f29af9e6357df9102ce75 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Sat, 4 Mar 2023 10:45:20 +0100
Subject: docs(luvref): update to version bump (#22508)

---
 runtime/doc/luvref.txt | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt
index 66cee0649c..0fdd010880 100644
--- a/runtime/doc/luvref.txt
+++ b/runtime/doc/luvref.txt
@@ -3360,14 +3360,17 @@ file system operations, as well as `getaddrinfo` and `getnameinfo` requests.
 uv.new_work({work_callback}, {after_work_callback})              *uv.new_work()*
 
                 Parameters:
-                - `work_callback`: `function`
+                - `work_callback`: `function` or `string`
                   - `...`: `threadargs` passed to/from
                     `uv.queue_work(work_ctx, ...)`
                 - `after_work_callback`: `function`
                   - `...`: `threadargs` returned from `work_callback`
 
                 Creates and initializes a new `luv_work_ctx_t` (not
-                `uv_work_t`). Returns the Lua userdata wrapping it.
+                `uv_work_t`).
+                `work_callback` is a Lua function or a string containing Lua
+                code or bytecode dumped from a function. Returns the Lua
+                userdata wrapping it.
 
                 Returns: `luv_work_ctx_t userdata`
 
@@ -3468,16 +3471,16 @@ uv.new_thread([{options}, ] {entry}, {...})                    *uv.new_thread()*
                 Parameters:
                 - `options`: `table` or `nil`
                   - `stack_size`: `integer` or `nil`
-                - `entry`: `function`
+                - `entry`: `function` or `string`
                 - `...`: `threadargs` passed to `entry`
 
                 Creates and initializes a `luv_thread_t` (not `uv_thread_t`).
                 Returns the Lua userdata wrapping it and asynchronously
-                executes `entry`, which can be either a Lua function or a Lua
-                function dumped to a string. Additional arguments `...` are
-                passed to the `entry` function and an optional `options` table
-                may be provided. Currently accepted `option` fields are
-                `stack_size`.
+                executes `entry`, which can be either a Lua function or a
+                string containing Lua code or bytecode dumped from a function.
+                Additional arguments `...` are passed to the `entry` function
+                and an optional `options` table may be provided. Currently
+                accepted `option` fields are `stack_size`.
 
                 Returns: `luv_thread_t userdata` or `fail`
 
-- 
cgit 


From 128b82103ba477482bdfaf10ec71e0986876cca1 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:04:05 +0900
Subject: docs(treesitter): number → integer (#22513)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/treesitter.txt                | 10 +++++-----
 runtime/lua/vim/treesitter/playground.lua | 22 +++++++++++-----------
 runtime/lua/vim/treesitter/query.lua      | 12 ++++++------
 3 files changed, 22 insertions(+), 22 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 94a93bdbbb..855fc6bdc6 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -748,7 +748,7 @@ add_directive({name}, {handler}, {force})
     Parameters: ~
       • {name}     (string) Name of the directive, without leading #
       • {handler}  function(match:table, pattern:string,
-                   bufnr:number, predicate:string[], metadata:table)
+                   bufnr:integer, predicate:string[], metadata:table)
                    • match: see |treesitter-query|
                      • node-level data are accessible via `match[capture_id]`
 
@@ -765,7 +765,7 @@ add_predicate({name}, {handler}, {force})
     Parameters: ~
       • {name}     (string) Name of the predicate, without leading #
       • {handler}  function(match:table, pattern:string,
-                   bufnr:number, predicate:string[])
+                   bufnr:integer, predicate:string[])
                    • see |vim.treesitter.add_directive()| for argument
                      meanings
       • {force}    (boolean|nil)
@@ -776,7 +776,7 @@ get_node_text({node}, {source}, {opts})
 
     Parameters: ~
       • {node}    |TSNode|
-      • {source}  (number|string) Buffer or string from which the {node} is
+      • {source}  (integer|string) Buffer or string from which the {node} is
                   extracted
       • {opts}    (table|nil) Optional parameters.
                   • concat: (boolean) Concatenate result in a string (default
@@ -872,8 +872,8 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop})
       • {node}    |TSNode| under which the search will occur
       • {source}  (integer|string) Source buffer or string to extract text
                   from
-      • {start}   (number) Starting line for the search
-      • {stop}    (number) Stopping line for the search (end-exclusive)
+      • {start}   (integer) Starting line for the search
+      • {stop}    (integer) Stopping line for the search (end-exclusive)
       • {self}
 
     Return: ~
diff --git a/runtime/lua/vim/treesitter/playground.lua b/runtime/lua/vim/treesitter/playground.lua
index 992433961f..7f181c23fd 100644
--- a/runtime/lua/vim/treesitter/playground.lua
+++ b/runtime/lua/vim/treesitter/playground.lua
@@ -1,7 +1,7 @@
 local api = vim.api
 
 ---@class TSPlayground
----@field ns number API namespace
+---@field ns integer API namespace
 ---@field opts table Options table with the following keys:
 ---                  - anon (boolean): If true, display anonymous nodes
 ---                  - lang (boolean): If true, display the language alongside each node
@@ -10,14 +10,14 @@ local api = vim.api
 local TSPlayground = {}
 ---
 ---@class Node
----@field id number Node id
+---@field id integer Node id
 ---@field text string Node text
 ---@field named boolean True if this is a named (non-anonymous) node
----@field depth number Depth of the node within the tree
----@field lnum number Beginning line number of this node in the source buffer
----@field col number Beginning column number of this node in the source buffer
----@field end_lnum number Final line number of this node in the source buffer
----@field end_col number Final column number of this node in the source buffer
+---@field depth integer Depth of the node within the tree
+---@field lnum integer Beginning line number of this node in the source buffer
+---@field col integer Beginning column number of this node in the source buffer
+---@field end_lnum integer Final line number of this node in the source buffer
+---@field end_col integer Final column number of this node in the source buffer
 ---@field lang string Source language of this node
 ---@field root TSNode
 
@@ -34,7 +34,7 @@ local TSPlayground = {}
 --- table maps nodes in the primary tree to root nodes of injected trees.
 ---
 ---@param node TSNode Starting node to begin traversal |tsnode|
----@param depth number Current recursion depth
+---@param depth integer Current recursion depth
 ---@param lang string Language of the tree currently being traversed
 ---@param injections table Mapping of node ids to root nodes of injected language trees (see
 ---                        explanation above)
@@ -153,7 +153,7 @@ end
 
 --- Write the contents of this Playground into {bufnr}.
 ---
----@param bufnr number Buffer number to write into.
+---@param bufnr integer Buffer number to write into.
 ---@private
 function TSPlayground:draw(bufnr)
   vim.bo[bufnr].modifiable = true
@@ -194,7 +194,7 @@ end
 ---
 --- The node number is dependent on whether or not anonymous nodes are displayed.
 ---
----@param i number Node number to get
+---@param i integer Node number to get
 ---@return Node
 ---@private
 function TSPlayground:get(i)
@@ -206,7 +206,7 @@ end
 ---
 ---@return (fun(): integer, Node) Iterator over all nodes in this Playground
 ---@return table
----@return number
+---@return integer
 ---@private
 function TSPlayground:iter()
   return ipairs(self.opts.anon and self.nodes or self.named)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 4e9871b59d..22f706585e 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -56,7 +56,7 @@ local function add_included_lang(base_langs, lang, ilang)
 end
 
 ---@private
----@param buf (number)
+---@param buf (integer)
 ---@param range (table)
 ---@param concat (boolean)
 ---@returns (string[]|string|nil)
@@ -269,7 +269,7 @@ end
 --- Gets the text corresponding to a given node
 ---
 ---@param node TSNode
----@param source (number|string) Buffer or string from which the {node} is extracted
+---@param source (integer|string) Buffer or string from which the {node} is extracted
 ---@param opts (table|nil) Optional parameters.
 ---          - concat: (boolean) Concatenate result in a string (default true)
 ---          - metadata (table) Metadata of a specific capture. This would be
@@ -484,7 +484,7 @@ local directive_handlers = {
 --- Adds a new predicate to be used in queries
 ---
 ---@param name string Name of the predicate, without leading #
----@param handler function(match:table, pattern:string, bufnr:number, predicate:string[])
+---@param handler function(match:table, pattern:string, bufnr:integer, predicate:string[])
 ---   - see |vim.treesitter.add_directive()| for argument meanings
 ---@param force boolean|nil
 function M.add_predicate(name, handler, force)
@@ -503,7 +503,7 @@ end
 --- metadata table `metadata[capture_id].key = value`
 ---
 ---@param name string Name of the directive, without leading #
----@param handler function(match:table, pattern:string, bufnr:number, predicate:string[], metadata:table)
+---@param handler function(match:table, pattern:string, bufnr:integer, predicate:string[], metadata:table)
 ---   - match: see |treesitter-query|
 ---      - node-level data are accessible via `match[capture_id]`
 ---   - pattern: see |treesitter-query|
@@ -644,8 +644,8 @@ end
 ---
 ---@param node TSNode under which the search will occur
 ---@param source (integer|string) Source buffer or string to extract text from
----@param start number Starting line for the search
----@param stop number Stopping line for the search (end-exclusive)
+---@param start integer Starting line for the search
+---@param stop integer Stopping line for the search (end-exclusive)
 ---
 ---@return (fun(): integer, TSNode, TSMetadata): capture id, capture node, metadata
 function Query:iter_captures(node, source, start, stop)
-- 
cgit 


From 6a20c29dcd050fee011ec1c451b5e70940152885 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:05:01 +0900
Subject: docs(filetype): number → integer (#22516)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/lua/vim/filetype.lua | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 8911eafc71..65579d3543 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -28,9 +28,9 @@ end
 --- If only start_lnum is specified, return a single line as a string.
 --- If both start_lnum and end_lnum are omitted, return all lines from the buffer.
 ---
----@param bufnr number|nil The buffer to get the lines from
----@param start_lnum number|nil The line number of the first line (inclusive, 1-based)
----@param end_lnum number|nil The line number of the last line (inclusive, 1-based)
+---@param bufnr integer|nil The buffer to get the lines from
+---@param start_lnum integer|nil The line number of the first line (inclusive, 1-based)
+---@param end_lnum integer|nil The line number of the last line (inclusive, 1-based)
 ---@return table|string Array of lines, or string when end_lnum is omitted
 function M.getlines(bufnr, start_lnum, end_lnum)
   if end_lnum then
@@ -67,8 +67,8 @@ end
 ---@private
 --- Get the next non-whitespace line in the buffer.
 ---
----@param bufnr number The buffer to get the line from
----@param start_lnum number The line number of the first line to start from (inclusive, 1-based)
+---@param bufnr integer The buffer to get the line from
+---@param start_lnum integer The line number of the first line to start from (inclusive, 1-based)
 ---@return string|nil The first non-blank line if found or `nil` otherwise
 function M.nextnonblank(bufnr, start_lnum)
   for _, line in ipairs(M.getlines(bufnr, start_lnum, -1)) do
-- 
cgit 


From ccd2cc1abd69f677edabd0b66dfd9689eeee54b9 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:05:16 +0900
Subject: docs(uri): number → integer (#22515)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/lua.txt     | 4 ++--
 runtime/lua/vim/uri.lua | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index e3e0665025..38ddff13bd 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -2007,7 +2007,7 @@ uri_from_bufnr({bufnr})                                 *vim.uri_from_bufnr()*
     Get a URI from a bufnr
 
     Parameters: ~
-      • {bufnr}  (number)
+      • {bufnr}  (integer)
 
     Return: ~
         (string) URI
@@ -2029,7 +2029,7 @@ uri_to_bufnr({uri})                                       *vim.uri_to_bufnr()*
       • {uri}  (string)
 
     Return: ~
-        (number) bufnr
+        (integer) bufnr
 
 uri_to_fname({uri})                                       *vim.uri_to_fname()*
     Get a filename from a URI
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index d6b0b7410e..38759fcdc0 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -80,7 +80,7 @@ local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*'
 local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
 
 --- Get a URI from a bufnr
----@param bufnr number
+---@param bufnr integer
 ---@return string URI
 local function uri_from_bufnr(bufnr)
   local fname = vim.api.nvim_buf_get_name(bufnr)
@@ -123,7 +123,7 @@ end
 --- Creates a new unloaded buffer if no buffer for the uri already exists.
 --
 ---@param uri string
----@return number bufnr
+---@return integer bufnr
 local function uri_to_bufnr(uri)
   return vim.fn.bufadd(uri_to_fname(uri))
 end
-- 
cgit 


From 1f07307aeb6564fb794921cc1b2879f84a822921 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:05:46 +0900
Subject: docs(inspect): number → integer (#22511)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/lua.txt            | 20 ++++++++++----------
 runtime/lua/vim/_inspector.lua | 14 +++++++-------
 2 files changed, 17 insertions(+), 17 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 38ddff13bd..87498c7599 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1542,11 +1542,11 @@ inspect_pos({bufnr}, {row}, {col}, {filter})               *vim.inspect_pos()*
     Can also be pretty-printed with `:Inspect!`.                   *:Inspect!*
 
     Parameters: ~
-      • {bufnr}   (number|nil) defaults to the current buffer
-      • {row}     (number|nil) row to inspect, 0-based. Defaults to the row of
-                  the current cursor
-      • {col}     (number|nil) col to inspect, 0-based. Defaults to the col of
-                  the current cursor
+      • {bufnr}   (integer|nil) defaults to the current buffer
+      • {row}     (integer|nil) row to inspect, 0-based. Defaults to the row
+                  of the current cursor
+      • {col}     (integer|nil) col to inspect, 0-based. Defaults to the col
+                  of the current cursor
       • {filter}  (table|nil) a table with key-value pairs to filter the items
                   • syntax (boolean): include syntax based highlight groups
                     (defaults to true)
@@ -1575,11 +1575,11 @@ show_pos({bufnr}, {row}, {col}, {filter})                     *vim.show_pos()*
     Can also be shown with `:Inspect`.                              *:Inspect*
 
     Parameters: ~
-      • {bufnr}   (number|nil) defaults to the current buffer
-      • {row}     (number|nil) row to inspect, 0-based. Defaults to the row of
-                  the current cursor
-      • {col}     (number|nil) col to inspect, 0-based. Defaults to the col of
-                  the current cursor
+      • {bufnr}   (integer|nil) defaults to the current buffer
+      • {row}     (integer|nil) row to inspect, 0-based. Defaults to the row
+                  of the current cursor
+      • {col}     (integer|nil) col to inspect, 0-based. Defaults to the col
+                  of the current cursor
       • {filter}  (table|nil) see |vim.inspect_pos()|
 
 
diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua
index bb6608421b..9e91597192 100644
--- a/runtime/lua/vim/_inspector.lua
+++ b/runtime/lua/vim/_inspector.lua
@@ -14,15 +14,15 @@ local defaults = {
 ---
 ---Can also be pretty-printed with `:Inspect!`. *:Inspect!*
 ---
----@param bufnr? number defaults to the current buffer
----@param row? number row to inspect, 0-based. Defaults to the row of the current cursor
----@param col? number col to inspect, 0-based. Defaults to the col of the current cursor
+---@param bufnr? integer defaults to the current buffer
+---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
+---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
 ---@param filter? InspectorFilter (table|nil) a table with key-value pairs to filter the items
 ---               - syntax (boolean): include syntax based highlight groups (defaults to true)
 ---               - treesitter (boolean): include treesitter based highlight groups (defaults to true)
 ---               - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
 ---               - semantic_tokens (boolean): include semantic tokens (defaults to true)
----@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:number,col:number,row:number} (table) a table with the following key-value pairs. Items are in "traversal order":
+---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:integer,col:integer,row:integer} (table) a table with the following key-value pairs. Items are in "traversal order":
 ---               - treesitter: a list of treesitter captures
 ---               - syntax: a list of syntax groups
 ---               - semantic_tokens: a list of semantic tokens
@@ -129,9 +129,9 @@ end
 ---
 ---Can also be shown with `:Inspect`. *:Inspect*
 ---
----@param bufnr? number defaults to the current buffer
----@param row? number row to inspect, 0-based. Defaults to the row of the current cursor
----@param col? number col to inspect, 0-based. Defaults to the col of the current cursor
+---@param bufnr? integer defaults to the current buffer
+---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
+---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
 ---@param filter? InspectorFilter (table|nil) see |vim.inspect_pos()|
 function vim.show_pos(bufnr, row, col, filter)
   local items = vim.inspect_pos(bufnr, row, col, filter)
-- 
cgit 


From 65e2feabeb9bd17a076206d98dadb93515e9b612 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:05:57 +0900
Subject: docs(editorconfig): number → integer (#22514)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/lua/editorconfig.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'runtime')

diff --git a/runtime/lua/editorconfig.lua b/runtime/lua/editorconfig.lua
index 2079006234..5b09126788 100644
--- a/runtime/lua/editorconfig.lua
+++ b/runtime/lua/editorconfig.lua
@@ -202,7 +202,7 @@ end
 
 --- Configure the given buffer with options from an .editorconfig file
 ---
----@param bufnr number Buffer number to configure
+---@param bufnr integer Buffer number to configure
 ---
 ---@private
 function M.config(bufnr)
-- 
cgit 


From 82b77900d7f85088c676be886937628230d0d5c2 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:06:20 +0900
Subject: docs(diagnostic): number → integer (#22512)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/diagnostic.txt     | 44 ++++++++++++++++++++--------------------
 runtime/lua/vim/diagnostic.lua | 46 +++++++++++++++++++++---------------------
 2 files changed, 45 insertions(+), 45 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index c661bf02bf..cff73ad097 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -423,25 +423,25 @@ config({opts}, {namespace})                          *vim.diagnostic.config()*
                        severities are displayed before lower severities (e.g.
                        ERROR is displayed before WARN). Options:
                        • reverse: (boolean) Reverse sort order
-      • {namespace}  (number|nil) Update the options for the given namespace.
+      • {namespace}  (integer|nil) Update the options for the given namespace.
                      When omitted, update the global diagnostic options.
 
 disable({bufnr}, {namespace})                       *vim.diagnostic.disable()*
     Disable diagnostics in the given buffer.
 
     Parameters: ~
-      • {bufnr}      (number|nil) Buffer number, or 0 for current buffer. When
-                     omitted, disable diagnostics in all buffers.
-      • {namespace}  (number|nil) Only disable diagnostics for the given
+      • {bufnr}      (integer|nil) Buffer number, or 0 for current buffer.
+                     When omitted, disable diagnostics in all buffers.
+      • {namespace}  (integer|nil) Only disable diagnostics for the given
                      namespace.
 
 enable({bufnr}, {namespace})                         *vim.diagnostic.enable()*
     Enable diagnostics in the given buffer.
 
     Parameters: ~
-      • {bufnr}      (number|nil) Buffer number, or 0 for current buffer. When
-                     omitted, enable diagnostics in all buffers.
-      • {namespace}  (number|nil) Only enable diagnostics for the given
+      • {bufnr}      (integer|nil) Buffer number, or 0 for current buffer.
+                     When omitted, enable diagnostics in all buffers.
+      • {namespace}  (integer|nil) Only enable diagnostics for the given
                      namespace.
 
 fromqflist({list})                               *vim.diagnostic.fromqflist()*
@@ -458,8 +458,8 @@ get({bufnr}, {opts})                                    *vim.diagnostic.get()*
     Get current diagnostics.
 
     Parameters: ~
-      • {bufnr}  (number|nil) Buffer number to get diagnostics from. Use 0 for
-                 current buffer or nil for all buffers.
+      • {bufnr}  (integer|nil) Buffer number to get diagnostics from. Use 0
+                 for current buffer or nil for all buffers.
       • {opts}   (table|nil) A table with the following keys:
                  • namespace: (number) Limit diagnostics to the given
                    namespace.
@@ -473,7 +473,7 @@ get_namespace({namespace})                    *vim.diagnostic.get_namespace()*
     Get namespace metadata.
 
     Parameters: ~
-      • {namespace}  (number) Diagnostic namespace
+      • {namespace}  (integer) Diagnostic namespace
 
     Return: ~
         (table) Namespace metadata
@@ -560,17 +560,17 @@ hide({namespace}, {bufnr})                             *vim.diagnostic.hide()*
     |vim.diagnostic.disable()|.
 
     Parameters: ~
-      • {namespace}  (number|nil) Diagnostic namespace. When omitted, hide diagnostics from all
+      • {namespace}  (integer|nil) Diagnostic namespace. When omitted, hide diagnostics from all
                      namespaces.
-      • {bufnr}      (number|nil) Buffer number, or 0 for current buffer. When
-                     omitted, hide diagnostics in all buffers.
+      • {bufnr}      (integer|nil) Buffer number, or 0 for current buffer.
+                     When omitted, hide diagnostics in all buffers.
 
 is_disabled({bufnr}, {namespace})               *vim.diagnostic.is_disabled()*
     Check whether diagnostics are disabled in a given buffer.
 
     Parameters: ~
-      • {bufnr}      (number|nil) Buffer number, or 0 for current buffer.
-      • {namespace}  (number|nil) Diagnostic namespace. When omitted, checks if all diagnostics are
+      • {bufnr}      (integer|nil) Buffer number, or 0 for current buffer.
+      • {namespace}  (integer|nil) Diagnostic namespace. When omitted, checks if all diagnostics are
                      disabled in {bufnr}. Otherwise, only checks if
                      diagnostics from {namespace} are disabled.
 
@@ -663,7 +663,7 @@ open_float({opts}, {...})                        *vim.diagnostic.open_float()*
                   from |vim.diagnostic.config()|.
 
     Return: ~
-        number|nil, number|nil: ({float_bufnr}, {win_id})
+        integer|nil, integer|nil: ({float_bufnr}, {win_id})
 
 reset({namespace}, {bufnr})                           *vim.diagnostic.reset()*
     Remove all diagnostics from the given namespace.
@@ -674,17 +674,17 @@ reset({namespace}, {bufnr})                           *vim.diagnostic.reset()*
     re-displayed, use |vim.diagnostic.hide()|.
 
     Parameters: ~
-      • {namespace}  (number|nil) Diagnostic namespace. When omitted, remove diagnostics from all
+      • {namespace}  (integer|nil) Diagnostic namespace. When omitted, remove diagnostics from all
                      namespaces.
-      • {bufnr}      (number|nil) Remove diagnostics for the given buffer.
+      • {bufnr}      (integer|nil) Remove diagnostics for the given buffer.
                      When omitted, diagnostics are removed for all buffers.
 
 set({namespace}, {bufnr}, {diagnostics}, {opts})        *vim.diagnostic.set()*
     Set diagnostics for the given namespace and buffer.
 
     Parameters: ~
-      • {namespace}    (number) The diagnostic namespace
-      • {bufnr}        (number) Buffer number
+      • {namespace}    (integer) The diagnostic namespace
+      • {bufnr}        (integer) Buffer number
       • {diagnostics}  (table) A list of diagnostic items
                        |diagnostic-structure|
       • {opts}         (table|nil) Display options to pass to
@@ -723,9 +723,9 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
     Display diagnostics for the given namespace and buffer.
 
     Parameters: ~
-      • {namespace}    (number|nil) Diagnostic namespace. When omitted, show diagnostics from all
+      • {namespace}    (integer|nil) Diagnostic namespace. When omitted, show diagnostics from all
                        namespaces.
-      • {bufnr}        (number|nil) Buffer number, or 0 for current buffer.
+      • {bufnr}        (integer|nil) Buffer number, or 0 for current buffer.
                        When omitted, show diagnostics in all buffers.
       • {diagnostics}  (table|nil) The diagnostics to display. When omitted,
                        use the saved diagnostics for the given namespace and
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 6fd000a029..56532d0184 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -630,7 +630,7 @@ end
 ---                         Options:
 ---                         * reverse: (boolean) Reverse sort order
 ---
----@param namespace number|nil Update the options for the given namespace. When omitted, update the
+---@param namespace integer|nil Update the options for the given namespace. When omitted, update the
 ---                            global diagnostic options.
 function M.config(opts, namespace)
   vim.validate({
@@ -674,8 +674,8 @@ end
 
 --- Set diagnostics for the given namespace and buffer.
 ---
----@param namespace number The diagnostic namespace
----@param bufnr number Buffer number
+---@param namespace integer The diagnostic namespace
+---@param bufnr integer Buffer number
 ---@param diagnostics table A list of diagnostic items |diagnostic-structure|
 ---@param opts table|nil Display options to pass to |vim.diagnostic.show()|
 function M.set(namespace, bufnr, diagnostics, opts)
@@ -711,7 +711,7 @@ end
 
 --- Get namespace metadata.
 ---
----@param namespace number Diagnostic namespace
+---@param namespace integer Diagnostic namespace
 ---@return table Namespace metadata
 function M.get_namespace(namespace)
   vim.validate({ namespace = { namespace, 'n' } })
@@ -743,11 +743,11 @@ function M.get_namespaces()
 end
 
 ---@class Diagnostic
----@field buffer number
----@field lnum number 0-indexed
----@field end_lnum nil|number 0-indexed
----@field col number 0-indexed
----@field end_col nil|number 0-indexed
+---@field buffer integer
+---@field lnum integer 0-indexed
+---@field end_lnum nil|integer 0-indexed
+---@field col integer 0-indexed
+---@field end_col nil|integer 0-indexed
 ---@field severity DiagnosticSeverity
 ---@field message string
 ---@field source nil|string
@@ -756,7 +756,7 @@ end
 
 --- Get current diagnostics.
 ---
----@param bufnr number|nil Buffer number to get diagnostics from. Use 0 for
+---@param bufnr integer|nil Buffer number to get diagnostics from. Use 0 for
 ---                        current buffer or nil for all buffers.
 ---@param opts table|nil A table with the following keys:
 ---                        - namespace: (number) Limit diagnostics to the given namespace.
@@ -1083,9 +1083,9 @@ end
 --- To hide diagnostics and prevent them from re-displaying, use
 --- |vim.diagnostic.disable()|.
 ---
----@param namespace number|nil Diagnostic namespace. When omitted, hide
+---@param namespace integer|nil Diagnostic namespace. When omitted, hide
 ---                            diagnostics from all namespaces.
----@param bufnr number|nil Buffer number, or 0 for current buffer. When
+---@param bufnr integer|nil Buffer number, or 0 for current buffer. When
 ---                        omitted, hide diagnostics in all buffers.
 function M.hide(namespace, bufnr)
   vim.validate({
@@ -1108,8 +1108,8 @@ end
 
 --- Check whether diagnostics are disabled in a given buffer.
 ---
----@param bufnr number|nil Buffer number, or 0 for current buffer.
----@param namespace number|nil Diagnostic namespace. When omitted, checks if
+---@param bufnr integer|nil Buffer number, or 0 for current buffer.
+---@param namespace integer|nil Diagnostic namespace. When omitted, checks if
 ---                            all diagnostics are disabled in {bufnr}.
 ---                            Otherwise, only checks if diagnostics from
 ---                            {namespace} are disabled.
@@ -1129,9 +1129,9 @@ end
 
 --- Display diagnostics for the given namespace and buffer.
 ---
----@param namespace number|nil Diagnostic namespace. When omitted, show
+---@param namespace integer|nil Diagnostic namespace. When omitted, show
 ---                            diagnostics from all namespaces.
----@param bufnr number|nil Buffer number, or 0 for current buffer. When omitted, show
+---@param bufnr integer|nil Buffer number, or 0 for current buffer. When omitted, show
 ---                        diagnostics in all buffers.
 ---@param diagnostics table|nil The diagnostics to display. When omitted, use the
 ---                             saved diagnostics for the given namespace and
@@ -1256,7 +1256,7 @@ end
 ---                      Overrides the setting from |vim.diagnostic.config()|.
 ---            - suffix: Same as {prefix}, but appends the text to the diagnostic instead of
 ---                      prepending it. Overrides the setting from |vim.diagnostic.config()|.
----@return number|nil, number|nil: ({float_bufnr}, {win_id})
+---@return integer|nil, integer|nil: ({float_bufnr}, {win_id})
 function M.open_float(opts, ...)
   -- Support old (bufnr, opts) signature
   local bufnr
@@ -1463,9 +1463,9 @@ end
 --- simply remove diagnostic decorations in a way that they can be
 --- re-displayed, use |vim.diagnostic.hide()|.
 ---
----@param namespace number|nil Diagnostic namespace. When omitted, remove
+---@param namespace integer|nil Diagnostic namespace. When omitted, remove
 ---                            diagnostics from all namespaces.
----@param bufnr number|nil Remove diagnostics for the given buffer. When omitted,
+---@param bufnr integer|nil Remove diagnostics for the given buffer. When omitted,
 ---             diagnostics are removed for all buffers.
 function M.reset(namespace, bufnr)
   vim.validate({
@@ -1518,9 +1518,9 @@ end
 
 --- Disable diagnostics in the given buffer.
 ---
----@param bufnr number|nil Buffer number, or 0 for current buffer. When
+---@param bufnr integer|nil Buffer number, or 0 for current buffer. When
 ---                        omitted, disable diagnostics in all buffers.
----@param namespace number|nil Only disable diagnostics for the given namespace.
+---@param namespace integer|nil Only disable diagnostics for the given namespace.
 function M.disable(bufnr, namespace)
   vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
   if bufnr == nil then
@@ -1555,9 +1555,9 @@ end
 
 --- Enable diagnostics in the given buffer.
 ---
----@param bufnr number|nil Buffer number, or 0 for current buffer. When
+---@param bufnr integer|nil Buffer number, or 0 for current buffer. When
 ---                        omitted, enable diagnostics in all buffers.
----@param namespace number|nil Only enable diagnostics for the given namespace.
+---@param namespace integer|nil Only enable diagnostics for the given namespace.
 function M.enable(bufnr, namespace)
   vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
   if bufnr == nil then
-- 
cgit 


From aa16590999a66798eca7d2ba09e971aacdeb54b4 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sat, 4 Mar 2023 22:07:39 +0900
Subject: docs(lua): number → integer (#22517)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/lua.txt         | 20 ++++++++++----------
 runtime/lua/vim/_editor.lua | 10 +++++-----
 runtime/lua/vim/shared.lua  | 10 +++++-----
 3 files changed, 20 insertions(+), 20 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 87498c7599..1eb5ab41e6 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1413,7 +1413,7 @@ notify({msg}, {level}, {opts})                                  *vim.notify()*
 
     Parameters: ~
       • {msg}    (string) Content of the notification to show to the user.
-      • {level}  (number|nil) One of the values from |vim.log.levels|.
+      • {level}  (integer|nil) One of the values from |vim.log.levels|.
       • {opts}   (table|nil) Optional parameters. Unused by default.
 
 notify_once({msg}, {level}, {opts})                        *vim.notify_once()*
@@ -1424,7 +1424,7 @@ notify_once({msg}, {level}, {opts})                        *vim.notify_once()*
 
     Parameters: ~
       • {msg}    (string) Content of the notification to show to the user.
-      • {level}  (number|nil) One of the values from |vim.log.levels|.
+      • {level}  (integer|nil) One of the values from |vim.log.levels|.
       • {opts}   (table|nil) Optional parameters. Unused by default.
 
     Return: ~
@@ -1448,11 +1448,11 @@ on_key({fn}, {ns_id})                                           *vim.on_key()*
                  argument. On each key press, Nvim passes the key char to
                  fn(). |i_CTRL-V| If {fn} is nil, it removes the callback for
                  the associated {ns_id}
-      • {ns_id}  number? Namespace ID. If nil or 0, generates and returns a
+      • {ns_id}  integer? Namespace ID. If nil or 0, generates and returns a
                  new |nvim_create_namespace()| id.
 
     Return: ~
-        (number) Namespace id associated with {fn}. Or count of all callbacks
+        (integer) Namespace id associated with {fn}. Or count of all callbacks
         if on_key() is called without arguments.
 
     Note:
@@ -1507,7 +1507,7 @@ region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive})         *vim.region()*
     points
 
     Parameters: ~
-      • {bufnr}      (number) of buffer
+      • {bufnr}      (integer) number of buffer
       • {pos1}       integer[] (line, column) tuple marking beginning of
                      region
       • {pos2}       integer[] (line, column) tuple marking end of region
@@ -1678,8 +1678,8 @@ list_extend({dst}, {src}, {start}, {finish})               *vim.list_extend()*
     Parameters: ~
       • {dst}     (table) List which will be modified and appended to
       • {src}     (table) List from which values will be inserted
-      • {start}   (number|nil) Start index on src. Defaults to 1
-      • {finish}  (number|nil) Final index on src. Defaults to `#src`
+      • {start}   (integer|nil) Start index on src. Defaults to 1
+      • {finish}  (integer|nil) Final index on src. Defaults to `#src`
 
     Return: ~
         (table) dst
@@ -1693,8 +1693,8 @@ list_slice({list}, {start}, {finish})                       *vim.list_slice()*
 
     Parameters: ~
       • {list}    (list) Table
-      • {start}   (number|nil) Start range of slice
-      • {finish}  (number|nil) End range of slice
+      • {start}   (integer|nil) Start range of slice
+      • {finish}  (integer|nil) End range of slice
 
     Return: ~
         (list) Copy of table sliced from start to finish (inclusive)
@@ -1794,7 +1794,7 @@ tbl_count({t})                                               *vim.tbl_count()*
       • {t}  (table) Table
 
     Return: ~
-        (number) Number of non-nil values in table
+        (integer) Number of non-nil values in table
 
     See also: ~
         https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 3f27e61810..ab49e26dde 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -386,7 +386,7 @@ end
 
 --- Get a table of lines with start, end columns for a region marked by two points
 ---
----@param bufnr number of buffer
+---@param bufnr integer number of buffer
 ---@param pos1 integer[] (line, column) tuple marking beginning of region
 ---@param pos2 integer[] (line, column) tuple marking end of region
 ---@param regtype string type of selection, see |setreg()|
@@ -471,7 +471,7 @@ end
 --- writes to |:messages|.
 ---
 ---@param msg string Content of the notification to show to the user.
----@param level number|nil One of the values from |vim.log.levels|.
+---@param level integer|nil One of the values from |vim.log.levels|.
 ---@param opts table|nil Optional parameters. Unused by default.
 function vim.notify(msg, level, opts) -- luacheck: no unused args
   if level == vim.log.levels.ERROR then
@@ -492,7 +492,7 @@ do
   --- display a notification.
   ---
   ---@param msg string Content of the notification to show to the user.
-  ---@param level number|nil One of the values from |vim.log.levels|.
+  ---@param level integer|nil One of the values from |vim.log.levels|.
   ---@param opts table|nil Optional parameters. Unused by default.
   ---@return boolean true if message was displayed, else false
   function vim.notify_once(msg, level, opts)
@@ -521,10 +521,10 @@ local on_key_cbs = {}
 ---@param fn function: Callback function. It should take one string argument.
 ---                   On each key press, Nvim passes the key char to fn(). |i_CTRL-V|
 ---                   If {fn} is nil, it removes the callback for the associated {ns_id}
----@param ns_id number? Namespace ID. If nil or 0, generates and returns a new
+---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a new
 ---                    |nvim_create_namespace()| id.
 ---
----@return number Namespace id associated with {fn}. Or count of all callbacks
+---@return integer Namespace id associated with {fn}. Or count of all callbacks
 ---if on_key() is called without arguments.
 ---
 ---@note {fn} will be removed if an error occurs while calling.
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index cc48e3f193..1c8defc93a 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -418,8 +418,8 @@ end
 ---@generic T: table
 ---@param dst T List which will be modified and appended to
 ---@param src table List from which values will be inserted
----@param start (number|nil) Start index on src. Defaults to 1
----@param finish (number|nil) Final index on src. Defaults to `#src`
+---@param start (integer|nil) Start index on src. Defaults to 1
+---@param finish (integer|nil) Final index on src. Defaults to `#src`
 ---@return T dst
 function vim.list_extend(dst, src, start, finish)
   vim.validate({
@@ -529,7 +529,7 @@ end
 ---
 ---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
 ---@param t table Table
----@return number Number of non-nil values in table
+---@return integer Number of non-nil values in table
 function vim.tbl_count(t)
   vim.validate({ t = { t, 't' } })
 
@@ -544,8 +544,8 @@ end
 ---
 ---@generic T
 ---@param list T[] (list) Table
----@param start number|nil Start range of slice
----@param finish number|nil End range of slice
+---@param start integer|nil Start range of slice
+---@param finish integer|nil End range of slice
 ---@return T[] (list) Copy of table sliced from start to finish (inclusive)
 function vim.list_slice(list, start, finish)
   local new_list = {}
-- 
cgit 


From 59542504b41dfddb6f26524fb4ce811e0f22a785 Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Sun, 5 Mar 2023 01:47:30 +0900
Subject: docs(highlight): fix type annotations (#22272)

---
 runtime/lua/vim/highlight.lua | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index 20ad48dd27..89eae0def5 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -36,12 +36,12 @@ end
 
 --- Highlight range between two positions
 ---
----@param bufnr number of buffer to apply highlighting to
----@param ns namespace to add highlight to
----@param higroup highlight group to use for highlighting
----@param start first position (tuple {line,col})
----@param finish second position (tuple {line,col})
----@param opts table with options:
+---@param bufnr integer Buffer number to apply highlighting to
+---@param ns integer Namespace to add highlight to
+---@param higroup string Highlight group to use for highlighting
+---@param start { [1]: integer, [2]: integer } Start position {line, col}
+---@param finish { [1]: integer, [2]: integer } Finish position {line, col}
+---@param opts table|nil Optional parameters
 --             - regtype type of range (see |setreg()|, default charwise)
 --             - inclusive boolean indicating whether the range is end-inclusive (default false)
 --             - priority number indicating priority of highlight (default priorities.user)
@@ -84,7 +84,7 @@ local yank_timer
 --- customize conditions (here: do not highlight a visual selection) via
 ---   au TextYankPost * lua vim.highlight.on_yank {on_visual=false}
 ---
--- @param opts table with options controlling the highlight:
+-- @param opts table|nil Optional parameters
 --              - higroup   highlight group for yanked region (default "IncSearch")
 --              - timeout   time in ms before highlight is cleared (default 150)
 --              - on_macro  highlight when executing macro (default false)
-- 
cgit 


From ac69ba5fa0081026f2c5e6e29d5788802479b7b9 Mon Sep 17 00:00:00 2001
From: Jon Huhn 
Date: Sun, 5 Mar 2023 00:52:27 -0600
Subject: feat(lsp): implement workspace/didChangeWatchedFiles (#22405)

---
 runtime/doc/news.txt                |   5 +
 runtime/lua/vim/_editor.lua         |   1 +
 runtime/lua/vim/_watch.lua          | 174 +++++++++++++++++++++
 runtime/lua/vim/lsp/_watchfiles.lua | 293 ++++++++++++++++++++++++++++++++++++
 runtime/lua/vim/lsp/handlers.lua    |  38 +++--
 runtime/lua/vim/lsp/protocol.lua    |   4 +
 6 files changed, 506 insertions(+), 9 deletions(-)
 create mode 100644 runtime/lua/vim/_watch.lua
 create mode 100644 runtime/lua/vim/lsp/_watchfiles.lua

(limited to 'runtime')

diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index cda4792c9e..415195e27e 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -184,6 +184,11 @@ The following new APIs or features were added.
 • Vim's `has('gui_running')` is now supported as a way for plugins to check if
   a GUI (not the |TUI|) is attached to Nvim. |has()|
 
+• Added preliminary support for the `workspace/didChangeWatchedFiles` capability
+  to the LSP client to notify servers of file changes on disk. The feature is
+  disabled by default and can be enabled by setting the
+  `workspace.didChangeWatchedFiles.dynamicRegistration=true` capability.
+
 ==============================================================================
 CHANGED FEATURES                                                 *news-changes*
 
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index ab49e26dde..c205451ff9 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -37,6 +37,7 @@ for k, v in pairs({
   health = true,
   fs = true,
   secure = true,
+  _watch = true,
 }) do
   vim._submodules[k] = v
 end
diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua
new file mode 100644
index 0000000000..dba1522ec8
--- /dev/null
+++ b/runtime/lua/vim/_watch.lua
@@ -0,0 +1,174 @@
+local M = {}
+
+--- Enumeration describing the types of events watchers will emit.
+M.FileChangeType = vim.tbl_add_reverse_lookup({
+  Created = 1,
+  Changed = 2,
+  Deleted = 3,
+})
+
+---@private
+--- Joins filepath elements by static '/' separator
+---
+---@param ... (string) The path elements.
+local function filepath_join(...)
+  return table.concat({ ... }, '/')
+end
+
+---@private
+--- Stops and closes a libuv |uv_fs_event_t| or |uv_fs_poll_t| handle
+---
+---@param handle (uv_fs_event_t|uv_fs_poll_t) The handle to stop
+local function stop(handle)
+  local _, stop_err = handle:stop()
+  assert(not stop_err, stop_err)
+  local is_closing, close_err = handle:is_closing()
+  assert(not close_err, close_err)
+  if not is_closing then
+    handle:close()
+  end
+end
+
+--- Initializes and starts a |uv_fs_event_t|
+---
+---@param path (string) The path to watch
+---@param opts (table|nil) Additional options
+---     - uvflags (table|nil)
+---                Same flags as accepted by |uv.fs_event_start()|
+---@param callback (function) The function called when new events
+---@returns (function) A function to stop the watch
+function M.watch(path, opts, callback)
+  vim.validate({
+    path = { path, 'string', false },
+    opts = { opts, 'table', true },
+    callback = { callback, 'function', false },
+  })
+
+  path = vim.fs.normalize(path)
+  local uvflags = opts and opts.uvflags or {}
+  local handle, new_err = vim.loop.new_fs_event()
+  assert(not new_err, new_err)
+  local _, start_err = handle:start(path, uvflags, function(err, filename, events)
+    assert(not err, err)
+    local fullpath = path
+    if filename then
+      filename = filename:gsub('\\', '/')
+      fullpath = filepath_join(fullpath, filename)
+    end
+    local change_type = events.change and M.FileChangeType.Changed or 0
+    if events.rename then
+      local _, staterr, staterrname = vim.loop.fs_stat(fullpath)
+      if staterrname == 'ENOENT' then
+        change_type = M.FileChangeType.Deleted
+      else
+        assert(not staterr, staterr)
+        change_type = M.FileChangeType.Created
+      end
+    end
+    callback(fullpath, change_type)
+  end)
+  assert(not start_err, start_err)
+  return function()
+    stop(handle)
+  end
+end
+
+local default_poll_interval_ms = 2000
+
+---@private
+--- Implementation for poll, hiding internally-used parameters.
+---
+---@param watches (table|nil) A tree structure to maintain state for recursive watches.
+---     - handle (uv_fs_poll_t)
+---               The libuv handle
+---     - cancel (function)
+---               A function that cancels the handle and all children's handles
+---     - is_dir (boolean)
+---               Indicates whether the path is a directory (and the poll should
+---               be invoked recursively)
+---     - children (table|nil)
+---               A mapping of directory entry name to its recursive watches
+local function poll_internal(path, opts, callback, watches)
+  path = vim.fs.normalize(path)
+  local interval = opts and opts.interval or default_poll_interval_ms
+  watches = watches or {
+    is_dir = true,
+  }
+
+  if not watches.handle then
+    local poll, new_err = vim.loop.new_fs_poll()
+    assert(not new_err, new_err)
+    watches.handle = poll
+    local _, start_err = poll:start(
+      path,
+      interval,
+      vim.schedule_wrap(function(err)
+        if err == 'ENOENT' then
+          return
+        end
+        assert(not err, err)
+        poll_internal(path, opts, callback, watches)
+        callback(path, M.FileChangeType.Changed)
+      end)
+    )
+    assert(not start_err, start_err)
+    callback(path, M.FileChangeType.Created)
+  end
+
+  watches.cancel = function()
+    if watches.children then
+      for _, w in pairs(watches.children) do
+        w.cancel()
+      end
+    end
+    stop(watches.handle)
+  end
+
+  if watches.is_dir then
+    watches.children = watches.children or {}
+    local exists = {}
+    for name, ftype in vim.fs.dir(path) do
+      exists[name] = true
+      if not watches.children[name] then
+        watches.children[name] = {
+          is_dir = ftype == 'directory',
+        }
+        poll_internal(filepath_join(path, name), opts, callback, watches.children[name])
+      end
+    end
+
+    local newchildren = {}
+    for name, watch in pairs(watches.children) do
+      if exists[name] then
+        newchildren[name] = watch
+      else
+        watch.cancel()
+        watches.children[name] = nil
+        callback(path .. '/' .. name, M.FileChangeType.Deleted)
+      end
+    end
+    watches.children = newchildren
+  end
+
+  return watches.cancel
+end
+
+--- Initializes and starts a |uv_fs_poll_t| recursively watching every file underneath the
+--- directory at path.
+---
+---@param path (string) The path to watch. Must refer to a directory.
+---@param opts (table|nil) Additional options
+---     - interval (number|nil)
+---                Polling interval in ms as passed to |uv.fs_poll_start()|. Defaults to 2000.
+---@param callback (function) The function called when new events
+---@returns (function) A function to stop the watch.
+function M.poll(path, opts, callback)
+  vim.validate({
+    path = { path, 'string', false },
+    opts = { opts, 'table', true },
+    callback = { callback, 'function', false },
+  })
+  return poll_internal(path, opts, callback, nil)
+end
+
+return M
diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
new file mode 100644
index 0000000000..96d7fa1d35
--- /dev/null
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -0,0 +1,293 @@
+local bit = require('bit')
+local watch = require('vim._watch')
+local protocol = require('vim.lsp.protocol')
+
+local M = {}
+
+---@private
+---Parses the raw pattern into a number of Lua-native patterns.
+---
+---@param pattern string The raw glob pattern
+---@return table A list of Lua patterns. A match with any of them matches the input glob pattern.
+local function parse(pattern)
+  local patterns = { '' }
+
+  local path_sep = '[/\\]'
+  local non_path_sep = '[^/\\]'
+
+  local function append(chunks)
+    local new_patterns = {}
+    for _, p in ipairs(patterns) do
+      for _, chunk in ipairs(chunks) do
+        table.insert(new_patterns, p .. chunk)
+      end
+    end
+    patterns = new_patterns
+  end
+
+  local function split(s, sep)
+    local segments = {}
+    local segment = ''
+    local in_braces = false
+    local in_brackets = false
+    for i = 1, #s do
+      local c = string.sub(s, i, i)
+      if c == sep and not in_braces and not in_brackets then
+        table.insert(segments, segment)
+        segment = ''
+      else
+        if c == '{' then
+          in_braces = true
+        elseif c == '}' then
+          in_braces = false
+        elseif c == '[' then
+          in_brackets = true
+        elseif c == ']' then
+          in_brackets = false
+        end
+        segment = segment .. c
+      end
+    end
+    if segment ~= '' then
+      table.insert(segments, segment)
+    end
+    return segments
+  end
+
+  local function escape(c)
+    if
+      c == '?'
+      or c == '.'
+      or c == '('
+      or c == ')'
+      or c == '%'
+      or c == '['
+      or c == ']'
+      or c == '*'
+      or c == '+'
+      or c == '-'
+    then
+      return '%' .. c
+    end
+    return c
+  end
+
+  local segments = split(pattern, '/')
+  for i, segment in ipairs(segments) do
+    local last_seg = i == #segments
+    if segment == '**' then
+      local chunks = {
+        path_sep .. '-',
+        '.-' .. path_sep,
+      }
+      if last_seg then
+        chunks = { '.-' }
+      end
+      append(chunks)
+    else
+      local in_braces = false
+      local brace_val = ''
+      local in_brackets = false
+      local bracket_val = ''
+      for j = 1, #segment do
+        local char = string.sub(segment, j, j)
+        if char ~= '}' and in_braces then
+          brace_val = brace_val .. char
+        else
+          if in_brackets and (char ~= ']' or bracket_val == '') then
+            local res
+            if char == '-' then
+              res = char
+            elseif bracket_val == '' and char == '!' then
+              res = '^'
+            elseif char == '/' then
+              res = ''
+            else
+              res = escape(char)
+            end
+            bracket_val = bracket_val .. res
+          else
+            if char == '{' then
+              in_braces = true
+            elseif char == '[' then
+              in_brackets = true
+            elseif char == '}' then
+              local choices = split(brace_val, ',')
+              local parsed_choices = {}
+              for _, choice in ipairs(choices) do
+                table.insert(parsed_choices, parse(choice))
+              end
+              append(vim.tbl_flatten(parsed_choices))
+              in_braces = false
+              brace_val = ''
+            elseif char == ']' then
+              append({ '[' .. bracket_val .. ']' })
+              in_brackets = false
+              bracket_val = ''
+            elseif char == '?' then
+              append({ non_path_sep })
+            elseif char == '*' then
+              append({ non_path_sep .. '-' })
+            else
+              append({ escape(char) })
+            end
+          end
+        end
+      end
+
+      if not last_seg and (segments[i + 1] ~= '**' or i + 1 < #segments) then
+        append({ path_sep })
+      end
+    end
+  end
+
+  return patterns
+end
+
+---@private
+--- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
+--- Modeled after VSCode's implementation: https://github.com/microsoft/vscode/blob/0319eed971719ad48e9093daba9d65a5013ec5ab/src/vs/base/common/glob.ts#L509
+---
+---@param pattern string|table The glob pattern (raw or parsed) to match.
+---@param s string The string to match against pattern.
+---@return boolean Whether or not pattern matches s.
+function M._match(pattern, s)
+  if type(pattern) == 'string' then
+    pattern = parse(pattern)
+  end
+  -- Since Lua's built-in string pattern matching does not have an alternate
+  -- operator like '|', `parse` will construct one pattern for each possible
+  -- alternative. Any pattern that matches thus matches the glob.
+  for _, p in ipairs(pattern) do
+    if s:match('^' .. p .. '$') then
+      return true
+    end
+  end
+  return false
+end
+
+M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll
+
+---@type table> client id -> registration id -> cancel function
+local cancels = vim.defaulttable()
+
+local queue_timeout_ms = 100
+---@type table client id -> libuv timer which will send queued changes at its timeout
+local queue_timers = {}
+---@type table client id -> set of queued changes to send in a single LSP notification
+local change_queues = {}
+---@type table> client id -> URI -> last type of change processed
+--- Used to prune consecutive events of the same type for the same file
+local change_cache = vim.defaulttable()
+
+local to_lsp_change_type = {
+  [watch.FileChangeType.Created] = protocol.FileChangeType.Created,
+  [watch.FileChangeType.Changed] = protocol.FileChangeType.Changed,
+  [watch.FileChangeType.Deleted] = protocol.FileChangeType.Deleted,
+}
+
+--- Registers the workspace/didChangeWatchedFiles capability dynamically.
+---
+---@param reg table LSP Registration object.
+---@param ctx table Context from the |lsp-handler|.
+function M.register(reg, ctx)
+  local client_id = ctx.client_id
+  local client = vim.lsp.get_client_by_id(client_id)
+  local watch_regs = {}
+  for _, w in ipairs(reg.registerOptions.watchers) do
+    local glob_patterns = {}
+    if type(w.globPattern) == 'string' then
+      for _, folder in ipairs(client.workspace_folders) do
+        table.insert(glob_patterns, { baseUri = folder.uri, pattern = w.globPattern })
+      end
+    else
+      table.insert(glob_patterns, w.globPattern)
+    end
+    for _, glob_pattern in ipairs(glob_patterns) do
+      local pattern = parse(glob_pattern.pattern)
+      local base_dir = nil
+      if type(glob_pattern.baseUri) == 'string' then
+        base_dir = glob_pattern.baseUri
+      elseif type(glob_pattern.baseUri) == 'table' then
+        base_dir = glob_pattern.baseUri.uri
+      end
+      assert(base_dir, "couldn't identify root of watch")
+      base_dir = vim.uri_to_fname(base_dir)
+      local kind = w.kind
+        or protocol.WatchKind.Create + protocol.WatchKind.Change + protocol.WatchKind.Delete
+
+      table.insert(watch_regs, {
+        base_dir = base_dir,
+        pattern = pattern,
+        kind = kind,
+      })
+    end
+  end
+
+  local callback = function(base_dir)
+    return function(fullpath, change_type)
+      for _, w in ipairs(watch_regs) do
+        change_type = to_lsp_change_type[change_type]
+        -- e.g. match kind with Delete bit (0b0100) to Delete change_type (3)
+        local kind_mask = bit.lshift(1, change_type - 1)
+        local change_type_match = bit.band(w.kind, kind_mask) == kind_mask
+        if base_dir == w.base_dir and M._match(w.pattern, fullpath) and change_type_match then
+          local change = {
+            uri = vim.uri_from_fname(fullpath),
+            type = change_type,
+          }
+
+          local last_type = change_cache[client_id][change.uri]
+          if last_type ~= change.type then
+            change_queues[client_id] = change_queues[client_id] or {}
+            table.insert(change_queues[client_id], change)
+            change_cache[client_id][change.uri] = change.type
+          end
+
+          if not queue_timers[client_id] then
+            queue_timers[client_id] = vim.defer_fn(function()
+              client.notify('workspace/didChangeWatchedFiles', {
+                changes = change_queues[client_id],
+              })
+              queue_timers[client_id] = nil
+              change_queues[client_id] = nil
+              change_cache[client_id] = nil
+            end, queue_timeout_ms)
+          end
+
+          break -- if an event matches multiple watchers, only send one notification
+        end
+      end
+    end
+  end
+
+  local watching = {}
+  for _, w in ipairs(watch_regs) do
+    if not watching[w.base_dir] then
+      watching[w.base_dir] = true
+      table.insert(
+        cancels[client_id][reg.id],
+        M._watchfunc(w.base_dir, { uvflags = { recursive = true } }, callback(w.base_dir))
+      )
+    end
+  end
+end
+
+--- Unregisters the workspace/didChangeWatchedFiles capability dynamically.
+---
+---@param unreg table LSP Unregistration object.
+---@param ctx table Context from the |lsp-handler|.
+function M.unregister(unreg, ctx)
+  local client_id = ctx.client_id
+  local client_cancels = cancels[client_id]
+  local reg_cancels = client_cancels[unreg.id]
+  while #reg_cancels > 0 do
+    table.remove(reg_cancels)()
+  end
+  client_cancels[unreg.id] = nil
+  if not next(cancels[client_id]) then
+    cancels[client_id] = nil
+  end
+end
+
+return M
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 5096100a60..ee5b63d260 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -117,15 +117,35 @@ M['window/showMessageRequest'] = function(_, result)
 end
 
 --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability
-M['client/registerCapability'] = function(_, _, ctx)
-  local client_id = ctx.client_id
-  local warning_tpl = 'The language server %s triggers a registerCapability '
-    .. 'handler despite dynamicRegistration set to false. '
-    .. 'Report upstream, this warning is harmless'
-  local client = vim.lsp.get_client_by_id(client_id)
-  local client_name = client and client.name or string.format('id=%d', client_id)
-  local warning = string.format(warning_tpl, client_name)
-  log.warn(warning)
+M['client/registerCapability'] = function(_, result, ctx)
+  local log_unsupported = false
+  for _, reg in ipairs(result.registrations) do
+    if reg.method == 'workspace/didChangeWatchedFiles' then
+      require('vim.lsp._watchfiles').register(reg, ctx)
+    else
+      log_unsupported = true
+    end
+  end
+  if log_unsupported then
+    local client_id = ctx.client_id
+    local warning_tpl = 'The language server %s triggers a registerCapability '
+      .. 'handler despite dynamicRegistration set to false. '
+      .. 'Report upstream, this warning is harmless'
+    local client = vim.lsp.get_client_by_id(client_id)
+    local client_name = client and client.name or string.format('id=%d', client_id)
+    local warning = string.format(warning_tpl, client_name)
+    log.warn(warning)
+  end
+  return vim.NIL
+end
+
+--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability
+M['client/unregisterCapability'] = function(_, result, ctx)
+  for _, unreg in ipairs(result.unregisterations) do
+    if unreg.method == 'workspace/didChangeWatchedFiles' then
+      require('vim.lsp._watchfiles').unregister(unreg, ctx)
+    end
+  end
   return vim.NIL
 end
 
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 41dfc9e00e..27dd68645a 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -834,6 +834,10 @@ function protocol.make_client_capabilities()
       semanticTokens = {
         refreshSupport = true,
       },
+      didChangeWatchedFiles = {
+        dynamicRegistration = false,
+        relativePatternSupport = true,
+      },
     },
     experimental = nil,
     window = {
-- 
cgit 


From ed05d38d9fa643c7e562b754c6cfed8b9da5c4d8 Mon Sep 17 00:00:00 2001
From: Mathias Fußenegger 
Date: Sun, 5 Mar 2023 08:42:15 +0100
Subject: fix(lsp): don't monitor files if workspace_folders is nil (#22531)

Fixes:

    Error SERVER_REQUEST_HANDLER_ERROR: "...di/dev/neovim/neovim/runtime/lua/vim/lsp/_watchfiles.lua
    :200: bad argument #1 to 'ipairs' (table expected, got nil)"

Language servers can be started without root_dir or workspace_folders.
---
 runtime/lua/vim/lsp/_watchfiles.lua | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'runtime')

diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index 96d7fa1d35..533a955925 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -168,11 +168,11 @@ end
 
 M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll
 
----@type table> client id -> registration id -> cancel function
+---@type table> client id -> registration id -> cancel function
 local cancels = vim.defaulttable()
 
 local queue_timeout_ms = 100
----@type table client id -> libuv timer which will send queued changes at its timeout
+---@type table client id -> libuv timer which will send queued changes at its timeout
 local queue_timers = {}
 ---@type table client id -> set of queued changes to send in a single LSP notification
 local change_queues = {}
@@ -193,6 +193,9 @@ local to_lsp_change_type = {
 function M.register(reg, ctx)
   local client_id = ctx.client_id
   local client = vim.lsp.get_client_by_id(client_id)
+  if not client.workspace_folders then
+    return
+  end
   local watch_regs = {}
   for _, w in ipairs(reg.registerOptions.watchers) do
     local glob_patterns = {}
-- 
cgit 


From 533d671271eb76373d9940161e7bfd201b7e7c2b Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Sun, 5 Mar 2023 18:15:29 -0500
Subject: docs: module-level docstrings (@defgroup) #22498

Problem:
gen_vimdoc.py / lua2dox.lua does not support @defgroup or \defgroup
except for "api-foo" modules.

Solution:
Modify `gen_vimdoc.py` to look for section names based on `helptag_fmt`.

TODO:
- Support @module ?
  https://github.com/LuaLS/lua-language-server/wiki/Annotations#module
---
 runtime/doc/treesitter.txt                  | 78 +++++++++++++++--------------
 runtime/lua/vim/treesitter/languagetree.lua | 34 +++++++++++++
 2 files changed, 74 insertions(+), 38 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 855fc6bdc6..1f78e4d5d9 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -28,42 +28,6 @@ A parser can also be loaded manually using a full path: >lua
 
     vim.treesitter.require_language("python", "/path/to/python.so")
 <
-==============================================================================
-LANGUAGE TREES                                       *treesitter-languagetree*
-                                                                *LanguageTree*
-
-As buffers can contain multiple languages (e.g., Vimscript commands in a Lua
-file), multiple parsers may be needed to parse the full buffer. These are
-combined in a |LanguageTree| object.
-
-To create a LanguageTree (parser object) for a buffer and a given language,
-use >lua
-
-    tsparser = vim.treesitter.get_parser(bufnr, lang)
-<
-`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'.
-Currently, the parser will be retained for the lifetime of a buffer but this
-is subject to change. A plugin should keep a reference to the parser object as
-long as it wants incremental updates.
-
-Whenever you need to access the current syntax tree, parse the buffer: >lua
-
-    tstree = tsparser:parse()
-<
-This will return a table of immutable |treesitter-tree|s that represent the
-current state of the buffer. When the plugin wants to access the state after a
-(possible) edit it should call `parse()` again. If the buffer wasn't edited,
-the same tree will be returned again without extra work. If the buffer was
-parsed before, incremental parsing will be done of the changed parts.
-
-Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback,
-you must call |vim.treesitter.get_parser()| before you register your callback.
-But preferably parsing shouldn't be done directly in the change callback
-anyway as they will be very frequent. Rather a plugin that does any kind of
-analysis on a tree should use a timer to throttle too frequent updates.
-
-See |lua-treesitter-languagetree| for the list of available methods.
-
 ==============================================================================
 TREESITTER TREES                                             *treesitter-tree*
                                                                       *TSTree*
@@ -221,7 +185,7 @@ Nvim looks for queries as `*.scm` files in a `queries` directory under
 purpose, e.g., `queries/lua/highlights.scm` for highlighting Lua files.
 By default, the first query on `runtimepath` is used (which usually implies
 that user config takes precedence over plugins, which take precedence over
-queries bundled with Neovim). If a query should extend other queries instead
+queries bundled with Nvim). If a query should extend other queries instead
 of replacing them, use |treesitter-query-modeline-extends|.
 
 See |lua-treesitter-query| for the list of available methods for working with
@@ -321,7 +285,7 @@ Use |vim.treesitter.list_directives()| to list all available directives.
 
 TREESITTER QUERY MODELINES                          *treesitter-query-modeline*
 
-Neovim supports to customize the behavior of the queries using a set of
+Nvim supports to customize the behavior of the queries using a set of
 "modelines", that is comments in the queries starting with `;`. Here are the
 currently supported modeline alternatives:
 
@@ -938,6 +902,44 @@ TSHighlighter:destroy({self})                        *TSHighlighter:destroy()*
 ==============================================================================
 Lua module: vim.treesitter.languagetree          *lua-treesitter-languagetree*
 
+
+A *LanguageTree* contains a tree of parsers: the root treesitter parser
+for {lang} and any "injected" language parsers, which themselves may
+inject other languages, recursively. For example a Lua buffer containing
+some Vimscript commands needs multiple parsers to fully understand its
+contents.
+
+To create a LanguageTree (parser object) for a given buffer and language, use:
+
+>lua
+    local parser = vim.treesitter.get_parser(bufnr, lang)
+<
+
+(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'.
+Note: currently the parser is retained for the lifetime of a buffer but
+this may change; a plugin should keep a reference to the parser object if
+it wants incremental updates.
+
+Whenever you need to access the current syntax tree, parse the buffer:
+
+>lua
+    local tree = parser:parse()
+<
+
+This returns a table of immutable |treesitter-tree| objects representing
+the current state of the buffer. When the plugin wants to access the state
+after a (possible) edit it must call `parse()` again. If the buffer wasn't
+edited, the same tree will be returned again without extra work. If the
+buffer was parsed before, incremental parsing will be done of the changed
+parts.
+
+Note: To use the parser directly inside a |nvim_buf_attach()| Lua
+callback, you must call |vim.treesitter.get_parser()| before you register
+your callback. But preferably parsing shouldn't be done directly in the
+change callback anyway as they will be very frequent. Rather a plugin that
+does any kind of analysis on a tree should use a timer to throttle too
+frequent updates.
+
 LanguageTree:children({self})                        *LanguageTree:children()*
     Returns a map of language to child tree.
 
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 1bc7971eba..b8b0dd867e 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -1,3 +1,37 @@
+--- @defgroup lua-treesitter-languagetree
+---
+--- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and
+--- any "injected" language parsers, which themselves may inject other languages, recursively.
+--- For example a Lua buffer containing some Vimscript commands needs multiple parsers to fully
+--- understand its contents.
+---
+--- To create a LanguageTree (parser object) for a given buffer and language, use:
+---
+--- 
lua
+---     local parser = vim.treesitter.get_parser(bufnr, lang)
+--- 
+--- +--- (where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. +--- Note: currently the parser is retained for the lifetime of a buffer but this may change; +--- a plugin should keep a reference to the parser object if it wants incremental updates. +--- +--- Whenever you need to access the current syntax tree, parse the buffer: +--- +---
lua
+---     local tree = parser:parse()
+--- 
+--- +--- This returns a table of immutable |treesitter-tree| objects representing the current state of +--- the buffer. When the plugin wants to access the state after a (possible) edit it must call +--- `parse()` again. If the buffer wasn't edited, the same tree will be returned again without extra +--- work. If the buffer was parsed before, incremental parsing will be done of the changed parts. +--- +--- Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback, you must call +--- |vim.treesitter.get_parser()| before you register your callback. But preferably parsing +--- shouldn't be done directly in the change callback anyway as they will be very frequent. Rather +--- a plugin that does any kind of analysis on a tree should use a timer to throttle too frequent +--- updates. + local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') -- cgit From f9a46391ab5961fe6c6b7d1efdc96befdd495c11 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 6 Mar 2023 10:57:14 +0000 Subject: refactor(treesitter): simplify some range functions --- runtime/lua/vim/treesitter.lua | 26 +++++++------------------- runtime/lua/vim/treesitter/_range.lua | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index ee66ba9f9b..d13824076e 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -2,6 +2,7 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') local LanguageTree = require('vim.treesitter.languagetree') +local Range = require('vim.treesitter._range') ---@type table local parsers = setmetatable({}, { __mode = 'v' }) @@ -190,20 +191,7 @@ end --- ---@return 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 - if line == start_line and line == end_line then - return col >= start_col and col < end_col - elseif line == start_line then - return col >= start_col - elseif line == end_line then - return col < end_col - else - return true - end - else - return false - end + return M.node_contains(node, { line, col, line, col }) end --- Determines if a node contains a range @@ -213,11 +201,11 @@ end --- ---@return boolean True if the {node} contains the {range} function M.node_contains(node, range) - local start_row, start_col, end_row, end_col = node:range() - local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) - local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) - - return start_fits and end_fits + vim.validate({ + node = { node, 'userdata' }, + range = { range, Range.validate, 'integer list with 4 or 6 elements' }, + }) + return Range.contains({ node:range() }, range) end --- Returns a list of highlight captures at the given position diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua index 8decd3a1fd..bec24a23a5 100644 --- a/runtime/lua/vim/treesitter/_range.lua +++ b/runtime/lua/vim/treesitter/_range.lua @@ -53,6 +53,26 @@ M.cmp_pos = { setmetatable(M.cmp_pos, { __call = cmp_pos }) +---@private +---Check if a variable is a valid range object +---@param r any +---@return boolean +function M.validate(r) + if type(r) ~= 'table' or #r ~= 6 and #r ~= 4 then + return false + end + + for _, e in + ipairs(r --[[@as any[] ]]) + do + if type(e) ~= 'number' then + return false + end + end + + return true +end + ---@private ---@param r1 Range4|Range6 ---@param r2 Range4|Range6 -- cgit From 0e7196438d8f856eecd7c90e160b79cbc8fb08dc Mon Sep 17 00:00:00 2001 From: Kelly Lin Date: Sun, 19 Feb 2023 22:33:57 +1100 Subject: feat(lua): add semver api --- runtime/doc/lua.txt | 72 +++++++++ runtime/doc/news.txt | 4 + runtime/lua/vim/_init_packages.lua | 3 + runtime/lua/vim/version.lua | 297 +++++++++++++++++++++++++++++++++++++ 4 files changed, 376 insertions(+) create mode 100644 runtime/lua/vim/version.lua (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 1eb5ab41e6..3c48cd37a6 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -2497,4 +2497,76 @@ trust({opts}) *vim.secure.trust()* • true and full path of target file if operation was successful • false and error message on failure + +============================================================================== +Lua module: version *lua-version* + +cmp({v1}, {v2}, {opts}) *version.cmp()* + Compares two strings ( `v1` and `v2` ) in semver format. + + Parameters: ~ + • {v1} (string) Version. + • {v2} (string) Version to be compared with v1. + • {opts} (table|nil) Optional keyword arguments: + • strict (boolean): see `semver.parse` for details. Defaults + to false. + + Return: ~ + (integer) `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. + +eq({version_1}, {version_2}) *version.eq()* + Returns `true` if `v1` are `v2` are equal versions. + + Parameters: ~ + • {version_1} (string) + • {version_2} (string) + + Return: ~ + (boolean) + +gt({version_1}, {version_2}) *version.gt()* + Returns `true` if `v1` is greater than `v2` . + + Parameters: ~ + • {version_1} (string) + • {version_2} (string) + + Return: ~ + (boolean) + +lt({version_1}, {version_2}) *version.lt()* + Returns `true` if `v1` is less than `v2` . + + Parameters: ~ + • {version_1} (string) + • {version_2} (string) + + Return: ~ + (boolean) + +parse({version}, {opts}) *version.parse()* + Parses a semantically formatted version string into a table. + + Supports leading "v" and leading and trailing whitespace in the version + string. e.g. `" v1.0.1-rc1+build.2"` , `"1.0.1-rc1+build.2"`, + `"v1.0.1-rc1+build.2"` and `"v1.0.1-rc1+build.2 "` will be parsed as: + + { major = 1, minor = 0, patch = 1, prerelease = 'rc1 , build = 'build.2' }` + + Parameters: ~ + • {version} (string) Version string to be parsed. + • {opts} (table|nil) Optional keyword arguments: + • strict (boolean): when set to `true` an error will be + thrown for version strings that do not conform to the + semver specification (v2.0.0) (see + semver.org/spec/v2.0.0.html for details). This means that + `semver.parse('v1.2)` will throw an error. When set to + `false`, `semver.parse('v1.2)` will coerce 'v1.2' to + 'v1.2.0' and return the table: `{ major = 1, minor = 2, + patch = 0 }`. Defaults to false. + + Return: ~ + (table|nil) parsed_version Parsed version table or `nil` if `version` + is not valid. + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 415195e27e..b5cb975066 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -55,6 +55,10 @@ NEW FEATURES *news-features* The following new APIs or features were added. +• Added |version.parse()|, |version.cmp()|, |version.lt()|, |version.eq()| + and |version.gt()| to |vim.version| for parsing and comparing version numbers + according to the semver specification, see |lua-version|. + • A new environment variable named NVIM_APPNAME enables configuring the directories where Neovim should find its configuration and state files. See `:help $NVIM_APPNAME` . diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index e3a442af5e..d032026796 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -69,6 +69,9 @@ setmetatable(vim, { t[key] = val return t[key] end + elseif key == 'version' then + t[key] = require('vim.version') + return t[key] end end, }) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua new file mode 100644 index 0000000000..49ef019295 --- /dev/null +++ b/runtime/lua/vim/version.lua @@ -0,0 +1,297 @@ +local M = {} + +---@private +--- Compares the prerelease component of the two versions. +---@param v1_parsed table Parsed version. +---@param v2_parsed table Parsed version. +---@return integer `-1` if `v1_parsed < v2_parsed`, `0` if `v1_parsed == v2_parsed`, `1` if `v1_parsed > v2_parsed`. +local function cmp_prerelease(v1_parsed, v2_parsed) + if v1_parsed.prerelease and not v2_parsed.prerelease then + return -1 + end + if not v1_parsed.prerelease and v2_parsed.prerelease then + return 1 + end + if not v1_parsed.prerelease and not v2_parsed.prerelease then + return 0 + end + + local v1_identifiers = vim.split(v1_parsed.prerelease, '.', { plain = true }) + local v2_identifiers = vim.split(v2_parsed.prerelease, '.', { plain = true }) + local i = 1 + local max = math.max(vim.tbl_count(v1_identifiers), vim.tbl_count(v2_identifiers)) + while i <= max do + local v1_identifier = v1_identifiers[i] + local v2_identifier = v2_identifiers[i] + if v1_identifier ~= v2_identifier then + local v1_num = tonumber(v1_identifier) + local v2_num = tonumber(v2_identifier) + local is_number = v1_num and v2_num + if is_number then + -- Number comparisons + if not v1_num and v2_num then + return -1 + end + if v1_num and not v2_num then + return 1 + end + if v1_num == v2_num then + return 0 + end + if v1_num > v2_num then + return 1 + end + if v1_num < v2_num then + return -1 + end + else + -- String comparisons + if v1_identifier and not v2_identifier then + return 1 + end + if not v1_identifier and v2_identifier then + return -1 + end + if v1_identifier < v2_identifier then + return -1 + end + if v1_identifier > v2_identifier then + return 1 + end + if v1_identifier == v2_identifier then + return 0 + end + end + end + i = i + 1 + end + + return 0 +end + +---@private +--- Compares the version core component of the two versions. +---@param v1_parsed table Parsed version. +---@param v2_parsed table Parsed version. +---@return integer `-1` if `v1_parsed < v2_parsed`, `0` if `v1_parsed == v2_parsed`, `1` if `v1_parsed > v2_parsed`. +local function cmp_version_core(v1_parsed, v2_parsed) + if + v1_parsed.major == v2_parsed.major + and v1_parsed.minor == v2_parsed.minor + and v1_parsed.patch == v2_parsed.patch + then + return 0 + end + + if + v1_parsed.major > v2_parsed.major + or v1_parsed.minor > v2_parsed.minor + or v1_parsed.patch > v2_parsed.patch + then + return 1 + end + + return -1 +end + +--- Compares two strings (`v1` and `v2`) in semver format. +---@param v1 string Version. +---@param v2 string Version to be compared with v1. +---@param opts table|nil Optional keyword arguments: +--- - strict (boolean): see `semver.parse` for details. Defaults to false. +---@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. +function M.cmp(v1, v2, opts) + opts = opts or { strict = false } + local v1_parsed = M.parse(v1, opts) + local v2_parsed = M.parse(v2, opts) + + local result = cmp_version_core(v1_parsed, v2_parsed) + if result == 0 then + result = cmp_prerelease(v1_parsed, v2_parsed) + end + return result +end + +---@private +---@param labels string Prerelease and build component of semantic version string e.g. "-rc1+build.0". +---@return string|nil +local function parse_prerelease(labels) + -- This pattern matches "-(alpha)+build.15". + -- '^%-[%w%.]+$' + local result = labels:match('^%-([%w%.]+)+.+$') + if result then + return result + end + -- This pattern matches "-(alpha)". + result = labels:match('^%-([%w%.]+)') + if result then + return result + end + + return nil +end + +---@private +---@param labels string Prerelease and build component of semantic version string e.g. "-rc1+build.0". +---@return string|nil +local function parse_build(labels) + -- Pattern matches "-alpha+(build.15)". + local result = labels:match('^%-[%w%.]+%+([%w%.]+)$') + if result then + return result + end + + -- Pattern matches "+(build.15)". + result = labels:match('^%+([%w%.]+)$') + if result then + return result + end + + return nil +end + +---@private +--- Extracts the major, minor, patch and preprelease and build components from +--- `version`. +---@param version string Version string +local function extract_components_strict(version) + local major, minor, patch, prerelease_and_build = version:match('^v?(%d+)%.(%d+)%.(%d+)(.*)$') + return tonumber(major), tonumber(minor), tonumber(patch), prerelease_and_build +end + +---@private +--- Extracts the major, minor, patch and preprelease and build components from +--- `version`. When `minor` and `patch` components are not found (nil), coerce +--- them to 0. +---@param version string Version string +local function extract_components_loose(version) + local major, minor, patch, prerelease_and_build = version:match('^v?(%d+)%.?(%d*)%.?(%d*)(.*)$') + major = tonumber(major) + minor = tonumber(minor) or 0 + patch = tonumber(patch) or 0 + return major, minor, patch, prerelease_and_build +end + +---@private +--- Validates the prerelease and build string e.g. "-rc1+build.0". If the +--- prerelease, build or both are valid forms then it will return true, if it +--- is not of any valid form, it will return false. +---@param prerelease_and_build string +---@return boolean +local function is_prerelease_and_build_valid(prerelease_and_build) + if prerelease_and_build == '' then + return true + end + local has_build = parse_build(prerelease_and_build) ~= nil + local has_prerelease = parse_prerelease(prerelease_and_build) ~= nil + local has_prerelease_and_build = has_prerelease and has_build + return has_build or has_prerelease or has_prerelease_and_build +end + +---@private +---@param version string +---@return string +local function create_err_msg(version) + return string.format('invalid version: "%s"', version) +end + +--- Parses a semantically formatted version string into a table. +--- +--- Supports leading "v" and leading and trailing whitespace in the version +--- string. e.g. `" v1.0.1-rc1+build.2"` , `"1.0.1-rc1+build.2"`, `"v1.0.1-rc1+build.2"` +--- and `"v1.0.1-rc1+build.2 "` will be parsed as: +--- +--- `{ major = 1, minor = 0, patch = 1, prerelease = 'rc1', build = 'build.2' }` +--- +---@param version string Version string to be parsed. +---@param opts table|nil Optional keyword arguments: +--- - strict (boolean): when set to `true` an error will be thrown for version +--- strings that do not conform to the semver specification (v2.0.0) (see +--- semver.org/spec/v2.0.0.html for details). This means that +--- `semver.parse('v1.2)` will throw an error. When set to `false`, +--- `semver.parse('v1.2)` will coerce 'v1.2' to 'v1.2.0' and return the table: +--- `{ major = 1, minor = 2, patch = 0 }`. Defaults to false. +---@return table|nil parsed_version Parsed version table or `nil` if `version` is not valid. +function M.parse(version, opts) + if type(version) ~= 'string' then + error(create_err_msg(version)) + end + + opts = opts or { strict = false } + + version = vim.trim(version) + + local extract_components = opts.strict and extract_components_strict or extract_components_loose + local major, minor, patch, prerelease_and_build = extract_components(version) + + -- If major is nil then that means that the version does not begin with a + -- digit with or without a "v" prefix. + if major == nil or not is_prerelease_and_build_valid(prerelease_and_build) then + return nil + end + + local prerelease = nil + local build = nil + if prerelease_and_build ~= nil then + prerelease = parse_prerelease(prerelease_and_build) + build = parse_build(prerelease_and_build) + end + + return { + major = major, + minor = minor, + patch = patch, + prerelease = prerelease, + build = build, + } +end + +---@private +--- Throws an error if `version` cannot be parsed. +---@param version string +local function assert_version(version) + if M.parse(version) == nil then + error(create_err_msg(version)) + end +end + +---Returns `true` if `v1` are `v2` are equal versions. +---@param version_1 string +---@param version_2 string +---@return boolean +function M.eq(version_1, version_2) + assert_version(version_1) + assert_version(version_2) + + return M.cmp(version_1, version_2) == 0 +end + +---Returns `true` if `v1` is less than `v2`. +---@param version_1 string +---@param version_2 string +---@return boolean +function M.lt(version_1, version_2) + assert_version(version_1) + assert_version(version_2) + + return M.cmp(version_1, version_2) == -1 +end + +---Returns `true` if `v1` is greater than `v2`. +---@param version_1 string +---@param version_2 string +---@return boolean +function M.gt(version_1, version_2) + assert_version(version_1) + assert_version(version_2) + + return M.cmp(version_1, version_2) == 1 +end + +setmetatable(M, { + __call = function() + return vim.fn.api_info().version + end, +}) + +return M -- cgit From e31e49a8e3aac25e923dce15cc76dca4a447947f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 6 Mar 2023 13:23:03 +0100 Subject: refactor(vim.version): cleanup - version.cmp(): assert valid version - add test for loading vim.version (the other tests use shared.lua in the test runner) - reduce test scopes, reword test descriptions --- runtime/doc/lua.txt | 47 ++++++------- runtime/doc/news.txt | 5 +- runtime/lua/vim/_init_packages.lua | 8 +-- runtime/lua/vim/version.lua | 134 ++++++++++++++++--------------------- 4 files changed, 85 insertions(+), 109 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 3c48cd37a6..697cd86e8a 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -2501,12 +2501,12 @@ trust({opts}) *vim.secure.trust()* ============================================================================== Lua module: version *lua-version* -cmp({v1}, {v2}, {opts}) *version.cmp()* +cmp({v1}, {v2}, {opts}) *vim.version.cmp()* Compares two strings ( `v1` and `v2` ) in semver format. Parameters: ~ • {v1} (string) Version. - • {v2} (string) Version to be compared with v1. + • {v2} (string) Version to compare with v1. • {opts} (table|nil) Optional keyword arguments: • strict (boolean): see `semver.parse` for details. Defaults to false. @@ -2514,59 +2514,54 @@ cmp({v1}, {v2}, {opts}) *version.cmp()* Return: ~ (integer) `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. -eq({version_1}, {version_2}) *version.eq()* +eq({v1}, {v2}) *vim.version.eq()* Returns `true` if `v1` are `v2` are equal versions. Parameters: ~ - • {version_1} (string) - • {version_2} (string) + • {v1} (string) + • {v2} (string) Return: ~ (boolean) -gt({version_1}, {version_2}) *version.gt()* +gt({v1}, {v2}) *vim.version.gt()* Returns `true` if `v1` is greater than `v2` . Parameters: ~ - • {version_1} (string) - • {version_2} (string) + • {v1} (string) + • {v2} (string) Return: ~ (boolean) -lt({version_1}, {version_2}) *version.lt()* +lt({v1}, {v2}) *vim.version.lt()* Returns `true` if `v1` is less than `v2` . Parameters: ~ - • {version_1} (string) - • {version_2} (string) + • {v1} (string) + • {v2} (string) Return: ~ (boolean) -parse({version}, {opts}) *version.parse()* - Parses a semantically formatted version string into a table. +parse({version}, {opts}) *vim.version.parse()* + Parses a semantic version string. - Supports leading "v" and leading and trailing whitespace in the version - string. e.g. `" v1.0.1-rc1+build.2"` , `"1.0.1-rc1+build.2"`, - `"v1.0.1-rc1+build.2"` and `"v1.0.1-rc1+build.2 "` will be parsed as: + Ignores leading "v" and surrounding whitespace, e.g. " + v1.0.1-rc1+build.2", "1.0.1-rc1+build.2", "v1.0.1-rc1+build.2" and + "v1.0.1-rc1+build.2 " are all parsed as: > - { major = 1, minor = 0, patch = 1, prerelease = 'rc1 , build = 'build.2' }` + { major = 1, minor = 0, patch = 1, prerelease = "rc1", build = "build.2" } +< Parameters: ~ • {version} (string) Version string to be parsed. • {opts} (table|nil) Optional keyword arguments: - • strict (boolean): when set to `true` an error will be - thrown for version strings that do not conform to the - semver specification (v2.0.0) (see - semver.org/spec/v2.0.0.html for details). This means that - `semver.parse('v1.2)` will throw an error. When set to - `false`, `semver.parse('v1.2)` will coerce 'v1.2' to - 'v1.2.0' and return the table: `{ major = 1, minor = 2, - patch = 0 }`. Defaults to false. + • strict (boolean): Default false. If `true` , no coercion is attempted on input not strictly + conforming to semver v2.0.0 ( https://semver.org/spec/v2.0.0.html ). E.g. `parse("v1.2")` returns nil. Return: ~ (table|nil) parsed_version Parsed version table or `nil` if `version` - is not valid. + is invalid. vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index b5cb975066..28fdaa770d 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -55,9 +55,8 @@ NEW FEATURES *news-features* The following new APIs or features were added. -• Added |version.parse()|, |version.cmp()|, |version.lt()|, |version.eq()| - and |version.gt()| to |vim.version| for parsing and comparing version numbers - according to the semver specification, see |lua-version|. +• Added |vim.version| for parsing and comparing version strings conforming to + the semver specification, see |lua-version|. • A new environment variable named NVIM_APPNAME enables configuring the directories where Neovim should find its configuration and state files. See diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index d032026796..57c0fc9122 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -51,7 +51,10 @@ end -- builtin functions which always should be available require('vim.shared') -vim._submodules = { inspect = true } +vim._submodules = { + inspect = true, + version = true, +} -- These are for loading runtime modules in the vim namespace lazily. setmetatable(vim, { @@ -69,9 +72,6 @@ setmetatable(vim, { t[key] = val return t[key] end - elseif key == 'version' then - t[key] = require('vim.version') - return t[key] end end, }) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 49ef019295..ddbe228244 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -1,23 +1,41 @@ local M = {} +---@private +---@param version string +---@return string +local function create_err_msg(version) + return string.format('invalid version: "%s"', version) +end + +---@private +--- Throws an error if `version` cannot be parsed. +---@param version string +local function assert_version(version, opt) + local rv = M.parse(version, opt) + if rv == nil then + error(create_err_msg(version)) + end + return rv +end + ---@private --- Compares the prerelease component of the two versions. ----@param v1_parsed table Parsed version. ----@param v2_parsed table Parsed version. ----@return integer `-1` if `v1_parsed < v2_parsed`, `0` if `v1_parsed == v2_parsed`, `1` if `v1_parsed > v2_parsed`. -local function cmp_prerelease(v1_parsed, v2_parsed) - if v1_parsed.prerelease and not v2_parsed.prerelease then +---@param v1 table Parsed version. +---@param v2 table Parsed version. +---@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. +local function cmp_prerelease(v1, v2) + if v1.prerelease and not v2.prerelease then return -1 end - if not v1_parsed.prerelease and v2_parsed.prerelease then + if not v1.prerelease and v2.prerelease then return 1 end - if not v1_parsed.prerelease and not v2_parsed.prerelease then + if not v1.prerelease and not v2.prerelease then return 0 end - local v1_identifiers = vim.split(v1_parsed.prerelease, '.', { plain = true }) - local v2_identifiers = vim.split(v2_parsed.prerelease, '.', { plain = true }) + local v1_identifiers = vim.split(v1.prerelease, '.', { plain = true }) + local v2_identifiers = vim.split(v2.prerelease, '.', { plain = true }) local i = 1 local max = math.max(vim.tbl_count(v1_identifiers), vim.tbl_count(v2_identifiers)) while i <= max do @@ -71,23 +89,15 @@ end ---@private --- Compares the version core component of the two versions. ----@param v1_parsed table Parsed version. ----@param v2_parsed table Parsed version. ----@return integer `-1` if `v1_parsed < v2_parsed`, `0` if `v1_parsed == v2_parsed`, `1` if `v1_parsed > v2_parsed`. -local function cmp_version_core(v1_parsed, v2_parsed) - if - v1_parsed.major == v2_parsed.major - and v1_parsed.minor == v2_parsed.minor - and v1_parsed.patch == v2_parsed.patch - then +---@param v1 table Parsed version. +---@param v2 table Parsed version. +---@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. +local function cmp_version_core(v1, v2) + if v1.major == v2.major and v1.minor == v2.minor and v1.patch == v2.patch then return 0 end - if - v1_parsed.major > v2_parsed.major - or v1_parsed.minor > v2_parsed.minor - or v1_parsed.patch > v2_parsed.patch - then + if v1.major > v2.major or v1.minor > v2.minor or v1.patch > v2.patch then return 1 end @@ -96,14 +106,14 @@ end --- Compares two strings (`v1` and `v2`) in semver format. ---@param v1 string Version. ----@param v2 string Version to be compared with v1. +---@param v2 string Version to compare with v1. ---@param opts table|nil Optional keyword arguments: --- - strict (boolean): see `semver.parse` for details. Defaults to false. ---@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. function M.cmp(v1, v2, opts) opts = opts or { strict = false } - local v1_parsed = M.parse(v1, opts) - local v2_parsed = M.parse(v2, opts) + local v1_parsed = assert_version(v1, opts) + local v2_parsed = assert_version(v2, opts) local result = cmp_version_core(v1_parsed, v2_parsed) if result == 0 then @@ -188,30 +198,20 @@ local function is_prerelease_and_build_valid(prerelease_and_build) return has_build or has_prerelease or has_prerelease_and_build end ----@private ----@param version string ----@return string -local function create_err_msg(version) - return string.format('invalid version: "%s"', version) -end - ---- Parses a semantically formatted version string into a table. ---- ---- Supports leading "v" and leading and trailing whitespace in the version ---- string. e.g. `" v1.0.1-rc1+build.2"` , `"1.0.1-rc1+build.2"`, `"v1.0.1-rc1+build.2"` ---- and `"v1.0.1-rc1+build.2 "` will be parsed as: +--- Parses a semantic version string. --- ---- `{ major = 1, minor = 0, patch = 1, prerelease = 'rc1', build = 'build.2' }` +--- Ignores leading "v" and surrounding whitespace, e.g. " v1.0.1-rc1+build.2", +--- "1.0.1-rc1+build.2", "v1.0.1-rc1+build.2" and "v1.0.1-rc1+build.2 " are all parsed as: +---
+---   { major = 1, minor = 0, patch = 1, prerelease = "rc1", build = "build.2" }
+--- 
--- ---@param version string Version string to be parsed. ---@param opts table|nil Optional keyword arguments: ---- - strict (boolean): when set to `true` an error will be thrown for version ---- strings that do not conform to the semver specification (v2.0.0) (see ---- semver.org/spec/v2.0.0.html for details). This means that ---- `semver.parse('v1.2)` will throw an error. When set to `false`, ---- `semver.parse('v1.2)` will coerce 'v1.2' to 'v1.2.0' and return the table: ---- `{ major = 1, minor = 2, patch = 0 }`. Defaults to false. ----@return table|nil parsed_version Parsed version table or `nil` if `version` is not valid. +--- - strict (boolean): Default false. If `true`, no coercion is attempted on +--- input not strictly conforming to semver v2.0.0 +--- (https://semver.org/spec/v2.0.0.html). E.g. `parse("v1.2")` returns nil. +---@return table|nil parsed_version Parsed version table or `nil` if `version` is invalid. function M.parse(version, opts) if type(version) ~= 'string' then error(create_err_msg(version)) @@ -246,46 +246,28 @@ function M.parse(version, opts) } end ----@private ---- Throws an error if `version` cannot be parsed. ----@param version string -local function assert_version(version) - if M.parse(version) == nil then - error(create_err_msg(version)) - end -end - ---Returns `true` if `v1` are `v2` are equal versions. ----@param version_1 string ----@param version_2 string +---@param v1 string +---@param v2 string ---@return boolean -function M.eq(version_1, version_2) - assert_version(version_1) - assert_version(version_2) - - return M.cmp(version_1, version_2) == 0 +function M.eq(v1, v2) + return M.cmp(v1, v2) == 0 end ---Returns `true` if `v1` is less than `v2`. ----@param version_1 string ----@param version_2 string +---@param v1 string +---@param v2 string ---@return boolean -function M.lt(version_1, version_2) - assert_version(version_1) - assert_version(version_2) - - return M.cmp(version_1, version_2) == -1 +function M.lt(v1, v2) + return M.cmp(v1, v2) == -1 end ---Returns `true` if `v1` is greater than `v2`. ----@param version_1 string ----@param version_2 string +---@param v1 string +---@param v2 string ---@return boolean -function M.gt(version_1, version_2) - assert_version(version_1) - assert_version(version_2) - - return M.cmp(version_1, version_2) == 1 +function M.gt(v1, v2) + return M.cmp(v1, v2) == 1 end setmetatable(M, { -- cgit From 74ffebf8ec725a25c2ae1dde81cf26b83fc7ae61 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 6 Mar 2023 15:08:22 +0100 Subject: fix(vim.version): incorrect version.cmp() Problem: If majorminor, cmp_version_core returns 1 Solution: - Fix logic in cmp_version_core - Delete most eq()/gt()/lt() tests, they are redundant. --- runtime/lua/vim/version.lua | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index ddbe228244..35629c461f 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -3,8 +3,11 @@ local M = {} ---@private ---@param version string ---@return string -local function create_err_msg(version) - return string.format('invalid version: "%s"', version) +local function create_err_msg(v) + if type(v) == 'string' then + return string.format('invalid version: "%s"', tostring(v)) + end + return string.format('invalid version: %s (%s)', tostring(v), type(v)) end ---@private @@ -20,9 +23,6 @@ end ---@private --- Compares the prerelease component of the two versions. ----@param v1 table Parsed version. ----@param v2 table Parsed version. ----@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. local function cmp_prerelease(v1, v2) if v1.prerelease and not v2.prerelease then return -1 @@ -88,19 +88,17 @@ local function cmp_prerelease(v1, v2) end ---@private ---- Compares the version core component of the two versions. ----@param v1 table Parsed version. ----@param v2 table Parsed version. ----@return integer `-1` if `v1 < v2`, `0` if `v1 == v2`, `1` if `v1 > v2`. local function cmp_version_core(v1, v2) if v1.major == v2.major and v1.minor == v2.minor and v1.patch == v2.patch then return 0 end - - if v1.major > v2.major or v1.minor > v2.minor or v1.patch > v2.patch then + if + v1.major > v2.major + or (v1.major == v2.major and v1.minor > v2.minor) + or (v1.major == v2.major and v1.minor == v2.minor and v1.patch > v2.patch) + then return 1 end - return -1 end -- cgit From 1cc23e1109ed88275df5c986c352f73b99a0301c Mon Sep 17 00:00:00 2001 From: swarn Date: Mon, 6 Mar 2023 12:03:13 -0600 Subject: feat(lsp)!: add rule-based sem token highlighting (#22022) feat(lsp)!: change semantic token highlighting Change the default highlights used, and add more highlights per token. Add an LspTokenUpdate event and a highlight_token function. :Inspect now shows any highlights applied by token highlighting rules, default or user-defined. BREAKING CHANGE: change the default highlight groups used by semantic token highlighting. --- runtime/doc/lsp.txt | 120 ++++++++++++++++++++- runtime/doc/news.txt | 2 +- runtime/lua/vim/_inspector.lua | 97 +++++++++-------- runtime/lua/vim/lsp/semantic_tokens.lua | 183 ++++++++++++++++++++++---------- 4 files changed, 297 insertions(+), 105 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 7e46698614..0d7e8e7ab4 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -482,6 +482,71 @@ LspSignatureActiveParameter Used to highlight the active parameter in the signature help. See |vim.lsp.handlers.signature_help()|. +------------------------------------------------------------------------------ +LSP SEMANTIC HIGHLIGHTS *lsp-semantic-highlight* + +When available, the LSP client highlights code using |lsp-semantic_tokens|, +which are another way that LSP servers can provide information about source +code. Note that this is in addition to treesitter syntax highlighting; +semantic highlighting does not replace syntax highlighting. + +The server will typically provide one token per identifier in the source code. +The token will have a `type` such as "function" or "variable", and 0 or more +`modifier`s such as "readonly" or "deprecated." The standard types and +modifiers are described here: +https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens +LSP servers may also use off-spec types and modifiers. + +The LSP client adds one or more highlights for each token. The highlight +groups are derived from the token's type and modifiers: + • `@lsp.type..` for the type + • `@lsp.mod..` for each modifier + • `@lsp.typemod...` for each modifier +Use |:Inspect| to view the higlights for a specific token. Use |:hi| or +|nvim_set_hl()| to change the appearance of semantic highlights: >vim + + hi @lsp.type.function guifg=Yellow " function names are yellow + hi @lsp.type.variable.lua guifg=Green " variables in lua are green + hi @lsp.mod.deprecated gui=strikethrough " deprecated is crossed out + hi @lsp.typemod.function.async guifg=Blue " async functions are blue +< +The value |vim.highlight.priorities|`.semantic_tokens` is the priority of the +`@lsp.type.*` highlights. The `@lsp.mod.*` and `@lsp.typemod.*` highlights +have priorities one and two higher, respectively. + +You can disable semantic highlights by clearing the highlight groups: >lua + + -- Hide semantic highlights for functions + vim.api.nvim_set_hl(0, '@lsp.type.function', {}) + + -- Hide all semantic highlights + for _, group in ipairs(vim.fn.getcompletion("@lsp", "highlight")) do + vim.api.nvim_set_hl(0, group, {}) + end +< +You probably want these inside a |ColorScheme| autocommand. + +Use |LspTokenUpdate| and |vim.lsp.semantic_tokens.highlight_token()| for more +complex highlighting. + +The following groups are linked by default to standard |group-name|s: +> + @lsp.type.class Structure + @lsp.type.decorator Function + @lsp.type.enum Structure + @lsp.type.enumMember Constant + @lsp.type.function Function + @lsp.type.interface Structure + @lsp.type.macro Macro + @lsp.type.method Function + @lsp.type.namespace Structure + @lsp.type.parameter Identifier + @lsp.type.property Identifier + @lsp.type.struct Structure + @lsp.type.type Type + @lsp.type.typeParameter TypeDef + @lsp.type.variable Identifier +< ============================================================================== EVENTS *lsp-events* @@ -516,6 +581,29 @@ callback in the "data" table. Example: >lua end, }) < + +LspTokenUpdate *LspTokenUpdate* + +When a visible semantic token is sent or updated by the LSP server, or when an +existing token becomes visible for the first time. The |autocmd-pattern| is +the name of the buffer. When used from Lua, the token and client ID are passed +to the callback in the "data" table. The token fields are documented in +|vim.lsp.semantic_tokens.get_at_pos()|. Example: >lua + + vim.api.nvim_create_autocmd('LspTokenUpdate', { + callback = function(args) + local token = args.data.token + if token.type == 'variable' and not token.modifiers.readonly then + vim.lsp.semantic_tokens.highlight_token( + token, args.buf, args.data.client_id, 'MyMutableVariableHighlight' + ) + end + end, + }) +< +Note: doing anything other than calling +|vim.lsp.semantic_tokens.highlight_token()| is considered experimental. + Also the following |User| |autocommand|s are provided: LspProgressUpdate *LspProgressUpdate* @@ -1332,7 +1420,8 @@ force_refresh({bufnr}) *vim.lsp.semantic_tokens.force_refresh()* highlighting (|vim.lsp.semantic_tokens.start()| has been called for it) Parameters: ~ - • {bufnr} (nil|number) default: current buffer + • {bufnr} (number|nil) filter by buffer. All buffers if nil, current + buffer if 0 *vim.lsp.semantic_tokens.get_at_pos()* get_at_pos({bufnr}, {row}, {col}) @@ -1345,7 +1434,34 @@ get_at_pos({bufnr}, {row}, {col}) • {col} (number|nil) Position column (default cursor position) Return: ~ - (table|nil) List of tokens at position + (table|nil) List of tokens at position. Each token has the following + fields: + • line (number) line number, 0-based + • start_col (number) start column, 0-based + • end_col (number) end column, 0-based + • type (string) token type as string, e.g. "variable" + • modifiers (table) token modifiers as a set. E.g., { static = true, + readonly = true } + + *vim.lsp.semantic_tokens.highlight_token()* +highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts}) + Highlight a semantic token. + + Apply an extmark with a given highlight group for a semantic token. The + mark will be deleted by the semantic token engine when appropriate; for + example, when the LSP sends updated tokens. This function is intended for + use inside |LspTokenUpdate| callbacks. + + Parameters: ~ + • {token} (table) a semantic token, found as `args.data.token` in + |LspTokenUpdate|. + • {bufnr} (number) the buffer to highlight + • {client_id} (number) The ID of the |vim.lsp.client| + • {hl_group} (string) Highlight group name + • {opts} (table|nil) Optional parameters. + • priority: (number|nil) Priority for the applied + extmark. Defaults to + `vim.highlight.priorities.semantic_tokens + 3` start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()* Start the semantic token highlighting engine for the given buffer with the diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 28fdaa770d..825496cff5 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -90,7 +90,7 @@ The following new APIs or features were added. `semanticTokensProvider` from the LSP client's {server_capabilities} in the `LspAttach` callback. - See |lsp-semantic_tokens| for more information. + See |lsp-semantic-highlight| for more information. • |vim.treesitter.inspect_tree()| and |:InspectTree| opens a split window showing a text representation of the nodes in a language tree for the current diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index 9e91597192..92d380b08c 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -2,7 +2,7 @@ ---@field syntax boolean include syntax based highlight groups (defaults to true) ---@field treesitter boolean include treesitter based highlight groups (defaults to true) ---@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) ----@field semantic_tokens boolean include semantic tokens (defaults to true) +---@field semantic_tokens boolean include semantic token highlights (defaults to true) local defaults = { syntax = true, treesitter = true, @@ -81,47 +81,54 @@ function vim.inspect_pos(bufnr, row, col, filter) end end - -- semantic tokens - if filter.semantic_tokens then - for _, token in ipairs(vim.lsp.semantic_tokens.get_at_pos(bufnr, row, col) or {}) do - token.hl_groups = { - type = resolve_hl({ hl_group = '@' .. token.type }), - modifiers = vim.tbl_map(function(modifier) - return resolve_hl({ hl_group = '@' .. modifier }) - end, token.modifiers or {}), - } - table.insert(results.semantic_tokens, token) + --- Convert an extmark tuple into a map-like table + --- @private + local function to_map(extmark) + extmark = { + id = extmark[1], + row = extmark[2], + col = extmark[3], + opts = resolve_hl(extmark[4]), + } + extmark.end_row = extmark.opts.end_row or extmark.row -- inclusive + extmark.end_col = extmark.opts.end_col or (extmark.col + 1) -- exclusive + return extmark + end + + --- Check if an extmark overlaps this position + --- @private + local function is_here(extmark) + return (row >= extmark.row and row <= extmark.end_row) -- within the rows of the extmark + and (row > extmark.row or col >= extmark.col) -- either not the first row, or in range of the col + and (row < extmark.end_row or col < extmark.end_col) -- either not in the last row or in range of the col + end + + -- all extmarks at this position + local extmarks = {} + for ns, nsid in pairs(vim.api.nvim_get_namespaces()) do + local ns_marks = vim.api.nvim_buf_get_extmarks(bufnr, nsid, 0, -1, { details = true }) + ns_marks = vim.tbl_map(to_map, ns_marks) + ns_marks = vim.tbl_filter(is_here, ns_marks) + for _, mark in ipairs(ns_marks) do + mark.ns_id = nsid + mark.ns = ns end + vim.list_extend(extmarks, ns_marks) + end + + if filter.semantic_tokens then + results.semantic_tokens = vim.tbl_filter(function(extmark) + return extmark.ns:find('vim_lsp_semantic_tokens') == 1 + end, extmarks) end - -- extmarks if filter.extmarks then - for ns, nsid in pairs(vim.api.nvim_get_namespaces()) do - if ns:find('vim_lsp_semantic_tokens') ~= 1 then - local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, nsid, 0, -1, { details = true }) - for _, extmark in ipairs(extmarks) do - extmark = { - ns_id = nsid, - ns = ns, - id = extmark[1], - row = extmark[2], - col = extmark[3], - opts = resolve_hl(extmark[4]), - } - local end_row = extmark.opts.end_row or extmark.row -- inclusive - local end_col = extmark.opts.end_col or (extmark.col + 1) -- exclusive - if - (filter.extmarks == 'all' or extmark.opts.hl_group) -- filter hl_group - and (row >= extmark.row and row <= end_row) -- within the rows of the extmark - and (row > extmark.row or col >= extmark.col) -- either not the first row, or in range of the col - and (row < end_row or col < end_col) -- either not in the last row or in range of the col - then - table.insert(results.extmarks, extmark) - end - end - end - end + results.extmarks = vim.tbl_filter(function(extmark) + return extmark.ns:find('vim_lsp_semantic_tokens') ~= 1 + and (filter.extmarks == 'all' or extmark.opts.hl_group) + end, extmarks) end + return results end @@ -174,16 +181,17 @@ function vim.show_pos(bufnr, row, col, filter) nl() end + -- semantic tokens if #items.semantic_tokens > 0 then append('Semantic Tokens', 'Title') nl() - for _, token in ipairs(items.semantic_tokens) do - local client = vim.lsp.get_client_by_id(token.client_id) - client = client and (' (' .. client.name .. ')') or '' - item(token.hl_groups.type, 'type' .. client) - for _, modifier in ipairs(token.hl_groups.modifiers) do - item(modifier, 'modifier' .. client) - end + local sorted_marks = vim.fn.sort(items.semantic_tokens, function(left, right) + local left_first = left.opts.priority < right.opts.priority + or left.opts.priority == right.opts.priority and left.opts.hl_group < right.opts.hl_group + return left_first and -1 or 1 + end) + for _, extmark in ipairs(sorted_marks) do + item(extmark.opts, 'priority: ' .. extmark.opts.priority) end nl() end @@ -197,6 +205,7 @@ function vim.show_pos(bufnr, row, col, filter) end nl() end + -- extmarks if #items.extmarks > 0 then append('Extmarks', 'Title') diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 24b5c6c24e..7983d066b8 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -8,8 +8,8 @@ local bit = require('bit') --- @field start_col number start column 0-based --- @field end_col number end column 0-based --- @field type string token type as string ---- @field modifiers string[] token modifiers as strings ---- @field extmark_added boolean whether this extmark has been added to the buffer yet +--- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true } +--- @field marked boolean whether this token has had extmarks applied --- --- @class STCurrentResult --- @field version number document version associated with this result @@ -36,10 +36,13 @@ local bit = require('bit') ---@field client_state table local STHighlighter = { active = {} } +--- Do a binary search of the tokens in the half-open range [lo, hi). +--- +--- Return the index i in range such that tokens[j].line < line for all j < i, and +--- tokens[j].line >= line for all j >= i, or return hi if no such index is found. +--- ---@private -local function binary_search(tokens, line) - local lo = 1 - local hi = #tokens +local function lower_bound(tokens, line, lo, hi) while lo < hi do local mid = math.floor((lo + hi) / 2) if tokens[mid].line < line then @@ -51,16 +54,34 @@ local function binary_search(tokens, line) return lo end +--- Do a binary search of the tokens in the half-open range [lo, hi). +--- +--- Return the index i in range such that tokens[j].line <= line for all j < i, and +--- tokens[j].line > line for all j >= i, or return hi if no such index is found. +--- +---@private +local function upper_bound(tokens, line, lo, hi) + while lo < hi do + local mid = math.floor((lo + hi) / 2) + if line < tokens[mid].line then + hi = mid + else + lo = mid + 1 + end + end + return lo +end + --- Extracts modifier strings from the encoded number in the token array --- ---@private ----@return string[] +---@return table local function modifiers_from_number(x, modifiers_table) local modifiers = {} local idx = 1 while x > 0 do if bit.band(x, 1) == 1 then - modifiers[#modifiers + 1] = modifiers_table[idx] + modifiers[modifiers_table[idx]] = true end x = bit.rshift(x, 1) idx = idx + 1 @@ -109,7 +130,7 @@ local function tokens_to_ranges(data, bufnr, client) end_col = end_col, type = token_type, modifiers = modifiers, - extmark_added = false, + marked = false, } end end @@ -355,7 +376,7 @@ end --- ---@private function STHighlighter:on_win(topline, botline) - for _, state in pairs(self.client_state) do + for client_id, state in pairs(self.client_state) do local current_result = state.current_result if current_result.version and current_result.version == util.buf_versions[self.bufnr] then if not current_result.namespace_cleared then @@ -372,52 +393,55 @@ function STHighlighter:on_win(topline, botline) -- -- Instead, we have to use normal extmarks that can attach to locations -- in the buffer and are persisted between redraws. + -- + -- `strict = false` is necessary here for the 1% of cases where the + -- current result doesn't actually match the buffer contents. Some + -- LSP servers can respond with stale tokens on requests if they are + -- still processing changes from a didChange notification. + -- + -- LSP servers that do this _should_ follow up known stale responses + -- with a refresh notification once they've finished processing the + -- didChange notification, which would re-synchronize the tokens from + -- our end. + -- + -- The server I know of that does this is clangd when the preamble of + -- a file changes and the token request is processed with a stale + -- preamble while the new one is still being built. Once the preamble + -- finishes, clangd sends a refresh request which lets the client + -- re-synchronize the tokens. + + local set_mark = function(token, hl_group, delta) + vim.api.nvim_buf_set_extmark(self.bufnr, state.namespace, token.line, token.start_col, { + hl_group = hl_group, + end_col = token.end_col, + priority = vim.highlight.priorities.semantic_tokens + delta, + strict = false, + }) + end + + local ft = vim.bo[self.bufnr].filetype local highlights = current_result.highlights - local idx = binary_search(highlights, topline) + local first = lower_bound(highlights, topline, 1, #highlights + 1) + local last = upper_bound(highlights, botline, first, #highlights + 1) - 1 - for i = idx, #highlights do + for i = first, last do local token = highlights[i] - - if token.line > botline then - break - end - - if not token.extmark_added then - -- `strict = false` is necessary here for the 1% of cases where the - -- current result doesn't actually match the buffer contents. Some - -- LSP servers can respond with stale tokens on requests if they are - -- still processing changes from a didChange notification. - -- - -- LSP servers that do this _should_ follow up known stale responses - -- with a refresh notification once they've finished processing the - -- didChange notification, which would re-synchronize the tokens from - -- our end. - -- - -- The server I know of that does this is clangd when the preamble of - -- a file changes and the token request is processed with a stale - -- preamble while the new one is still being built. Once the preamble - -- finishes, clangd sends a refresh request which lets the client - -- re-synchronize the tokens. - api.nvim_buf_set_extmark(self.bufnr, state.namespace, token.line, token.start_col, { - hl_group = '@' .. token.type, - end_col = token.end_col, - priority = vim.highlight.priorities.semantic_tokens, - strict = false, - }) - - -- TODO(bfredl) use single extmark when hl_group supports table - if #token.modifiers > 0 then - for _, modifier in pairs(token.modifiers) do - api.nvim_buf_set_extmark(self.bufnr, state.namespace, token.line, token.start_col, { - hl_group = '@' .. modifier, - end_col = token.end_col, - priority = vim.highlight.priorities.semantic_tokens + 1, - strict = false, - }) - end + if not token.marked then + set_mark(token, string.format('@lsp.type.%s.%s', token.type, ft), 0) + for modifier, _ in pairs(token.modifiers) do + set_mark(token, string.format('@lsp.mod.%s.%s', modifier, ft), 1) + set_mark(token, string.format('@lsp.typemod.%s.%s.%s', token.type, modifier, ft), 2) end - - token.extmark_added = true + token.marked = true + + api.nvim_exec_autocmds('LspTokenUpdate', { + pattern = vim.api.nvim_buf_get_name(self.bufnr), + modeline = false, + data = { + token = token, + client_id = client_id, + }, + }) end end end @@ -588,7 +612,13 @@ end ---@param row number|nil Position row (default cursor position) ---@param col number|nil Position column (default cursor position) --- ----@return table|nil (table|nil) List of tokens at position +---@return table|nil (table|nil) List of tokens at position. Each token has +--- the following fields: +--- - line (number) line number, 0-based +--- - start_col (number) start column, 0-based +--- - end_col (number) end column, 0-based +--- - type (string) token type as string, e.g. "variable" +--- - modifiers (table) token modifiers as a set. E.g., { static = true, readonly = true } function M.get_at_pos(bufnr, row, col) if bufnr == nil or bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -608,7 +638,7 @@ function M.get_at_pos(bufnr, row, col) for client_id, client in pairs(highlighter.client_state) do local highlights = client.current_result.highlights if highlights then - local idx = binary_search(highlights, row) + local idx = lower_bound(highlights, row, 1, #highlights + 1) for i = idx, #highlights do local token = highlights[i] @@ -631,23 +661,60 @@ end --- Only has an effect if the buffer is currently active for semantic token --- highlighting (|vim.lsp.semantic_tokens.start()| has been called for it) --- ----@param bufnr (nil|number) default: current buffer +---@param bufnr (number|nil) filter by buffer. All buffers if nil, current +--- buffer if 0 function M.force_refresh(bufnr) vim.validate({ bufnr = { bufnr, 'n', true }, }) - if bufnr == nil or bufnr == 0 then - bufnr = api.nvim_get_current_buf() + local buffers = bufnr == nil and vim.tbl_keys(STHighlighter.active) + or bufnr == 0 and { api.nvim_get_current_buf() } + or { bufnr } + + for _, buffer in ipairs(buffers) do + local highlighter = STHighlighter.active[buffer] + if highlighter then + highlighter:reset() + highlighter:send_request() + end end +end +--- Highlight a semantic token. +--- +--- Apply an extmark with a given highlight group for a semantic token. The +--- mark will be deleted by the semantic token engine when appropriate; for +--- example, when the LSP sends updated tokens. This function is intended for +--- use inside |LspTokenUpdate| callbacks. +---@param token (table) a semantic token, found as `args.data.token` in +--- |LspTokenUpdate|. +---@param bufnr (number) the buffer to highlight +---@param client_id (number) The ID of the |vim.lsp.client| +---@param hl_group (string) Highlight group name +---@param opts (table|nil) Optional parameters. +--- - priority: (number|nil) Priority for the applied extmark. Defaults +--- to `vim.highlight.priorities.semantic_tokens + 3` +function M.highlight_token(token, bufnr, client_id, hl_group, opts) local highlighter = STHighlighter.active[bufnr] if not highlighter then return end - highlighter:reset() - highlighter:send_request() + local state = highlighter.client_state[client_id] + if not state then + return + end + + opts = opts or {} + local priority = opts.priority or vim.highlight.priorities.semantic_tokens + 3 + + vim.api.nvim_buf_set_extmark(bufnr, state.namespace, token.line, token.start_col, { + hl_group = hl_group, + end_col = token.end_col, + priority = priority, + strict = false, + }) end --- |lsp-handler| for the method `workspace/semanticTokens/refresh` -- cgit From 79571b92ced968ad27bee2a7515a4a04e84dbad2 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 27 Jan 2021 09:00:28 +0100 Subject: feat(lua): omnifunc for builting lua interpreter also make implicit submodules "uri" and "_inspector" work with completion this is needed for `:lua=vim.uri_` wildmenu completion to work even before uri or _inspector functions are used. --- runtime/doc/lua.txt | 6 ++++++ runtime/doc/news.txt | 2 ++ runtime/lua/vim/_editor.lua | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 4 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 1eb5ab41e6..cb309eaf1a 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1404,6 +1404,12 @@ inspect({object}, {options}) *vim.inspect()* https://github.com/kikito/inspect.lua https://github.com/mpeterv/vinspect +lua_omnifunc({find_start}, {_}) *vim.lua_omnifunc()* + Omnifunc for completing lua values from from the runtime lua interpreter, + similar to the builtin completion for the `:lua` command. + + Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a lua buffer. + notify({msg}, {level}, {opts}) *vim.notify()* Display a notification to the user. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 415195e27e..41b59681ae 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -189,6 +189,8 @@ The following new APIs or features were added. disabled by default and can be enabled by setting the `workspace.didChangeWatchedFiles.dynamicRegistration=true` capability. +• Added an omnifunc implementation for lua, |vim.lua_omnifunc()| + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index c205451ff9..9516233b45 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -42,6 +42,18 @@ for k, v in pairs({ vim._submodules[k] = v end +-- There are things which have special rules in vim._init_packages +-- for legacy reasons (uri) or for performance (_inspector). +-- most new things should go into a submodule namespace ( vim.foobar.do_thing() ) +vim._extra = { + uri_from_fname = true, + uri_from_bufnr = true, + uri_to_fname = true, + uri_to_bufnr = true, + show_pos = true, + inspect_pos = true, +} + vim.log = { levels = { TRACE = 0, @@ -575,15 +587,13 @@ function vim._on_key(char) end --- Generate a list of possible completions for the string. ---- String starts with ^ and then has the pattern. +--- String has the pattern. --- --- 1. Can we get it to just return things in the global namespace with that name prefix --- 2. Can we get it to return things from global namespace even with `print(` in front. function vim._expand_pat(pat, env) env = env or _G - pat = string.sub(pat, 2, #pat) - if pat == '' then local result = vim.tbl_keys(env) table.sort(result) @@ -644,7 +654,7 @@ function vim._expand_pat(pat, env) local mt = getmetatable(final_env) if mt and type(mt.__index) == 'table' then field = rawget(mt.__index, key) - elseif final_env == vim and vim._submodules[key] then + elseif final_env == vim and (vim._submodules[key] or vim._extra[key]) then field = vim[key] end end @@ -674,6 +684,7 @@ function vim._expand_pat(pat, env) end if final_env == vim then insert_keys(vim._submodules) + insert_keys(vim._extra) end keys = vim.tbl_keys(keys) @@ -745,6 +756,28 @@ vim._expand_pat_get_parts = function(lua_string) return parts, search_index end +do + -- Ideally we should just call complete() inside omnifunc, though there are + -- some bugs, so fake the two-step dance for now. + local matches + + --- Omnifunc for completing lua values from from the runtime lua interpreter, + --- similar to the builtin completion for the `:lua` command. + --- + --- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a lua buffer. + function vim.lua_omnifunc(find_start, _) + if find_start == 1 then + local line = vim.api.nvim_get_current_line() + local prefix = string.sub(line, 1, vim.api.nvim_win_get_cursor(0)[2]) + local pos + matches, pos = vim._expand_pat(prefix) + return (#matches > 0 and pos) or -1 + else + return matches + end + end +end + ---Prints given arguments in human-readable format. ---Example: ---
lua
-- 
cgit 


From 2882b1543a4f30ee3d7b039a5d51bb994fd6aa1d Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Tue, 7 Mar 2023 11:04:36 +0800
Subject: vim-patch:8.2.3969: value of MAXCOL not available in Vim script

Problem:    Value of MAXCOL not available in Vim script.
Solution:   Add v:maxcol. (Naohiro Ono, closes vim/vim#9451)

https://github.com/vim/vim/commit/56200eed62e59ad831f6564dcafe346e6f97ac20

The variable is always 2147483647, but introducing it makes functions
easier to document.

Co-authored-by: naohiro ono 
---
 runtime/doc/builtin.txt | 22 +++++++++++++++-------
 runtime/doc/eval.txt    |  3 +++
 2 files changed, 18 insertions(+), 7 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 7fab2ac6ff..dd5b77e8ac 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -2890,6 +2890,9 @@ getcharpos({expr})
 		Get the position for String {expr}. Same as |getpos()| but the
 		column number in the returned List is a character index
 		instead of a byte index.
+		If |getpos()| returns a very large column number, equal to
+		|v:maxcol|, then getcharpos() will return the character index
+		of the last character.
 
 		Example:
 		With the cursor on '세' in line 5 with text "여보세요": >
@@ -3064,10 +3067,11 @@ getcompletion({pat}, {type} [, {filtered}])		*getcompletion()*
 							*getcurpos()*
 getcurpos([{winid}])
 		Get the position of the cursor.  This is like getpos('.'), but
-		includes an extra "curswant" in the list:
+		includes an extra "curswant" item in the list:
 		    [0, lnum, col, off, curswant] ~
 		The "curswant" number is the preferred column when moving the
-		cursor vertically.  Also see |getcursorcharpos()| and
+		cursor vertically.  After |$| command it will be a very large
+		number equal to |v:maxcol|.  Also see |getcursorcharpos()| and
 		|getpos()|.
 		The first "bufnum" item is always zero. The byte position of
 		the cursor is returned in "col". To get the character
@@ -3389,12 +3393,12 @@ getpos({expr})	Get the position for String {expr}.  For possible values of
 		character.
 		Note that for '< and '> Visual mode matters: when it is "V"
 		(visual line mode) the column of '< is zero and the column of
-		'> is a large number.
+		'> is a large number equal to |v:maxcol|.
 		The column number in the returned List is the byte position
 		within the line. To get the character position in the line,
 		use |getcharpos()|.
-		The column number can be very large, e.g. 2147483647, in which
-		case it means "after the end of the line".
+		A very large column number equal to |v:maxcol| can be returned,
+		in which case it means "after the end of the line".
 		If {expr} is invalid, returns a list with all zeros.
 		This can be used to save and restore the position of a mark: >
 			let save_a_mark = getpos("'a")
@@ -9407,10 +9411,14 @@ winsaveview()	Returns a |Dictionary| that contains information to restore
 		The return value includes:
 			lnum		cursor line number
 			col		cursor column (Note: the first column
-					zero, as opposed to what getpos()
+					zero, as opposed to what |getcurpos()|
 					returns)
 			coladd		cursor column offset for 'virtualedit'
-			curswant	column for vertical movement
+			curswant	column for vertical movement (Note:
+					the first column is zero, as opposed
+					to what |getcurpos()| returns).  After
+					|$| command it will be a very large
+					number equal to |v:maxcol|.
 			topline		first line in the window
 			topfill		filler lines, only in diff mode
 			leftcol		first column displayed; only used when
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index d79b446986..51e26cc28b 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1979,6 +1979,9 @@ v:lnum		Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
 v:lua		Prefix for calling Lua functions from expressions.
 		See |v:lua-call| for more information.
 
+						*v:maxcol* *maxcol-variable*
+v:maxcol	Maximum line length.
+
 					*v:mouse_win* *mouse_win-variable*
 v:mouse_win	Window number for a mouse click obtained with |getchar()|.
 		First window has number 1, like with |winnr()|.  The value is
-- 
cgit 


From 08d0f99ae122b21e9470d58224edd69d1615ee3d Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Tue, 7 Mar 2023 11:41:25 +0800
Subject: vim-patch:partial:944697ae196

Update runtime files

https://github.com/vim/vim/commit/944697ae19683441981539cd4d2469df89d6ec82

Co-authored-by: Bram Moolenaar 
---
 runtime/doc/builtin.txt | 2 ++
 runtime/doc/eval.txt    | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

(limited to 'runtime')

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index dd5b77e8ac..b0b7809e8c 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -6574,6 +6574,8 @@ screenpos({winid}, {lnum}, {col})				*screenpos()*
 		as if 'conceallevel' is zero.  You can set the cursor to the
 		right position and use |screencol()| to get the value with
 		|conceal| taken into account.
+		If the position is in a closed fold the screen position of the
+		first character is returned, {col} is not used.
 		Returns an empty Dict if {winid} is invalid.
 
 		Can also be used as a |method|: >
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 51e26cc28b..fe15ba6115 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1980,7 +1980,9 @@ v:lua		Prefix for calling Lua functions from expressions.
 		See |v:lua-call| for more information.
 
 						*v:maxcol* *maxcol-variable*
-v:maxcol	Maximum line length.
+v:maxcol	Maximum line length.  Depending on where it is used it can be
+		screen columns, characters or bytes.  The value currently is
+		2147483647 on all systems.
 
 					*v:mouse_win* *mouse_win-variable*
 v:mouse_win	Window number for a mouse click obtained with |getchar()|.
-- 
cgit 


From 706bcab75eaad2c370d61bf828531054439d3a3e Mon Sep 17 00:00:00 2001
From: Jaehwang Jung 
Date: Tue, 7 Mar 2023 15:17:52 +0900
Subject: docs(lsp): change type annotations from number → integer (#22510)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 runtime/doc/lsp.txt                     | 150 ++++++++++++++++----------------
 runtime/lua/vim/lsp.lua                 |  72 +++++++--------
 runtime/lua/vim/lsp/_snippet.lua        |   2 +-
 runtime/lua/vim/lsp/codelens.lua        |  14 +--
 runtime/lua/vim/lsp/diagnostic.lua      |  12 +--
 runtime/lua/vim/lsp/log.lua             |   4 +-
 runtime/lua/vim/lsp/rpc.lua             |  16 ++--
 runtime/lua/vim/lsp/semantic_tokens.lua |  60 ++++++-------
 runtime/lua/vim/lsp/sync.lua            |   6 +-
 runtime/lua/vim/lsp/util.lua            |  76 ++++++++--------
 10 files changed, 207 insertions(+), 205 deletions(-)

(limited to 'runtime')

diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 0d7e8e7ab4..b73e2958ef 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -629,8 +629,8 @@ buf_attach_client({bufnr}, {client_id})          *vim.lsp.buf_attach_client()*
     Without calling this, the server won't be notified of changes to a buffer.
 
     Parameters: ~
-      • {bufnr}      (number) Buffer handle, or 0 for current
-      • {client_id}  (number) Client id
+      • {bufnr}      (integer) Buffer handle, or 0 for current
+      • {client_id}  (integer) Client id
 
 buf_detach_client({bufnr}, {client_id})          *vim.lsp.buf_detach_client()*
     Detaches client from the specified buffer. Note: While the server is
@@ -638,15 +638,15 @@ buf_detach_client({bufnr}, {client_id})          *vim.lsp.buf_detach_client()*
     send notifications should it ignore this notification.
 
     Parameters: ~
-      • {bufnr}      (number) Buffer handle, or 0 for current
-      • {client_id}  (number) Client id
+      • {bufnr}      (integer) Buffer handle, or 0 for current
+      • {client_id}  (integer) Client id
 
 buf_is_attached({bufnr}, {client_id})              *vim.lsp.buf_is_attached()*
     Checks if a buffer is attached for a particular client.
 
     Parameters: ~
-      • {bufnr}      (number) Buffer handle, or 0 for current
-      • {client_id}  (number) the client id
+      • {bufnr}      (integer) Buffer handle, or 0 for current
+      • {client_id}  (integer) the client id
 
 buf_notify({bufnr}, {method}, {params})                 *vim.lsp.buf_notify()*
     Send a notification to a server
@@ -666,7 +666,7 @@ buf_request_all({bufnr}, {method}, {params}, {callback})
     |vim.lsp.buf_request()| but the return result and callback are different.
 
     Parameters: ~
-      • {bufnr}     (number) Buffer handle, or 0 for current.
+      • {bufnr}     (integer) Buffer handle, or 0 for current.
       • {method}    (string) LSP method name
       • {params}    (table|nil) Parameters to send to the server
       • {callback}  (function) The callback to call when all requests are
@@ -687,10 +687,10 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
     result is different. Wait maximum of {timeout_ms} (default 1000) ms.
 
     Parameters: ~
-      • {bufnr}       (number) Buffer handle, or 0 for current.
+      • {bufnr}       (integer) Buffer handle, or 0 for current.
       • {method}      (string) LSP method name
       • {params}      (table|nil) Parameters to send to the server
-      • {timeout_ms}  (number|nil) Maximum time in milliseconds to wait for a
+      • {timeout_ms}  (integer|nil) Maximum time in milliseconds to wait for a
                       result. Defaults to 1000
 
     Return: ~
@@ -759,7 +759,7 @@ client_is_stopped({client_id})                   *vim.lsp.client_is_stopped()*
     Checks whether a client is stopped.
 
     Parameters: ~
-      • {client_id}  (number)
+      • {client_id}  (integer)
 
     Return: ~
         (boolean) stopped true if client is stopped, false otherwise.
@@ -769,7 +769,7 @@ for_each_buffer_client({bufnr}, {fn})
     Invokes a function for each LSP client attached to a buffer.
 
     Parameters: ~
-      • {bufnr}  (number) Buffer number
+      • {bufnr}  (integer) Buffer number
       • {fn}     (function) Function to run on each client attached to buffer
                  {bufnr}. The function takes the client, client ID, and buffer
                  number as arguments. Example: >lua
@@ -823,7 +823,7 @@ get_client_by_id({client_id})                     *vim.lsp.get_client_by_id()*
     not yet be fully initialized.
 
     Parameters: ~
-      • {client_id}  (number) client id
+      • {client_id}  (integer) client id
 
     Return: ~
         |vim.lsp.client| object, or nil
@@ -838,11 +838,11 @@ omnifunc({findstart}, {base})                             *vim.lsp.omnifunc()*
     Implements 'omnifunc' compatible LSP completion.
 
     Parameters: ~
-      • {findstart}  (number) 0 or 1, decides behavior
-      • {base}       (number) findstart=0, text to match against
+      • {findstart}  (integer) 0 or 1, decides behavior
+      • {base}       (integer) findstart=0, text to match against
 
     Return: ~
-        (number) Decided by {findstart}:
+        (integer) Decided by {findstart}:
         • findstart=0: column where the completion starts, or -2 or -3
         • findstart=1: list of matches (actually just calls |complete()|)
 
@@ -861,7 +861,7 @@ set_log_level({level})                               *vim.lsp.set_log_level()*
     Use `lsp.log_levels` for reverse lookup.
 
     Parameters: ~
-      • {level}  (number|string) the case insensitive level name or number
+      • {level}  (integer|string) the case insensitive level name or number
 
     See also: ~
         |vim.lsp.log_levels|
@@ -1052,7 +1052,7 @@ stop_client({client_id}, {force})                      *vim.lsp.stop_client()*
     for this client, then force-shutdown is attempted.
 
     Parameters: ~
-      • {client_id}  number|table id or |vim.lsp.client| object, or list
+      • {client_id}  integer|table id or |vim.lsp.client| object, or list
                      thereof
       • {force}      (boolean|nil) shutdown forcefully
 
@@ -1326,7 +1326,7 @@ get_namespace({client_id})                *vim.lsp.diagnostic.get_namespace()*
     |vim.diagnostic|.
 
     Parameters: ~
-      • {client_id}  (number) The id of the LSP client
+      • {client_id}  (integer) The id of the LSP client
 
                                  *vim.lsp.diagnostic.on_publish_diagnostics()*
 on_publish_diagnostics({_}, {result}, {ctx}, {config})
@@ -1365,22 +1365,23 @@ clear({client_id}, {bufnr})                         *vim.lsp.codelens.clear()*
     Clear the lenses
 
     Parameters: ~
-      • {client_id}  (number|nil) filter by client_id. All clients if nil
-      • {bufnr}      (number|nil) filter by buffer. All buffers if nil
+      • {client_id}  (integer|nil) filter by client_id. All clients if nil
+      • {bufnr}      (integer|nil) filter by buffer. All buffers if nil
 
 display({lenses}, {bufnr}, {client_id})           *vim.lsp.codelens.display()*
     Display the lenses using virtual text
 
     Parameters: ~
       • {lenses}     (table) of lenses to display (`CodeLens[] | null`)
-      • {bufnr}      (number)
-      • {client_id}  (number)
+      • {bufnr}      (integer)
+      • {client_id}  (integer)
 
 get({bufnr})                                          *vim.lsp.codelens.get()*
     Return all lenses for the given buffer
 
     Parameters: ~
-      • {bufnr}  (number) Buffer number. 0 can be used for the current buffer.
+      • {bufnr}  (integer) Buffer number. 0 can be used for the current
+                 buffer.
 
     Return: ~
         (table) (`CodeLens[]`)
@@ -1406,8 +1407,8 @@ save({lenses}, {bufnr}, {client_id})                 *vim.lsp.codelens.save()*
 
     Parameters: ~
       • {lenses}     (table) of lenses to store (`CodeLens[] | null`)
-      • {bufnr}      (number)
-      • {client_id}  (number)
+      • {bufnr}      (integer)
+      • {client_id}  (integer)
 
 
 ==============================================================================
@@ -1420,7 +1421,7 @@ force_refresh({bufnr})               *vim.lsp.semantic_tokens.force_refresh()*
     highlighting (|vim.lsp.semantic_tokens.start()| has been called for it)
 
     Parameters: ~
-      • {bufnr}  (number|nil) filter by buffer. All buffers if nil, current
+      • {bufnr}  (integer|nil) filter by buffer. All buffers if nil, current
                  buffer if 0
 
                                         *vim.lsp.semantic_tokens.get_at_pos()*
@@ -1429,16 +1430,16 @@ get_at_pos({bufnr}, {row}, {col})
     arguments, returns the token under the cursor.
 
     Parameters: ~
-      • {bufnr}  (number|nil) Buffer number (0 for current buffer, default)
-      • {row}    (number|nil) Position row (default cursor position)
-      • {col}    (number|nil) Position column (default cursor position)
+      • {bufnr}  (integer|nil) Buffer number (0 for current buffer, default)
+      • {row}    (integer|nil) Position row (default cursor position)
+      • {col}    (integer|nil) Position column (default cursor position)
 
     Return: ~
         (table|nil) List of tokens at position. Each token has the following
         fields:
-        • line (number) line number, 0-based
-        • start_col (number) start column, 0-based
-        • end_col (number) end column, 0-based
+        • line (integer) line number, 0-based
+        • start_col (integer) start column, 0-based
+        • end_col (integer) end column, 0-based
         • type (string) token type as string, e.g. "variable"
         • modifiers (table) token modifiers as a set. E.g., { static = true,
           readonly = true }
@@ -1455,11 +1456,11 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts})
     Parameters: ~
       • {token}      (table) a semantic token, found as `args.data.token` in
                      |LspTokenUpdate|.
-      • {bufnr}      (number) the buffer to highlight
-      • {client_id}  (number) The ID of the |vim.lsp.client|
+      • {bufnr}      (integer) the buffer to highlight
+      • {client_id}  (integer) The ID of the |vim.lsp.client|
       • {hl_group}   (string) Highlight group name
       • {opts}       (table|nil) Optional parameters.
-                     • priority: (number|nil) Priority for the applied
+                     • priority: (integer|nil) Priority for the applied
                        extmark. Defaults to
                        `vim.highlight.priorities.semantic_tokens + 3`
 
@@ -1477,10 +1478,10 @@ start({bufnr}, {client_id}, {opts})          *vim.lsp.semantic_tokens.start()*
 <
 
     Parameters: ~
-      • {bufnr}      (number)
-      • {client_id}  (number)
+      • {bufnr}      (integer)
+      • {client_id}  (integer)
       • {opts}       (nil|table) Optional keyword arguments
-                     • debounce (number, default: 200): Debounce token
+                     • debounce (integer, default: 200): Debounce token
                        requests to the server by the given number in
                        milliseconds
 
@@ -1494,8 +1495,8 @@ stop({bufnr}, {client_id})                    *vim.lsp.semantic_tokens.stop()*
     from the buffer.
 
     Parameters: ~
-      • {bufnr}      (number)
-      • {client_id}  (number)
+      • {bufnr}      (integer)
+      • {client_id}  (integer)
 
 
 ==============================================================================
@@ -1550,7 +1551,7 @@ apply_text_document_edit({text_document_edit}, {index}, {offset_encoding})
 
     Parameters: ~
       • {text_document_edit}  (table) a `TextDocumentEdit` object
-      • {index}               (number) Optional index of the edit, if from a
+      • {index}               (integer) Optional index of the edit, if from a
                               list of edits (or nil, if not from a list)
 
     See also: ~
@@ -1562,7 +1563,7 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding})
 
     Parameters: ~
       • {text_edits}       (table) list of `TextEdit` objects
-      • {bufnr}            (number) Buffer id
+      • {bufnr}            (integer) Buffer id
       • {offset_encoding}  (string) utf-8|utf-16|utf-32
 
     See also: ~
@@ -1580,14 +1581,14 @@ buf_clear_references({bufnr})            *vim.lsp.util.buf_clear_references()*
     Removes document highlights from a buffer.
 
     Parameters: ~
-      • {bufnr}  (number) Buffer id
+      • {bufnr}  (integer) Buffer id
 
                                      *vim.lsp.util.buf_highlight_references()*
 buf_highlight_references({bufnr}, {references}, {offset_encoding})
     Shows a list of document highlights for a certain buffer.
 
     Parameters: ~
-      • {bufnr}            (number) Buffer id
+      • {bufnr}            (integer) Buffer id
       • {references}       (table) List of `DocumentHighlight` objects to
                            highlight
       • {offset_encoding}  (string) One of "utf-8", "utf-16", "utf-32".
@@ -1600,14 +1601,14 @@ character_offset({buf}, {row}, {col}, {offset_encoding})
     Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer.
 
     Parameters: ~
-      • {buf}              (number) buffer number (0 for current)
+      • {buf}              (integer) buffer number (0 for current)
       • {row}              0-indexed line
       • {col}              0-indexed byte offset in line
       • {offset_encoding}  (string) utf-8|utf-16|utf-32|nil defaults to
                            `offset_encoding` of first client of `buf`
 
     Return: ~
-        (number, number) `offset_encoding` index of the character in line
+        (integer, integer) `offset_encoding` index of the character in line
         {row} column {col} in buffer {buf}
 
                               *vim.lsp.util.convert_input_to_markdown_lines()*
@@ -1662,10 +1663,10 @@ get_effective_tabstop({bufnr})          *vim.lsp.util.get_effective_tabstop()*
     Returns indentation size.
 
     Parameters: ~
-      • {bufnr}  (number|nil) Buffer handle, defaults to current
+      • {bufnr}  (integer|nil) Buffer handle, defaults to current
 
     Return: ~
-        (number) indentation size
+        (integer) indentation size
 
     See also: ~
         'shiftwidth'
@@ -1715,11 +1716,11 @@ make_floating_popup_options({width}, {height}, {opts})
     table can be passed to |nvim_open_win()|.
 
     Parameters: ~
-      • {width}   (number) window width (in character cells)
-      • {height}  (number) window height (in character cells)
+      • {width}   (integer) window width (in character cells)
+      • {height}  (integer) window height (in character cells)
       • {opts}    (table, optional)
-                  • offset_x (number) offset to add to `col`
-                  • offset_y (number) offset to add to `row`
+                  • offset_x (integer) offset to add to `col`
+                  • offset_y (integer) offset to add to `row`
                   • border (string or table) override `border`
                   • focusable (string or table) override `focusable`
                   • zindex (string or table) override `zindex`, defaults to 50
@@ -1748,11 +1749,11 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
     similar to |vim.lsp.util.make_range_params()|.
 
     Parameters: ~
-      • {start_pos}        number[]|nil {row, col} mark-indexed position.
+      • {start_pos}        integer[]|nil {row, col} mark-indexed position.
                            Defaults to the start of the last visual selection.
-      • {end_pos}          number[]|nil {row, col} mark-indexed position.
+      • {end_pos}          integer[]|nil {row, col} mark-indexed position.
                            Defaults to the end of the last visual selection.
-      • {bufnr}            (number|nil) buffer handle or 0 for current,
+      • {bufnr}            (integer|nil) buffer handle or 0 for current,
                            defaults to current
       • {offset_encoding}  "utf-8"|"utf-16"|"utf-32"|nil defaults to
                            `offset_encoding` of first client of `bufnr`
@@ -1767,7 +1768,7 @@ make_position_params({window}, {offset_encoding})
     cursor position.
 
     Parameters: ~
-      • {window}           (number|nil) window handle or 0 for current,
+      • {window}           (integer|nil) window handle or 0 for current,
                            defaults to current
       • {offset_encoding}  (string|nil) utf-8|utf-16|utf-32|nil defaults to
                            `offset_encoding` of first client of buffer of
@@ -1787,7 +1788,7 @@ make_range_params({window}, {offset_encoding})
     `textDocument/rangeFormatting`.
 
     Parameters: ~
-      • {window}           (number|nil) window handle or 0 for current,
+      • {window}           (integer|nil) window handle or 0 for current,
                            defaults to current
       • {offset_encoding}  "utf-8"|"utf-16"|"utf-32"|nil defaults to
                            `offset_encoding` of first client of buffer of
@@ -1802,7 +1803,7 @@ make_text_document_params({bufnr})
     Creates a `TextDocumentIdentifier` object for the current buffer.
 
     Parameters: ~
-      • {bufnr}  (number|nil) Buffer handle, defaults to current
+      • {bufnr}  (integer|nil) Buffer handle, defaults to current
 
     Return: ~
         `TextDocumentIdentifier`
@@ -1827,15 +1828,16 @@ open_floating_preview({contents}, {syntax}, {opts})
       • {syntax}    (string) of syntax to set for opened buffer
       • {opts}      (table) with optional fields (additional keys are passed
                     on to |nvim_open_win()|)
-                    • height: (number) height of floating window
-                    • width: (number) width of floating window
+                    • height: (integer) height of floating window
+                    • width: (integer) width of floating window
                     • wrap: (boolean, default true) wrap long lines
-                    • wrap_at: (number) character to wrap at for computing
+                    • wrap_at: (integer) character to wrap at for computing
                       height when wrap is enabled
-                    • max_width: (number) maximal width of floating window
-                    • max_height: (number) maximal height of floating window
-                    • pad_top: (number) number of lines to pad contents at top
-                    • pad_bottom: (number) number of lines to pad contents at
+                    • max_width: (integer) maximal width of floating window
+                    • max_height: (integer) maximal height of floating window
+                    • pad_top: (integer) number of lines to pad contents at
+                      top
+                    • pad_bottom: (integer) number of lines to pad contents at
                       bottom
                     • focus_id: (string) if a popup with this id is opened,
                       then focus it
@@ -2008,13 +2010,13 @@ set_level({level})                                   *vim.lsp.log.set_level()*
     Sets the current log level.
 
     Parameters: ~
-      • {level}  (string|number) One of `vim.lsp.log.levels`
+      • {level}  (string|integer) One of `vim.lsp.log.levels`
 
 should_log({level})                                 *vim.lsp.log.should_log()*
     Checks whether the level is sufficient for logging.
 
     Parameters: ~
-      • {level}  (number) log level
+      • {level}  (integer) log level
 
     Return: ~
         (bool) true if would log, false if not
@@ -2029,7 +2031,7 @@ connect({host}, {port})                                *vim.lsp.rpc.connect()*
 
     Parameters: ~
       • {host}  (string)
-      • {port}  (number)
+      • {port}  (integer)
 
     Return: ~
         (function)
@@ -2074,7 +2076,7 @@ rpc_response_error({code}, {message}, {data})
     Creates an RPC response object/table.
 
     Parameters: ~
-      • {code}     (number) RPC error code defined in
+      • {code}     (integer) RPC error code defined in
                    `vim.lsp.protocol.ErrorCodes`
       • {message}  (string|nil) arbitrary message to send to server
       • {data}     any|nil arbitrary data to send to server
@@ -2122,11 +2124,11 @@ compute_diff({___MissingCloseParenHere___})
     Parameters: ~
       • {prev_lines}       (table) list of lines
       • {curr_lines}       (table) list of lines
-      • {firstline}        (number) line to begin search for first difference
-      • {lastline}         (number) line to begin search in old_lines for last
-                           difference
-      • {new_lastline}     (number) line to begin search in new_lines for last
-                           difference
+      • {firstline}        (integer) line to begin search for first difference
+      • {lastline}         (integer) line to begin search in old_lines for
+                           last difference
+      • {new_lastline}     (integer) line to begin search in new_lines for
+                           last difference
       • {offset_encoding}  (string) encoding requested by language server
 
     Return: ~
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index a56e141c29..9a0b3f3100 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -363,7 +363,7 @@ do
   --- smallest debounce interval is used and we don't group clients by different intervals.
   ---
   --- @class CTGroup
-  --- @field sync_kind number TextDocumentSyncKind, considers config.flags.allow_incremental_sync
+  --- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync
   --- @field offset_encoding "utf-8"|"utf-16"|"utf-32"
   ---
   --- @class CTBufferState
@@ -374,12 +374,12 @@ do
   --- @field timer nil|uv.uv_timer_t uv_timer
   --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification
   --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet
-  --- @field refs number how many clients are using this group
+  --- @field refs integer how many clients are using this group
   ---
   --- @class CTGroupState
-  --- @field buffers table
-  --- @field debounce number debounce duration in ms
-  --- @field clients table clients using this state. {client_id, client}
+  --- @field buffers table
+  --- @field debounce integer debounce duration in ms
+  --- @field clients table clients using this state. {client_id, client}
 
   ---@private
   ---@param group CTGroup
@@ -568,7 +568,7 @@ do
   --
   -- This turns the debounce into a kind of client rate limiting
   --
-  ---@param debounce number
+  ---@param debounce integer
   ---@param buf_state CTBufferState
   ---@return number
   local function next_debounce(debounce, buf_state)
@@ -585,8 +585,8 @@ do
   end
 
   ---@private
-  ---@param bufnr number
-  ---@param sync_kind number protocol.TextDocumentSyncKind
+  ---@param bufnr integer
+  ---@param sync_kind integer protocol.TextDocumentSyncKind
   ---@param state CTGroupState
   ---@param buf_state CTBufferState
   local function send_changes(bufnr, sync_kind, state, buf_state)
@@ -714,7 +714,7 @@ end
 ---@private
 --- Default handler for the 'textDocument/didOpen' LSP notification.
 ---
----@param bufnr number Number of the buffer, or 0 for current
+---@param bufnr integer Number of the buffer, or 0 for current
 ---@param client table Client object
 local function text_document_did_open_handler(bufnr, client)
   changetracking.init(client, bufnr)
@@ -1095,7 +1095,7 @@ function lsp.start_client(config)
   ---@private
   --- Invoked when the client operation throws an error.
   ---
-  ---@param code (number) Error code
+  ---@param code (integer) Error code
   ---@param err (...) Other arguments may be passed depending on the error kind
   ---@see `vim.lsp.rpc.client_errors` for possible errors. Use
   ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
@@ -1148,8 +1148,8 @@ function lsp.start_client(config)
   ---@private
   --- Invoked on client exit.
   ---
-  ---@param code (number) exit code of the process
-  ---@param signal (number) the signal used to terminate (if any)
+  ---@param code (integer) exit code of the process
+  ---@param signal (integer) the signal used to terminate (if any)
   function dispatch.on_exit(code, signal)
     if config.on_exit then
       pcall(config.on_exit, code, signal, client_id)
@@ -1414,9 +1414,9 @@ function lsp.start_client(config)
   ---
   ---@param method (string) LSP method name.
   ---@param params (table) LSP request params.
-  ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for
+  ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for
   ---                               a result. Defaults to 1000
-  ---@param bufnr (number) Buffer handle (0 for current).
+  ---@param bufnr (integer) Buffer handle (0 for current).
   ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where
   --- `err` and `result` come from the |lsp-handler|.
   --- On timeout, cancel or error, returns `(nil, err)` where `err` is a
@@ -1465,7 +1465,7 @@ function lsp.start_client(config)
   ---@private
   --- Cancels a request with a given request id.
   ---
-  ---@param id (number) id of request to cancel
+  ---@param id (integer) id of request to cancel
   ---@return boolean status true if notification was successful. false otherwise
   ---@see |vim.lsp.client.notify()|
   function client.cancel_request(id)
@@ -1622,8 +1622,8 @@ end
 ---
 --- Without calling this, the server won't be notified of changes to a buffer.
 ---
----@param bufnr (number) Buffer handle, or 0 for current
----@param client_id (number) Client id
+---@param bufnr (integer) Buffer handle, or 0 for current
+---@param client_id (integer) Client id
 function lsp.buf_attach_client(bufnr, client_id)
   validate({
     bufnr = { bufnr, 'n', true },
@@ -1734,8 +1734,8 @@ end
 --- Note: While the server is notified that the text document (buffer)
 --- was closed, it is still able to send notifications should it ignore this notification.
 ---
----@param bufnr number Buffer handle, or 0 for current
----@param client_id number Client id
+---@param bufnr integer Buffer handle, or 0 for current
+---@param client_id integer Client id
 function lsp.buf_detach_client(bufnr, client_id)
   validate({
     bufnr = { bufnr, 'n', true },
@@ -1785,8 +1785,8 @@ end
 
 --- Checks if a buffer is attached for a particular client.
 ---
----@param bufnr (number) Buffer handle, or 0 for current
----@param client_id (number) the client id
+---@param bufnr (integer) Buffer handle, or 0 for current
+---@param client_id (integer) the client id
 function lsp.buf_is_attached(bufnr, client_id)
   return (all_buffer_active_clients[resolve_bufnr(bufnr)] or {})[client_id] == true
 end
@@ -1794,7 +1794,7 @@ end
 --- Gets a client by id, or nil if the id is invalid.
 --- The returned client may not yet be fully initialized.
 ---
----@param client_id number client id
+---@param client_id integer client id
 ---
 ---@returns |vim.lsp.client| object, or nil
 function lsp.get_client_by_id(client_id)
@@ -1821,7 +1821,7 @@ end
 --- By default asks the server to shutdown, unless stop was requested
 --- already for this client, then force-shutdown is attempted.
 ---
----@param client_id number|table id or |vim.lsp.client| object, or list thereof
+---@param client_id integer|table id or |vim.lsp.client| object, or list thereof
 ---@param force boolean|nil shutdown forcefully
 function lsp.stop_client(client_id, force)
   local ids = type(client_id) == 'table' and client_id or { client_id }
@@ -1837,8 +1837,8 @@ function lsp.stop_client(client_id, force)
 end
 
 ---@class vim.lsp.get_active_clients.filter
----@field id number|nil Match clients by id
----@field bufnr number|nil match clients attached to the given buffer
+---@field id integer|nil Match clients by id
+---@field bufnr integer|nil match clients attached to the given buffer
 ---@field name string|nil match clients by name
 
 --- Get active clients.
@@ -1932,7 +1932,7 @@ api.nvim_create_autocmd('VimLeavePre', {
 --- Sends an async request for all active clients attached to the
 --- buffer.
 ---
----@param bufnr (number) Buffer handle, or 0 for current.
+---@param bufnr (integer) Buffer handle, or 0 for current.
 ---@param method (string) LSP method name
 ---@param params table|nil Parameters to send to the server
 ---@param handler function|nil See |lsp-handler|
@@ -1992,7 +1992,7 @@ end
 ---Parameters are the same as |vim.lsp.buf_request()| but the return result and callback are
 ---different.
 ---
----@param bufnr (number) Buffer handle, or 0 for current.
+---@param bufnr (integer) Buffer handle, or 0 for current.
 ---@param method (string) LSP method name
 ---@param params (table|nil) Parameters to send to the server
 ---@param callback (function) The callback to call when all requests are finished.
@@ -2034,10 +2034,10 @@ end
 --- Parameters are the same as |vim.lsp.buf_request()| but the return result is
 --- different. Wait maximum of {timeout_ms} (default 1000) ms.
 ---
----@param bufnr (number) Buffer handle, or 0 for current.
+---@param bufnr (integer) Buffer handle, or 0 for current.
 ---@param method (string) LSP method name
 ---@param params (table|nil) Parameters to send to the server
----@param timeout_ms (number|nil) Maximum time in milliseconds to wait for a
+---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a
 ---                               result. Defaults to 1000
 ---
 ---@return table|nil result, string|nil err Map of client_id:request_result.
@@ -2106,10 +2106,10 @@ end
 ---@see |complete-items|
 ---@see |CompleteDone|
 ---
----@param findstart number 0 or 1, decides behavior
----@param base number findstart=0, text to match against
+---@param findstart integer 0 or 1, decides behavior
+---@param base integer findstart=0, text to match against
 ---
----@returns (number) Decided by {findstart}:
+---@returns (integer) Decided by {findstart}:
 --- - findstart=0: column where the completion starts, or -2 or -3
 --- - findstart=1: list of matches (actually just calls |complete()|)
 function lsp.omnifunc(findstart, base)
@@ -2246,7 +2246,7 @@ end
 
 ---Checks whether a client is stopped.
 ---
----@param client_id (number)
+---@param client_id (integer)
 ---@return boolean stopped true if client is stopped, false otherwise.
 function lsp.client_is_stopped(client_id)
   return active_clients[client_id] == nil
@@ -2255,7 +2255,7 @@ end
 --- Gets a map of client_id:client pairs for the given buffer, where each value
 --- is a |vim.lsp.client| object.
 ---
----@param bufnr (number|nil): Buffer handle, or 0 for current
+---@param bufnr (integer|nil): Buffer handle, or 0 for current
 ---@returns (table) Table of (client_id, client) pairs
 ---@deprecated Use |vim.lsp.get_active_clients()| instead.
 function lsp.buf_get_clients(bufnr)
@@ -2284,7 +2284,7 @@ lsp.log_levels = log.levels
 ---
 ---@see |vim.lsp.log_levels|
 ---
----@param level (number|string) the case insensitive level name or number
+---@param level (integer|string) the case insensitive level name or number
 function lsp.set_log_level(level)
   if type(level) == 'string' or type(level) == 'number' then
     log.set_level(level)
@@ -2301,7 +2301,7 @@ end
 
 --- Invokes a function for each LSP client attached to a buffer.
 ---
----@param bufnr number Buffer number
+---@param bufnr integer Buffer number
 ---@param fn function Function to run on each client attached to buffer
 ---                   {bufnr}. The function takes the client, client ID, and
 ---                   buffer number as arguments. Example:
diff --git a/runtime/lua/vim/lsp/_snippet.lua b/runtime/lua/vim/lsp/_snippet.lua
index 3488639fb4..797d8960d5 100644
--- a/runtime/lua/vim/lsp/_snippet.lua
+++ b/runtime/lua/vim/lsp/_snippet.lua
@@ -483,7 +483,7 @@ end)
 local M = {}
 
 ---The snippet node type enum
----@types table
+---@types table
 M.NodeType = Node.Type
 
 ---Parse snippet string and returns the AST
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 17489ed84d..81cac6a511 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -61,7 +61,7 @@ end
 
 --- Return all lenses for the given buffer
 ---
----@param bufnr number  Buffer number. 0 can be used for the current buffer.
+---@param bufnr integer  Buffer number. 0 can be used for the current buffer.
 ---@return table (`CodeLens[]`)
 function M.get(bufnr)
   local lenses_by_client = lens_cache_by_buf[bufnr or 0]
@@ -115,8 +115,8 @@ end
 
 --- Clear the lenses
 ---
----@param client_id number|nil filter by client_id. All clients if nil
----@param bufnr number|nil filter by buffer. All buffers if nil
+---@param client_id integer|nil filter by client_id. All clients if nil
+---@param bufnr integer|nil filter by buffer. All buffers if nil
 function M.clear(client_id, bufnr)
   local buffers = bufnr and { resolve_bufnr(bufnr) } or vim.tbl_keys(lens_cache_by_buf)
   for _, iter_bufnr in pairs(buffers) do
@@ -132,8 +132,8 @@ end
 --- Display the lenses using virtual text
 ---
 ---@param lenses table of lenses to display (`CodeLens[] | null`)
----@param bufnr number
----@param client_id number
+---@param bufnr integer
+---@param client_id integer
 function M.display(lenses, bufnr, client_id)
   local ns = namespaces[client_id]
   if not lenses or not next(lenses) then
@@ -177,8 +177,8 @@ end
 --- Store lenses for a specific buffer and client
 ---
 ---@param lenses table of lenses to store (`CodeLens[] | null`)
----@param bufnr number
----@param client_id number
+---@param bufnr integer
+---@param client_id integer
 function M.save(lenses, bufnr, client_id)
   local lenses_by_client = lens_cache_by_buf[bufnr]
   if not lenses_by_client then
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 5e2bf75f1b..b27bf6e425 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -4,7 +4,7 @@
 ---@field range Range
 ---@field message string
 ---@field severity DiagnosticSeverity|nil
----@field code number | string
+---@field code integer | string
 ---@field source string
 ---@field tags DiagnosticTag[]
 ---@field relatedInformation DiagnosticRelatedInformation[]
@@ -135,7 +135,7 @@ local _client_namespaces = {}
 
 --- Get the diagnostic namespace associated with an LSP client |vim.diagnostic|.
 ---
----@param client_id number The id of the LSP client
+---@param client_id integer The id of the LSP client
 function M.get_namespace(client_id)
   vim.validate({ client_id = { client_id, 'n' } })
   if not _client_namespaces[client_id] then
@@ -212,7 +212,7 @@ end
 --- this method signature is still used internally in some parts of the LSP
 --- implementation so it's simply marked @private rather than @deprecated.
 ---
----@param client_id number
+---@param client_id integer
 ---@param buffer_client_map table map of buffers to active clients
 ---@private
 function M.reset(client_id, buffer_client_map)
@@ -232,14 +232,14 @@ end
 --- Marked private as this is used internally by the LSP subsystem, but
 --- most users should instead prefer |vim.diagnostic.get()|.
 ---
----@param bufnr number|nil The buffer number
----@param line_nr number|nil The line number
+---@param bufnr integer|nil The buffer number
+---@param line_nr integer|nil The line number
 ---@param opts table|nil Configuration keys
 ---         - severity: (DiagnosticSeverity, default nil)
 ---             - Only return diagnostics with this severity. Overrides severity_limit
 ---         - severity_limit: (DiagnosticSeverity, default nil)
 ---             - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
----@param client_id|nil number the client id
+---@param client_id integer|nil the client id
 ---@return table Table with map of line number to list of diagnostics.
 ---              Structured: { [1] = {...}, [5] = {.... } }
 ---@private
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index d1a78572aa..51dcb7d21d 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -141,7 +141,7 @@ end
 vim.tbl_add_reverse_lookup(log.levels)
 
 --- Sets the current log level.
----@param level (string|number) One of `vim.lsp.log.levels`
+---@param level (string|integer) One of `vim.lsp.log.levels`
 function log.set_level(level)
   if type(level) == 'string' then
     current_log_level =
@@ -167,7 +167,7 @@ function log.set_format_func(handle)
 end
 
 --- Checks whether the level is sufficient for logging.
----@param level number log level
+---@param level integer log level
 ---@returns (bool) true if would log, false if not
 function log.should_log(level)
   return level >= current_log_level
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index aa833deb99..30b61d01d6 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -186,7 +186,7 @@ end
 
 --- Creates an RPC response object/table.
 ---
----@param code number RPC error code defined in `vim.lsp.protocol.ErrorCodes`
+---@param code integer RPC error code defined in `vim.lsp.protocol.ErrorCodes`
 ---@param message string|nil arbitrary message to send to server
 ---@param data any|nil arbitrary data to send to server
 local function rpc_response_error(code, message, data)
@@ -224,8 +224,8 @@ end
 ---@private
 --- Default dispatcher for when a client exits.
 ---
----@param code (number): Exit code
----@param signal (number): Number describing the signal used to terminate (if
+---@param code (integer): Exit code
+---@param signal (integer): Number describing the signal used to terminate (if
 ---any)
 function default_dispatchers.on_exit(code, signal)
   local _ = log.info() and log.info('client_exit', { code = code, signal = signal })
@@ -233,7 +233,7 @@ end
 ---@private
 --- Default dispatcher for client errors.
 ---
----@param code (number): Error code
+---@param code (integer): Error code
 ---@param err (any): Details about the error
 ---any)
 function default_dispatchers.on_error(code, err)
@@ -270,7 +270,7 @@ local function create_read_loop(handle_body, on_no_chunk, on_error)
 end
 
 ---@class RpcClient
----@field message_index number
+---@field message_index integer
 ---@field message_callbacks table
 ---@field notify_reply_callbacks table
 ---@field transport table
@@ -588,7 +588,7 @@ end
 --- and port
 ---
 ---@param host string
----@param port number
+---@param port integer
 ---@return function
 local function connect(host, port)
   return function(dispatchers)
@@ -692,8 +692,8 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
 
   ---@private
   --- Callback for |vim.loop.spawn()| Closes all streams and runs the `on_exit` dispatcher.
-  ---@param code (number) Exit code
-  ---@param signal (number) Signal that was used to terminate (if any)
+  ---@param code (integer) Exit code
+  ---@param signal (integer) Signal that was used to terminate (if any)
   local function onexit(code, signal)
     stdin:close()
     stdout:close()
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua
index 7983d066b8..9eaccd539f 100644
--- a/runtime/lua/vim/lsp/semantic_tokens.lua
+++ b/runtime/lua/vim/lsp/semantic_tokens.lua
@@ -4,36 +4,36 @@ local util = require('vim.lsp.util')
 local bit = require('bit')
 
 --- @class STTokenRange
---- @field line number line number 0-based
---- @field start_col number start column 0-based
---- @field end_col number end column 0-based
+--- @field line integer line number 0-based
+--- @field start_col integer start column 0-based
+--- @field end_col integer end column 0-based
 --- @field type string token type as string
 --- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true }
 --- @field marked boolean whether this token has had extmarks applied
 ---
 --- @class STCurrentResult
---- @field version number document version associated with this result
+--- @field version integer document version associated with this result
 --- @field result_id string resultId from the server; used with delta requests
 --- @field highlights STTokenRange[] cache of highlight ranges for this document version
---- @field tokens number[] raw token array as received by the server. used for calculating delta responses
+--- @field tokens integer[] raw token array as received by the server. used for calculating delta responses
 --- @field namespace_cleared boolean whether the namespace was cleared for this result yet
 ---
 --- @class STActiveRequest
---- @field request_id number the LSP request ID of the most recent request sent to the server
---- @field version number the document version associated with the most recent request
+--- @field request_id integer the LSP request ID of the most recent request sent to the server
+--- @field version integer the document version associated with the most recent request
 ---
 --- @class STClientState
---- @field namespace number
+--- @field namespace integer
 --- @field active_request STActiveRequest
 --- @field current_result STCurrentResult
 
 ---@class STHighlighter
----@field active table
----@field bufnr number
----@field augroup number augroup for buffer events
----@field debounce number milliseconds to debounce requests for new tokens
+---@field active table
+---@field bufnr integer
+---@field augroup integer augroup for buffer events
+---@field debounce integer milliseconds to debounce requests for new tokens
 ---@field timer table uv_timer for debouncing requests for new tokens
----@field client_state table
+---@field client_state table
 local STHighlighter = { active = {} }
 
 --- Do a binary search of the tokens in the half-open range [lo, hi).
@@ -141,7 +141,7 @@ end
 --- Construct a new STHighlighter for the buffer
 ---
 ---@private
----@param bufnr number
+---@param bufnr integer
 function STHighlighter.new(bufnr)
   local self = setmetatable({}, { __index = STHighlighter })
 
@@ -470,7 +470,7 @@ end
 --- in case the server supports delta requests.
 ---
 ---@private
----@param client_id number
+---@param client_id integer
 function STHighlighter:mark_dirty(client_id)
   local state = self.client_state[client_id]
   assert(state)
@@ -529,10 +529,10 @@ local M = {}
 ---   client.server_capabilities.semanticTokensProvider = nil
 --- 
--- ----@param bufnr number ----@param client_id number +---@param bufnr integer +---@param client_id integer ---@param opts (nil|table) Optional keyword arguments ---- - debounce (number, default: 200): Debounce token requests +--- - debounce (integer, default: 200): Debounce token requests --- to the server by the given number in milliseconds function M.start(bufnr, client_id, opts) vim.validate({ @@ -585,8 +585,8 @@ end --- of `start()`, so you should only need this function to manually disengage the semantic --- token engine without fully detaching the LSP client from the buffer. --- ----@param bufnr number ----@param client_id number +---@param bufnr integer +---@param client_id integer function M.stop(bufnr, client_id) vim.validate({ bufnr = { bufnr, 'n', false }, @@ -608,15 +608,15 @@ end --- Return the semantic token(s) at the given position. --- If called without arguments, returns the token under the cursor. --- ----@param bufnr number|nil Buffer number (0 for current buffer, default) ----@param row number|nil Position row (default cursor position) ----@param col number|nil Position column (default cursor position) +---@param bufnr integer|nil Buffer number (0 for current buffer, default) +---@param row integer|nil Position row (default cursor position) +---@param col integer|nil Position column (default cursor position) --- ---@return table|nil (table|nil) List of tokens at position. Each token has --- the following fields: ---- - line (number) line number, 0-based ---- - start_col (number) start column, 0-based ---- - end_col (number) end column, 0-based +--- - line (integer) line number, 0-based +--- - start_col (integer) start column, 0-based +--- - end_col (integer) end column, 0-based --- - type (string) token type as string, e.g. "variable" --- - modifiers (table) token modifiers as a set. E.g., { static = true, readonly = true } function M.get_at_pos(bufnr, row, col) @@ -661,7 +661,7 @@ end --- Only has an effect if the buffer is currently active for semantic token --- highlighting (|vim.lsp.semantic_tokens.start()| has been called for it) --- ----@param bufnr (number|nil) filter by buffer. All buffers if nil, current +---@param bufnr (integer|nil) filter by buffer. All buffers if nil, current --- buffer if 0 function M.force_refresh(bufnr) vim.validate({ @@ -689,11 +689,11 @@ end --- use inside |LspTokenUpdate| callbacks. ---@param token (table) a semantic token, found as `args.data.token` in --- |LspTokenUpdate|. ----@param bufnr (number) the buffer to highlight ----@param client_id (number) The ID of the |vim.lsp.client| +---@param bufnr (integer) the buffer to highlight +---@param client_id (integer) The ID of the |vim.lsp.client| ---@param hl_group (string) Highlight group name ---@param opts (table|nil) Optional parameters. ---- - priority: (number|nil) Priority for the applied extmark. Defaults +--- - priority: (integer|nil) Priority for the applied extmark. Defaults --- to `vim.highlight.priorities.semantic_tokens + 3` function M.highlight_token(token, bufnr, client_id, hl_group, opts) local highlighter = STHighlighter.active[bufnr] diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 826352f036..fb5b0b3194 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -388,9 +388,9 @@ end --- Returns the range table for the difference between prev and curr lines ---@param prev_lines table list of lines ---@param curr_lines table list of lines ----@param firstline number line to begin search for first difference ----@param lastline number line to begin search in old_lines for last difference ----@param new_lastline number line to begin search in new_lines for last difference +---@param firstline integer line to begin search for first difference +---@param lastline integer line to begin search in old_lines for last difference +---@param new_lastline integer line to begin search in new_lines for last difference ---@param offset_encoding string encoding requested by language server ---@returns table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentContentChangeEvent function M.compute_diff( diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 554e26022c..c9613dc7a7 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -121,9 +121,9 @@ end --- Convert byte index to `encoding` index. --- Convenience wrapper around vim.str_utfindex ---@param line string line to be indexed ----@param index number|nil byte index (utf-8), or `nil` for length +---@param index integer|nil byte index (utf-8), or `nil` for length ---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 ----@return number `encoding` index of `index` in `line` +---@return integer `encoding` index of `index` in `line` function M._str_utfindex_enc(line, index, encoding) if not encoding then encoding = 'utf-16' @@ -149,9 +149,9 @@ end --- Convenience wrapper around vim.str_byteindex ---Alternative to vim.str_byteindex that takes an encoding. ---@param line string line to be indexed ----@param index number UTF index +---@param index integer UTF index ---@param encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 ----@return number byte (utf-8) index of `encoding` index `index` in `line` +---@return integer byte (utf-8) index of `encoding` index `index` in `line` function M._str_byteindex_enc(line, index, encoding) if not encoding then encoding = 'utf-16' @@ -239,9 +239,9 @@ end --- Works on unloaded buffers by reading the file using libuv to bypass buf reading events. --- Falls back to loading the buffer and nvim_buf_get_lines for buffers with non-file URI. --- ----@param bufnr number bufnr to get the lines from ----@param rows number[] zero-indexed line numbers ----@return table a table mapping rows to lines +---@param bufnr integer bufnr to get the lines from +---@param rows integer[] zero-indexed line numbers +---@return table a table mapping rows to lines local function get_lines(bufnr, rows) rows = type(rows) == 'table' and rows or { rows } @@ -321,8 +321,8 @@ end --- Works on unloaded buffers by reading the file using libuv to bypass buf reading events. --- Falls back to loading the buffer and nvim_buf_get_lines for buffers with non-file URI. --- ----@param bufnr number ----@param row number zero-indexed line number +---@param bufnr integer +---@param row integer zero-indexed line number ---@return string the line at row in filename local function get_line(bufnr, row) return get_lines(bufnr, { row })[row] @@ -386,7 +386,7 @@ end --- Applies a list of text edits to a buffer. ---@param text_edits table list of `TextEdit` objects ----@param bufnr number Buffer id +---@param bufnr integer Buffer id ---@param offset_encoding string utf-8|utf-16|utf-32 ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit function M.apply_text_edits(text_edits, bufnr, offset_encoding) @@ -571,7 +571,7 @@ end --- document. --- ---@param text_document_edit table: a `TextDocumentEdit` object ----@param index number: Optional index of the edit, if from a list of edits (or nil, if not from a list) +---@param index integer: Optional index of the edit, if from a list of edits (or nil, if not from a list) ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit function M.apply_text_document_edit(text_document_edit, index, offset_encoding) local text_document = text_document_edit.textDocument @@ -1009,11 +1009,11 @@ end --- Creates a table with sensible default options for a floating window. The --- table can be passed to |nvim_open_win()|. --- ----@param width (number) window width (in character cells) ----@param height (number) window height (in character cells) +---@param width (integer) window width (in character cells) +---@param height (integer) window height (in character cells) ---@param opts (table, optional) ---- - offset_x (number) offset to add to `col` ---- - offset_y (number) offset to add to `row` +--- - offset_x (integer) offset to add to `col` +--- - offset_y (integer) offset to add to `row` --- - border (string or table) override `border` --- - focusable (string or table) override `focusable` --- - zindex (string or table) override `zindex`, defaults to 50 @@ -1429,7 +1429,7 @@ end ---@private --- Closes the preview window --- ----@param winnr number window id of preview window +---@param winnr integer window id of preview window ---@param bufnrs table|nil optional list of ignored buffers local function close_preview_window(winnr, bufnrs) vim.schedule(function() @@ -1448,7 +1448,7 @@ end --- Creates autocommands to close a preview window when events happen. --- ---@param events table list of events ----@param winnr number window id of preview window +---@param winnr integer window id of preview window ---@param bufnrs table list of buffers where the preview window will remain visible ---@see |autocmd-events| local function close_preview_autocmd(events, winnr, bufnrs) @@ -1556,14 +1556,14 @@ end ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ---@param opts table with optional fields (additional keys are passed on to |nvim_open_win()|) ---- - height: (number) height of floating window ---- - width: (number) width of floating window +--- - height: (integer) height of floating window +--- - width: (integer) width of floating window --- - wrap: (boolean, default true) wrap long lines ---- - wrap_at: (number) character to wrap at for computing height when wrap is enabled ---- - max_width: (number) maximal width of floating window ---- - max_height: (number) maximal height of floating window ---- - pad_top: (number) number of lines to pad contents at top ---- - pad_bottom: (number) number of lines to pad contents at bottom +--- - wrap_at: (integer) character to wrap at for computing height when wrap is enabled +--- - max_width: (integer) maximal width of floating window +--- - max_height: (integer) maximal height of floating window +--- - pad_top: (integer) number of lines to pad contents at top +--- - pad_bottom: (integer) number of lines to pad contents at bottom --- - focus_id: (string) if a popup with this id is opened, then focus it --- - close_events: (table) list of events that closes the floating window --- - focusable: (boolean, default true) Make float focusable @@ -1672,7 +1672,7 @@ do --[[ References ]] --- Removes document highlights from a buffer. --- - ---@param bufnr number Buffer id + ---@param bufnr integer Buffer id function M.buf_clear_references(bufnr) validate({ bufnr = { bufnr, 'n', true } }) api.nvim_buf_clear_namespace(bufnr or 0, reference_ns, 0, -1) @@ -1680,7 +1680,7 @@ do --[[ References ]] --- Shows a list of document highlights for a certain buffer. --- - ---@param bufnr number Buffer id + ---@param bufnr integer Buffer id ---@param references table List of `DocumentHighlight` objects to highlight ---@param offset_encoding string One of "utf-8", "utf-16", "utf-32". ---@see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentContentChangeEvent @@ -1893,7 +1893,7 @@ function M.try_trim_markdown_code_blocks(lines) end ---@private ----@param window number|nil: window handle or 0 for current, defaults to current +---@param window integer|nil: window handle or 0 for current, defaults to current ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` local function make_position_param(window, offset_encoding) window = window or 0 @@ -1913,7 +1913,7 @@ end --- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position. --- ----@param window number|nil: window handle or 0 for current, defaults to current +---@param window integer|nil: window handle or 0 for current, defaults to current ---@param offset_encoding string|nil utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of buffer of `window` ---@returns `TextDocumentPositionParams` object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams @@ -1928,7 +1928,7 @@ function M.make_position_params(window, offset_encoding) end --- Utility function for getting the encoding of the first LSP client on the given buffer. ----@param bufnr (number) buffer handle or 0 for current, defaults to current +---@param bufnr (integer) buffer handle or 0 for current, defaults to current ---@returns (string) encoding first client if there is one, nil otherwise function M._get_offset_encoding(bufnr) validate({ @@ -1966,7 +1966,7 @@ end --- `textDocument/codeAction`, `textDocument/colorPresentation`, --- `textDocument/rangeFormatting`. --- ----@param window number|nil: window handle or 0 for current, defaults to current +---@param window integer|nil: window handle or 0 for current, defaults to current ---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of buffer of `window` ---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---`current_position`, end = `current_position` } } @@ -1983,11 +1983,11 @@ end --- Using the given range in the current buffer, creates an object that --- is similar to |vim.lsp.util.make_range_params()|. --- ----@param start_pos number[]|nil {row, col} mark-indexed position. +---@param start_pos integer[]|nil {row, col} mark-indexed position. --- Defaults to the start of the last visual selection. ----@param end_pos number[]|nil {row, col} mark-indexed position. +---@param end_pos integer[]|nil {row, col} mark-indexed position. --- Defaults to the end of the last visual selection. ----@param bufnr number|nil buffer handle or 0 for current, defaults to current +---@param bufnr integer|nil buffer handle or 0 for current, defaults to current ---@param offset_encoding "utf-8"|"utf-16"|"utf-32"|nil defaults to `offset_encoding` of first client of `bufnr` ---@returns { textDocument = { uri = `current_file_uri` }, range = { start = ---`start_position`, end = `end_position` } } @@ -2028,7 +2028,7 @@ end --- Creates a `TextDocumentIdentifier` object for the current buffer. --- ----@param bufnr number|nil: Buffer handle, defaults to current +---@param bufnr integer|nil: Buffer handle, defaults to current ---@returns `TextDocumentIdentifier` ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier function M.make_text_document_params(bufnr) @@ -2049,8 +2049,8 @@ end --- Returns indentation size. --- ---@see 'shiftwidth' ----@param bufnr (number|nil): Buffer handle, defaults to current ----@returns (number) indentation size +---@param bufnr (integer|nil): Buffer handle, defaults to current +---@returns (integer) indentation size function M.get_effective_tabstop(bufnr) validate({ bufnr = { bufnr, 'n', true } }) local bo = bufnr and vim.bo[bufnr] or vim.bo @@ -2077,11 +2077,11 @@ end --- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer. --- ----@param buf number buffer number (0 for current) +---@param buf integer buffer number (0 for current) ---@param row 0-indexed line ---@param col 0-indexed byte offset in line ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to `offset_encoding` of first client of `buf` ----@returns (number, number) `offset_encoding` index of the character in line {row} column {col} in buffer {buf} +---@returns (integer, integer) `offset_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, offset_encoding) local line = get_line(buf, row) if offset_encoding == nil then -- cgit From 1637bcce7ba52c4c5c451308f8a3adfedde18a2a Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 7 Mar 2023 09:39:08 +0100 Subject: build!: make libintl a required dependency Libintl being an optional dependency is not by design, but a workaround as it didn't use work on all platforms. That should be fixed by now. --- runtime/doc/news.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 2db1e75bf7..254ffc51b8 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -45,7 +45,7 @@ The following changes may require adaptations in user config or plugins. - `printheader` - `printmbcharset` -• libiconv is now a required build dependency. +• libiconv and intl are now required build dependencies. • Unsaved changes are now preserved rather than discarded when |channel-stdio| is closed. -- cgit From 160a019ffa104eebd65f4037729954d98aca6ad0 Mon Sep 17 00:00:00 2001 From: Eriks Muhins Date: Fri, 3 Mar 2023 21:44:13 +0200 Subject: feat(man.lua): support spaces in manpage names Problem: :Man command errors if given more than two arguments. Thus, it is impossible to open man pages that contain spaces in their names. Solution: Adjust :Man so that it tries variants with spaces and underscores, and uses the first found. --- runtime/lua/man.lua | 54 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'runtime') diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 61a9575312..f420cc0d67 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -328,7 +328,8 @@ local function get_path(sect, name, silent) -- find any that match the specified name ---@param v string local namematches = vim.tbl_filter(function(v) - return fn.fnamemodify(v, ':t'):match(name) + local tail = fn.fnamemodify(v, ':t') + return string.find(tail, name, 1, true) end, results) or {} local sectmatches = {} @@ -372,18 +373,18 @@ local function extract_sect_and_name_ref(ref) if not name then man_error('manpage reference cannot contain only parentheses: ' .. ref) end - return '', spaces_to_underscores(name) + return '', name end local parts = vim.split(ref1, '(', { plain = true }) -- see ':Man 3X curses' on why tolower. -- TODO(nhooyr) Not sure if this is portable across OSs -- but I have not seen a single uppercase section. local sect = vim.split(parts[2] or '', ')', { plain = true })[1]:lower() - local name = spaces_to_underscores(parts[1]) + local name = parts[1] return sect, name end --- verify_exists attempts to find the path to a manpage +-- search_for_path attempts to find the path to a manpage -- based on the passed section and name. -- -- 1. If manpage could not be found with the given sect and name, @@ -391,10 +392,10 @@ end -- 2. If it still could not be found, then we try again without a section. -- 3. If still not found but $MANSECT is set, then we try again with $MANSECT -- unset. +-- 4. If a path still wasn't found, return nil. ---@param sect string? ---@param name string ----@param silent boolean? -local function verify_exists(sect, name, silent) +function M.search_for_path(sect, name) if sect and sect ~= '' then local ret = get_path(sect, name, true) if ret then @@ -430,10 +431,8 @@ local function verify_exists(sect, name, silent) end end - if not silent then - -- finally, if that didn't work, there is no hope - man_error('no manual entry for ' .. name) - end + -- finally, if that didn't work, there is no hope + return nil end local EXT_RE = vim.regex([[\.\%([glx]z\|bz2\|lzma\|Z\)$]]) @@ -585,8 +584,8 @@ local function get_paths(sect, name) ---@type string[] local paths = fn.globpath(mandirs, 'man?/' .. name .. '*.' .. sect .. '*', false, true) - -- Prioritize the result from verify_exists as it obeys b:man_default_sects. - local first = verify_exists(sect, name, true) + -- Prioritize the result from search_for_path as it obeys b:man_default_sects. + local first = M.search_for_path(sect, name) if first then paths = move_elem_to_head(paths, first) end @@ -728,10 +727,6 @@ end ---@param count integer ---@param args string[] function M.open_page(count, smods, args) - if #args > 2 then - man_error('too many arguments') - end - local ref ---@type string if #args == 0 then ref = vim.bo.filetype == 'man' and fn.expand('') or fn.expand('') @@ -743,9 +738,14 @@ function M.open_page(count, smods, args) else -- Combine the name and sect into a manpage reference so that all -- verification/extraction can be kept in a single function. - -- If args[2] is a reference as well, that is fine because it is the only - -- reference that will match. - ref = ('%s(%s)'):format(args[2], args[1]) + if tonumber(args[1]) then + local sect = args[1] + table.remove(args, 1) + local name = table.concat(args, ' ') + ref = ('%s(%s)'):format(name, sect) + else + ref = table.concat(args, ' ') + end end local sect, name = extract_sect_and_name_ref(ref) @@ -753,9 +753,16 @@ function M.open_page(count, smods, args) sect = tostring(count) end - local path = verify_exists(sect, name) - sect, name = extract_sect_and_name_path(path) + -- Try both spaces and underscores, use the first that exists. + local path = M.search_for_path(sect, name) + if path == nil then + path = M.search_for_path(sect, spaces_to_underscores(name)) + if path == nil then + man_error('no manual entry for ' .. name) + end + end + sect, name = extract_sect_and_name_path(path) local buf = fn.bufnr() local save_tfu = vim.bo[buf].tagfunc vim.bo[buf].tagfunc = "v:lua.require'man'.goto_tag" @@ -786,7 +793,10 @@ end -- Called when a man:// buffer is opened. function M.read_page(ref) local sect, name = extract_sect_and_name_ref(ref) - local path = verify_exists(sect, name) + local path = M.search_for_path(sect, name) + if path == nil then + man_error('no manual entry for ' .. name) + end sect = extract_sect_and_name_path(path) local page = get_page(path) vim.b.man_sect = sect -- cgit From 304477ff3504373a336c83127654e65eddfa2ef9 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 7 Mar 2023 15:13:09 +0100 Subject: fix(man.lua): tests, naming --- runtime/doc/news.txt | 2 ++ runtime/lua/man.lua | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 254ffc51b8..f5b9f39d93 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -162,6 +162,8 @@ The following new APIs or features were added. • |:highlight| now supports an additional attribute "altfont". +• |:Man| manpage viewer supports manpage names containing spaces. + • Treesitter captures can now be transformed by directives. This will allow more complicated dynamic language injections. diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index f420cc0d67..cca9434e9c 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -384,7 +384,7 @@ local function extract_sect_and_name_ref(ref) return sect, name end --- search_for_path attempts to find the path to a manpage +-- find_path attempts to find the path to a manpage -- based on the passed section and name. -- -- 1. If manpage could not be found with the given sect and name, @@ -395,7 +395,7 @@ end -- 4. If a path still wasn't found, return nil. ---@param sect string? ---@param name string -function M.search_for_path(sect, name) +function M.find_path(sect, name) if sect and sect ~= '' then local ret = get_path(sect, name, true) if ret then @@ -584,8 +584,8 @@ local function get_paths(sect, name) ---@type string[] local paths = fn.globpath(mandirs, 'man?/' .. name .. '*.' .. sect .. '*', false, true) - -- Prioritize the result from search_for_path as it obeys b:man_default_sects. - local first = M.search_for_path(sect, name) + -- Prioritize the result from find_path as it obeys b:man_default_sects. + local first = M.find_path(sect, name) if first then paths = move_elem_to_head(paths, first) end @@ -754,9 +754,9 @@ function M.open_page(count, smods, args) end -- Try both spaces and underscores, use the first that exists. - local path = M.search_for_path(sect, name) + local path = M.find_path(sect, name) if path == nil then - path = M.search_for_path(sect, spaces_to_underscores(name)) + path = M.find_path(sect, spaces_to_underscores(name)) if path == nil then man_error('no manual entry for ' .. name) end @@ -793,7 +793,7 @@ end -- Called when a man:// buffer is opened. function M.read_page(ref) local sect, name = extract_sect_and_name_ref(ref) - local path = M.search_for_path(sect, name) + local path = M.find_path(sect, name) if path == nil then man_error('no manual entry for ' .. name) end -- cgit From 04e8e1f9eaa9ca64fa6418639d595f142585a934 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 7 Mar 2023 09:28:53 -0500 Subject: refactor(runtime): use vim.version to compare versions #22550 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: Unfortunately, cannot (yet) use vim.version for tmux version comparison, because `vim.version.parse(…,{strict=false})` does not coerce tmux's funny "tmux 3.3a" version string. https://github.com/neovim/neovim/blob/6969d3d7491fc2f10d80309b26dd0c26d211b1b3/runtime/autoload/provider/clipboard.vim#L148 --- runtime/autoload/health/provider.vim | 28 ++++++---------------------- runtime/autoload/provider/node.vim | 18 +++++++----------- 2 files changed, 13 insertions(+), 33 deletions(-) (limited to 'runtime') diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim index d104bcfd67..59361eb735 100644 --- a/runtime/autoload/health/provider.vim +++ b/runtime/autoload/health/provider.vim @@ -19,22 +19,6 @@ function! s:cmd_ok(cmd) abort return v:shell_error == 0 endfunction -" Simple version comparison. -function! s:version_cmp(a, b) abort - let a = split(a:a, '\.', 0) - let b = split(a:b, '\.', 0) - - for i in range(len(a)) - if str2nr(a[i]) > str2nr(b[i]) - return 1 - elseif str2nr(a[i]) < str2nr(b[i]) - return -1 - endif - endfor - - return 0 -endfunction - " Handler for s:system() function. function! s:system_handler(jobid, data, event) dict abort if a:event ==# 'stderr' @@ -244,7 +228,7 @@ function! s:version_info(python) abort let nvim_path_base = fnamemodify(nvim_path, ':~:h') let version_status = 'unknown; '.nvim_path_base if !s:is_bad_response(nvim_version) && !s:is_bad_response(pypi_version) - if s:version_cmp(nvim_version, pypi_version) == -1 + if v:lua.vim.version.lt(nvim_version, pypi_version) let version_status = 'outdated; from '.nvim_path_base else let version_status = 'up to date' @@ -598,7 +582,7 @@ function! s:check_ruby() abort return endif - if s:version_cmp(current_gem, latest_gem) == -1 + if v:lua.vim.version.lt(current_gem, latest_gem) call health#report_warn( \ printf('Gem "neovim" is out-of-date. Installed: %s, latest: %s', \ current_gem, latest_gem), @@ -623,8 +607,8 @@ function! s:check_node() abort endif let node_v = get(split(s:system(['node', '-v']), "\n"), 0, '') call health#report_info('Node.js: '. node_v) - if s:shell_error || s:version_cmp(node_v[1:], '6.0.0') < 0 - call health#report_warn('Nvim node.js host does not support '.node_v) + if s:shell_error || v:lua.vim.version.lt(node_v[1:], '6.0.0') + call health#report_warn('Nvim node.js host does not support Node '.node_v) " Skip further checks, they are nonsense if nodejs is too old. return endif @@ -675,7 +659,7 @@ function! s:check_node() abort return endif - if s:version_cmp(current_npm, latest_npm) == -1 + if latest_npm !=# 'unable to parse' && v:lua.vim.version.lt(current_npm, latest_npm) call health#report_warn( \ printf('Package "neovim" is out-of-date. Installed: %s, latest: %s', \ current_npm, latest_npm), @@ -751,7 +735,7 @@ function! s:check_perl() abort return endif - if s:version_cmp(current_cpan, latest_cpan) == -1 + if v:lua.vim.version.lt(current_cpan, latest_cpan) call health#report_warn( \ printf('Module "Neovim::Ext" is out-of-date. Installed: %s, latest: %s', \ current_cpan, latest_cpan), diff --git a/runtime/autoload/provider/node.vim b/runtime/autoload/provider/node.vim index 87af0094fe..3e7b8b4ef9 100644 --- a/runtime/autoload/provider/node.vim +++ b/runtime/autoload/provider/node.vim @@ -3,7 +3,7 @@ if exists('g:loaded_node_provider') endif let g:loaded_node_provider = 1 -function! s:is_minimum_version(version, min_major, min_minor) abort +function! s:is_minimum_version(version, min_version) abort if empty(a:version) let nodejs_version = get(split(system(['node', '-v']), "\n"), 0, '') if v:shell_error || nodejs_version[0] !=# 'v' @@ -15,11 +15,7 @@ function! s:is_minimum_version(version, min_major, min_minor) abort " Remove surrounding junk. Example: 'v4.12.0' => '4.12.0' let nodejs_version = matchstr(nodejs_version, '\(\d\.\?\)\+') " [major, minor, patch] - let v_list = split(nodejs_version, '\.') - return len(v_list) == 3 - \ && ((str2nr(v_list[0]) > str2nr(a:min_major)) - \ || (str2nr(v_list[0]) == str2nr(a:min_major) - \ && str2nr(v_list[1]) >= str2nr(a:min_minor))) + return !v:lua.vim.version.lt(nodejs_version, a:min_version) endfunction let s:NodeHandler = { @@ -43,20 +39,20 @@ function! provider#node#can_inspect() abort if v:shell_error || ver[0] !=# 'v' return 0 endif - return (ver[1] ==# '6' && s:is_minimum_version(ver, 6, 12)) - \ || s:is_minimum_version(ver, 7, 6) + return (ver[1] ==# '6' && s:is_minimum_version(ver, '6.12.0')) + \ || s:is_minimum_version(ver, '7.6.0') endfunction function! provider#node#Detect() abort - let minver = [6, 0] + let minver = '6.0.0' if exists('g:node_host_prog') return [expand(g:node_host_prog, v:true), ''] endif if !executable('node') return ['', 'node not found (or not executable)'] endif - if !s:is_minimum_version(v:null, minver[0], minver[1]) - return ['', printf('node version %s.%s not found', minver[0], minver[1])] + if !s:is_minimum_version(v:null, minver) + return ['', printf('node version %s not found', minver)] endif let npm_opts = {} -- cgit From 4385f8a7430f8181189f385a6cfb4e295d30b21e Mon Sep 17 00:00:00 2001 From: jdrouhard Date: Tue, 7 Mar 2023 10:35:12 -0600 Subject: fix(lsp): change LspTokenUpdate to use buffer instead of pattern (#22559) --- runtime/lua/vim/lsp/semantic_tokens.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime') diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 9eaccd539f..a5e007a011 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -435,7 +435,7 @@ function STHighlighter:on_win(topline, botline) token.marked = true api.nvim_exec_autocmds('LspTokenUpdate', { - pattern = vim.api.nvim_buf_get_name(self.bufnr), + buffer = self.bufnr, modeline = false, data = { token = token, -- cgit From 30632dd21ab243bb2c4eb115819a32fdfd9155dc Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 7 Mar 2023 15:00:51 +0100 Subject: refactor(build): make installation of runtime/ more effective Currently files to install in runtime/ is detected by recursive glob pattern which has two problems: - cmake needs to do a of work at config time and build/runtime/cmake_install.cmake becomes HUGE (2.5MB, biggest config file) - we need to explicitly specify each file suffix used in the entire runtime, which is duplication of information. These globs specify every single file in a subdirectory. Thus, we can just install every runtime/ subdirectory as a single install command. Furthermore, at the top-level, only .vim and .lua files need to be installed. Further possible refactor: we could move files which does not belong in $PREFIX/runtime out of $REPO/runtime. Then runtime could be installed with a single install_helper(DIRECTORY ...) command. --- runtime/CMakeLists.txt | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'runtime') diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 581a4545db..c6447721a0 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -116,23 +116,17 @@ install_helper( FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps) -install_helper( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/neovim.ico - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime) - -globrecurse_wrapper(RUNTIME_PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR} *.awk *.sh *.bat) - -foreach(PROG ${RUNTIME_PROGRAMS}) - get_filename_component(BASEDIR ${PROG} DIRECTORY) - install_helper(PROGRAMS ${PROG} - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR}) +glob_wrapper(RUNTIME_ROOT_FILES *.vim *.lua *.ico) +install_helper(FILES ${RUNTIME_ROOT_FILES} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/) + +glob_wrapper(RUNTIME_DIRS */) +foreach(D ${RUNTIME_DIRS}) + if(IS_DIRECTORY ${D}) + install_helper(DIRECTORY ${D} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/) + endif() endforeach() -globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR} - *.vim *.lua *.scm *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json) - -foreach(F ${RUNTIME_FILES}) - get_filename_component(BASEDIR ${F} DIRECTORY) - install_helper(FILES ${F} - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/${BASEDIR}) -endforeach() +# only foo.sh script in runtime/ +install_helper(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/macros/less.sh DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/macros/) -- cgit From ddd257f75301a50c177fc24a693d39a45b47a689 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 8 Mar 2023 11:03:11 +0000 Subject: feat(treesitter): use upstream format for injection queries --- runtime/doc/news.txt | 4 + runtime/doc/treesitter.txt | 46 ++++++ runtime/lua/vim/treesitter/_meta.lua | 8 +- runtime/lua/vim/treesitter/languagetree.lua | 240 ++++++++++++++++++++-------- runtime/lua/vim/treesitter/query.lua | 21 +-- runtime/queries/c/injections.scm | 6 +- runtime/queries/help/injections.scm | 7 +- runtime/queries/lua/injections.scm | 16 +- runtime/queries/vim/injections.scm | 46 ++++-- 9 files changed, 283 insertions(+), 111 deletions(-) (limited to 'runtime') diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index f5b9f39d93..04ae9360a0 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -196,6 +196,10 @@ The following new APIs or features were added. • Added an omnifunc implementation for lua, |vim.lua_omnifunc()| +• Treesitter injection queries now use the format described at + https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection . + Support for the previous format will be removed in a future release. + ============================================================================== CHANGED FEATURES *news-changes* diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 1f78e4d5d9..3b0936941f 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -441,7 +441,53 @@ individual query pattern manually by setting its `"priority"` metadata attribute: > (super_important_node) @ImportantHighlight (#set! "priority" 105) + +============================================================================== +TREESITTER LANGUAGE INJECTIONS *treesitter-language-injections* < + +Note the following information is adapted from: + https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection + +Some source files contain code written in multiple different languages. +Examples include: + + • HTML files, which can contain JavaScript inside of `