From 3ac55fe0831b6af7277e6b26333ddb49ef423fcb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 30 Jan 2023 07:15:38 +0800 Subject: build(bump_deps.lua): run command -v in shell (#22030) When I run ./scripts/bump_deps.lua I get an error: Vim:E475: Invalid value for argument cmd: 'command' is not executable Running command -v in shell fixes this. --- scripts/bump_deps.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua index 1873c3cd0d..f980e800cf 100755 --- a/scripts/bump_deps.lua +++ b/scripts/bump_deps.lua @@ -54,7 +54,7 @@ local function run_die(cmd, err_msg) end local function require_executable(cmd) - local cmd_path = run_die({ 'command', '-v', cmd }, cmd .. ' not found!') + local cmd_path = run_die({ 'sh', '-c', 'command -v ' .. cmd }, cmd .. ' not found!') run_die({ 'test', '-x', cmd_path }, cmd .. ' is not executable') end -- 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 --- scripts/lua2dox.lua | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 19f8f8141d..fc0e915307 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -286,7 +286,12 @@ local function checkComment4fn(Fn_magic, MagicLines) return fn_magic end -local types = { 'number', 'string', 'table', 'list', 'boolean', 'function' } +local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' } + +local tagged_types = { 'TSNode', 'LanguageTree' } + +-- Document these as 'table' +local alias_types = { 'Range' } --! \brief run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) @@ -320,7 +325,12 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) offset = 1 end - if string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment + if vim.startswith(line, '---@cast') + or vim.startswith(line, '---@diagnostic') + or vim.startswith(line, '---@type') then + -- Ignore LSP directives + outStream:writeln('// gg:"' .. line .. '"') + elseif string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment state = 'in_magic_comment' local magic = string.sub(line, 4 + offset) @@ -366,6 +376,17 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) magic_split[type_index] = magic_split[type_index]:gsub(k, v) end end + + for _, type in ipairs(tagged_types) do + magic_split[type_index] = + magic_split[type_index]:gsub(type, '|%1|') + end + + for _, type in ipairs(alias_types) do + magic_split[type_index] = + magic_split[type_index]:gsub('^'..type..'$', 'table') + end + -- surround some types by () for _, type in ipairs(types) do magic_split[type_index] = @@ -373,6 +394,8 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) magic_split[type_index] = magic_split[type_index]:gsub('^(' .. type .. '):?$', '(%1)') end + + end magic = table.concat(magic_split, ' ') -- cgit From e5d8220179f932ab9c9ef59996cab357a25eaaf8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 10 Feb 2023 17:03:01 +0100 Subject: ci: simplify lintcommit output (#22204) - Suggest reading CONTRIBUTING.md once, not for each commit failure - Suggest using "fix" type if none of the provided types are appropriate - Remove "dist" type. It's rarely used and can be replaced by using the "build" type --- scripts/lintcommit.lua | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 87a8e62503..71796a5e02 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -78,10 +78,12 @@ local function validate_commit(commit_message) -- Check if type is correct local type = vim.split(before_colon, "%(")[1] - local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'dist', 'vim-patch'} + local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'} if not vim.tbl_contains(allowed_types, type) then return string.format( - 'Invalid commit type "%s". Allowed types are:\n %s', + [[Invalid commit type "%s". Allowed types are: + %s. + If none of these seem appropriate then use "fix"]], type, vim.inspect(allowed_types)) end @@ -164,13 +166,16 @@ function M.main(opt) local invalid_msg = validate_commit(msg) if invalid_msg then failed = failed + 1 + + -- Some breathing room + if failed == 1 then + p('\n') + end + p(string.format([[ Invalid commit message: "%s" Commit: %s %s - See also: - https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages - https://www.conventionalcommits.org/en/v1.0.0/ ]], msg, commit_id, @@ -180,6 +185,10 @@ Invalid commit message: "%s" end if failed > 0 then + p([[ +See also: + https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages +]]) die() -- Exit with error. else p('') @@ -198,7 +207,6 @@ function M._test() ['refactor: normal message'] = true, ['revert: normal message'] = true, ['test: normal message'] = true, - ['dist: normal message'] = true, ['ci(window): message with scope'] = true, ['ci!: message with breaking change'] = true, ['ci(tui)!: message with scope and breaking change'] = true, -- cgit From 84cf6a0a7e58aace0e659f2c6bb61d7179164add Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 13 Feb 2023 12:26:27 -0500 Subject: ci(lintcommit): allow UPPER_CASE first word (#22245) --- scripts/lintcommit.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 71796a5e02..977f7e7e46 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -128,10 +128,10 @@ local function validate_commit(commit_message) return [[There should only be one whitespace after the colon.]] end - -- Check that first character after space isn't uppercase. - if string.match(after_colon:sub(2,2), '%u') then - return [[First character should not be uppercase.]] - end + -- Allow lowercase or ALL_UPPER but not Titlecase. + if after_colon:match(' *%u%l') then + return [[Description should not be Capitalized.]] + end -- Check that description isn't just whitespaces if vim.trim(after_colon) == "" then @@ -231,7 +231,8 @@ function M._test() ['refactor(): empty scope'] = false, ['ci( ): whitespace as scope'] = false, ['ci: period at end of sentence.'] = false, - ['ci: Starting sentence capitalized'] = false, + ['ci: Capitalized first word'] = false, + ['ci: UPPER_CASE first word'] = true, ['unknown: using unknown type'] = false, ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false, } -- cgit From 5420bf99988be798938f7ee45b2f993e3c4ff2ee Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 16 Feb 2023 09:43:05 -0500 Subject: fix(lintcommit): capitalized description #22282 Problem: The "Capitalized" check should only check the first word of a description. Solution: Specify "^". --- scripts/lintcommit.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 977f7e7e46..7e08ca4ea0 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -129,8 +129,8 @@ local function validate_commit(commit_message) end -- Allow lowercase or ALL_UPPER but not Titlecase. - if after_colon:match(' *%u%l') then - return [[Description should not be Capitalized.]] + if after_colon:match('^ *%u%l') then + return [[Description first word should not be Capitalized.]] end -- Check that description isn't just whitespaces @@ -232,7 +232,7 @@ function M._test() ['ci( ): whitespace as scope'] = false, ['ci: period at end of sentence.'] = false, ['ci: Capitalized first word'] = false, - ['ci: UPPER_CASE first word'] = true, + ['ci: UPPER_CASE First Word'] = true, ['unknown: using unknown type'] = false, ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false, } -- cgit From 9301abdf748b54fa3d41375cc4659ca9f4b57dd8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:43:39 +0100 Subject: ci: enable CI_BUILD automatically if environment variable CI is true (#22312) Having to specify CI_BUILD for every CI job requires boilerplate. More importantly, it's easy to forget to enable CI_BUILD, as seen by 8a20f9f98a90a7a43aea08fcde2c40a5356b4f7b. It's simpler to remember to turn CI_BUILD off when a job errors instead of remembering that every new job should have CI_BUILD on. --- scripts/genappimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh index 9944b5eb31..dc46f4ce17 100755 --- a/scripts/genappimage.sh +++ b/scripts/genappimage.sh @@ -26,7 +26,7 @@ APP_DIR="$APP.AppDir" ######################################################################## # Build and install nvim into the AppImage -make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" +make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCI_BUILD=OFF -DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" make install ######################################################################## -- 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. --- scripts/lua2dox.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index fc0e915307..17de0ea9b4 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -291,7 +291,7 @@ local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local alias_types = { 'Range' } +local alias_types = { 'Range4', 'Range6' } --! \brief run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) -- cgit From 2708507e877f3255076bab2f5f074667dd25f8fc Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 25 Feb 2023 16:35:45 +0100 Subject: docs: use build/bin/nvim instead of nvim in gen_vimdoc (#22398) Problem: `nvim` could point to stable release missing the `nvim -l` functionality. Solution: Require to build nvim first and use `build/bin/nvim` --- scripts/gen_vimdoc.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 8e1d6ef80a..b8c36dc35d 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -42,6 +42,7 @@ import subprocess import collections import msgpack import logging +from pathlib import Path from xml.dom import minidom @@ -55,19 +56,19 @@ if sys.version_info < MIN_PYTHON_VERSION: doxygen_version = tuple((int(i) for i in subprocess.check_output(["doxygen", "-v"], universal_newlines=True).split()[0].split('.'))) -# Until 0.9 is released, need this hacky way to check that "nvim -l foo.lua" works. -nvim_version = list(line for line in subprocess.check_output(['nvim', '-h'], universal_newlines=True).split('\n') - if '-l ' in line) - if doxygen_version < MIN_DOXYGEN_VERSION: print("\nRequires doxygen {}.{}.{}+".format(*MIN_DOXYGEN_VERSION)) print("Your doxygen version is {}.{}.{}\n".format(*doxygen_version)) sys.exit(1) -if len(nvim_version) == 0: - print("\nRequires 'nvim -l' feature, see https://github.com/neovim/neovim/pull/18706") + +# Need a `nvim` that supports `-l`, so use the local build +nvim = Path(__file__).parent / "../build/bin/nvim" +if not nvim.exists(): + print("\nYou need to build Neovim first to build the documentation.") sys.exit(1) + # DEBUG = ('DEBUG' in os.environ) INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ) INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ) @@ -1163,7 +1164,7 @@ def main(doxygen_config, args): def filter_source(filename): name, extension = os.path.splitext(filename) if extension == '.lua': - p = subprocess.run(['nvim', '-l', lua2dox, filename], stdout=subprocess.PIPE) + p = subprocess.run([str(nvim), '-l', lua2dox, filename], stdout=subprocess.PIPE) op = ('?' if 0 != p.returncode else p.stdout.decode('utf-8')) print(op) else: -- cgit From db32d312acd4bee96b3463ff85a6574b5180502d Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 25 Feb 2023 17:24:43 +0100 Subject: ci(fix): repair regen-api-docs (#22403) https://github.com/neovim/neovim/pull/22398 broke the job because there is no `build/bin/nvim` This keeps the preference for `build/bin/nvim` but adds back `nvim` as fallback if it doesn't exist. --- scripts/gen_vimdoc.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index b8c36dc35d..dd593475e2 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -62,11 +62,21 @@ if doxygen_version < MIN_DOXYGEN_VERSION: sys.exit(1) -# Need a `nvim` that supports `-l`, so use the local build -nvim = Path(__file__).parent / "../build/bin/nvim" -if not nvim.exists(): - print("\nYou need to build Neovim first to build the documentation.") - sys.exit(1) +# Need a `nvim` that supports `-l`, try the local build +nvim_path = Path(__file__).parent / "../build/bin/nvim" +if nvim_path.exists(): + nvim = str(nvim_path) +else: + # Until 0.9 is released, use this hacky way to check that "nvim -l foo.lua" works. + nvim_out = subprocess.check_output(['nvim', '-h'], universal_newlines=True) + nvim_version = [line for line in nvim_out.split('\n') + if '-l ' in line] + if len(nvim_version) == 0: + print(( + "\nYou need to have a local Neovim build or a `nvim` version 0.9 for `-l` " + "support to build the documentation.")) + sys.exit(1) + nvim = 'nvim' # DEBUG = ('DEBUG' in os.environ) -- 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. --- scripts/gen_vimdoc.py | 2 +- scripts/lua2dox.lua | 55 +++++++++++++++++++++++++++------------------------ 2 files changed, 30 insertions(+), 27 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index dd593475e2..a4d6c3e2af 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -286,7 +286,7 @@ CONFIG = { if fstem == 'treesitter' else f'*{name}()*' if name[0].isupper() - else f'*vim.treesitter.{fstem}.{name}()*'), + else f'*vim.treesitter.{name}()*'), 'module_override': {}, 'append_only': [], } diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 17de0ea9b4..d5b693a1a7 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -27,7 +27,10 @@ http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm Running ------- -This script "lua2dox.lua" gets called by "gen_vimdoc.py". +This script "lua2dox.lua" gets called by "gen_vimdoc.py". To debug, run gen_vimdoc.py with +--keep-tmpfiles: + + python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles Doxygen must be on your system. You can experiment like so: @@ -71,14 +74,14 @@ local function class() return newClass end ---! \brief write to stdout +-- write to stdout local function TCore_IO_write(Str) if Str then io.write(Str) end end ---! \brief write to stdout +-- write to stdout local function TCore_IO_writeln(Str) if Str then io.write(Str) @@ -86,12 +89,12 @@ local function TCore_IO_writeln(Str) io.write('\n') end ---! \brief trims a string +-- trims a string local function string_trim(Str) return Str:match('^%s*(.-)%s*$') end ---! \brief split a string +-- split a string --! --! \param Str --! \param Pattern @@ -117,12 +120,12 @@ local function string_split(Str, Pattern) end ------------------------------- ---! \brief file buffer +-- file buffer --! --! an input file buffer local TStream_Read = class() ---! \brief get contents of file +-- get contents of file --! --! \param Filename name of file to read (or nil == stdin) function TStream_Read.getContents(this, Filename) @@ -143,12 +146,12 @@ function TStream_Read.getContents(this, Filename) return filecontents end ---! \brief get lineno +-- get lineno function TStream_Read.getLineNo(this) return this.currentLineNo end ---! \brief get a line +-- get a line function TStream_Read.getLine(this) local line if this.currentLine then @@ -166,12 +169,12 @@ function TStream_Read.getLine(this) return line end ---! \brief save line fragment +-- save line fragment function TStream_Read.ungetLine(this, LineFrag) this.currentLine = LineFrag end ---! \brief is it eof? +-- is it eof? function TStream_Read.eof(this) if this.currentLine or this.currentLineNo <= this.contentsLen then return false @@ -179,31 +182,31 @@ function TStream_Read.eof(this) return true end ---! \brief output stream +-- output stream local TStream_Write = class() ---! \brief constructor +-- constructor function TStream_Write.init(this) this.tailLine = {} end ---! \brief write immediately +-- write immediately function TStream_Write.write(_, Str) TCore_IO_write(Str) end ---! \brief write immediately +-- write immediately function TStream_Write.writeln(_, Str) TCore_IO_writeln(Str) end ---! \brief write immediately +-- write immediately function TStream_Write.writelnComment(_, Str) TCore_IO_write('// ZZ: ') TCore_IO_writeln(Str) end ---! \brief write to tail +-- write to tail function TStream_Write.writelnTail(this, Line) if not Line then Line = '' @@ -211,7 +214,7 @@ function TStream_Write.writelnTail(this, Line) table.insert(this.tailLine, Line) end ---! \brief output tail lines +-- output tail lines function TStream_Write.write_tailLines(this) for _, line in ipairs(this.tailLine) do TCore_IO_writeln(line) @@ -219,17 +222,17 @@ function TStream_Write.write_tailLines(this) TCore_IO_write('// Lua2DoX new eof') end ---! \brief input filter +-- input filter local TLua2DoX_filter = class() ---! \brief allow us to do errormessages +-- allow us to do errormessages function TLua2DoX_filter.warning(this, Line, LineNo, Legend) this.outStream:writelnTail( '//! \todo warning! ' .. Legend .. ' (@' .. LineNo .. ')"' .. Line .. '"' ) end ---! \brief trim comment off end of string +-- trim comment off end of string --! --! If the string has a comment on the end, this trims it off. --! @@ -243,7 +246,7 @@ local function TString_removeCommentFromLine(Line) return Line, tailComment end ---! \brief get directive from magic +-- get directive from magic local function getMagicDirective(Line) local macro, tail local macroStr = '[\\@]' @@ -264,7 +267,7 @@ local function getMagicDirective(Line) return macro, tail end ---! \brief check comment for fn +-- check comment for fn local function checkComment4fn(Fn_magic, MagicLines) local fn_magic = Fn_magic -- TCore_IO_writeln('// checkComment4fn "' .. MagicLines .. '"') @@ -293,7 +296,7 @@ local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' local alias_types = { 'Range4', 'Range6' } ---! \brief run the filter +-- run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) local inStream = TStream_Read() local outStream = TStream_Write() @@ -524,10 +527,10 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) end end ---! \brief this application +-- this application local TApp = class() ---! \brief constructor +-- constructor function TApp.init(this) this.timestamp = os.date('%c %Z', os.time()) this.name = 'Lua2DoX' -- cgit From 57f26e0903af0e4569a70d310ca18696e7680c74 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 3 Mar 2023 13:49:22 +0100 Subject: docs: lua2dox.lua debugging --- scripts/gen_vimdoc.py | 16 +++++++++++---- scripts/lua2dox.lua | 57 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 22 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index a4d6c3e2af..9e9e966627 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -265,6 +265,7 @@ CONFIG = { 'query.lua', 'highlighter.lua', 'languagetree.lua', + 'playground.lua', ], 'files': [ 'runtime/lua/vim/treesitter.lua', @@ -1171,10 +1172,12 @@ def main(doxygen_config, args): msg_report() -def filter_source(filename): +def filter_source(filename, keep_tmpfiles): + output_dir = out_dir.format(target='lua2dox') name, extension = os.path.splitext(filename) if extension == '.lua': - p = subprocess.run([str(nvim), '-l', lua2dox, filename], stdout=subprocess.PIPE) + args = [str(nvim), '-l', lua2dox, filename] + (['--outdir', output_dir] if keep_tmpfiles else []) + p = subprocess.run(args, stdout=subprocess.PIPE) op = ('?' if 0 != p.returncode else p.stdout.decode('utf-8')) print(op) else: @@ -1197,7 +1200,7 @@ def parse_args(): ap.add_argument('source_filter', nargs='*', help="Filter source file(s)") ap.add_argument('-k', '--keep-tmpfiles', action='store_true', - help="Keep temporary files") + help="Keep temporary files (tmp-xx-doc/ directories, including tmp-lua2dox-doc/ for lua2dox.lua quasi-C output)") ap.add_argument('-t', '--target', help=f'One of ({targets}), defaults to "all"') return ap.parse_args() @@ -1245,8 +1248,13 @@ if __name__ == "__main__": log.setLevel(args.log_level) log.addHandler(logging.StreamHandler()) + # When invoked as a filter, args won't be passed, so use an env var. + if args.keep_tmpfiles: + os.environ['NVIM_KEEP_TMPFILES'] = '1' + keep_tmpfiles = ('NVIM_KEEP_TMPFILES' in os.environ) + if len(args.source_filter) > 0: - filter_source(args.source_filter[0]) + filter_source(args.source_filter[0], keep_tmpfiles) else: main(Doxyfile, args) diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index d5b693a1a7..b99cd955f4 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -24,13 +24,17 @@ Lua-to-Doxygen converter Partially from lua2dox http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm -Running +RUNNING ------- -This script "lua2dox.lua" gets called by "gen_vimdoc.py". To debug, run gen_vimdoc.py with ---keep-tmpfiles: +This script "lua2dox.lua" gets called by "gen_vimdoc.py". - python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles +DEBUGGING/DEVELOPING +--------------------- + +1. To debug, run gen_vimdoc.py with --keep-tmpfiles: + python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles +2. The filtered result will be written to ./tmp-lua2dox-doc/….lua.c Doxygen must be on your system. You can experiment like so: @@ -52,6 +56,9 @@ However I have put in a hack that will insert the "missing" close paren. The effect is that you will get the function documented, but not with the parameter list you might expect. ]] +local _debug_outfile = nil +local _debug_output = {} + local function class() local newClass = {} -- a new class newClass -- the class will be the metatable for all its newInstanceects, @@ -78,15 +85,16 @@ end local function TCore_IO_write(Str) if Str then io.write(Str) + if _debug_outfile then + table.insert(_debug_output, Str) + end end end -- write to stdout local function TCore_IO_writeln(Str) - if Str then - io.write(Str) - end - io.write('\n') + TCore_IO_write(Str) + TCore_IO_write('\n') end -- trims a string @@ -296,8 +304,8 @@ local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' local alias_types = { 'Range4', 'Range6' } --- run the filter -function TLua2DoX_filter.readfile(this, AppStamp, Filename) +-- Processes the file and writes filtered output to stdout. +function TLua2DoX_filter.filter(this, AppStamp, Filename) local inStream = TStream_Read() local outStream = TStream_Write() this.outStream = outStream -- save to this obj @@ -554,8 +562,7 @@ local This_app = TApp() --main -local argv1 = arg[1] -if argv1 == '--help' then +if arg[1] == '--help' then TCore_IO_writeln(This_app:getVersion()) TCore_IO_writeln(This_app:getCopyright()) TCore_IO_writeln([[ @@ -566,16 +573,30 @@ if argv1 == '--help' then : interprets filename --version : show version/copyright info --help : this help text]]) -elseif argv1 == '--version' then +elseif arg[1] == '--version' then TCore_IO_writeln(This_app:getVersion()) TCore_IO_writeln(This_app:getCopyright()) -else - -- it's a filter - local appStamp = This_app:getRunStamp() - local filename = argv1 +else -- It's a filter. + local filename = arg[1] + + if arg[2] == '--outdir' then + local outdir = arg[3] + if type(outdir) ~= 'string' or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir)) then + error(('invalid --outdir: "%s"'):format(tostring(outdir))) + end + vim.fn.mkdir(outdir, 'p') + _debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename)) + end + local appStamp = This_app:getRunStamp() local filter = TLua2DoX_filter() - filter:readfile(appStamp, filename) + filter:filter(appStamp, filename) + + if _debug_outfile then + local f = assert(io.open(_debug_outfile, 'w')) + f:write(table.concat(_debug_output)) + f:close() + end end --eof -- 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 --- scripts/gen_vimdoc.py | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 9e9e966627..0164278b34 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -1054,17 +1054,18 @@ def main(doxygen_config, args): fn_map_full = {} # Collects all functions as each module is processed. sections = {} - intros = {} + section_docs = {} sep = '=' * text_width base = os.path.join(output_dir, 'xml') dom = minidom.parse(os.path.join(base, 'index.xml')) - # generate docs for section intros + # Generate module-level (section) docs (@defgroup). for compound in dom.getElementsByTagName('compound'): if compound.getAttribute('kind') != 'group': continue + # Doxygen "@defgroup" directive. groupname = get_text(find_first(compound, 'name')) groupxml = os.path.join(base, '%s.xml' % compound.getAttribute('refid')) @@ -1083,33 +1084,39 @@ def main(doxygen_config, args): if doc: doc_list.append(doc) - intros[groupname] = "\n".join(doc_list) + section_docs[groupname] = "\n".join(doc_list) + # Generate docs for all functions in the current module. for compound in dom.getElementsByTagName('compound'): if compound.getAttribute('kind') != 'file': continue filename = get_text(find_first(compound, 'name')) if filename.endswith('.c') or filename.endswith('.lua'): - xmlfile = os.path.join(base, - '{}.xml'.format(compound.getAttribute('refid'))) + xmlfile = os.path.join(base, '{}.xml'.format(compound.getAttribute('refid'))) # Extract unformatted (*.mpack). fn_map, _ = extract_from_xml(xmlfile, target, 9999, False) # Extract formatted (:help). functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp( - os.path.join(base, '{}.xml'.format( - compound.getAttribute('refid'))), target) + os.path.join(base, '{}.xml'.format(compound.getAttribute('refid'))), target) if not functions_text and not deprecated_text: continue else: - name = os.path.splitext( - os.path.basename(filename))[0].lower() + filename = os.path.basename(filename) + name = os.path.splitext(filename)[0].lower() sectname = name.upper() if name == 'ui' else name.title() + sectname = CONFIG[target]['section_name'].get(filename, sectname) + title = CONFIG[target]['section_fmt'](sectname) + section_tag = CONFIG[target]['helptag_fmt'](sectname) + # Module/Section id matched against @defgroup. + # "*api-buffer*" => "api-buffer" + section_id = section_tag.strip('*') + doc = '' - intro = intros.get(f'api-{name}') - if intro: - doc += '\n\n' + intro + section_doc = section_docs.get(section_id) + if section_doc: + doc += '\n\n' + section_doc if functions_text: doc += '\n\n' + functions_text @@ -1119,12 +1126,7 @@ def main(doxygen_config, args): doc += deprecated_text if doc: - filename = os.path.basename(filename) - sectname = CONFIG[target]['section_name'].get( - filename, sectname) - title = CONFIG[target]['section_fmt'](sectname) - helptag = CONFIG[target]['helptag_fmt'](sectname) - sections[filename] = (title, helptag, doc) + sections[filename] = (title, section_tag, doc) fn_map_full.update(fn_map) if len(sections) == 0: @@ -1139,15 +1141,14 @@ def main(doxygen_config, args): for filename in CONFIG[target]['section_order']: try: - title, helptag, section_doc = sections.pop(filename) + title, section_tag, section_doc = sections.pop(filename) except KeyError: msg(f'warning: empty docs, skipping (target={target}): {filename}') msg(f' existing docs: {sections.keys()}') continue if filename not in CONFIG[target]['append_only']: docs += sep - docs += '\n%s%s' % (title, - helptag.rjust(text_width - len(title))) + docs += '\n{}{}'.format(title, section_tag.rjust(text_width - len(title))) docs += section_doc docs += '\n\n\n' -- 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 --- scripts/gen_vimdoc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 0164278b34..45a6d8e402 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -152,6 +152,7 @@ CONFIG = { 'keymap.lua', 'fs.lua', 'secure.lua', + 'version.lua', ], 'files': [ 'runtime/lua/vim/_editor.lua', @@ -162,6 +163,7 @@ CONFIG = { 'runtime/lua/vim/keymap.lua', 'runtime/lua/vim/fs.lua', 'runtime/lua/vim/secure.lua', + 'runtime/lua/vim/version.lua', 'runtime/lua/vim/_inspector.lua', ], 'file_patterns': '*.lua', -- 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 --- scripts/gen_vimdoc.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 45a6d8e402..1e85fa49e9 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -194,6 +194,7 @@ CONFIG = { 'keymap': 'vim.keymap', 'fs': 'vim.fs', 'secure': 'vim.secure', + 'version': 'vim.version', }, 'append_only': [ 'shared.lua', -- cgit From af23d173883f47fd02a9a380c719e4428370b484 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 7 Mar 2023 04:13:04 +0100 Subject: test: move oldtests to test directory (#22536) The new oldtest directory is in test/old/testdir. The reason for this is that many tests have hardcoded the parent directory name to be 'testdir'. --- scripts/vim-patch.sh | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index f9f7330097..06ddf0f3b8 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -226,6 +226,10 @@ preprocess_patch() { local na_vimrcexample='vimrc_example\.vim' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file" + # Rename src/testdir/ paths to test/old/testdir/ + LC_ALL=C sed -e 's/\( [ab]\)\/src\/testdir/\1\/test\/old\/testdir/g' \ + "$file" > "$file".tmp && mv "$file".tmp "$file" + # Rename src/ paths to src/nvim/ LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \ "$file" > "$file".tmp && mv "$file".tmp "$file" -- cgit From 0e7edd70a95d962dfbe5b52c2767887a7131e0a0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 8 Mar 2023 10:46:09 +0800 Subject: test(old): move memfile_test.c to test/old/ (#22567) --- scripts/vim-patch.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 06ddf0f3b8..20e337afcb 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -598,6 +598,7 @@ _set_missing_vimpatches() { # Massage arguments for git-log. declare -A git_log_replacements=( [^\(.*/\)?src/nvim/\(.*\)]="\${BASH_REMATCH[1]}src/\${BASH_REMATCH[2]}" + [^\(.*/\)?test/old/\(.*\)]="\${BASH_REMATCH[1]}src/\${BASH_REMATCH[2]}" [^\(.*/\)?\.vim-src/\(.*\)]="\${BASH_REMATCH[2]}" ) local i j -- cgit From 58bbc2ea0b3dfed13471e8cc0447d7598be24276 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 10 Mar 2023 16:40:27 +0000 Subject: refactor(treesitter): add Range type aliase for Range4|Range6 --- scripts/lua2dox.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index b99cd955f4..de9f2926f2 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -302,7 +302,7 @@ local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local alias_types = { 'Range4', 'Range6' } +local alias_types = { 'Range', 'Range4', 'Range6', 'TSMetadata' } -- Processes the file and writes filtered output to stdout. function TLua2DoX_filter.filter(this, AppStamp, Filename) -- cgit From 21eacbfef399f124e9d50f1757c89453c4e02944 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 15 Mar 2023 07:51:44 -0400 Subject: docs(html): render @see items as a list #22675 Needed for "flow" HTML layout. Flow layout before: See also: https://github.com/kikito/inspect.lua https://github.com/mpeterv/vinspect Flow layout after: See also: - https://github.com/kikito/inspect.lua - https://github.com/mpeterv/vinspect --- scripts/gen_vimdoc.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 1e85fa49e9..72f9df325b 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -537,7 +537,7 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation, text += '>{}{}\n<'.format(ensure_nl, o) elif is_inline(n): - text = doc_wrap(get_text(n), indent=indent, width=width) + text = doc_wrap(get_text(n), prefix=prefix, indent=indent, width=width) elif n.nodeName == 'verbatim': # TODO: currently we don't use this. The "[verbatim]" hint is there as # a reminder that we must decide how to format this if we do use it. @@ -550,19 +550,19 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation, indent=indent + (' ' * len(prefix)), width=width ) - if is_blank(result): continue - text += indent + prefix + result elif n.nodeName in ('para', 'heading'): + did_prefix = False for c in n.childNodes: if (is_inline(c) and '' != get_text(c).strip() and text and ' ' != text[-1]): text += ' ' - text += render_node(c, text, indent=indent, width=width) + text += render_node(c, text, prefix=(prefix if not did_prefix else ''), indent=indent, width=width) + did_prefix = True elif n.nodeName == 'itemizedlist': for c in n.childNodes: text += '{}\n'.format(render_node(c, text, prefix='• ', @@ -586,8 +586,15 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation, for c in n.childNodes: text += render_node(c, text, indent=' ', width=width) text += '\n' - elif (n.nodeName == 'simplesect' - and n.getAttribute('kind') in ('return', 'see')): + elif n.nodeName == 'simplesect' and 'see' == n.getAttribute('kind'): + text += ind(' ') + # Example: + # + # |autocommand| + # + for c in n.childNodes: + text += render_node(c, text, prefix='• ', indent=' ', width=width) + elif n.nodeName == 'simplesect' and 'return' == n.getAttribute('kind'): text += ind(' ') for c in n.childNodes: text += render_node(c, text, indent=' ', width=width) @@ -678,6 +685,10 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F chunks['return'].append(render_node( child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp)) for child in groups['seealso']: + # Example: + # + # |autocommand| + # chunks['seealso'].append(render_node( child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp)) -- cgit From a7b537c7a4e5b6114cd75df5178199f4449c6480 Mon Sep 17 00:00:00 2001 From: Ankit Goel Date: Wed, 22 Mar 2023 02:57:23 +0000 Subject: ci(lintcommit): allow colon in commit message scope Close #21464 --- scripts/lintcommit.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 7e08ca4ea0..92b07c4f73 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -69,7 +69,7 @@ local function validate_commit(commit_message) end local before_colon = commit_split[1] - local after_colon = commit_split[2] + local after_colon = commit_split[#commit_split] -- Check if commit introduces a breaking change. if vim.endswith(before_colon, "!") then @@ -90,7 +90,7 @@ local function validate_commit(commit_message) -- Check if scope is appropriate if before_colon:match("%(") then - local scope = vim.trim(before_colon:match("%((.*)%)")) + local scope = vim.trim(commit_message:match("%((.-)%)")) if scope == '' then return [[Scope can't be empty]] @@ -234,6 +234,7 @@ function M._test() ['ci: Capitalized first word'] = false, ['ci: UPPER_CASE First Word'] = true, ['unknown: using unknown type'] = false, + ['feat(:grep): read from pipe'] = true, ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false, } -- cgit From 4e4203f71b0b9bb2ca4ad9abd2fbf4ea1deaf9a6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Mar 2023 11:23:51 +0000 Subject: fix(treesitter): annotations - Begin using `@package` in place of `@private` for functions that are accessed internally but outside their defined class. - Rename Node -> TSP.Node --- scripts/lua2dox.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index de9f2926f2..014934aebe 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -336,6 +336,8 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) offset = 1 end + line = line:gsub('@package', '@private') + if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') or vim.startswith(line, '---@type') then -- cgit From cbbf8bd666c8419fdab80a0887948c8a36279c19 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 24 Mar 2023 14:43:14 +0000 Subject: feat(treesitter)!: deprecate top level indexes to modules (#22761) The following top level Treesitter functions have been moved: - vim.treesitter.inspect_language() -> vim.treesitter.language.inspect() - vim.treesitter.get_query_files() -> vim.treesitter.query.get_files() - vim.treesitter.set_query() -> vim.treesitter.query.set() - vim.treesitter.query.set_query() -> vim.treesitter.query.set() - vim.treesitter.get_query() -> vim.treesitter.query.get() - vim.treesitter.query.get_query() -> vim.treesitter.query.get() - vim.treesitter.parse_query() -> vim.treesitter.query.parse() - vim.treesitter.query.parse_query() -> vim.treesitter.query.parse() - vim.treesitter.add_predicate() -> vim.treesitter.query.add_predicate() - vim.treesitter.add_directive() -> vim.treesitter.query.add_directive() - vim.treesitter.list_predicates() -> vim.treesitter.query.list_predicates() - vim.treesitter.list_directives() -> vim.treesitter.query.list_directives() - vim.treesitter.query.get_range() -> vim.treesitter.get_range() - vim.treesitter.query.get_node_text() -> vim.treesitter.get_node_text() --- scripts/gen_vimdoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 72f9df325b..de95caf376 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -290,7 +290,7 @@ CONFIG = { if fstem == 'treesitter' else f'*{name}()*' if name[0].isupper() - else f'*vim.treesitter.{name}()*'), + else f'*vim.treesitter.{fstem}.{name}()*'), 'module_override': {}, 'append_only': [], } -- cgit From 2257ade3dc2daab5ee12d27807c0b3bcf103cd29 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Sun, 26 Mar 2023 12:42:15 +0200 Subject: feat(lua): add `vim.loader` feat: new faster lua loader using byte-compilation --- scripts/gen_vimdoc.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index de95caf376..8860bdd5c6 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -146,6 +146,7 @@ CONFIG = { '_editor.lua', '_inspector.lua', 'shared.lua', + 'loader.lua', 'uri.lua', 'ui.lua', 'filetype.lua', @@ -157,6 +158,7 @@ CONFIG = { 'files': [ 'runtime/lua/vim/_editor.lua', 'runtime/lua/vim/shared.lua', + 'runtime/lua/vim/loader.lua', 'runtime/lua/vim/uri.lua', 'runtime/lua/vim/ui.lua', 'runtime/lua/vim/filetype.lua', @@ -190,6 +192,7 @@ CONFIG = { '_inspector': 'vim', 'uri': 'vim', 'ui': 'vim.ui', + 'loader': 'vim.loader', 'filetype': 'vim.filetype', 'keymap': 'vim.keymap', 'fs': 'vim.fs', -- cgit From d7f7450017b9b05303698a6cda54303ef22c63b3 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 31 Mar 2023 17:09:00 +0200 Subject: refactor(treesitter)!: rename help parser to vimdoc --- scripts/gen_help_html.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 2563f2f410..367ce60765 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -624,7 +624,7 @@ local function get_helptags(help_dir) return m end --- Use the help.so parser defined in the build, not whatever happens to be installed on the system. +-- Use the vimdoc parser defined in the build, not whatever happens to be installed on the system. local function ensure_runtimepath() if not vim.o.runtimepath:find('build/lib/nvim/') then vim.cmd[[set runtimepath^=./build/lib/nvim/]] @@ -643,8 +643,8 @@ local function parse_buf(fname) buf = fname vim.cmd('sbuffer '..tostring(fname)) -- Buffer number. end - -- vim.treesitter.require_language('help', './build/lib/nvim/parser/help.so') - local lang_tree = vim.treesitter.get_parser(buf, 'help') + -- vim.treesitter.require_language('help', './build/lib/nvim/parser/vimdoc.so') + local lang_tree = vim.treesitter.get_parser(buf) return lang_tree, buf end -- cgit From d4398f40214fb6175e2bff4c5823e0e6ca13fbda Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:31:04 +0200 Subject: ci: don't automatically enable -Werror on CI environments This catches downstream consumers of neovim off guard when using neovim in an esoteric environment not tested in our own CI. Closes https://github.com/neovim/neovim/issues/22932 --- scripts/genappimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh index dc46f4ce17..9944b5eb31 100755 --- a/scripts/genappimage.sh +++ b/scripts/genappimage.sh @@ -26,7 +26,7 @@ APP_DIR="$APP.AppDir" ######################################################################## # Build and install nvim into the AppImage -make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCI_BUILD=OFF -DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" +make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" make install ######################################################################## -- cgit From e23c6ebed7a6dcc878a64690bbd7252c18591d54 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 12 Apr 2023 09:50:48 +0800 Subject: ci(lintcommit): allow colon not followed by space in description (#23035) --- scripts/lintcommit.lua | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 92b07c4f73..f9a4631b7e 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -51,7 +51,7 @@ local function validate_commit(commit_message) return nil end - local commit_split = vim.split(commit_message, ":") + local commit_split = vim.split(commit_message, ":", {plain = true}) -- Return nil if the type is vim-patch since most of the normal rules don't -- apply. if commit_split[1] == "vim-patch" then @@ -63,13 +63,22 @@ local function validate_commit(commit_message) return [[Commit message is too long, a maximum of 80 characters is allowed.]] end + local before_colon = commit_split[1] - if vim.tbl_count(commit_split) < 2 then + local after_idx = 2 + if before_colon:match('^[^%(]*%([^%)]*$') then + -- Need to find the end of commit scope when commit scope contains colons. + while after_idx <= vim.tbl_count(commit_split) do + after_idx = after_idx + 1 + if commit_split[after_idx - 1]:find(')') then + break + end + end + end + if after_idx > vim.tbl_count(commit_split) then return [[Commit message does not include colons.]] end - - local before_colon = commit_split[1] - local after_colon = commit_split[#commit_split] + local after_colon = commit_split[after_idx] -- Check if commit introduces a breaking change. if vim.endswith(before_colon, "!") then @@ -77,7 +86,7 @@ local function validate_commit(commit_message) end -- Check if type is correct - local type = vim.split(before_colon, "%(")[1] + local type = vim.split(before_colon, "(", {plain = true})[1] local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'} if not vim.tbl_contains(allowed_types, type) then return string.format( @@ -234,7 +243,16 @@ function M._test() ['ci: Capitalized first word'] = false, ['ci: UPPER_CASE First Word'] = true, ['unknown: using unknown type'] = false, + ['feat: foo:bar'] = true, + ['feat(something): foo:bar'] = true, ['feat(:grep): read from pipe'] = true, + ['feat(:grep/:make): read from pipe'] = true, + ['feat(:grep): foo:bar'] = true, + ['feat(:grep/:make): foo:bar'] = true, + ['feat(:grep)'] = false, + ['feat(:grep/:make)'] = false, + ['feat(:grep'] = false, + ['feat(:grep/:make'] = false, ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false, } -- cgit From c8c7912a4deed6351e77b42d42742d675f5d45c6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 13 Apr 2023 19:07:42 +0800 Subject: build(vim-patch.sh): ignore test_behave.vim (#23062) --- scripts/vim-patch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 20e337afcb..385005a442 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -212,7 +212,7 @@ preprocess_patch() { 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove testdir/test_*.vim files - local na_src_testdir='balloon.*\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim' + local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove version.c #7555 -- cgit From 4d04feb6629cb049cb2a13ba35f0c8d3c6b67ff4 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 14 Apr 2023 10:39:57 +0200 Subject: feat(lua): vim.tbl_contains supports general tables and predicates (#23040) * feat(lua): vim.tbl_contains supports general tables and predicates Problem: `vim.tbl_contains` only works for list-like tables (integer keys without gaps) and primitive values (in particular, not for nested tables). Solution: Rename `vim.tbl_contains` to `vim.list_contains` and add new `vim.tbl_contains` that works for general tables and optionally allows `value` to be a predicate function that is checked for every key. --- scripts/gen_help_html.lua | 8 ++++---- scripts/lintcommit.lua | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 367ce60765..e2ab70eca2 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -491,7 +491,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) return '' -- Discard common "noise" lines. end -- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout. - local div = opt.old and root:child(0) and vim.tbl_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type()) + local div = opt.old and root:child(0) and vim.list_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type()) return string.format('%s%s', div and trim(text) or text, div and '' or '\n') elseif node_name == 'line_li' then local sib = root:prev_sibling() @@ -522,7 +522,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) s = fix_tab_after_conceal(s, node_text(root:next_sibling())) end return s - elseif vim.tbl_contains({'codespan', 'keycode'}, node_name) then + elseif vim.list_contains({'codespan', 'keycode'}, node_name) then if root:has_error() then return text end @@ -554,7 +554,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) if root:has_error() then return text end - local in_heading = vim.tbl_contains({'h1', 'h2', 'h3'}, parent) + local in_heading = vim.list_contains({'h1', 'h2', 'h3'}, parent) local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag' local tagname = node_text(root:child(1), false) if vim.tbl_count(stats.first_tags) < 2 then @@ -601,7 +601,7 @@ local function get_helpfiles(include) for f, type in vim.fs.dir(dir) do if (vim.endswith(f, '.txt') and type == 'file' - and (not include or vim.tbl_contains(include, f))) then + and (not include or vim.list_contains(include, f))) then local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p') table.insert(rv, fullpath) end diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index f9a4631b7e..7f3dffd22c 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -88,7 +88,7 @@ local function validate_commit(commit_message) -- Check if type is correct local type = vim.split(before_colon, "(", {plain = true})[1] local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'} - if not vim.tbl_contains(allowed_types, type) then + if not vim.list_contains(allowed_types, type) then return string.format( [[Invalid commit type "%s". Allowed types are: %s. -- cgit From 5465adcbab29b57d497d7260c6f85ddbf76c43ab Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 14 Apr 2023 12:41:50 +0100 Subject: fix(lint): use tbl_contains --- scripts/lintcommit.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 7f3dffd22c..f9a4631b7e 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -88,7 +88,7 @@ local function validate_commit(commit_message) -- Check if type is correct local type = vim.split(before_colon, "(", {plain = true})[1] local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'} - if not vim.list_contains(allowed_types, type) then + if not vim.tbl_contains(allowed_types, type) then return string.format( [[Invalid commit type "%s". Allowed types are: %s. -- cgit From ab1edecfb7c73c82c2d5886cb8e270b44aca7d01 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Mon, 17 Apr 2023 12:54:19 -0600 Subject: feat(lua): add vim.iter (#23029) vim.iter wraps a table or iterator function into an `Iter` object with methods such as `filter`, `map`, and `fold` which can be chained to produce iterator pipelines that do not create new tables at each step. --- scripts/gen_vimdoc.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 8860bdd5c6..52d03d9746 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -154,8 +154,10 @@ CONFIG = { 'fs.lua', 'secure.lua', 'version.lua', + 'iter.lua', ], 'files': [ + 'runtime/lua/vim/iter.lua', 'runtime/lua/vim/_editor.lua', 'runtime/lua/vim/shared.lua', 'runtime/lua/vim/loader.lua', @@ -185,6 +187,8 @@ CONFIG = { 'fn_helptag_fmt': lambda fstem, name: ( f'*vim.{name}()*' if fstem.lower() == '_editor' + else f'*{name}()*' + if fstem in ('iter.lua') else f'*{fstem}.{name}()*'), 'module_override': { # `shared` functions are exposed on the `vim` module. -- cgit From 240c41e1af556cd17329d5c46d26a3ca91be2db8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 18 Apr 2023 09:40:05 +0800 Subject: fix(genvimvim): add special abbreviations of :delete (#23172) Also don't highlight :def as vimCommand. --- scripts/genvimvim.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'scripts') diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 3e9e7077be..52bf46399d 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -37,6 +37,9 @@ local function cmd_kw(prev_cmd, cmd) while cmd:sub(shift, shift) == prev_cmd:sub(shift, shift) do shift = shift + 1 end + if cmd:sub(1, shift) == 'def' then + shift = shift + 1 + end if shift >= #cmd then return cmd else @@ -67,6 +70,20 @@ for _, cmd_desc in ipairs(ex_cmds.cmds) do if cmd:match('%w') and cmd ~= 'z' and not is_special_cased_cmd(cmd) then w(' ' .. cmd_kw(prev_cmd, cmd)) end + if cmd == 'delete' then + -- Add special abbreviations of :delete + w(' ' .. cmd_kw('d', 'dl')) + w(' ' .. cmd_kw('del', 'dell')) + w(' ' .. cmd_kw('dele', 'delel')) + w(' ' .. cmd_kw('delet', 'deletl')) + w(' ' .. cmd_kw('delete', 'deletel')) + w(' ' .. cmd_kw('d', 'dp')) + w(' ' .. cmd_kw('de', 'dep')) + w(' ' .. cmd_kw('del', 'delp')) + w(' ' .. cmd_kw('dele', 'delep')) + w(' ' .. cmd_kw('delet', 'deletp')) + w(' ' .. cmd_kw('delete', 'deletep')) + end prev_cmd = cmd end -- cgit From 1e60e8c0406f6b4b51c51abb5f53e25bd52fee5e Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 15 Apr 2023 12:23:45 +0200 Subject: refactor(build): use vendored versions of mpack and luabitop --- scripts/genvimvim.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 52bf46399d..9f67d7c417 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -144,7 +144,7 @@ end w('\n\nsyn case match') local vimfun_start = 'syn keyword vimFuncName contained ' w('\n\n' .. vimfun_start) -local funcs = mpack.unpack(io.open(funcs_file, 'rb'):read("*all")) +local funcs = mpack.decode(io.open(funcs_file, 'rb'):read("*all")) for _, name in ipairs(funcs) do if name then if lld.line_length > 850 then -- cgit From ffaf74f1477d3182ffc70bcc9913effc44c90ea7 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 20 Apr 2023 14:41:47 +0200 Subject: fix(build): distinguish vim.mpack from global require'mpack' problem: the api of vim.mpack is not compatible with a system provided mpack solution: don't require 'mpack' directly from the system path --- scripts/genvimvim.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 9f67d7c417..18279d160e 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -1,4 +1,4 @@ -local mpack = require('mpack') +local mpack = vim.mpack if arg[1] == '--help' then print('Usage: lua genvimvim.lua src/nvim runtime/syntax/vim/generated.vim') -- cgit From 702892270dec627acb3dd585495ee0950f690bde Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 21 Apr 2023 16:46:35 +0200 Subject: refactor(build): move the last generator from scripts/ to src/nvim/generators This one generates a runtime/ file instead of a source file. But otherwise it works the same like all other generators. It has the same prerequisites (shared and mpack modules, etc), and, importantly, it uses results from the source generators. The odd location makes it easy to overlook when refactoring generators (like I did last time, lol) --- scripts/genvimvim.lua | 158 -------------------------------------------------- 1 file changed, 158 deletions(-) delete mode 100644 scripts/genvimvim.lua (limited to 'scripts') diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua deleted file mode 100644 index 18279d160e..0000000000 --- a/scripts/genvimvim.lua +++ /dev/null @@ -1,158 +0,0 @@ -local mpack = vim.mpack - -if arg[1] == '--help' then - print('Usage: lua genvimvim.lua src/nvim runtime/syntax/vim/generated.vim') - os.exit(0) -end - -local nvimsrcdir = arg[1] -local syntax_file = arg[2] -local funcs_file = arg[3] - -package.path = nvimsrcdir .. '/?.lua;' .. package.path - -_G.vim = loadfile(nvimsrcdir..'/../../runtime/lua/vim/shared.lua')() - -local lld = {} -local syn_fd = io.open(syntax_file, 'w') -lld.line_length = 0 -local function w(s) - syn_fd:write(s) - if s:find('\n') then - lld.line_length = #(s:gsub('.*\n', '')) - else - lld.line_length = lld.line_length + #s - end -end - -local options = require('options') -local auevents = require('auevents') -local ex_cmds = require('ex_cmds') - -local function cmd_kw(prev_cmd, cmd) - if not prev_cmd then - return cmd:sub(1, 1) .. '[' .. cmd:sub(2) .. ']' - else - local shift = 1 - while cmd:sub(shift, shift) == prev_cmd:sub(shift, shift) do - shift = shift + 1 - end - if cmd:sub(1, shift) == 'def' then - shift = shift + 1 - end - if shift >= #cmd then - return cmd - else - return cmd:sub(1, shift) .. '[' .. cmd:sub(shift + 1) .. ']' - end - end -end - --- Exclude these from the vimCommand keyword list, they are handled specially --- in syntax/vim.vim (vimAugroupKey, vimAutoCmd, vimGlobal, vimSubst). #9327 -local function is_special_cased_cmd(cmd) - return (cmd == 'augroup' - or cmd == 'autocmd' - or cmd == 'doautocmd' - or cmd == 'doautoall' - or cmd == 'global' - or cmd == 'substitute') -end - -local vimcmd_start = 'syn keyword vimCommand contained ' -w(vimcmd_start) -local prev_cmd = nil -for _, cmd_desc in ipairs(ex_cmds.cmds) do - if lld.line_length > 850 then - w('\n' .. vimcmd_start) - end - local cmd = cmd_desc.command - if cmd:match('%w') and cmd ~= 'z' and not is_special_cased_cmd(cmd) then - w(' ' .. cmd_kw(prev_cmd, cmd)) - end - if cmd == 'delete' then - -- Add special abbreviations of :delete - w(' ' .. cmd_kw('d', 'dl')) - w(' ' .. cmd_kw('del', 'dell')) - w(' ' .. cmd_kw('dele', 'delel')) - w(' ' .. cmd_kw('delet', 'deletl')) - w(' ' .. cmd_kw('delete', 'deletel')) - w(' ' .. cmd_kw('d', 'dp')) - w(' ' .. cmd_kw('de', 'dep')) - w(' ' .. cmd_kw('del', 'delp')) - w(' ' .. cmd_kw('dele', 'delep')) - w(' ' .. cmd_kw('delet', 'deletp')) - w(' ' .. cmd_kw('delete', 'deletep')) - end - prev_cmd = cmd -end - -local vimopt_start = 'syn keyword vimOption contained ' -w('\n\n' .. vimopt_start) - -for _, opt_desc in ipairs(options.options) do - if not opt_desc.varname or opt_desc.varname:sub(1, 7) ~= 'p_force' then - if lld.line_length > 850 then - w('\n' .. vimopt_start) - end - w(' ' .. opt_desc.full_name) - if opt_desc.abbreviation then - w(' ' .. opt_desc.abbreviation) - end - if opt_desc.type == 'bool' then - w(' inv' .. opt_desc.full_name) - w(' no' .. opt_desc.full_name) - if opt_desc.abbreviation then - w(' inv' .. opt_desc.abbreviation) - w(' no' .. opt_desc.abbreviation) - end - end - end -end - -w('\n\nsyn case ignore') -local vimau_start = 'syn keyword vimAutoEvent contained ' -w('\n\n' .. vimau_start) - -for _, au in ipairs(auevents.events) do - if not auevents.nvim_specific[au] then - if lld.line_length > 850 then - w('\n' .. vimau_start) - end - w(' ' .. au) - end -end -for au, _ in pairs(auevents.aliases) do - if not auevents.nvim_specific[au] then - if lld.line_length > 850 then - w('\n' .. vimau_start) - end - w(' ' .. au) - end -end - -local nvimau_start = 'syn keyword nvimAutoEvent contained ' -w('\n\n' .. nvimau_start) - -for au, _ in vim.spairs(auevents.nvim_specific) do - if lld.line_length > 850 then - w('\n' .. nvimau_start) - end - w(' ' .. au) -end - -w('\n\nsyn case match') -local vimfun_start = 'syn keyword vimFuncName contained ' -w('\n\n' .. vimfun_start) -local funcs = mpack.decode(io.open(funcs_file, 'rb'):read("*all")) -for _, name in ipairs(funcs) do - if name then - if lld.line_length > 850 then - w('\n' .. vimfun_start) - end - w(' ' .. name) - end -end - -w('\n') -syn_fd:close() -- cgit From 732cb9e1e0a90f40d9189bffe009bbb7f8456eeb Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 22 Apr 2023 14:10:35 +0100 Subject: ci(lintcommit): use nvim -l --- scripts/lintcommit.lua | 70 +++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 29 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index f9a4631b7e..7193821afe 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -1,41 +1,30 @@ -- Usage: -- # verbose --- nvim -es +"lua require('scripts.lintcommit').main()" +-- nvim -l scripts/lintcommit.lua main -- -- # silent --- nvim -es +"lua require('scripts.lintcommit').main({trace=false})" +-- nvim -l scripts/lintcommit.lua main --notrace -- -- # self-test --- nvim -es +"lua require('scripts.lintcommit')._test()" +-- nvim -l scripts/lintcommit.lua _test +--- @type table local M = {} local _trace = false --- Print message -local function p(s) - vim.cmd('set verbose=1') - vim.api.nvim_echo({{s, ''}}, false, {}) - vim.cmd('set verbose=0') -end - -local function die() - p('') - vim.cmd("cquit 1") -end - -- Executes and returns the output of `cmd`, or nil on failure. -- -- Prints `cmd` if `trace` is enabled. local function run(cmd, or_die) if _trace then - p('run: '..vim.inspect(cmd)) + print('run: '..vim.inspect(cmd)) end local rv = vim.trim(vim.fn.system(cmd)) or '' if vim.v.shell_error ~= 0 then if or_die then - p(rv) - die() + print(rv) + os.exit(1) end return nil end @@ -150,6 +139,7 @@ local function validate_commit(commit_message) return nil end +--- @param opt? LintcommitOptions function M.main(opt) _trace = not opt or not not opt.trace @@ -160,17 +150,18 @@ function M.main(opt) ancestor = run({'git', 'merge-base', 'upstream/master', branch}) end local commits_str = run({'git', 'rev-list', ancestor..'..'..branch}, true) + assert(commits_str) - local commits = {} + local commits = {} --- @type string[] for substring in commits_str:gmatch("%S+") do - table.insert(commits, substring) + table.insert(commits, substring) end local failed = 0 for _, commit_id in ipairs(commits) do local msg = run({'git', 'show', '-s', '--format=%s' , commit_id}) if vim.v.shell_error ~= 0 then - p('Invalid commit-id: '..commit_id..'"') + print('Invalid commit-id: '..commit_id..'"') else local invalid_msg = validate_commit(msg) if invalid_msg then @@ -178,10 +169,10 @@ function M.main(opt) -- Some breathing room if failed == 1 then - p('\n') + print('\n') end - p(string.format([[ + print(string.format([[ Invalid commit message: "%s" Commit: %s %s @@ -194,13 +185,13 @@ Invalid commit message: "%s" end if failed > 0 then - p([[ + print([[ See also: https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages ]]) - die() -- Exit with error. + os.exit(1) else - p('') + print('') end end @@ -261,14 +252,35 @@ function M._test() local is_valid = (nil == validate_commit(message)) if is_valid ~= expected then failed = failed + 1 - p(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)) + print(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)) end end if failed > 0 then - die() -- Exit with error. + os.exit(1) end end -return M +--- @class LintcommitOptions +--- @field trace? boolean +local opt = {} + +for _, a in ipairs(arg) do + if vim.startswith(a, '--') then + local nm, val = a:sub(3), true + if vim.startswith(a, '--no') then + nm, val = a:sub(5), false + end + + if nm == 'trace' then + opt.trace = val + end + end +end + +for _, a in ipairs(arg) do + if M[a] then + M[a](opt) + end +end -- cgit From ccce200cde296aa65a720e028a5eacf715f29e4f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 22 Apr 2023 17:37:45 +0200 Subject: ci(lintcommit): fix error output Using print() alone doesn't work properly, toggling the verbose option is still required. --- scripts/lintcommit.lua | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 7193821afe..d2c8601c25 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -1,9 +1,9 @@ -- Usage: -- # verbose --- nvim -l scripts/lintcommit.lua main +-- nvim -l scripts/lintcommit.lua main --trace -- -- # silent --- nvim -l scripts/lintcommit.lua main --notrace +-- nvim -l scripts/lintcommit.lua main -- -- # self-test -- nvim -l scripts/lintcommit.lua _test @@ -13,17 +13,24 @@ local M = {} local _trace = false +-- Print message +local function p(s) + vim.cmd('set verbose=1') + vim.api.nvim_echo({{s, ''}}, false, {}) + vim.cmd('set verbose=0') +end + -- Executes and returns the output of `cmd`, or nil on failure. -- -- Prints `cmd` if `trace` is enabled. local function run(cmd, or_die) if _trace then - print('run: '..vim.inspect(cmd)) + p('run: '..vim.inspect(cmd)) end local rv = vim.trim(vim.fn.system(cmd)) or '' if vim.v.shell_error ~= 0 then if or_die then - print(rv) + p(rv) os.exit(1) end return nil @@ -161,7 +168,7 @@ function M.main(opt) for _, commit_id in ipairs(commits) do local msg = run({'git', 'show', '-s', '--format=%s' , commit_id}) if vim.v.shell_error ~= 0 then - print('Invalid commit-id: '..commit_id..'"') + p('Invalid commit-id: '..commit_id..'"') else local invalid_msg = validate_commit(msg) if invalid_msg then @@ -169,10 +176,10 @@ function M.main(opt) -- Some breathing room if failed == 1 then - print('\n') + p('\n') end - print(string.format([[ + p(string.format([[ Invalid commit message: "%s" Commit: %s %s @@ -185,13 +192,14 @@ Invalid commit message: "%s" end if failed > 0 then - print([[ + p([[ See also: https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages + ]]) os.exit(1) else - print('') + p('') end end @@ -252,7 +260,7 @@ function M._test() local is_valid = (nil == validate_commit(message)) if is_valid ~= expected then failed = failed + 1 - print(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)) + p(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)) end end -- cgit From 8994389845ae4ca5e6a797b8f957dea76320ff94 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 22 Apr 2023 22:58:14 +0200 Subject: ci: make all linux releases work with same glibc version --- scripts/genappimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh index 9944b5eb31..b0bf186f85 100755 --- a/scripts/genappimage.sh +++ b/scripts/genappimage.sh @@ -26,7 +26,7 @@ APP_DIR="$APP.AppDir" ######################################################################## # Build and install nvim into the AppImage -make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" +make CMAKE_BUILD_TYPE="${NVIM_BUILD_TYPE}" CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" make install ######################################################################## -- cgit From 1e73891d696a00b046ab19d245001424b174c931 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 24 Apr 2023 19:57:40 -0600 Subject: refactor(iter): move helper functions under vim.iter vim.iter is now both a function and a module (similar to vim.version). --- scripts/gen_vimdoc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 52d03d9746..d0686e92bc 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -188,7 +188,7 @@ CONFIG = { f'*vim.{name}()*' if fstem.lower() == '_editor' else f'*{name}()*' - if fstem in ('iter.lua') + if name[0].isupper() else f'*{fstem}.{name}()*'), 'module_override': { # `shared` functions are exposed on the `vim` module. @@ -202,6 +202,7 @@ CONFIG = { 'fs': 'vim.fs', 'secure': 'vim.secure', 'version': 'vim.version', + 'iter': 'vim.iter', }, 'append_only': [ 'shared.lua', -- cgit From 5e31f53457c1feceb57a55734508c37d07e255b4 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Mon, 1 May 2023 10:54:37 +0200 Subject: docs(lsp): remove vim.lsp.sync (#23416) The module is used internally and not intended to be used by plugins or users. --- scripts/gen_vimdoc.py | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index d0686e92bc..e9209e219e 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -222,7 +222,6 @@ CONFIG = { 'util.lua', 'log.lua', 'rpc.lua', - 'sync.lua', 'protocol.lua', ], 'files': [ -- cgit From bfb19a110d93ce5cb7c09fee2442651db182ca4b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 2 May 2023 09:45:44 +0200 Subject: docs(html): right-align inline tags (#23403) --- scripts/gen_help_html.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index e2ab70eca2..1bddd3aa8b 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -927,6 +927,9 @@ local function gen_css(fname) /* Tag pseudo-header common in :help docs. */ .help-tag-right { color: var(--tag-color); + margin-left: auto; + margin-right: 0; + float: right; } h1 .help-tag, h2 .help-tag, h3 .help-tag { font-size: smaller; -- cgit From 9909668111f521c7fc829ec8d8aa89beafff8777 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 3 May 2023 00:31:07 +0200 Subject: build: create a text file for specifying dependency information The cmake.deps build will read this file and set the left part of the text as the variable name and the right part as the variable value. The benefit of doing this is that it becomes much easier to parse which dependencies are required, as well as to bump dependencies with scripts/bump_deps.lua. Adjust bump_deps.lua script to work with this new format. --- scripts/bump_deps.lua | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'scripts') diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua index f980e800cf..6a049d136a 100755 --- a/scripts/bump_deps.lua +++ b/scripts/bump_deps.lua @@ -63,6 +63,7 @@ local function rm_file_if_present(path_to_file) end local nvim_src_dir = vim.fn.getcwd() +local deps_file = nvim_src_dir .. '/' .. 'cmake.deps/deps.txt' local temp_dir = nvim_src_dir .. '/tmp' run({ 'mkdir', '-p', temp_dir }) @@ -127,26 +128,24 @@ end local function write_cmakelists_line(symbol, kind, value) require_executable('sed') - local cmakelists_path = nvim_src_dir .. '/' .. 'cmake.deps/CMakeLists.txt' run_die({ 'sed', '-i', '-e', - 's/set(' + 's/' .. symbol .. '_' .. kind .. '.*$' - .. '/set(' + .. '/' .. symbol .. '_' .. kind .. ' ' .. value - .. ')' .. '/', - cmakelists_path, - }, 'Failed to write ' .. cmakelists_path) + deps_file, + }, 'Failed to write ' .. deps_file) end local function explicit_create_branch(dep) @@ -181,8 +180,6 @@ local function update_cmakelists(dependency, archive, comment) verify_branch(dependency.name) - local changed_file = nvim_src_dir .. '/' .. 'cmake.deps/CMakeLists.txt' - p('Updating ' .. dependency.name .. ' to ' .. archive.url .. '\n') write_cmakelists_line(dependency.symbol, 'URL', archive.url:gsub('/', '\\/')) write_cmakelists_line(dependency.symbol, 'SHA256', archive.sha) @@ -190,7 +187,7 @@ local function update_cmakelists(dependency, archive, comment) { 'git', 'commit', - changed_file, + deps_file, '-m', commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment, }, @@ -201,10 +198,9 @@ end local function verify_cmakelists_committed() require_executable('git') - local cmakelists_path = nvim_src_dir .. '/' .. 'cmake.deps/CMakeLists.txt' run_die( - { 'git', 'diff', '--quiet', 'HEAD', '--', cmakelists_path }, - cmakelists_path .. ' has uncommitted changes' + { 'git', 'diff', '--quiet', 'HEAD', '--', deps_file }, + deps_file .. ' has uncommitted changes' ) end -- cgit From 84378c4dd56db9846b70a333530505a8048bd26e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 9 May 2023 09:18:21 +0800 Subject: test(old): remove python2 tests (#23547) Because python2 provider is no longer supported. --- scripts/vim-patch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 385005a442..df0af72fdb 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -212,7 +212,7 @@ preprocess_patch() { 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove testdir/test_*.vim files - local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim' + local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove version.c #7555 -- cgit From ed8c44f76762061e30cb8056483f55d38802eaef Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 13 May 2023 11:44:56 +0200 Subject: ci(deps): update bump_deps script (#23604) * consistent capitalization (lower-case) of dependency names * add bundled tree-sitter parsers --- scripts/bump_deps.lua | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua index 6a049d136a..076ad374cf 100755 --- a/scripts/bump_deps.lua +++ b/scripts/bump_deps.lua @@ -69,7 +69,7 @@ run({ 'mkdir', '-p', temp_dir }) local function get_dependency(dependency_name) local dependency_table = { - ['LuaJIT'] = { + ['luajit'] = { repo = 'LuaJIT/LuaJIT', symbol = 'LUAJIT', }, @@ -77,7 +77,7 @@ local function get_dependency(dependency_name) repo = 'libuv/libuv', symbol = 'LIBUV', }, - ['Luv'] = { + ['luv'] = { repo = 'luvit/luv', symbol = 'LUV', }, @@ -85,6 +85,26 @@ local function get_dependency(dependency_name) repo = 'tree-sitter/tree-sitter', symbol = 'TREESITTER', }, + ['tree-sitter-c'] = { + repo = 'tree-sitter/tree-sitter-c', + symbol = 'TREESITTER_C', + }, + ['tree-sitter-lua'] = { + repo = 'MunifTanjim/tree-sitter-lua', + symbol = 'TREESITTER_LUA', + }, + ['tree-sitter-vim'] = { + repo = 'neovim/tree-sitter-vim', + symbol = 'TREESITTER_VIM', + }, + ['tree-sitter-vimdoc'] = { + repo = 'neovim/tree-sitter-vimdoc', + symbol = 'TREESITTER_VIMDOC', + }, + ['tree-sitter-query'] = { + repo = 'nvim-treesitter/tree-sitter-query', + symbol = 'TREESITTER_QUERY', + }, } local dependency = dependency_table[dependency_name] if dependency == nil then -- cgit From d3a22ff242526e36e6e5b76fdc70656dd3d7ca31 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 26 May 2023 22:22:56 +0800 Subject: build(vim-patch.sh): use bundled uncrustify (#23770) --- scripts/vim-patch.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index df0af72fdb..7af055640b 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -297,7 +297,7 @@ uncrustify_patch() { exit 1 } - local patch_path=$NVIM_SOURCE_DIR/build/vim_patch + local patch_path="$NVIM_SOURCE_DIR"/build/vim_patch rm -rf "$patch_path" mkdir -p "$patch_path"/{a,b} @@ -314,7 +314,7 @@ uncrustify_patch() { # than once. This is obviously a bug that needs to be fixed on uncrustify's # end, but in the meantime this workaround is sufficient. for _ in {1..2}; do - uncrustify -c "$NVIM_SOURCE_DIR"/src/uncrustify.cfg -q --replace --no-backup "$patch_path"/{a,b}/src/*.[ch] + "$NVIM_SOURCE_DIR"/build/usr/bin/uncrustify -c "$NVIM_SOURCE_DIR"/src/uncrustify.cfg -q --replace --no-backup "$patch_path"/{a,b}/src/*.[ch] done (cd "$patch_path" && (git --no-pager diff --no-index --no-prefix --patch --unified=5 --color=never a/ b/ || true)) @@ -328,7 +328,7 @@ get_vimpatch() { msg_ok "Found Vim revision '${vim_commit}'." local patch_content - if check_executable uncrustify; then + if check_executable "$NVIM_SOURCE_DIR"/build/usr/bin/uncrustify; then patch_content="$(uncrustify_patch "${vim_commit}")" else patch_content="$(git --no-pager show --unified=5 --color=never -1 --pretty=medium "${vim_commit}")" -- cgit From 3913ebbfcde7d327dd6f1d85e30ce114a9e8193e Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 30 May 2023 17:32:38 -0700 Subject: docs(html): algolia docsearch #23839 Need to manually include this in the generated docs html because it doesn't use the website's (jekyll) layout template. Maintenance notes: https://github.com/neovim/neovim.github.io/#maintenance Related: https://github.com/neovim/neovim.github.io/commit/ce9aef12eb1c98135965e3a9c5c792bf9e506a76 --- scripts/gen_help_html.lua | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 1bddd3aa8b..96289c45ec 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -696,6 +696,11 @@ local function gen_one(fname, to_fname, old, commit) + + + + + %s - Neovim docs @@ -766,12 +771,13 @@ local function gen_one(fname, to_fname, old, commit) main = ([[
@@ -825,6 +831,18 @@ local function gen_one(fname, to_fname, old, commit) parse_errors: %d %s | noise_lines: %d
+ + + + + ]]):format( os.date('%Y-%m-%d %H:%M'), commit, commit:sub(1, 7), #stats.parse_errors, bug_link, -- cgit From 36fd2fcaae757e8ac64c8ff7a66e4f480a075dcf Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 2 Jun 2023 02:45:23 -0700 Subject: docs(html): define anchors for search engine #23879 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Selecting a search result from the Algolia Docsearch widget does not navigate to a page anchor. The docs HTML provides `` anchors _near_ the `

`/`

`/… headings, but Algolia Docsearch expects the anchors to be _defined on_ the headings. That's also "semantically" nicer. https://docsearch.algolia.com/docs/manage-your-crawls/ Solution: Set `id` on the heading element instead of placing `` nearby. related: 3913ebbfcde7 #23839 --- scripts/gen_help_html.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 96289c45ec..7bc48a0662 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -461,6 +461,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', '')) -- Use the first *tag* node as the heading anchor, if any. local tagnode = first(root, 'tag') + -- Use the *tag* as the heading anchor id, if possible. local tagname = tagnode and url_encode(node_text(tagnode:child(1), false)) or to_heading_tag(hname) if node_name == 'h1' or #headings == 0 then table.insert(headings, { name = hname, subheadings = {}, tag = tagname }) @@ -468,9 +469,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, tag = tagname }) end local el = node_name == 'h1' and 'h2' or 'h3' - -- If we are re-using the *tag*, this heading anchor is redundant. - local a = tagnode and '' or (''):format(tagname) - return ('%s<%s class="help-heading">%s\n'):format(a, el, text, el) + return ('<%s id="%s" class="help-heading">%s\n'):format(el, tagname, text, el) elseif node_name == 'column_heading' or node_name == 'column_name' then if root:has_error() then return text @@ -563,12 +562,14 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) return '' end local el = in_heading and 'span' or 'code' - local s = ('%s<%s class="%s">%s'):format(ws(), url_encode(tagname), el, cssclass, trimmed, el) + local s = ('%s<%s id="%s" class="%s">%s'):format(ws(), el, url_encode(tagname), cssclass, trimmed, el) if opt.old then s = fix_tab_after_conceal(s, node_text(root:next_sibling())) end if in_heading and prev ~= 'tag' then + -- Don't set "id", let the heading use the tag as its "id" (used by search engines). + s = ('%s<%s class="%s">%s'):format(ws(), el, cssclass, trimmed, el) -- Start the container for tags in a heading. -- This makes "justify-content:space-between" right-align the tags. --

foo bartag1 tag2

@@ -643,7 +644,7 @@ local function parse_buf(fname) buf = fname vim.cmd('sbuffer '..tostring(fname)) -- Buffer number. end - -- vim.treesitter.require_language('help', './build/lib/nvim/parser/vimdoc.so') + -- vim.treesitter.language.add('vimdoc', { path = vim.fn.expand('~/Library/Caches/tree-sitter/lib/vimdoc.so') }) local lang_tree = vim.treesitter.get_parser(buf) return lang_tree, buf end @@ -784,7 +785,7 @@ local function gen_one(fname, to_fname, old, commit)
-

%s

+

%s

Nvim :help pages, generated @@ -795,7 +796,7 @@ local function gen_one(fname, to_fname, old, commit)


%s
- ]]):format(logo_svg, stats.first_tags[1] or '', stats.first_tags[2] or '', title, vim.fs.basename(fname), main) + ]]):format(logo_svg, stats.first_tags[2] or '', stats.first_tags[1] or '', title, vim.fs.basename(fname), main) local toc = [[
-- cgit From c48b1421af28d0317c807bca00c7e2fff97d9ad0 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 6 Jun 2023 08:23:20 -0700 Subject: refactor!: rename "playground" => "dev" #23919 Problem: "playground" is new jargon that overlaps with existing concepts: "dev" (`:help dev`) and "view" (also "scratch" `:help scratch-buffer`) . Solution: We should consistently use "dev" as the namespace for where "developer tools" live. For purposes of a "throwaway sandbox object", we can use the name "view". - Rename `TSPlayground` => `TSView` - Rename `playground.lua` => `dev.lua` --- scripts/gen_vimdoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index e9209e219e..b40f8526ea 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -275,7 +275,7 @@ CONFIG = { 'query.lua', 'highlighter.lua', 'languagetree.lua', - 'playground.lua', + 'dev.lua', ], 'files': [ 'runtime/lua/vim/treesitter.lua', -- cgit From 5f4895200a49d92e636dea9c5474ab5b0882384d Mon Sep 17 00:00:00 2001 From: max397574 <81827001+max397574@users.noreply.github.com> Date: Wed, 7 Jun 2023 13:32:39 +0200 Subject: feat(scripts): add lsp_types.lua (#23750) --- scripts/lsp_types.lua | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 scripts/lsp_types.lua (limited to 'scripts') diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua new file mode 100644 index 0000000000..8f3ed811d6 --- /dev/null +++ b/scripts/lsp_types.lua @@ -0,0 +1,207 @@ +--[[ +Generates lua-ls annotations for lsp +USAGE: +nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua +--]] + +local M = {} + +local function tofile(fname, text) + local f = io.open(fname, 'w') + if not f then + error(('failed to write: %s'):format(f)) + else + f:write(text) + f:close() + end +end + +function M.gen(opt) + if vim.loop.fs_stat('./lsp.json') then + vim.fn.delete('./lsp.json') + end + vim.fn.system({ + 'curl', + 'https://raw.githubusercontent.com/microsoft/lsprotocol/main/generator/lsp.json', + '-o', + './lsp.json', + }) + local protocol = vim.fn.json_decode(vim.fn.readfile('./lsp.json')) + vim.fn.delete('./lsp.json') + local output_file = opt[1] + protocol = protocol or {} + local output = { + '--[[', + 'This file is autogenerated from scripts/lsp_types.lua', + 'Regenerate:', + [=[nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua]=], + '--]]', + '', + '---@alias lsp.null nil', + '---@alias uinteger integer', + '---@alias lsp.decimal number', + '---@alias lsp.DocumentUri string', + '---@alias lsp.URI string', + '---@alias lsp.LSPObject table', + '---@alias lsp.LSPArray lsp.LSPAny[]', + '---@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil', + '', + } + + local anonymous_num = 0 + + local anonym_classes = {} + + local simple_types = { + 'string', + 'boolean', + 'integer', + 'uinteger', + 'decimal', + } + + local function parse_type(type) + if type.kind == 'reference' or type.kind == 'base' then + if vim.tbl_contains(simple_types, type.name) then + return type.name + end + return 'lsp.' .. type.name + elseif type.kind == 'array' then + return parse_type(type.element) .. '[]' + elseif type.kind == 'or' then + local val = '' + for _, item in ipairs(type.items) do + val = val .. parse_type(item) .. '|' + end + val = val:sub(0, -2) + return val + elseif type.kind == 'stringLiteral' then + return '"' .. type.value .. '"' + elseif type.kind == 'map' then + return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>' + elseif type.kind == 'literal' then + -- can I use ---@param disabled? {reason: string} + -- use | to continue the inline class to be able to add docs + -- https://github.com/LuaLS/lua-language-server/issues/2128 + anonymous_num = anonymous_num + 1 + local anonym = { '---@class anonym' .. anonymous_num } + for _, field in ipairs(type.value.properties) do + if field.documentation then + field.documentation = field.documentation:gsub('\n', '\n---') + anonym[#anonym + 1] = '---' .. field.documentation + end + anonym[#anonym + 1] = '---@field ' + .. field.name + .. (field.optional and '?' or '') + .. ' ' + .. parse_type(field.type) + end + anonym[#anonym + 1] = '' + for _, line in ipairs(anonym) do + anonym_classes[#anonym_classes + 1] = line + end + return 'anonym' .. anonymous_num + elseif type.kind == 'tuple' then + local tuple = '{ ' + for i, value in ipairs(type.items) do + tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value) .. ', ' + end + -- remove , at the end + tuple = tuple:sub(0, -3) + return tuple .. ' }' + end + vim.print(type) + return '' + end + + for _, structure in ipairs(protocol.structures) do + if structure.documentation then + structure.documentation = structure.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. structure.documentation + end + if structure.extends then + local class_string = '---@class lsp.' + .. structure.name + .. ': ' + .. parse_type(structure.extends[1]) + for _, mixin in ipairs(structure.mixins or {}) do + class_string = class_string .. ', ' .. parse_type(mixin) + end + output[#output + 1] = class_string + else + output[#output + 1] = '---@class lsp.' .. structure.name + end + for _, field in ipairs(structure.properties or {}) do + if field.documentation then + field.documentation = field.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. field.documentation + end + output[#output + 1] = '---@field ' + .. field.name + .. (field.optional and '?' or '') + .. ' ' + .. parse_type(field.type) + end + output[#output + 1] = '' + end + + for _, enum in ipairs(protocol.enumerations) do + if enum.documentation then + enum.documentation = enum.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. enum.documentation + end + local enum_type = '---@alias lsp.' .. enum.name + for _, value in ipairs(enum.values) do + enum_type = enum_type + .. '\n---| ' + .. (type(value.value) == 'string' and '"' .. value.value .. '"' or value.value) + .. ' # ' + .. value.name + end + output[#output + 1] = enum_type + output[#output + 1] = '' + end + + for _, alias in ipairs(protocol.typeAliases) do + if alias.documentation then + alias.documentation = alias.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. alias.documentation + end + if alias.type.kind == 'or' then + local alias_type = '---@alias lsp.' .. alias.name .. ' ' + for _, item in ipairs(alias.type.items) do + alias_type = alias_type .. parse_type(item) .. '|' + end + alias_type = alias_type:sub(0, -2) + output[#output + 1] = alias_type + else + output[#output + 1] = '---@alias lsp.' .. alias.name .. ' ' .. parse_type(alias.type) + end + output[#output + 1] = '' + end + + for _, line in ipairs(anonym_classes) do + output[#output + 1] = line + end + + tofile(output_file, table.concat(output, '\n')) +end + +local opt = {} + +local index = 1 +for _, a in ipairs(arg) do + if vim.startswith(a, '--') then + local name = a:sub(3) + opt[index] = name + index = index + 1 + end +end + +for _, a in ipairs(arg) do + if M[a] then + M[a](opt) + end +end + +return M -- cgit From c0952e62fd0ee16a3275bb69e0de04c836b39015 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 7 Jun 2023 13:52:23 +0100 Subject: feat(lua): add `vim.system()` feat(lua): add vim.system() Problem: Handling system commands in Lua is tedious and error-prone: - vim.fn.jobstart() is vimscript and comes with all limitations attached to typval. - vim.loop.spawn is too low level Solution: Add vim.system(). Partly inspired by Python's subprocess module Does not expose any libuv objects. --- scripts/lua2dox.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 014934aebe..bb5214f091 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -340,6 +340,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') + or vim.startswith(line, '---@overload') or vim.startswith(line, '---@type') then -- Ignore LSP directives outStream:writeln('// gg:"' .. line .. '"') -- cgit From 643546b82b4bc0c29ca869f81af868a019723d83 Mon Sep 17 00:00:00 2001 From: Chinmay Dalal Date: Sun, 11 Jun 2023 15:23:37 +0530 Subject: feat(lsp): add handlers for inlay hints (#23736) initial support; public API left for a follow-up PR --- scripts/gen_vimdoc.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index b40f8526ea..2d4c8b2234 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -223,6 +223,7 @@ CONFIG = { 'log.lua', 'rpc.lua', 'protocol.lua', + 'inlay_hint.lua' ], 'files': [ 'runtime/lua/vim/lsp', -- cgit From 72a6643b1380cdf6f1153d70eeaffb90bdca30d6 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 19 Jun 2023 08:40:33 -0700 Subject: docs #24061 - nvim requires rpc responses in reverse order. https://github.com/neovim/neovim/issues/19932 - NVIM_APPNAME: UIs normally should NOT set this. ref #23520 fix #24050 fix #23660 fix #23353 fix #23337 fix #22213 fix #19161 fix #18088 fix #20693 --- scripts/gen_help_html.lua | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 7bc48a0662..6cdf028f5c 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -62,7 +62,6 @@ local exclude_invalid = { ["'string'"] = "eval.txt", Query = 'treesitter.txt', ['eq?'] = 'treesitter.txt', - ['lsp-request'] = 'lsp.txt', matchit = 'vim_diff.txt', ['matchit.txt'] = 'help.txt', ["set!"] = "treesitter.txt", @@ -70,7 +69,6 @@ local exclude_invalid = { ['v:_null_dict'] = 'builtin.txt', ['v:_null_list'] = 'builtin.txt', ['v:_null_string'] = 'builtin.txt', - ['vim.lsp.buf_request()'] = 'lsp.txt', ['vim.lsp.util.get_progress_messages()'] = 'lsp.txt', } -- cgit From ca5de9306c00d07cce1daef1f0038c937098bc66 Mon Sep 17 00:00:00 2001 From: Chinmay Dalal Date: Tue, 20 Jun 2023 11:36:54 +0530 Subject: feat(lsp): inlay hints #23984 Add automatic refresh and a public interface on top of #23736 * add on_reload, on_detach handlers in `enable()` buf_attach, and LspDetach autocommand in case of manual detach * unify `__buffers` and `hint_cache_by_buf` * use callback bufnr in `on_lines` callback, bufstate: remove __index override * move user-facing functions into vim.lsp.buf, unify enable/disable/toggle Closes #18086 --- scripts/gen_vimdoc.py | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 2d4c8b2234..b40f8526ea 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -223,7 +223,6 @@ CONFIG = { 'log.lua', 'rpc.lua', 'protocol.lua', - 'inlay_hint.lua' ], 'files': [ 'runtime/lua/vim/lsp', -- cgit From 5c73b1bb4c876d207e868bffc9f741c2a60d4aaf Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 20 Jun 2023 09:49:49 +0200 Subject: docs: lsp, vim_diff - quickstart - mark lsp.txt as `new_layout` - remove lsp-handler documentation for notifications: they don't have handlers because they don't have server responses. --- scripts/gen_help_html.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 6cdf028f5c..43c0e135d4 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -43,6 +43,7 @@ local M = {} -- All other files are "legacy" files which require fixed-width layout. local new_layout = { ['api.txt'] = true, + ['lsp.txt'] = true, ['channel.txt'] = true, ['deprecated.txt'] = true, ['develop.txt'] = true, -- cgit From 81d8fce8f9e1b369e64d57b018221e378841fb88 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 22 Jun 2023 09:00:49 +0200 Subject: feat(gen_help_html): non-default vimdoc.so parser Callers can specify a non-default vimdoc.so file path. --- scripts/gen_help_html.lua | 105 +++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 47 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 43c0e135d4..c03dc21d85 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -144,11 +144,11 @@ local function trim(s, dir) return vim.fn.trim(s, '\r\t\n ', dir or 0) end --- Remove common punctuation from URLs. --- --- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc --- --- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input. +--- Removes common punctuation from URLs. +--- +--- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc +--- +--- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input. local function fix_url(url) local removed_chars = '' local fixed_url = url @@ -162,7 +162,7 @@ local function fix_url(url) return fixed_url, removed_chars end --- Checks if a given line is a "noise" line that doesn't look good in HTML form. +--- Checks if a given line is a "noise" line that doesn't look good in HTML form. local function is_noise(line, noise_lines) if ( -- First line is always noise. @@ -187,7 +187,7 @@ local function is_noise(line, noise_lines) return false end --- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content. +--- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content. local function get_bug_url_vimdoc(fname, to_fname, sample_text) local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname)) local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+' @@ -200,7 +200,7 @@ local function get_bug_url_vimdoc(fname, to_fname, sample_text) return bug_url end --- Creates a github issue URL at neovim/neovim with prefilled content. +--- Creates a github issue URL at neovim/neovim with prefilled content. local function get_bug_url_nvim(fname, to_fname, sample_text, token_name) local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname)) local bug_url = ('https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+' @@ -215,7 +215,7 @@ local function get_bug_url_nvim(fname, to_fname, sample_text, token_name) return bug_url end --- Gets a "foo.html" name from a "foo.txt" helpfile name. +--- Gets a "foo.html" name from a "foo.txt" helpfile name. local function get_helppage(f) if not f then return nil @@ -230,9 +230,9 @@ local function get_helppage(f) return (f:gsub('%.txt$', '.html')) end --- Counts leading spaces (tab=8) to decide the indent size of multiline text. --- --- Blank lines (empty or whitespace-only) are ignored. +--- Counts leading spaces (tab=8) to decide the indent size of multiline text. +--- +--- Blank lines (empty or whitespace-only) are ignored. local function get_indent(s) local min_indent = nil for line in vim.gsplit(s, '\n') do @@ -244,7 +244,7 @@ local function get_indent(s) return min_indent or 0 end --- Removes the common indent level, after expanding tabs to 8 spaces. +--- Removes the common indent level, after expanding tabs to 8 spaces. local function trim_indent(s) local indent_size = get_indent(s) local trimmed = '' @@ -255,7 +255,7 @@ local function trim_indent(s) return trimmed:sub(1, -2) end --- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string. +--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string. local function getbuflinestr(node, bufnr, offset) local line1, _, line2, _ = node:range() line1 = line1 - offset @@ -264,8 +264,8 @@ local function getbuflinestr(node, bufnr, offset) return table.concat(lines, '\n') end --- Gets the whitespace just before `node` from the raw buffer text. --- Needed for preformatted `old` lines. +--- Gets the whitespace just before `node` from the raw buffer text. +--- Needed for preformatted `old` lines. local function getws(node, bufnr) local line1, c1, line2, _ = node:range() local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1] @@ -282,7 +282,7 @@ local function get_tagname(node, bufnr) return helppage, tag end --- Returns true if the given invalid tagname is a false positive. +--- Returns true if the given invalid tagname is a false positive. local function ignore_invalid(s) return not not ( exclude_invalid[s] @@ -314,7 +314,7 @@ local function has_ancestor(node, ancestor_name) return false end --- Gets the first matching child node matching `name`. +--- Gets the first matching child node matching `name`. local function first(node, name) for c, _ in node:iter_children() do if c:named() and c:type() == name then @@ -336,7 +336,7 @@ local function validate_link(node, bufnr, fname) return helppage, tagname, ignored end --- TODO: port the logic from scripts/check_urls.vim +--- TODO: port the logic from scripts/check_urls.vim local function validate_url(text, fname) local ignored = false if vim.fs.basename(fname) == 'pi_netrw.txt' then @@ -347,7 +347,7 @@ local function validate_url(text, fname) return ignored end --- Traverses the tree at `root` and checks that |tag| links point to valid helptags. +--- Traverses the tree at `root` and checks that |tag| links point to valid helptags. local function visit_validate(root, level, lang_tree, opt, stats) level = level or 0 local node_name = (root.named and root:named()) and root:type() or nil @@ -609,7 +609,7 @@ local function get_helpfiles(include) return rv end --- Populates the helptags map. +--- Populates the helptags map. local function get_helptags(help_dir) local m = {} -- Load a random help file to convince taglist() to do its job. @@ -624,17 +624,19 @@ local function get_helptags(help_dir) return m end --- Use the vimdoc parser defined in the build, not whatever happens to be installed on the system. +--- Use the vimdoc parser defined in the build, not whatever happens to be installed on the system. local function ensure_runtimepath() if not vim.o.runtimepath:find('build/lib/nvim/') then vim.cmd[[set runtimepath^=./build/lib/nvim/]] end end --- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents. --- --- @returns lang_tree, bufnr -local function parse_buf(fname) +--- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents. +--- +--- @param fname string help file to parse +--- @param parser_path string? path to non-default vimdoc.so +--- @returns lang_tree, bufnr +local function parse_buf(fname, parser_path) local buf if type(fname) == 'string' then vim.cmd('split '..vim.fn.fnameescape(fname)) -- Filename. @@ -643,21 +645,25 @@ local function parse_buf(fname) buf = fname vim.cmd('sbuffer '..tostring(fname)) -- Buffer number. end - -- vim.treesitter.language.add('vimdoc', { path = vim.fn.expand('~/Library/Caches/tree-sitter/lib/vimdoc.so') }) + if parser_path then + vim.treesitter.language.add('vimdoc', { path = parser_path }) + end local lang_tree = vim.treesitter.get_parser(buf) return lang_tree, buf end --- Validates one :help file `fname`: --- - checks that |tag| links point to valid helptags. --- - recursively counts parse errors ("ERROR" nodes) --- --- @returns { invalid_links: number, parse_errors: number } -local function validate_one(fname) +--- Validates one :help file `fname`: +--- - checks that |tag| links point to valid helptags. +--- - recursively counts parse errors ("ERROR" nodes) +--- +--- @param fname string help file to validate +--- @param parser_path string? path to non-default vimdoc.so +--- @returns { invalid_links: number, parse_errors: number } +local function validate_one(fname, parser_path) local stats = { parse_errors = {}, } - local lang_tree, buf = parse_buf(fname) + local lang_tree, buf = parse_buf(fname, parser_path) for _, tree in ipairs(lang_tree:trees()) do visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname, }, stats) end @@ -666,20 +672,21 @@ local function validate_one(fname) return stats end --- Generates HTML from one :help file `fname` and writes the result to `to_fname`. --- --- @param fname Source :help file --- @param to_fname Destination .html file --- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace) --- --- @returns html, stats -local function gen_one(fname, to_fname, old, commit) +--- Generates HTML from one :help file `fname` and writes the result to `to_fname`. +--- +--- @param fname string Source :help file +--- @param to_fname string Destination .html file +--- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace) +--- @param parser_path string? path to non-default vimdoc.so +--- +--- @returns html, stats +local function gen_one(fname, to_fname, old, commit, parser_path) local stats = { noise_lines = {}, parse_errors = {}, first_tags = {}, -- Track the first few tags in doc. } - local lang_tree, buf = parse_buf(fname) + local lang_tree, buf = parse_buf(fname, parser_path) local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3. local title = to_titlecase(basename_noext(fname)) @@ -1059,18 +1066,20 @@ end --- @param include table|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'} --- --- @returns info dict -function M.gen(help_dir, to_dir, include, commit) +function M.gen(help_dir, to_dir, include, commit, parser_path) vim.validate{ help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'}, to_dir={to_dir, 's'}, include={include, 't', true}, commit={commit, 's', true}, + parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'}, } local err_count = 0 ensure_runtimepath() tagmap = get_helptags(help_dir) helpfiles = get_helpfiles(include) + parser_path = parser_path and vim.fn.expand(parser_path) or nil print(('output dir: %s'):format(to_dir)) vim.fn.mkdir(to_dir, 'p') @@ -1079,7 +1088,7 @@ function M.gen(help_dir, to_dir, include, commit) for _, f in ipairs(helpfiles) do local helpfile = vim.fs.basename(f) local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile)) - local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?') + local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?', parser_path) tofile(to_fname, html) print(('generated (%-4s errors): %-15s => %s'):format(#stats.parse_errors, helpfile, vim.fs.basename(to_fname))) err_count = err_count + #stats.parse_errors @@ -1102,19 +1111,21 @@ end -- This is 10x faster than gen(), for use in CI. -- -- @returns results dict -function M.validate(help_dir, include) +function M.validate(help_dir, include, parser_path) vim.validate{ help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'}, include={include, 't', true}, + parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'}, } local err_count = 0 ensure_runtimepath() tagmap = get_helptags(help_dir) helpfiles = get_helpfiles(include) + parser_path = parser_path and vim.fn.expand(parser_path) or nil for _, f in ipairs(helpfiles) do local helpfile = vim.fs.basename(f) - local rv = validate_one(f) + local rv = validate_one(f, parser_path) print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile)) err_count = err_count + #rv.parse_errors end -- cgit From b0cf9c5feeae789d832256569488a3b98d265d2c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 22 Jun 2023 08:42:10 +0200 Subject: feat(gen_help_html): ignore pi_netrw.txt errors IDGAF about netrw --- scripts/gen_help_html.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index c03dc21d85..268fd12f6f 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -89,6 +89,11 @@ local exclude_invalid_urls = { ["http://www.jclark.com/"] = "quickfix.txt", } +-- Deprecated, brain-damaged files that I don't care about. +local ignore_errors = { + ['pi_netrw.txt'] = true, +} + local function tofile(fname, text) local f = io.open(fname, 'w') if not f then @@ -293,7 +298,10 @@ local function ignore_invalid(s) ) end -local function ignore_parse_error(s) +local function ignore_parse_error(fname, s) + if ignore_errors[vim.fs.basename(fname)] then + return true + end return ( -- Ignore parse errors for unclosed tag. -- This is common in vimdocs and is treated as plaintext by :help. @@ -339,7 +347,7 @@ end --- TODO: port the logic from scripts/check_urls.vim local function validate_url(text, fname) local ignored = false - if vim.fs.basename(fname) == 'pi_netrw.txt' then + if ignore_errors[vim.fs.basename(fname)] then ignored = true elseif text:find('http%:') and not exclude_invalid_urls[text] then invalid_urls[text] = vim.fs.basename(fname) @@ -366,7 +374,7 @@ local function visit_validate(root, level, lang_tree, opt, stats) end if node_name == 'ERROR' then - if ignore_parse_error(text) then + if ignore_parse_error(opt.fname, text) then return end -- Store the raw text to give context to the error report. @@ -579,7 +587,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) end return s elseif node_name == 'ERROR' then - if ignore_parse_error(trimmed) then + if ignore_parse_error(opt.fname, trimmed) then return text end -- cgit From 4e6356559c8cd44dbcaa765d1f39e176064526ec Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 22 Jun 2023 03:44:51 -0700 Subject: test: spellcheck :help (vimdoc) files #24109 Enforce consistent terminology (defined in `gen_help_html.lua:spell_dict`) for common misspellings. This does not spellcheck English in general (perhaps a future TODO, though it may be noisy). --- scripts/gen_help_html.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 268fd12f6f..b369e0db5e 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -70,7 +70,6 @@ local exclude_invalid = { ['v:_null_dict'] = 'builtin.txt', ['v:_null_list'] = 'builtin.txt', ['v:_null_string'] = 'builtin.txt', - ['vim.lsp.util.get_progress_messages()'] = 'lsp.txt', } -- False-positive "invalid URLs". @@ -359,6 +358,8 @@ end local function visit_validate(root, level, lang_tree, opt, stats) level = level or 0 local node_name = (root.named and root:named()) and root:type() or nil + -- Parent kind (string). + local parent = root:parent() and root:parent():type() or nil local toplevel = level < 1 local function node_text(node) return vim.treesitter.get_node_text(node or root, opt.buf) @@ -380,13 +381,13 @@ local function visit_validate(root, level, lang_tree, opt, stats) -- Store the raw text to give context to the error report. local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]' table.insert(stats.parse_errors, sample_text) - elseif node_name == 'word' or node_name == 'uppercase_name' then - if spell_dict[text] then - if not invalid_spelling[text] then - invalid_spelling[text] = { vim.fs.basename(opt.fname) } - else - table.insert(invalid_spelling[text], vim.fs.basename(opt.fname)) - end + elseif (node_name == 'word' or node_name == 'uppercase_name') + and (not vim.tbl_contains({'codespan', 'taglink', 'tag'}, parent)) + then + local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation. + if spell_dict[text_nopunct] then + invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {} + invalid_spelling[text_nopunct][vim.fs.basename(opt.fname)] = node_text(root:parent()) end elseif node_name == 'url' then local fixed_url, _ = fix_url(trim(text)) @@ -544,7 +545,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) elseif node_name == 'language' then language = node_text(root) return '' - elseif node_name == 'code' then + elseif node_name == 'code' then -- Highlighted codeblock (child). if is_blank(text) then return '' end -- cgit From 036da0d07921e67090d1a62c9a4e382ca09d8584 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 24 Jun 2023 13:47:10 +0200 Subject: fix(docs): vimdoc syntax errors gen_help_html: truncate parse-error sample text --- scripts/gen_help_html.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index b369e0db5e..c89a7c70da 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -379,7 +379,9 @@ local function visit_validate(root, level, lang_tree, opt, stats) return end -- Store the raw text to give context to the error report. - local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]' + local sample_text = not toplevel and getbuflinestr(root, opt.buf, 0) or '[top level!]' + -- Flatten the sample text to a single, truncated line. + sample_text = vim.trim(sample_text):gsub('[\t\n]', ' '):sub(1, 80) table.insert(stats.parse_errors, sample_text) elseif (node_name == 'word' or node_name == 'uppercase_name') and (not vim.tbl_contains({'codespan', 'taglink', 'tag'}, parent)) @@ -667,7 +669,7 @@ end --- --- @param fname string help file to validate --- @param parser_path string? path to non-default vimdoc.so ---- @returns { invalid_links: number, parse_errors: number } +--- @returns { invalid_links: number, parse_errors: string[] } local function validate_one(fname, parser_path) local stats = { parse_errors = {}, @@ -1127,6 +1129,7 @@ function M.validate(help_dir, include, parser_path) parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'}, } local err_count = 0 + local files_to_errors = {} ensure_runtimepath() tagmap = get_helptags(help_dir) helpfiles = get_helpfiles(include) @@ -1136,6 +1139,10 @@ function M.validate(help_dir, include, parser_path) local helpfile = vim.fs.basename(f) local rv = validate_one(f, parser_path) print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile)) + if #rv.parse_errors > 0 then + files_to_errors[helpfile] = rv.parse_errors + vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v) return s..'\n '..v end))) + end err_count = err_count + #rv.parse_errors end @@ -1145,6 +1152,7 @@ function M.validate(help_dir, include, parser_path) invalid_links = invalid_links, invalid_urls = invalid_urls, invalid_spelling = invalid_spelling, + parse_errors = files_to_errors, } end -- cgit From 49a7585981cdf7403e76a614558e602a98e64301 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 23 Jun 2023 12:16:55 +0200 Subject: docs: autocmds, misc --- scripts/gen_vimdoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index b40f8526ea..96db0d1aad 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -2,7 +2,7 @@ """Generates Nvim :help docs from C/Lua docstrings, using Doxygen. Also generates *.mpack files. To inspect the *.mpack structure: - :new | put=v:lua.vim.inspect(v:lua.vim.mpack.unpack(readfile('runtime/doc/api.mpack','B'))) + :new | put=v:lua.vim.inspect(v:lua.vim.mpack.decode(readfile('runtime/doc/api.mpack','B'))) Flow: main -- cgit From 957d05d16bc80cef14c2e9fe31b6b847e698f9d1 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Jun 2023 12:29:56 -0700 Subject: fix(docs): too much whitespace around
 blocks #24151

Problem:
In the generated docs HTML there is too much whitespace before/after `
`
blocks.
- In the old layout (fixed-width), all text in `.old-help-para` is formatted as
  `white-space:pre`.
- In the new layout, when `
` is at the end of a `
`, the margins of both are redundant, causing too much space. Solution: - In the old layout, always remove `
` margin.
- In the new layout, disable `
` margin if it is the last child.
---
 scripts/gen_help_html.lua | 10 ++++++++++
 1 file changed, 10 insertions(+)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index c89a7c70da..f741efcaeb 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -944,6 +944,7 @@ local function gen_css(fname)
       padding-top: 10px;
       padding-bottom: 10px;
     }
+
     .old-help-para {
       padding-top: 10px;
       padding-bottom: 10px;
@@ -953,6 +954,12 @@ local function gen_css(fname)
       font-size: 16px;
       font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
     }
+    .old-help-para pre {
+      /* All text in .old-help-para is formatted as "white-space:pre" so text following 
 is
+         already visually separated by the linebreak. */
+      margin-bottom: 0;
+    }
+
     a.help-tag, a.help-tag:focus, a.help-tag:hover {
       color: inherit;
       text-decoration: none;
@@ -1006,6 +1013,9 @@ local function gen_css(fname)
       font-size: 16px;
       margin-top: 10px;
     }
+    pre:last-child {
+      margin-bottom: 0;
+    }
     pre:hover,
     .help-heading:hover {
       overflow: visible;
-- 
cgit 


From ab65a98adba4d32b03e7296529c4bf1491c783eb Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Tue, 27 Jun 2023 10:21:27 -0700
Subject: fix(docs): ignore_invalid #24174

Regex bug in scripts/gen_help_html.lua:ignore_invalid()
---
 scripts/gen_help_html.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index f741efcaeb..7f84a4d54d 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -293,7 +293,7 @@ local function ignore_invalid(s)
     -- Strings like |~/====| appear in various places and the parser thinks they are links, but they
     -- are just table borders.
     or s:find('===')
-    or s:find('---')
+    or s:find('%-%-%-')
   )
 end
 
-- 
cgit 


From 6da110d617dba6378f770c5d66d523df92f2d355 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Mon, 3 Jul 2023 05:04:43 -0700
Subject: docs(gen_help_html): accept "~/" in file/dir params #24240

---
 scripts/gen_help_html.lua | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 7f84a4d54d..5575de5b36 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -1089,7 +1089,7 @@ end
 --- @returns info dict
 function M.gen(help_dir, to_dir, include, commit, parser_path)
   vim.validate{
-    help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'},
+    help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
     to_dir={to_dir, 's'},
     include={include, 't', true},
     commit={commit, 's', true},
@@ -1098,8 +1098,9 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
 
   local err_count = 0
   ensure_runtimepath()
-  tagmap = get_helptags(help_dir)
+  tagmap = get_helptags(vim.fn.expand(help_dir))
   helpfiles = get_helpfiles(include)
+  to_dir = vim.fn.expand(to_dir)
   parser_path = parser_path and vim.fn.expand(parser_path) or nil
 
   print(('output dir: %s'):format(to_dir))
@@ -1134,14 +1135,14 @@ end
 -- @returns results dict
 function M.validate(help_dir, include, parser_path)
   vim.validate{
-    help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'},
+    help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
     include={include, 't', true},
     parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'},
   }
   local err_count = 0
   local files_to_errors = {}
   ensure_runtimepath()
-  tagmap = get_helptags(help_dir)
+  tagmap = get_helptags(vim.fn.expand(help_dir))
   helpfiles = get_helpfiles(include)
   parser_path = parser_path and vim.fn.expand(parser_path) or nil
 
-- 
cgit 


From 77118d0da8badc4135be430f4cbb15bc95bc760f Mon Sep 17 00:00:00 2001
From: Sean Dewar 
Date: Thu, 20 Apr 2023 21:17:25 +0100
Subject: fix(api): use text_locked() to check textlock

Problem: some API functions that check textlock (usually those that can change
curwin or curbuf) can break the cmdwin.

Solution: make FUNC_API_CHECK_TEXTLOCK call text_locked() instead, which already
checks for textlock, cmdwin and `` status.

Add FUNC_API_TEXTLOCK_ALLOW_CMDWIN to allow such functions to be usable in the
cmdwin if they can work properly there; the opt-in nature of this attribute
should hopefully help mitigate future bugs.

Also fix a regression in #22634 that made functions checking textlock usable in
`` mappings, and rename FUNC_API_CHECK_TEXTLOCK to FUNC_API_TEXTLOCK.
---
 scripts/gen_vimdoc.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 96db0d1aad..8410a3b5b1 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -310,7 +310,8 @@ param_exclude = (
 # Annotations are displayed as line items after API function descriptions.
 annotation_map = {
     'FUNC_API_FAST': '|api-fast|',
-    'FUNC_API_CHECK_TEXTLOCK': 'not allowed when |textlock| is active',
+    'FUNC_API_TEXTLOCK': 'not allowed when |textlock| is active or in the |cmdwin|',
+    'FUNC_API_TEXTLOCK_ALLOW_CMDWIN': 'not allowed when |textlock| is active',
     'FUNC_API_REMOTE_ONLY': '|RPC| only',
     'FUNC_API_LUA_ONLY': 'Lua |vim.api| only',
 }
-- 
cgit 


From 3a721820c39b7524a2e6d6a73774498104a38962 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Thu, 6 Jul 2023 15:32:39 +0200
Subject: docs: "Return (multiple)" heading

Problem:
Lua functions that return multiple results are declared by using
multiple `@return` docstring directives. But the generated docs don't
make it obvious what this represents.

Solution:
- Generate a "Return (multiple)" heading for multiple-value functions.
- Fix `@note` directives randomly placed after `@return`.
---
 scripts/gen_vimdoc.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 8410a3b5b1..eea56840ef 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -745,7 +745,7 @@ def fmt_node_as_vimhelp(parent, width=text_width - indentation, indent='',
             chunks.append('\nParameters: ~')
             chunks.append(fmt_param_doc(para['params']))
         if len(para['return']) > 0:
-            chunks.append('\nReturn: ~')
+            chunks.append('\nReturn (multiple): ~' if len(para['return']) > 1 else '\nReturn: ~')
             for s in para['return']:
                 chunks.append(s)
         if len(para['seealso']) > 0:
-- 
cgit 


From d2e44da516816e2616b531886eb9ba7f4c271fb4 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Thu, 6 Jul 2023 22:47:27 +0200
Subject: docs: gather @notes items into one section

related: 21eacbfef399
---
 scripts/gen_vimdoc.py | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index eea56840ef..8ad6442f3b 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -585,10 +585,12 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation,
                                               indent=indent, width=width))
             i = i + 1
     elif n.nodeName == 'simplesect' and 'note' == n.getAttribute('kind'):
-        text += '\nNote:\n    '
+        text += ind('  ')
         for c in n.childNodes:
-            text += render_node(c, text, indent='    ', width=width)
-        text += '\n'
+            if is_blank(render_node(c, text, prefix='• ', indent='    ', width=width)):
+                continue
+            text += render_node(c, text, prefix='• ', indent='    ', width=width)
+        # text += '\n'
     elif n.nodeName == 'simplesect' and 'warning' == n.getAttribute('kind'):
         text += 'Warning:\n    '
         for c in n.childNodes:
@@ -620,6 +622,7 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
 
     Keys:
         'text': Text from this  element
+        'note': List of @note strings
         'params':  map
         'return': List of @return strings
         'seealso': List of @see strings
@@ -627,6 +630,7 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
     """
     chunks = {
         'text': '',
+        'note': [],
         'params': collections.OrderedDict(),
         'return': [],
         'seealso': [],
@@ -635,6 +639,7 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
 
     # Ordered dict of ordered lists.
     groups = collections.OrderedDict([
+        ('note', []),
         ('params', []),
         ('return', []),
         ('seealso', []),
@@ -645,7 +650,6 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
     # nodes to appear together.
     text = ''
     kind = ''
-    last = ''
     if is_inline(parent):
         # Flatten inline text from a tree of non-block nodes.
         text = doc_wrap(render_node(parent, "", fmt_vimhelp=fmt_vimhelp),
@@ -658,13 +662,14 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
             elif child.nodeName == 'xrefsect':
                 groups['xrefs'].append(child)
             elif child.nodeName == 'simplesect':
-                last = kind
                 kind = child.getAttribute('kind')
-                if kind == 'return' or (kind == 'note' and last == 'return'):
+                if kind == 'note':
+                    groups['note'].append(child)
+                elif kind == 'return':
                     groups['return'].append(child)
                 elif kind == 'see':
                     groups['seealso'].append(child)
-                elif kind in ('note', 'warning'):
+                elif kind == 'warning':
                     text += render_node(child, text, indent=indent,
                                         width=width, fmt_vimhelp=fmt_vimhelp)
                 else:
@@ -689,6 +694,9 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
     if len(groups['params']) > 0:
         for child in groups['params']:
             update_params_map(child, ret_map=chunks['params'], width=width)
+    for child in groups['note']:
+        chunks['note'].append(render_node(
+            child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp).rstrip())
     for child in groups['return']:
         chunks['return'].append(render_node(
             child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp))
@@ -741,6 +749,10 @@ def fmt_node_as_vimhelp(parent, width=text_width - indentation, indent='',
 
         # Generate text from the gathered items.
         chunks = [para['text']]
+        if len(para['note']) > 0:
+            chunks.append('\nNote: ~')
+            for s in para['note']:
+                chunks.append(s)
         if len(para['params']) > 0 and has_nonexcluded_params(para['params']):
             chunks.append('\nParameters: ~')
             chunks.append(fmt_param_doc(para['params']))
-- 
cgit 


From 0a90e4b05ad3263bf656e24f616b6dadf6ba92e4 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Sat, 8 Jul 2023 15:58:50 +0200
Subject: fix(docs): match DocSearch style with site theme

ref https://github.com/neovim/neovim.github.io/commit/2b4f9e47809c16743f7d31d0dc1f1e3c2f313a56
---
 scripts/gen_help_html.lua | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 5575de5b36..1b997a5614 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -709,16 +709,17 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
     
     
     
+
+    
+    
+    
+
     
     
     
     
     
 
-    
-    
-    
-
     
     
     %s - Neovim docs
-- 
cgit 


From a54f88ea64c02f9fa7bf3d7445cdaaea424d439f Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 17 Jul 2023 10:39:52 +0100
Subject: docs(lua): do not render self args

---
 scripts/gen_vimdoc.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 8ad6442f3b..6ca330ae22 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -45,6 +45,7 @@ import logging
 from pathlib import Path
 
 from xml.dom import minidom
+Element = minidom.Element
 
 MIN_PYTHON_VERSION = (3, 6)
 MIN_DOXYGEN_VERSION = (1, 9, 0)
@@ -720,8 +721,7 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
 
     return chunks, xrefs
 
-
-def fmt_node_as_vimhelp(parent, width=text_width - indentation, indent='',
+def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent='',
                         fmt_vimhelp=False):
     """Renders (nested) Doxygen  nodes as Vim :help text.
 
@@ -734,6 +734,8 @@ def fmt_node_as_vimhelp(parent, width=text_width - indentation, indent='',
         max_name_len = max_name(m.keys()) + 4
         out = ''
         for name, desc in m.items():
+            if name == 'self':
+                continue
             name = '  • {}'.format('{{{}}}'.format(name).ljust(max_name_len))
             out += '{}{}\n'.format(name, desc)
         return out.rstrip()
@@ -851,6 +853,7 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
                 and any(x[1] == 'self' for x in params):
             split_return = return_type.split(' ')
             name = f'{split_return[1]}:{name}'
+            params = [x for x in params if x[1] != 'self']
 
         c_args = []
         for param_type, param_name in params:
-- 
cgit 


From 3fd504dbec39eeced1bea17d9f3bd06de7f3e4d8 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Sun, 16 Jul 2023 09:34:50 +0100
Subject: docs: handle whitespace in emmycomments

---
 scripts/lua2dox.lua | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index bb5214f091..b0eb4c086c 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -328,6 +328,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename)
       line = string_trim(inStream:getLine())
       l = l + 1
       if string.sub(line, 1, 2) == '--' then -- it's a comment
+        line = line:gsub('^---%s+@', '---@')
         -- Allow people to write style similar to EmmyLua (since they are basically the same)
         -- instead of silently skipping things that start with ---
         if string.sub(line, 3, 3) == '@' then -- it's a magic comment
@@ -341,6 +342,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename)
         if vim.startswith(line, '---@cast')
           or vim.startswith(line, '---@diagnostic')
           or vim.startswith(line, '---@overload')
+          or vim.startswith(line, '---@meta')
           or vim.startswith(line, '---@type') then
           -- Ignore LSP directives
           outStream:writeln('// gg:"' .. line .. '"')
-- 
cgit 


From 0ac3c4d6314df5fe40571a83e157a425ab7ce16d Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Sat, 15 Jul 2023 16:55:32 +0100
Subject: docs(lua): move function docs to lua files

---
 scripts/gen_vimdoc.py | 61 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 11 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 6ca330ae22..eacf4dc24d 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -144,6 +144,14 @@ CONFIG = {
         'mode': 'lua',
         'filename': 'lua.txt',
         'section_order': [
+            'highlight.lua',
+            'regex.lua',
+            'diff.lua',
+            'mpack.lua',
+            'json.lua',
+            'spell.lua',
+            'builtin.lua',
+            '_options.lua',
             '_editor.lua',
             '_inspector.lua',
             'shared.lua',
@@ -160,6 +168,7 @@ CONFIG = {
         'files': [
             'runtime/lua/vim/iter.lua',
             'runtime/lua/vim/_editor.lua',
+            'runtime/lua/vim/_options.lua',
             'runtime/lua/vim/shared.lua',
             'runtime/lua/vim/loader.lua',
             'runtime/lua/vim/uri.lua',
@@ -167,30 +176,48 @@ CONFIG = {
             'runtime/lua/vim/filetype.lua',
             'runtime/lua/vim/keymap.lua',
             'runtime/lua/vim/fs.lua',
+            'runtime/lua/vim/highlight.lua',
             'runtime/lua/vim/secure.lua',
             'runtime/lua/vim/version.lua',
             'runtime/lua/vim/_inspector.lua',
+            'runtime/lua/vim/_meta/builtin.lua',
+            'runtime/lua/vim/_meta/diff.lua',
+            'runtime/lua/vim/_meta/mpack.lua',
+            'runtime/lua/vim/_meta/json.lua',
+            'runtime/lua/vim/_meta/regex.lua',
+            'runtime/lua/vim/_meta/spell.lua',
         ],
         'file_patterns': '*.lua',
         'fn_name_prefix': '',
+        'fn_name_fmt': lambda fstem, name: (
+            name if fstem in [ 'vim.iter' ] else
+            f'vim.{name}' if fstem in [ '_editor', 'vim.regex'] else
+            f'{fstem}.{name}' if fstem.startswith('vim') else
+            name
+        ),
         'section_name': {
             'lsp.lua': 'core',
             '_inspector.lua': 'inspector',
         },
         'section_fmt': lambda name: (
-            'Lua module: vim'
-            if name.lower() == '_editor'
-            else f'Lua module: {name.lower()}'),
+            'Lua module: vim' if name.lower() == '_editor' else
+            'LUA-VIMSCRIPT BRIDGE' if name.lower() == '_options' else
+            f'VIM.{name.upper()}' if name.lower() in [ 'highlight', 'mpack', 'json', 'diff', 'spell', 'regex' ] else
+            'VIM' if name.lower() == 'builtin' else
+            f'Lua module: vim.{name.lower()}'),
         'helptag_fmt': lambda name: (
-            '*lua-vim*'
-            if name.lower() == '_editor'
-            else f'*lua-{name.lower()}*'),
+            '*lua-vim*' if name.lower() == '_editor' else
+            '*lua-vimscript*' if name.lower() == '_options' else
+            f'*lua-{name.lower()}*'),
         'fn_helptag_fmt': lambda fstem, name: (
-            f'*vim.{name}()*'
-            if fstem.lower() == '_editor'
-            else f'*{name}()*'
-            if name[0].isupper()
-            else f'*{fstem}.{name}()*'),
+            f'*vim.opt:{name.split(":")[-1]}()*' if ':' in name and name.startswith('Option') else
+            # Exclude fstem for methods
+            f'*{name}()*' if ':' in name else
+            f'*vim.{name}()*' if fstem.lower() == '_editor' else
+            # Prevents vim.regex.regex
+            f'*{fstem}()*' if fstem.endswith('.' + name) else
+            f'*{fstem}.{name}()*'
+            ),
         'module_override': {
             # `shared` functions are exposed on the `vim` module.
             'shared': 'vim',
@@ -201,9 +228,16 @@ CONFIG = {
             'filetype': 'vim.filetype',
             'keymap': 'vim.keymap',
             'fs': 'vim.fs',
+            'highlight': 'vim.highlight',
             'secure': 'vim.secure',
             'version': 'vim.version',
             'iter': 'vim.iter',
+            'diff': 'vim',
+            'builtin': 'vim',
+            'mpack': 'vim.mpack',
+            'json': 'vim.json',
+            'regex': 'vim.regex',
+            'spell': 'vim.spell',
         },
         'append_only': [
             'shared.lua',
@@ -542,6 +576,8 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation,
             text += '>lua{}{}\n<'.format(ensure_nl, o[3:-1])
         elif o[0:4] == 'vim\n':
             text += '>vim{}{}\n<'.format(ensure_nl, o[3:-1])
+        elif o[0:5] == 'help\n':
+            text += o[4:-1]
         else:
             text += '>{}{}\n<'.format(ensure_nl, o)
 
@@ -869,6 +905,9 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
                 fstem = CONFIG[target]['module_override'].get(fstem, fstem)
             vimtag = CONFIG[target]['fn_helptag_fmt'](fstem, name)
 
+            if 'fn_name_fmt' in CONFIG[target]:
+                name = CONFIG[target]['fn_name_fmt'](fstem, name)
+
         prefix = '%s(' % name
         suffix = '%s)' % ', '.join('{%s}' % a[1] for a in params
                                    if a[0] not in ('void', 'Error', 'Arena',
-- 
cgit 


From c2d7c2826ca77b0ca31bec511fdcdf1e4abaf946 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 17 Jul 2023 15:13:54 +0100
Subject: docs(lua): change *lua-foo* -> *vim.foo*

---
 scripts/gen_vimdoc.py | 6 +++++-
 scripts/lua2dox.lua   | 5 +++++
 2 files changed, 10 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index eacf4dc24d..984939a692 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -208,7 +208,7 @@ CONFIG = {
         'helptag_fmt': lambda name: (
             '*lua-vim*' if name.lower() == '_editor' else
             '*lua-vimscript*' if name.lower() == '_options' else
-            f'*lua-{name.lower()}*'),
+            f'*vim.{name.lower()}*'),
         'fn_helptag_fmt': lambda fstem, name: (
             f'*vim.opt:{name.split(":")[-1]}()*' if ':' in name and name.startswith('Option') else
             # Exclude fstem for methods
@@ -1160,6 +1160,10 @@ def main(doxygen_config, args):
                 if doc:
                     doc_list.append(doc)
 
+            # Can't use '.' in @defgroup, so convert to '--'
+            # "vim.json" => "vim-dot-json"
+            groupname = groupname.replace('-dot-', '.')
+
             section_docs[groupname] = "\n".join(doc_list)
 
         # Generate docs for all functions in the current module.
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index b0eb4c086c..3f0d0505dd 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -416,6 +416,11 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename)
 
             magic = table.concat(magic_split, ' ')
 
+            if magic_split[1] == 'defgroup' or magic_split[1] == 'addtogroup' then
+              -- Can't use '.' in defgroup, so convert to '--'
+              magic = magic:gsub('%.', '-dot-')
+            end
+
             outStream:writeln('/// @' .. magic)
             fn_magic = checkComment4fn(fn_magic, magic)
           end
-- 
cgit 


From e6e0bc225b14f135e2270f3bacd5fb8ebf7e3792 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 17 Jul 2023 15:22:44 +0100
Subject: refactor(gen_vimdoc): put defgroup handling in a function

---
 scripts/gen_vimdoc.py | 68 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 30 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 984939a692..0a7dd6e9ab 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -46,6 +46,7 @@ from pathlib import Path
 
 from xml.dom import minidom
 Element = minidom.Element
+Document = minidom.Document
 
 MIN_PYTHON_VERSION = (3, 6)
 MIN_DOXYGEN_VERSION = (1, 9, 0)
@@ -1089,6 +1090,42 @@ def delete_lines_below(filename, tokenstr):
         fp.writelines(lines[0:i])
 
 
+def extract_defgroups(base: str, dom: Document):
+    '''Generate module-level (section) docs (@defgroup).'''
+    section_docs = {}
+
+    for compound in dom.getElementsByTagName('compound'):
+        if compound.getAttribute('kind') != 'group':
+            continue
+
+        # Doxygen "@defgroup" directive.
+        groupname = get_text(find_first(compound, 'name'))
+        groupxml = os.path.join(base, '%s.xml' %
+                                compound.getAttribute('refid'))
+
+        group_parsed = minidom.parse(groupxml)
+        doc_list = []
+        brief_desc = find_first(group_parsed, 'briefdescription')
+        if brief_desc:
+            for child in brief_desc.childNodes:
+                doc_list.append(fmt_node_as_vimhelp(child))
+
+        desc = find_first(group_parsed, 'detaileddescription')
+        if desc:
+            doc = fmt_node_as_vimhelp(desc)
+
+            if doc:
+                doc_list.append(doc)
+
+        # Can't use '.' in @defgroup, so convert to '--'
+        # "vim.json" => "vim-dot-json"
+        groupname = groupname.replace('-dot-', '.')
+
+        section_docs[groupname] = "\n".join(doc_list)
+
+    return section_docs
+
+
 def main(doxygen_config, args):
     """Generates:
 
@@ -1130,41 +1167,12 @@ def main(doxygen_config, args):
 
         fn_map_full = {}  # Collects all functions as each module is processed.
         sections = {}
-        section_docs = {}
         sep = '=' * text_width
 
         base = os.path.join(output_dir, 'xml')
         dom = minidom.parse(os.path.join(base, 'index.xml'))
 
-        # Generate module-level (section) docs (@defgroup).
-        for compound in dom.getElementsByTagName('compound'):
-            if compound.getAttribute('kind') != 'group':
-                continue
-
-            # Doxygen "@defgroup" directive.
-            groupname = get_text(find_first(compound, 'name'))
-            groupxml = os.path.join(base, '%s.xml' %
-                                    compound.getAttribute('refid'))
-
-            group_parsed = minidom.parse(groupxml)
-            doc_list = []
-            brief_desc = find_first(group_parsed, 'briefdescription')
-            if brief_desc:
-                for child in brief_desc.childNodes:
-                    doc_list.append(fmt_node_as_vimhelp(child))
-
-            desc = find_first(group_parsed, 'detaileddescription')
-            if desc:
-                doc = fmt_node_as_vimhelp(desc)
-
-                if doc:
-                    doc_list.append(doc)
-
-            # Can't use '.' in @defgroup, so convert to '--'
-            # "vim.json" => "vim-dot-json"
-            groupname = groupname.replace('-dot-', '.')
-
-            section_docs[groupname] = "\n".join(doc_list)
+        section_docs = extract_defgroups(base, dom)
 
         # Generate docs for all functions in the current module.
         for compound in dom.getElementsByTagName('compound'):
-- 
cgit 


From 6e9b204afbe5f16c44a2697aed07aafff36bf856 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 17 Jul 2023 16:39:57 +0100
Subject: fix: doc errors

---
 scripts/lua2dox.lua | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 3f0d0505dd..55cb566ca3 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -363,6 +363,8 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename)
               magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1')
               magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1')
             end
+            -- handle the return of vim.spell.check
+            magic = magic:gsub('({.*}%[%])', '`%1`')
             magic_split = string_split(magic, ' ')
           end
 
-- 
cgit 


From 9fcb0a64ee9195434113c10cb6e958cfe3b2c2cd Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 18 Jul 2023 12:24:53 +0100
Subject: refactor(lua2dox): overhaul (#24386)

---
 scripts/lua2dox.lua | 774 ++++++++++++++++++++--------------------------------
 1 file changed, 302 insertions(+), 472 deletions(-)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 55cb566ca3..be72b9e1c0 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -1,6 +1,6 @@
---[[--------------------------------------------------------------------------
---   Copyright (C) 2012 by Simon Dales   --
---   simon@purrsoft.co.uk   --
+-----------------------------------------------------------------------------
+--   Copyright (C) 2012 by Simon Dales                                     --
+--   simon@purrsoft.co.uk                                                  --
 --                                                                         --
 --   This program is free software; you can redistribute it and/or modify  --
 --   it under the terms of the GNU General Public License as published by  --
@@ -16,7 +16,7 @@
 --   along with this program; if not, write to the                         --
 --   Free Software Foundation, Inc.,                                       --
 --   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             --
-----------------------------------------------------------------------------]]
+-----------------------------------------------------------------------------
 
 --[[!
 Lua-to-Doxygen converter
@@ -48,536 +48,364 @@ It only has to be good enough for doxygen to see it as legal.
 
 One limitation is that each line is treated separately (except for long comments).
 The implication is that class and function declarations must be on the same line.
-Some functions can have their parameter lists extended over multiple lines to make it look neat.
-Managing this where there are also some comments is a bit more coding than I want to do at this stage,
-so it will probably not document accurately if we do do this.
 
-However I have put in a hack that will insert the "missing" close paren.
+There is hack that will insert the "missing" close paren.
 The effect is that you will get the function documented, but not with the parameter list you might expect.
 ]]
 
-local _debug_outfile = nil
-local _debug_output = {}
-
-local function class()
-  local newClass = {} -- a new class newClass
-  -- the class will be the metatable for all its newInstanceects,
-  -- and they will look up their methods in it.
-  newClass.__index = newClass
-
-  -- expose a constructor which can be called by ()
-  setmetatable(newClass, {
-    __call = function(class_tbl, ...)
-      local newInstance = {}
-      setmetatable(newInstance, newClass)
-      --if init then
-      --  init(newInstance,...)
-      if class_tbl.init then
-        class_tbl.init(newInstance, ...)
-      end
-      return newInstance
-    end
-  })
-  return newClass
-end
+local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' }
 
--- write to stdout
-local function TCore_IO_write(Str)
-  if Str then
-    io.write(Str)
-    if _debug_outfile then
-      table.insert(_debug_output, Str)
-    end
-  end
-end
+local TAGGED_TYPES = { 'TSNode', 'LanguageTree' }
 
--- write to stdout
-local function TCore_IO_writeln(Str)
-  TCore_IO_write(Str)
-  TCore_IO_write('\n')
-end
+-- Document these as 'table'
+local ALIAS_TYPES = { 'Range', 'Range4', 'Range6', 'TSMetadata' }
 
--- trims a string
-local function string_trim(Str)
-  return Str:match('^%s*(.-)%s*$')
-end
+local debug_outfile = nil --- @type string?
+local debug_output = {}
 
--- split a string
---!
---! \param Str
---! \param Pattern
---! \returns table of string fragments
----@return string[]
-local function string_split(Str, Pattern)
-  local splitStr = {}
-  local fpat = '(.-)' .. Pattern
-  local last_end = 1
-  local str, e, cap = string.find(Str, fpat, 1)
-  while str do
-    if str ~= 1 or cap ~= '' then
-      table.insert(splitStr, cap)
-    end
-    last_end = e + 1
-    str, e, cap = string.find(Str, fpat, last_end)
+--- write to stdout
+--- @param str? string
+local function write(str)
+  if not str then
+    return
   end
-  if last_end <= #Str then
-    cap = string.sub(Str, last_end)
-    table.insert(splitStr, cap)
+
+  io.write(str)
+  if debug_outfile then
+    table.insert(debug_output, str)
   end
-  return splitStr
 end
 
--------------------------------
--- file buffer
---!
---! an input file buffer
-local TStream_Read = class()
-
--- get contents of file
---!
---! \param Filename name of file to read (or nil == stdin)
-function TStream_Read.getContents(this, Filename)
-  assert(Filename, ('invalid file: %s'):format(Filename))
+--- write to stdout
+--- @param str? string
+local function writeln(str)
+  write(str)
+  write('\n')
+end
+
+--- an input file buffer
+--- @class StreamRead
+--- @field currentLine string?
+--- @field contentsLen integer
+--- @field currentLineNo integer
+--- @field filecontents string[]
+local StreamRead = {}
+
+--- @return StreamRead
+--- @param filename string
+function StreamRead.new(filename)
+  assert(filename, ('invalid file: %s'):format(filename))
   -- get lines from file
   -- syphon lines to our table
-  local filecontents = {}
-  for line in io.lines(Filename) do
-    table.insert(filecontents, line)
-  end
-
-  if filecontents then
-    this.filecontents = filecontents
-    this.contentsLen = #filecontents
-    this.currentLineNo = 1
+  local filecontents = {} --- @type string[]
+  for line in io.lines(filename) do
+    filecontents[#filecontents+1] = line
   end
 
-  return filecontents
-end
-
--- get lineno
-function TStream_Read.getLineNo(this)
-  return this.currentLineNo
+  return setmetatable({
+    filecontents = filecontents,
+    contentsLen = #filecontents,
+    currentLineNo = 1,
+  }, { __index = StreamRead })
 end
 
 -- get a line
-function TStream_Read.getLine(this)
-  local line
-  if this.currentLine then
-    line = this.currentLine
-    this.currentLine = nil
-  else
-    -- get line
-    if this.currentLineNo <= this.contentsLen then
-      line = this.filecontents[this.currentLineNo]
-      this.currentLineNo = this.currentLineNo + 1
-    else
-      line = ''
-    end
+function StreamRead:getLine()
+  if self.currentLine then
+    self.currentLine = nil
+    return self.currentLine
   end
-  return line
+
+  -- get line
+  if self.currentLineNo <= self.contentsLen then
+    local line = self.filecontents[self.currentLineNo]
+    self.currentLineNo = self.currentLineNo + 1
+    return line
+  end
+
+  return ''
 end
 
 -- save line fragment
-function TStream_Read.ungetLine(this, LineFrag)
-  this.currentLine = LineFrag
+--- @param line_fragment string
+function StreamRead:ungetLine(line_fragment)
+  self.currentLine = line_fragment
 end
 
 -- is it eof?
-function TStream_Read.eof(this)
-  if this.currentLine or this.currentLineNo <= this.contentsLen then
-    return false
+function StreamRead:eof()
+  return not self.currentLine and self.currentLineNo > self.contentsLen
+end
+
+-- input filter
+--- @class Lua2DoxFilter
+local Lua2DoxFilter = {}
+setmetatable(Lua2DoxFilter, { __index = Lua2DoxFilter })
+
+--- trim comment off end of string
+---
+--- @param line string
+--- @return string, string?
+local function removeCommentFromLine(line)
+  local pos_comment = line:find('%-%-')
+  if not pos_comment then
+    return line
   end
-  return true
+  return line:sub(1, pos_comment - 1), line:sub(pos_comment)
 end
 
--- output stream
-local TStream_Write = class()
+--- @param line string
+--- @param generics table
+--- @return string?
+local function process_magic(line, generics)
+  line = line:gsub('^%s+@', '@')
+  line = line:gsub('@package', '@private')
 
--- constructor
-function TStream_Write.init(this)
-  this.tailLine = {}
-end
+  if not vim.startswith(line, '@') then -- it's a magic comment
+    return '/// ' .. line
+  end
 
--- write immediately
-function TStream_Write.write(_, Str)
-  TCore_IO_write(Str)
-end
+  local magic = line:sub(2)
+  local magic_split = vim.split(magic, ' ', { plain = true })
+  local directive = magic_split[1]
 
--- write immediately
-function TStream_Write.writeln(_, Str)
-  TCore_IO_writeln(Str)
-end
+  if vim.list_contains({
+    'cast', 'diagnostic', 'overload', 'meta', 'type'
+  }, directive) then
+    -- Ignore LSP directives
+    return '// gg:"' .. line .. '"'
+  end
 
--- write immediately
-function TStream_Write.writelnComment(_, Str)
-  TCore_IO_write('// ZZ: ')
-  TCore_IO_writeln(Str)
-end
+  if directive == 'defgroup' or directive == 'addtogroup' then
+    -- Can't use '.' in defgroup, so convert to '--'
+    return '/// @' .. magic:gsub('%.', '-dot-')
+  end
 
--- write to tail
-function TStream_Write.writelnTail(this, Line)
-  if not Line then
-    Line = ''
+  if directive == 'generic' then
+    local generic_name, generic_type = line:match('@generic%s*(%w+)%s*:?%s*(.*)')
+    if generic_type == '' then
+      generic_type = 'any'
+    end
+    generics[generic_name] = generic_type
+    return
   end
-  table.insert(this.tailLine, Line)
-end
 
--- output tail lines
-function TStream_Write.write_tailLines(this)
-  for _, line in ipairs(this.tailLine) do
-    TCore_IO_writeln(line)
+  local type_index = 2
+
+  if directive == 'param' then
+    for _, type in ipairs(TYPES) do
+      magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2')
+      magic =
+        magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2')
+    end
+    magic_split = vim.split(magic, ' ', { plain = true })
+    type_index = 3
+  elseif directive == 'return' then
+    for _, type in ipairs(TYPES) do
+      magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1')
+      magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1')
+    end
+    -- handle the return of vim.spell.check
+    magic = magic:gsub('({.*}%[%])', '`%1`')
+    magic_split = vim.split(magic, ' ', { plain = true })
   end
-  TCore_IO_write('// Lua2DoX new eof')
-end
 
--- input filter
-local TLua2DoX_filter = class()
+  local ty = magic_split[type_index]
 
--- allow us to do errormessages
-function TLua2DoX_filter.warning(this, Line, LineNo, Legend)
-  this.outStream:writelnTail(
-    '//! \todo warning! ' .. Legend .. ' (@' .. LineNo .. ')"' .. Line .. '"'
-  )
-end
+  if ty then
+    -- fix optional parameters
+    if magic_split[2]:find('%?$') then
+      if not ty:find('nil') then
+        ty = ty  .. '|nil'
+      end
+      magic_split[2] = magic_split[2]:sub(1, -2)
+    end
+
+    -- replace generic types
+    for k, v in pairs(generics) do
+      ty = ty:gsub(k, v) --- @type string
+    end
+
+    for _, type in ipairs(TAGGED_TYPES) do
+      ty = ty:gsub(type, '|%1|')
+    end
+
+    for _, type in ipairs(ALIAS_TYPES) do
+      ty = ty:gsub('^'..type..'$', 'table') --- @type string
+    end
+
+    -- surround some types by ()
+    for _, type in ipairs(TYPES) do
+      ty = ty
+        :gsub('^(' .. type .. '|nil):?$', '(%1)')
+        :gsub('^(' .. type .. '):?$', '(%1)')
+    end
+
+    magic_split[type_index] = ty
 
--- trim comment off end of string
---!
---! If the string has a comment on the end, this trims it off.
---!
-local function TString_removeCommentFromLine(Line)
-  local pos_comment = string.find(Line, '%-%-')
-  local tailComment
-  if pos_comment then
-    Line = string.sub(Line, 1, pos_comment - 1)
-    tailComment = string.sub(Line, pos_comment)
   end
-  return Line, tailComment
+
+  magic = table.concat(magic_split, ' ')
+
+  return '/// @' .. magic
 end
 
--- get directive from magic
-local function getMagicDirective(Line)
-  local macro, tail
-  local macroStr = '[\\@]'
-  local pos_macro = string.find(Line, macroStr)
-  if pos_macro then
-    --! ....\\ macro...stuff
-    --! ....\@ macro...stuff
-    local line = string.sub(Line, pos_macro + 1)
-    local space = string.find(line, '%s+')
-    if space then
-      macro = string.sub(line, 1, space - 1)
-      tail = string_trim(string.sub(line, space + 1))
+--- @param line string
+--- @param in_stream StreamRead
+--- @return string
+local function process_block_comment(line, in_stream)
+  local comment_parts = {} --- @type string[]
+  local done --- @type boolean?
+
+  while not done and not in_stream:eof() do
+    local thisComment --- @type string?
+    local closeSquare = line:find(']]')
+    if not closeSquare then -- need to look on another line
+      thisComment = line .. '\n'
+      line = in_stream:getLine()
     else
-      macro = line
-      tail = ''
+      thisComment = line:sub(1, closeSquare - 1)
+      done = true
+
+      -- unget the tail of the line
+      -- in most cases it's empty. This may make us less efficient but
+      -- easier to program
+      in_stream:ungetLine(vim.trim(line:sub(closeSquare + 2)))
     end
+    comment_parts[#comment_parts+1] = thisComment
   end
-  return macro, tail
+
+  local comment = table.concat(comment_parts)
+
+  if comment:sub(1, 1) == '@' then -- it's a long magic comment
+    return '/*' .. comment .. '*/  '
+  end
+
+  -- discard
+  return '/* zz:' .. comment .. '*/  '
 end
 
--- check comment for fn
-local function checkComment4fn(Fn_magic, MagicLines)
-  local fn_magic = Fn_magic
-  --    TCore_IO_writeln('// checkComment4fn "' .. MagicLines .. '"')
+--- @param line string
+--- @return string
+local function process_function_header(line)
+  local pos_fn = assert(line:find('function'))
+  -- we've got a function
+  local fn = removeCommentFromLine(vim.trim(line:sub(pos_fn + 8)))
+
+  if fn:sub(1, 1) == '(' then
+    -- it's an anonymous function
+    return '// ZZ: '..line
+  end
+  -- fn has a name, so is interesting
 
-  local magicLines = string_split(MagicLines, '\n')
+  -- want to fix for iffy declarations
+  if fn:find('[%({]') then
+    -- we might have a missing close paren
+    if not fn:find('%)') then
+      fn = fn .. ' ___MissingCloseParenHere___)'
+    end
+  end
 
-  local macro, tail
+  -- Big hax
+  if fn:find(':') then
+    fn = fn:gsub(':', '.', 1)
 
-  for _, line in ipairs(magicLines) do
-    macro, tail = getMagicDirective(line)
-    if macro == 'fn' then
-      fn_magic = tail
-      --    TCore_IO_writeln('// found fn "' .. fn_magic .. '"')
-      --else
-      --TCore_IO_writeln('// not found fn "' .. line .. '"')
+    local paren_start = fn:find('(', 1, true)
+    local paren_finish = fn:find(')', 1, true)
+
+    -- Nothing in between the parens
+    local comma --- @type string
+    if paren_finish == paren_start + 1 then
+      comma = ''
+    else
+      comma = ', '
     end
+
+    fn = fn:sub(1, paren_start)
+      .. 'self'
+      .. comma
+      .. fn:sub(paren_start + 1)
   end
 
-  return fn_magic
+  -- add vanilla function
+  return 'function ' .. fn .. '{}'
 end
 
-local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' }
-
-local tagged_types = { 'TSNode', 'LanguageTree' }
+--- @param line string
+--- @param in_stream StreamRead
+--- @param generics table>
+--- @return string?
+local function process_line(line, in_stream, generics)
+  if vim.startswith(line, '---') then
+    return process_magic(line:sub(4), generics)
+  end
 
--- Document these as 'table'
-local alias_types = { 'Range', 'Range4', 'Range6', 'TSMetadata' }
+  if vim.startswith(line, '--'..'[[') then -- it's a long comment
+    return process_block_comment(line:sub(5), in_stream)
+  end
 
--- Processes the file and writes filtered output to stdout.
-function TLua2DoX_filter.filter(this, AppStamp, Filename)
-  local inStream = TStream_Read()
-  local outStream = TStream_Write()
-  this.outStream = outStream -- save to this obj
-
-  if inStream:getContents(Filename) then
-    -- output the file
-    local line
-    local fn_magic -- function name/def from  magic comment
-
-    outStream:writelnTail('// #######################')
-    outStream:writelnTail('// app run:' .. AppStamp)
-    outStream:writelnTail('// #######################')
-    outStream:writelnTail()
-
-    local state = '' -- luacheck: ignore 231 variable is set but never accessed.
-    local offset = 0
-    local generic = {}
-    local l = 0
-    while not (inStream:eof()) do
-      line = string_trim(inStream:getLine())
-      l = l + 1
-      if string.sub(line, 1, 2) == '--' then -- it's a comment
-        line = line:gsub('^---%s+@', '---@')
-        -- Allow people to write style similar to EmmyLua (since they are basically the same)
-        -- instead of silently skipping things that start with ---
-        if string.sub(line, 3, 3) == '@' then -- it's a magic comment
-          offset = 0
-        elseif string.sub(line, 1, 4) == '---@' then -- it's a magic comment
-          offset = 1
-        end
-
-        line = line:gsub('@package', '@private')
-
-        if vim.startswith(line, '---@cast')
-          or vim.startswith(line, '---@diagnostic')
-          or vim.startswith(line, '---@overload')
-          or vim.startswith(line, '---@meta')
-          or vim.startswith(line, '---@type') then
-          -- Ignore LSP directives
-          outStream:writeln('// gg:"' .. line .. '"')
-        elseif string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment
-          state = 'in_magic_comment'
-          local magic = string.sub(line, 4 + offset)
-
-          local magic_split = string_split(magic, ' ')
-          if magic_split[1] == 'param' then
-            for _, type in ipairs(types) do
-              magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2')
-              magic =
-                magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2')
-            end
-            magic_split = string_split(magic, ' ')
-          elseif magic_split[1] == 'return' then
-            for _, type in ipairs(types) do
-              magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1')
-              magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1')
-            end
-            -- handle the return of vim.spell.check
-            magic = magic:gsub('({.*}%[%])', '`%1`')
-            magic_split = string_split(magic, ' ')
-          end
-
-          if magic_split[1] == 'generic' then
-            local generic_name, generic_type = line:match('@generic%s*(%w+)%s*:?%s*(.*)')
-            if generic_type == '' then
-              generic_type = 'any'
-            end
-            generic[generic_name] = generic_type
-          else
-            local type_index = 2
-            if magic_split[1] == 'param' then
-              type_index = type_index + 1
-            end
-
-            if magic_split[type_index] then
-              -- fix optional parameters
-              if magic_split[type_index] and magic_split[2]:find('%?$') then
-                if not magic_split[type_index]:find('nil') then
-                  magic_split[type_index] = magic_split[type_index] .. '|nil'
-                end
-                magic_split[2] = magic_split[2]:sub(1, -2)
-              end
-              -- replace generic types
-              if magic_split[type_index] then
-                for k, v in pairs(generic) do
-                  magic_split[type_index] = magic_split[type_index]:gsub(k, v)
-                end
-              end
-
-              for _, type in ipairs(tagged_types) do
-                magic_split[type_index] =
-                  magic_split[type_index]:gsub(type, '|%1|')
-              end
-
-              for _, type in ipairs(alias_types) do
-                magic_split[type_index] =
-                  magic_split[type_index]:gsub('^'..type..'$', 'table')
-              end
-
-              -- surround some types by ()
-              for _, type in ipairs(types) do
-                magic_split[type_index] =
-                  magic_split[type_index]:gsub('^(' .. type .. '|nil):?$', '(%1)')
-                magic_split[type_index] =
-                  magic_split[type_index]:gsub('^(' .. type .. '):?$', '(%1)')
-              end
-
-
-            end
-
-            magic = table.concat(magic_split, ' ')
-
-            if magic_split[1] == 'defgroup' or magic_split[1] == 'addtogroup' then
-              -- Can't use '.' in defgroup, so convert to '--'
-              magic = magic:gsub('%.', '-dot-')
-            end
-
-            outStream:writeln('/// @' .. magic)
-            fn_magic = checkComment4fn(fn_magic, magic)
-          end
-        elseif string.sub(line, 3, 3) == '-' then -- it's a nonmagic doc comment
-          local comment = string.sub(line, 4)
-          outStream:writeln('/// ' .. comment)
-        elseif string.sub(line, 3, 4) == '[[' then -- it's a long comment
-          line = string.sub(line, 5) -- nibble head
-          local comment = ''
-          local closeSquare, hitend, thisComment
-          while not hitend and (not inStream:eof()) do
-            closeSquare = string.find(line, ']]')
-            if not closeSquare then -- need to look on another line
-              thisComment = line .. '\n'
-              line = inStream:getLine()
-            else
-              thisComment = string.sub(line, 1, closeSquare - 1)
-              hitend = true
-
-              -- unget the tail of the line
-              -- in most cases it's empty. This may make us less efficient but
-              -- easier to program
-              inStream:ungetLine(string_trim(string.sub(line, closeSquare + 2)))
-            end
-            comment = comment .. thisComment
-          end
-          if string.sub(comment, 1, 1) == '@' then -- it's a long magic comment
-            outStream:write('/*' .. comment .. '*/  ')
-            fn_magic = checkComment4fn(fn_magic, comment)
-          else -- discard
-            outStream:write('/* zz:' .. comment .. '*/  ')
-            fn_magic = nil
-          end
-        -- TODO(justinmk): Uncomment this if we want "--" lines to continue the
-        --                 preceding magic ("---", "--@", …) lines.
-        -- elseif state == 'in_magic_comment' then  -- next line of magic comment
-        --   outStream:writeln('/// '.. line:sub(3))
-        else -- discard
-          outStream:writeln('// zz:"' .. line .. '"')
-          fn_magic = nil
-        end
-      elseif string.find(line, '^function') or string.find(line, '^local%s+function') then
-        generic = {}
-        state = 'in_function' -- it's a function
-        local pos_fn = string.find(line, 'function')
-        -- function
-        -- ....v...
-        if pos_fn then
-          -- we've got a function
-          local fn = TString_removeCommentFromLine(string_trim(string.sub(line, pos_fn + 8)))
-          if fn_magic then
-            fn = fn_magic
-          end
-
-          if string.sub(fn, 1, 1) == '(' then
-            -- it's an anonymous function
-            outStream:writelnComment(line)
-          else
-            -- fn has a name, so is interesting
-
-            -- want to fix for iffy declarations
-            local open_paren = string.find(fn, '[%({]')
-            if open_paren then
-              -- we might have a missing close paren
-              if not string.find(fn, '%)') then
-                fn = fn .. ' ___MissingCloseParenHere___)'
-              end
-            end
-
-            -- Big hax
-            if string.find(fn, ':') then
-              -- TODO: We need to add a first parameter of "SELF" here
-              -- local colon_place = string.find(fn, ":")
-              -- local name = string.sub(fn, 1, colon_place)
-              fn = fn:gsub(':', '.', 1)
-              outStream:writeln('/// @param self')
-
-              local paren_start = string.find(fn, '(', 1, true)
-              local paren_finish = string.find(fn, ')', 1, true)
-
-              -- Nothing in between the parens
-              local comma
-              if paren_finish == paren_start + 1 then
-                comma = ''
-              else
-                comma = ', '
-              end
-              fn = string.sub(fn, 1, paren_start)
-                .. 'self'
-                .. comma
-                .. string.sub(fn, paren_start + 1)
-            end
-
-            -- add vanilla function
-            outStream:writeln('function ' .. fn .. '{}')
-          end
-        else
-          this:warning(inStream:getLineNo(), 'something weird here')
-        end
-        fn_magic = nil -- mustn't inadvertently use it again
-
-      -- TODO: If we can make this learn how to generate these, that would be helpful.
-      -- elseif string.find(line, "^M%['.*'%] = function") then
-      --   state = 'in_function'  -- it's a function
-      --   outStream:writeln("function textDocument/publishDiagnostics(...){}")
-
-      --   fn_magic = nil -- mustn't inadvertently use it again
-      else
-        state = '' -- unknown
-        if #line > 0 then -- we don't know what this line means, so just comment it out
-          outStream:writeln('// zz: ' .. line)
-        else
-          outStream:writeln() -- keep this line blank
-        end
-      end
-    end
+  if line:find('^function') or line:find('^local%s+function') then
+    return process_function_header(line)
+  end
 
-    -- output the tail
-    outStream:write_tailLines()
-  else
-    outStream:writeln('!empty file')
+  if #line > 0 then -- we don't know what this line means, so just comment it out
+    return '// zz: ' .. line
   end
+
+  return ''
 end
 
--- this application
-local TApp = class()
+-- Processes the file and writes filtered output to stdout.
+---@param filename string
+function Lua2DoxFilter:filter(filename)
+  local in_stream = StreamRead.new(filename)
 
--- constructor
-function TApp.init(this)
-  this.timestamp = os.date('%c %Z', os.time())
-  this.name = 'Lua2DoX'
-  this.version = '0.2 20130128'
-  this.copyright = 'Copyright (c) Simon Dales 2012-13'
-end
+  local generics = {} --- @type table
 
-function TApp.getRunStamp(this)
-  return this.name .. ' (' .. this.version .. ') ' .. this.timestamp
-end
+  while not in_stream:eof() do
+    local line = vim.trim(in_stream:getLine())
+
+    local out_line = process_line(line, in_stream, generics)
+
+    if not vim.startswith(line, '---') then
+      generics = {}
+    end
 
-function TApp.getVersion(this)
-  return this.name .. ' (' .. this.version .. ') '
+    if out_line then
+      writeln(out_line)
+    end
+  end
 end
 
-function TApp.getCopyright(this)
-  return this.copyright
+--- @class TApp
+--- @field timestamp string|osdate
+--- @field name string
+--- @field version string
+--- @field copyright string
+--- this application
+local TApp = {
+  timestamp = os.date('%c %Z', os.time()),
+  name = 'Lua2DoX',
+  version = '0.2 20130128',
+  copyright = 'Copyright (c) Simon Dales 2012-13'
+}
+
+setmetatable(TApp, { __index = TApp })
+
+function TApp:getRunStamp()
+  return self.name .. ' (' .. self.version .. ') ' .. self.timestamp
 end
 
-local This_app = TApp()
+function TApp:getVersion()
+  return self.name .. ' (' .. self.version .. ') '
+end
 
 --main
 
 if arg[1] == '--help' then
-  TCore_IO_writeln(This_app:getVersion())
-  TCore_IO_writeln(This_app:getCopyright())
-  TCore_IO_writeln([[
+  writeln(TApp:getVersion())
+  writeln(TApp.copyright)
+  writeln([[
   run as:
   nvim -l scripts/lua2dox.lua 
   --------------
@@ -586,8 +414,8 @@ if arg[1] == '--help' then
   --version  : show version/copyright info
   --help     : this help text]])
 elseif arg[1] == '--version' then
-  TCore_IO_writeln(This_app:getVersion())
-  TCore_IO_writeln(This_app:getCopyright())
+  writeln(TApp:getVersion())
+  writeln(TApp.copyright)
 else  -- It's a filter.
   local filename = arg[1]
 
@@ -597,18 +425,20 @@ else  -- It's a filter.
       error(('invalid --outdir: "%s"'):format(tostring(outdir)))
     end
     vim.fn.mkdir(outdir, 'p')
-    _debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename))
+    debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename))
   end
 
-  local appStamp = This_app:getRunStamp()
-  local filter = TLua2DoX_filter()
-  filter:filter(appStamp, filename)
+  Lua2DoxFilter:filter(filename)
 
-  if _debug_outfile then
-    local f = assert(io.open(_debug_outfile, 'w'))
-    f:write(table.concat(_debug_output))
+  -- output the tail
+  writeln('// #######################')
+  writeln('// app run:' .. TApp:getRunStamp())
+  writeln('// #######################')
+  writeln()
+
+  if debug_outfile then
+    local f = assert(io.open(debug_outfile, 'w'))
+    f:write(table.concat(debug_output))
     f:close()
   end
 end
-
---eof
-- 
cgit 


From d0ae529861594b2e89a436ed2cfb3d2243f8bfcc Mon Sep 17 00:00:00 2001
From: kylo252 <59826753+kylo252@users.noreply.github.com>
Date: Tue, 18 Jul 2023 15:00:44 +0200
Subject: build(scripts): allow a git ref for lsp_types #24377

USAGE:
nvim -l scripts/lsp_types.lua gen
nvim -l scripts/lsp_types.lua gen --build/new_lsp_types.lua
nvim -l scripts/lsp_types.lua gen --out runtime/lua/vim/lsp/types/protocol.lua --ref 2023.0.0a2
---
 scripts/lsp_types.lua | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

(limited to 'scripts')

diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua
index 8f3ed811d6..4a089bd76d 100644
--- a/scripts/lsp_types.lua
+++ b/scripts/lsp_types.lua
@@ -1,7 +1,9 @@
 --[[
 Generates lua-ls annotations for lsp
 USAGE:
-nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/lsp_types.lua gen  # this will overwrite runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/lsp_types.lua gen --build/new_lsp_types.lua
+nvim -l scripts/lsp_types.lua gen --out runtime/lua/vim/lsp/types/protocol.lua --ref 2023.0.0a2 # specify a git reference from microsoft/lsprotocol
 --]]
 
 local M = {}
@@ -17,18 +19,17 @@ local function tofile(fname, text)
 end
 
 function M.gen(opt)
-  if vim.loop.fs_stat('./lsp.json') then
+  if vim.uv.fs_stat('./lsp.json') then
     vim.fn.delete('./lsp.json')
   end
   vim.fn.system({
     'curl',
-    'https://raw.githubusercontent.com/microsoft/lsprotocol/main/generator/lsp.json',
+    'https://raw.githubusercontent.com/microsoft/lsprotocol/' .. opt.ref .. '/generator/lsp.json',
     '-o',
     './lsp.json',
   })
   local protocol = vim.fn.json_decode(vim.fn.readfile('./lsp.json'))
   vim.fn.delete('./lsp.json')
-  local output_file = opt[1]
   protocol = protocol or {}
   local output = {
     '--[[',
@@ -184,17 +185,21 @@ function M.gen(opt)
     output[#output + 1] = line
   end
 
-  tofile(output_file, table.concat(output, '\n'))
+  tofile(opt.output_file, table.concat(output, '\n'))
 end
 
-local opt = {}
-
-local index = 1
-for _, a in ipairs(arg) do
-  if vim.startswith(a, '--') then
-    local name = a:sub(3)
-    opt[index] = name
-    index = index + 1
+local opt = {
+  output_file = 'runtime/lua/vim/lsp/types/protocol.lua',
+  ref = 'main',
+}
+
+for i = 1, #_G.arg do
+  if _G.arg[i] == '--out' then
+    opt.output_file = _G.arg[i+1]
+  elseif _G.arg[i] == '--ref' then
+    opt.ref = _G.arg[i+1]
+  elseif vim.startswith(_G.arg[i], '--') then
+    opt.output_file = _G.arg[i]:sub(3)
   end
 end
 
-- 
cgit 


From be74807eef13ff8c90d55cf8b22b01d6d33b1641 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 18 Jul 2023 15:42:30 +0100
Subject: docs(lua): more improvements (#24387)

* docs(lua): teach lua2dox how to table

* docs(lua): teach gen_vimdoc.py about local functions

No more need to mark local functions with @private

* docs(lua): mention @nodoc and @meta in dev-lua-doc

* fixup!

Co-authored-by: Justin M. Keyes 

---------

Co-authored-by: Justin M. Keyes 
---
 scripts/gen_vimdoc.py | 48 ++++++++++++++++++++++++++++++------------------
 scripts/lua2dox.lua   | 21 +++++++++++++++++++--
 2 files changed, 49 insertions(+), 20 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 0a7dd6e9ab..dfad1f000c 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -135,7 +135,7 @@ CONFIG = {
         # Section helptag.
         'helptag_fmt': lambda name: f'*api-{name.lower()}*',
         # Per-function helptag.
-        'fn_helptag_fmt': lambda fstem, name: f'*{name}()*',
+        'fn_helptag_fmt': lambda fstem, name, istbl: f'*{name}()*',
         # Module name overrides (for Lua).
         'module_override': {},
         # Append the docs for these modules, do not start a new section.
@@ -193,6 +193,7 @@ CONFIG = {
         'fn_name_fmt': lambda fstem, name: (
             name if fstem in [ 'vim.iter' ] else
             f'vim.{name}' if fstem in [ '_editor', 'vim.regex'] else
+            f'vim.{name}' if fstem == '_options' and not name[0].isupper() else
             f'{fstem}.{name}' if fstem.startswith('vim') else
             name
         ),
@@ -210,14 +211,15 @@ CONFIG = {
             '*lua-vim*' if name.lower() == '_editor' else
             '*lua-vimscript*' if name.lower() == '_options' else
             f'*vim.{name.lower()}*'),
-        'fn_helptag_fmt': lambda fstem, name: (
+        'fn_helptag_fmt': lambda fstem, name, istbl: (
             f'*vim.opt:{name.split(":")[-1]}()*' if ':' in name and name.startswith('Option') else
             # Exclude fstem for methods
             f'*{name}()*' if ':' in name else
             f'*vim.{name}()*' if fstem.lower() == '_editor' else
+            f'*vim.{name}*' if fstem.lower() == '_options' and istbl else
             # Prevents vim.regex.regex
             f'*{fstem}()*' if fstem.endswith('.' + name) else
-            f'*{fstem}.{name}()*'
+            f'*{fstem}.{name}{"" if istbl else "()"}*'
             ),
         'module_override': {
             # `shared` functions are exposed on the `vim` module.
@@ -275,14 +277,11 @@ CONFIG = {
             '*lsp-core*'
             if name.lower() == 'lsp'
             else f'*lsp-{name.lower()}*'),
-        'fn_helptag_fmt': lambda fstem, name: (
-            f'*vim.lsp.{name}()*'
-            if fstem == 'lsp' and name != 'client'
-            else (
-                '*vim.lsp.client*'
-                # HACK. TODO(justinmk): class/structure support in lua2dox
-                if 'lsp.client' == f'{fstem}.{name}'
-                else f'*vim.lsp.{fstem}.{name}()*')),
+        'fn_helptag_fmt': lambda fstem, name, istbl: (
+            f'*vim.lsp.{name}{"" if istbl else "()"}*' if fstem == 'lsp' and name != 'client' else
+            # HACK. TODO(justinmk): class/structure support in lua2dox
+            '*vim.lsp.client*' if 'lsp.client' == f'{fstem}.{name}' else
+            f'*vim.lsp.{fstem}.{name}{"" if istbl else "()"}*'),
         'module_override': {},
         'append_only': [],
     },
@@ -295,10 +294,11 @@ CONFIG = {
         'files': ['runtime/lua/vim/diagnostic.lua'],
         'file_patterns': '*.lua',
         'fn_name_prefix': '',
+        'include_tables': False,
         'section_name': {'diagnostic.lua': 'diagnostic'},
         'section_fmt': lambda _: 'Lua module: vim.diagnostic',
         'helptag_fmt': lambda _: '*diagnostic-api*',
-        'fn_helptag_fmt': lambda fstem, name: f'*vim.{fstem}.{name}()*',
+        'fn_helptag_fmt': lambda fstem, name, istbl: f'*vim.{fstem}.{name}{"" if istbl else "()"}*',
         'module_override': {},
         'append_only': [],
     },
@@ -328,7 +328,7 @@ CONFIG = {
             '*lua-treesitter-core*'
             if name.lower() == 'treesitter'
             else f'*lua-treesitter-{name.lower()}*'),
-        'fn_helptag_fmt': lambda fstem, name: (
+        'fn_helptag_fmt': lambda fstem, name, istbl: (
             f'*vim.{fstem}.{name}()*'
             if fstem == 'treesitter'
             else f'*{name}()*'
@@ -842,6 +842,13 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
         if return_type == '':
             continue
 
+        if 'local_function' in return_type:  # Special from lua2dox.lua.
+            continue
+
+        istbl = return_type.startswith('table')  # Special from lua2dox.lua.
+        if istbl and not CONFIG[target].get('include_tables', True):
+            continue
+
         if return_type.startswith(('ArrayOf', 'DictionaryOf')):
             parts = return_type.strip('_').split('_')
             return_type = '{}({})'.format(parts[0], ', '.join(parts[1:]))
@@ -904,15 +911,20 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
             if '.' in compoundname:
                 fstem = compoundname.split('.')[0]
                 fstem = CONFIG[target]['module_override'].get(fstem, fstem)
-            vimtag = CONFIG[target]['fn_helptag_fmt'](fstem, name)
+            vimtag = CONFIG[target]['fn_helptag_fmt'](fstem, name, istbl)
 
             if 'fn_name_fmt' in CONFIG[target]:
                 name = CONFIG[target]['fn_name_fmt'](fstem, name)
 
-        prefix = '%s(' % name
-        suffix = '%s)' % ', '.join('{%s}' % a[1] for a in params
-                                   if a[0] not in ('void', 'Error', 'Arena',
-                                                   'lua_State'))
+        if istbl:
+            aopen, aclose = '', ''
+        else:
+            aopen, aclose = '(', ')'
+
+        prefix = name + aopen
+        suffix = ', '.join('{%s}' % a[1] for a in params
+                           if a[0] not in ('void', 'Error', 'Arena',
+                                           'lua_State')) + aclose
 
         if not fmt_vimhelp:
             c_decl = '%s %s(%s);' % (return_type, name, ', '.join(c_args))
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index be72b9e1c0..9a666ea629 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -160,6 +160,7 @@ end
 local function process_magic(line, generics)
   line = line:gsub('^%s+@', '@')
   line = line:gsub('@package', '@private')
+  line = line:gsub('@nodoc', '@private')
 
   if not vim.startswith(line, '@') then -- it's a magic comment
     return '/// ' .. line
@@ -327,6 +328,11 @@ local function process_function_header(line)
       .. fn:sub(paren_start + 1)
   end
 
+  if line:match('local') then
+    -- Special: tell gen_vimdoc.py this is a local function.
+    return 'local_function ' .. fn .. '{}'
+  end
+
   -- add vanilla function
   return 'function ' .. fn .. '{}'
 end
@@ -336,6 +342,9 @@ end
 --- @param generics table>
 --- @return string?
 local function process_line(line, in_stream, generics)
+  local line_raw = line
+  line = vim.trim(line)
+
   if vim.startswith(line, '---') then
     return process_magic(line:sub(4), generics)
   end
@@ -348,6 +357,14 @@ local function process_line(line, in_stream, generics)
     return process_function_header(line)
   end
 
+  if not line:match('^local') then
+    local v = line_raw:match('^([A-Za-z][.a-zA-Z_]*)%s+%=')
+    if v and v:match('%.') then
+      -- Special: this lets gen_vimdoc.py handle tables.
+      return 'table '..v..'() {}'
+    end
+  end
+
   if #line > 0 then -- we don't know what this line means, so just comment it out
     return '// zz: ' .. line
   end
@@ -363,11 +380,11 @@ function Lua2DoxFilter:filter(filename)
   local generics = {} --- @type table
 
   while not in_stream:eof() do
-    local line = vim.trim(in_stream:getLine())
+    local line = in_stream:getLine()
 
     local out_line = process_line(line, in_stream, generics)
 
-    if not vim.startswith(line, '---') then
+    if not vim.startswith(vim.trim(line), '---') then
       generics = {}
     end
 
-- 
cgit 


From ca9f4a7cb1fea1ef1f22c011679fd8afa0a5d161 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Fri, 21 Jul 2023 16:30:05 +0800
Subject: docs: also change "vimL" and "viml" to "Vimscript" (#24414)

---
 scripts/gen_help_html.lua | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 1b997a5614..5e06830336 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -34,6 +34,8 @@ local spell_dict = {
   neovim = 'Nvim',
   lua = 'Lua',
   VimL = 'Vimscript',
+  vimL = 'Vimscript',
+  viml = 'Vimscript',
 }
 local language = nil
 
-- 
cgit 


From fd089c8e50c211d7beae15dbc9492ae5a1a5f2e2 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Wed, 26 Jul 2023 09:50:54 +0100
Subject: feat(lua): typing for vim.fn.* (#24473)

Problem:
  No LSP information for `vim.fn.*`

Solution:
  Add meta file for `vim.fn.*`.
---
 scripts/gen_vimfn_types.lua | 244 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 244 insertions(+)
 create mode 100755 scripts/gen_vimfn_types.lua

(limited to 'scripts')

diff --git a/scripts/gen_vimfn_types.lua b/scripts/gen_vimfn_types.lua
new file mode 100755
index 0000000000..f0dfd0665c
--- /dev/null
+++ b/scripts/gen_vimfn_types.lua
@@ -0,0 +1,244 @@
+#!/usr/bin/env -S nvim -l
+
+--- @class vim.EvalFn2 : vim.EvalFn
+--- @field signature string
+--- @field desc string[]
+--- @field params {[1]: string, [2]: string}[]
+
+--- @param filename string
+--- @return string
+local function safe_read(filename)
+  local file, err = io.open(filename, 'r')
+  if not file then
+    error(err)
+  end
+  local content = file:read('*a')
+  io.close(file)
+  return content
+end
+
+local nvim_eval = require'src/nvim/eval'
+
+local funcs = nvim_eval.funcs --[[@as table]]
+
+local LUA_KEYWORDS = {
+  ['and'] = true,
+  ['end'] = true,
+  ['function'] = true,
+  ['or'] = true,
+  ['if'] = true,
+  ['while'] = true,
+  ['repeat'] = true
+}
+
+local SOURCES = {
+  {
+    path = 'runtime/doc/builtin.txt',
+    from = '^2. Details',
+    to = '==========',
+  },
+  {
+    path = 'runtime/doc/sign.txt',
+    from = '^3. Functions',
+    to = 'vim:'
+  },
+  {
+    path = 'runtime/doc/testing.txt',
+    from = '^3. Assert functions',
+    to = 'vim:'
+  }
+}
+
+local ARG_NAME_TYPES = {
+  col = 'integer',
+  nosuf = 'boolean',
+  dir = 'string',
+  mode = 'string',
+  width = 'integer',
+  height = 'integer',
+  timeout = 'integer',
+  libname = 'string',
+  funcname = 'string',
+  end_ = 'integer',
+  file = 'string',
+  flags = 'string',
+  fname = 'integer',
+  idx = 'integer',
+  lnum = 'integer',
+  mods = 'string',
+  name = 'string',
+  nr = 'integer',
+  options = 'table',
+  opts = 'table',
+  path = 'string',
+  regname = 'string',
+  silent = 'boolean',
+  string = 'string',
+  tabnr = 'integer',
+  varname = 'string',
+  winid = 'integer',
+  winnr = 'integer',
+}
+
+local function process_source(source)
+  local src_txt = safe_read(source.path)
+
+  --- @type string[]
+  local src_lines = vim.split(src_txt, '\n', { plain = true })
+
+  local s = 0
+  for i, l in ipairs(src_lines) do
+    if l:match(source.from) then
+      s = i+1
+    end
+  end
+
+  local lines = {} --- @type string[]
+  local last_f --- @type string?
+
+  for i = s, #src_lines do
+    local l = src_lines[i]
+    if not l or l:match(source.to) then
+      break
+    end
+    local f = l:match('^([a-z][a-zA-Z0-9_]*)%(')
+    if f then
+      if last_f then
+        funcs[last_f].desc = lines
+      end
+      last_f = f
+      local sig = l:match('[^)]+%)')
+      local params = {} --- @type string[]
+      if sig then
+        for param in string.gmatch(sig, '{([a-z][a-zA-Z0-9_]*)}') do
+          local t = ARG_NAME_TYPES[param] or 'any'
+          params[#params+1] = {param, t}
+        end
+      else
+        print('error parsing', l)
+      end
+
+      funcs[last_f].signature = sig
+      funcs[last_f].params = params
+
+      lines = {}
+    else
+      lines[#lines+1] = l:gsub('^(
+  local sfx = 1
+
+  for _, p in ipairs(fun.params) do
+    if LUA_KEYWORDS[p[1]] then
+      p[1] = p[1]..'_'
+    end
+    if seen[p[1]] then
+      p[1] = p[1]..sfx
+      sfx = sfx + 1
+    else
+      seen[p[1]] = true
+    end
+  end
+end
+
+--- @param funname string
+--- @param fun vim.EvalFn2
+--- @param write fun(line: string)
+local function render_fun(funname, fun, write)
+  if fun.deprecated then
+    write('')
+    write('--- @deprecated')
+    for _, l in ipairs(fun.deprecated) do
+      write('--- '.. l)
+    end
+    write(render_fun_sig(funname, true))
+    return
+  end
+
+  if fun.desc and fun.signature then
+    write('')
+    for _, l in ipairs(fun.desc) do
+      write('--- '.. l:gsub('@', '\\@'))
+    end
+
+    local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
+
+    for i, param in ipairs(fun.params) do
+      if i <= req_args then
+        write('--- @param '..param[1]..' '..param[2])
+      else
+        write('--- @param '..param[1]..'? '..param[2])
+      end
+    end
+    if fun.returns ~= false then
+      write('--- @return '..(fun.returns or 'any'))
+    end
+    write(render_fun_sig(funname, fun.params))
+    return
+  end
+
+  print('no doc for', funname)
+end
+
+local function main(outfile)
+  local o = assert(io.open(outfile, 'w'))
+
+  local function write(l)
+    local l1 = l:gsub('%s+$', '')
+    o:write(l1)
+    o:write('\n')
+  end
+
+  for _, source in ipairs(SOURCES) do
+    process_source(source)
+  end
+
+  --- @type string[]
+  local fnames = vim.tbl_keys(funcs)
+  table.sort(fnames)
+
+  write('--- @meta')
+  write('-- THIS FILE IS GENERATED')
+  write('-- DO NOT EDIT')
+
+  for _, f in ipairs(fnames) do
+    local fun = funcs[f]
+    process_params(fun)
+    render_fun(f, fun, write)
+  end
+end
+
+main('runtime/lua/vim/_meta/vimfn.lua')
+
-- 
cgit 


From ccf328172bac2b02f9bd19fa58e105958514a28a Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Wed, 26 Jul 2023 21:07:39 +0800
Subject: fix(gen_vimfn_types): don't include tag before signature's line
 (#24492)

When signature is a bit long or there are too many tags, the tags appear
before the signature's line. Don't include the line with tags in the
previous function' docs.

Also fix lint warnings.
---
 scripts/gen_vimfn_types.lua | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimfn_types.lua b/scripts/gen_vimfn_types.lua
index f0dfd0665c..32de1d3c95 100755
--- a/scripts/gen_vimfn_types.lua
+++ b/scripts/gen_vimfn_types.lua
@@ -95,6 +95,7 @@ local function process_source(source)
 
   local lines = {} --- @type string[]
   local last_f --- @type string?
+  local last_l --- @type string?
 
   for i = s, #src_lines do
     local l = src_lines[i]
@@ -104,11 +105,14 @@ local function process_source(source)
     local f = l:match('^([a-z][a-zA-Z0-9_]*)%(')
     if f then
       if last_f then
+        if last_l and last_l:find('*' .. f .. '()*', 1, true) then
+          lines[#lines] = nil
+        end
         funcs[last_f].desc = lines
       end
       last_f = f
       local sig = l:match('[^)]+%)')
-      local params = {} --- @type string[]
+      local params = {} --- @type table[]
       if sig then
         for param in string.gmatch(sig, '{([a-z][a-zA-Z0-9_]*)}') do
           local t = ARG_NAME_TYPES[param] or 'any'
@@ -125,6 +129,7 @@ local function process_source(source)
     else
       lines[#lines+1] = l:gsub('^(
Date: Fri, 28 Jul 2023 14:48:41 +0100
Subject: feat(docs): generate builtin.txt (#24493)

- eval.lua is now the source of truth.

- Formatting is much more consistent.

- Fixed Lua type generation for polymorphic functions (get(), etc).

- Removed "Overview" section from builtin.txt
  - Can generate this if we really want it.

- Moved functions from sign.txt and testing.txt into builtin.txt.

- Removed the *timer* *timers* tags since libuv timers via vim.uv should be preferred.

- Removed the temp-file-name tag from tempname()

- Moved lueval() from lua.txt to builtin.txt.

* Fix indent

* fixup!

* fixup! fixup!

* fixup! better tag formatting

* fixup: revert changes no longer needed

* fixup! CI

---------

Co-authored-by: zeertzjq 
---
 scripts/gen_eval_files.lua  | 274 ++++++++++++++++++++++++++++++++++++++++++++
 scripts/gen_vimdoc.py       |   3 +
 scripts/gen_vimfn_types.lua | 249 ----------------------------------------
 3 files changed, 277 insertions(+), 249 deletions(-)
 create mode 100755 scripts/gen_eval_files.lua
 delete mode 100755 scripts/gen_vimfn_types.lua

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
new file mode 100755
index 0000000000..7193346758
--- /dev/null
+++ b/scripts/gen_eval_files.lua
@@ -0,0 +1,274 @@
+#!/usr/bin/env -S nvim -l
+-- Generator for src/nvim/eval.lua
+
+local funcs = require('src/nvim/eval').funcs
+
+local LUA_KEYWORDS = {
+  ['and'] = true,
+  ['end'] = true,
+  ['function'] = true,
+  ['or'] = true,
+  ['if'] = true,
+  ['while'] = true,
+  ['repeat'] = true,
+}
+
+--- @param f string
+--- @param params {[1]:string,[2]:string}[]|true
+local function render_fun_sig(f, params)
+  local param_str --- @type string
+  if params == true then
+    param_str = '...'
+  else
+    param_str = table.concat(
+      vim.tbl_map(
+        --- @param v {[1]:string,[2]:string}
+        function(v)
+          return v[1]
+        end,
+        params
+      ),
+      ', '
+    )
+  end
+
+  if LUA_KEYWORDS[f] then
+    return string.format("vim.fn['%s'] = function(%s) end", f, param_str)
+  else
+    return string.format('function vim.fn.%s(%s) end', f, param_str)
+  end
+end
+
+--- Uniquify names
+--- Fix any names that are lua keywords
+--- @param params {[1]:string,[2]:string}[]
+--- @return {[1]:string,[2]:string}[]
+local function process_params(params)
+  local seen = {} --- @type table
+  local sfx = 1
+
+  for _, p in ipairs(params) do
+    if LUA_KEYWORDS[p[1]] then
+      p[1] = p[1] .. '_'
+    end
+    if seen[p[1]] then
+      p[1] = p[1] .. sfx
+      sfx = sfx + 1
+    else
+      seen[p[1]] = true
+    end
+  end
+
+  return params
+end
+
+--- @param f string
+--- @param fun vim.EvalFn
+--- @param write fun(line: string)
+local function render_vimfn(f, fun, write)
+  if fun.lua == false then
+    return
+  end
+
+  local funname = fun.name or f
+
+  local params = process_params(fun.params)
+
+  if fun.signature then
+    write('')
+    if fun.deprecated then
+      write('--- @deprecated')
+    end
+
+    local desc = fun.desc
+
+    if desc then
+      desc = desc:gsub('\n%s*\n%s*$', '\n')
+      for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do
+        l = l:gsub('^      ', ''):gsub('\t', '  '):gsub('@', '\\@')
+        write('--- ' .. l)
+      end
+    end
+
+    local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
+
+    for i, param in ipairs(params) do
+      local pname, ptype = param[1], param[2]
+      local optional = (pname ~= '...' and i > req_args) and '?' or ''
+      write(string.format('--- @param %s%s %s', pname, optional, ptype))
+    end
+
+    if fun.returns ~= false then
+      write('--- @return ' .. (fun.returns or 'any'))
+    end
+
+    write(render_fun_sig(funname, params))
+
+    return
+  end
+
+  print('no doc for', funname)
+end
+
+--- @type table
+local rendered_tags = {}
+
+--- @param f string
+--- @param fun vim.EvalFn
+--- @param write fun(line: string)
+local function render_eval_doc(f, fun, write)
+  if fun.deprecated then
+    return
+  end
+
+  if not fun.signature then
+    return
+  end
+
+  local desc = fun.desc
+
+  if not desc then
+    write(fun.signature)
+    return
+  end
+
+  local name = fun.name or f
+  local tags = { '*' .. name .. '()*' }
+  if fun.tags then
+    for _, t in ipairs(fun.tags) do
+      tags[#tags + 1] = '*' .. t .. '*'
+    end
+  end
+  local tag = table.concat(tags, ' ')
+
+  local siglen = #fun.signature
+  if rendered_tags[name] then
+    write(fun.signature)
+  else
+    if siglen + #tag > 80 then
+      write(string.rep('\t', 6) .. tag)
+      write(fun.signature)
+    else
+      local tt = math.max(1, (76 - siglen - #tag) / 8)
+      write(string.format('%s%s%s', fun.signature, string.rep('\t', tt), tag))
+    end
+  end
+  rendered_tags[name] = true
+
+  desc = vim.trim(desc)
+  local desc_l = vim.split(desc, '\n', { plain = true })
+  for _, l in ipairs(desc_l) do
+    l = l:gsub('^      ', '')
+    if vim.startswith(l, '<') and not l:match('^<[A-Z][A-Z]') then
+      write('<\t\t' .. l:sub(2))
+    else
+      write('\t\t' .. l)
+    end
+  end
+
+  if #desc_l > 0 and not desc_l[#desc_l]:match('^',
+      '\t:let a = "aaaa\\nxxxx"',
+      '\t:echo matchstr(a, "..\\n..")',
+      '\taa',
+      '\txx',
+      '\t:echo matchstr(a, "a.x")',
+      '\ta',
+      '\tx',
+      '',
+      'Don\'t forget that "^" will only match at the first character of the String and',
+      '"$" at the last character of the string.  They don\'t match after or before a',
+      '"\\n".',
+      '',
+      ' vim:tw=78:ts=8:noet:ft=help:norl:',
+    },
+  },
+}
+
+--- @param elem nvim.gen_eval_files.elem
+local function render(elem)
+  local o = assert(io.open(elem.path, 'w'))
+
+  --- @param l string
+  local function write(l)
+    local l1 = l:gsub('%s+$', '')
+    o:write(l1)
+    o:write('\n')
+  end
+
+  for _, l in ipairs(elem.header or {}) do
+    write(l)
+  end
+
+  --- @type string[]
+  local fnames = vim.tbl_keys(funcs)
+  table.sort(fnames)
+
+  for _, f in ipairs(fnames) do
+    elem.render(f, funcs[f], write)
+  end
+
+  for _, l in ipairs(elem.footer or {}) do
+    write(l)
+  end
+
+  o:close()
+end
+
+local function main()
+  for _, c in ipairs(CONFIG) do
+    render(c)
+  end
+end
+
+main()
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index dfad1f000c..61f18ad794 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -1359,4 +1359,7 @@ if __name__ == "__main__":
     else:
         main(Doxyfile, args)
 
+    print('Running ./scripts/gen_eval_files.lua')
+    subprocess.call(['./scripts/gen_eval_files.lua'])
+
 # vim: set ft=python ts=4 sw=4 tw=79 et :
diff --git a/scripts/gen_vimfn_types.lua b/scripts/gen_vimfn_types.lua
deleted file mode 100755
index 32de1d3c95..0000000000
--- a/scripts/gen_vimfn_types.lua
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/usr/bin/env -S nvim -l
-
---- @class vim.EvalFn2 : vim.EvalFn
---- @field signature string
---- @field desc string[]
---- @field params {[1]: string, [2]: string}[]
-
---- @param filename string
---- @return string
-local function safe_read(filename)
-  local file, err = io.open(filename, 'r')
-  if not file then
-    error(err)
-  end
-  local content = file:read('*a')
-  io.close(file)
-  return content
-end
-
-local nvim_eval = require'src/nvim/eval'
-
-local funcs = nvim_eval.funcs --[[@as table]]
-
-local LUA_KEYWORDS = {
-  ['and'] = true,
-  ['end'] = true,
-  ['function'] = true,
-  ['or'] = true,
-  ['if'] = true,
-  ['while'] = true,
-  ['repeat'] = true
-}
-
-local SOURCES = {
-  {
-    path = 'runtime/doc/builtin.txt',
-    from = '^2. Details',
-    to = '==========',
-  },
-  {
-    path = 'runtime/doc/sign.txt',
-    from = '^3. Functions',
-    to = 'vim:'
-  },
-  {
-    path = 'runtime/doc/testing.txt',
-    from = '^3. Assert functions',
-    to = 'vim:'
-  }
-}
-
-local ARG_NAME_TYPES = {
-  col = 'integer',
-  nosuf = 'boolean',
-  dir = 'string',
-  mode = 'string',
-  width = 'integer',
-  height = 'integer',
-  timeout = 'integer',
-  libname = 'string',
-  funcname = 'string',
-  end_ = 'integer',
-  file = 'string',
-  flags = 'string',
-  fname = 'integer',
-  idx = 'integer',
-  lnum = 'integer',
-  mods = 'string',
-  name = 'string',
-  nr = 'integer',
-  options = 'table',
-  opts = 'table',
-  path = 'string',
-  regname = 'string',
-  silent = 'boolean',
-  string = 'string',
-  tabnr = 'integer',
-  varname = 'string',
-  winid = 'integer',
-  winnr = 'integer',
-}
-
-local function process_source(source)
-  local src_txt = safe_read(source.path)
-
-  --- @type string[]
-  local src_lines = vim.split(src_txt, '\n', { plain = true })
-
-  local s = 0
-  for i, l in ipairs(src_lines) do
-    if l:match(source.from) then
-      s = i+1
-    end
-  end
-
-  local lines = {} --- @type string[]
-  local last_f --- @type string?
-  local last_l --- @type string?
-
-  for i = s, #src_lines do
-    local l = src_lines[i]
-    if not l or l:match(source.to) then
-      break
-    end
-    local f = l:match('^([a-z][a-zA-Z0-9_]*)%(')
-    if f then
-      if last_f then
-        if last_l and last_l:find('*' .. f .. '()*', 1, true) then
-          lines[#lines] = nil
-        end
-        funcs[last_f].desc = lines
-      end
-      last_f = f
-      local sig = l:match('[^)]+%)')
-      local params = {} --- @type table[]
-      if sig then
-        for param in string.gmatch(sig, '{([a-z][a-zA-Z0-9_]*)}') do
-          local t = ARG_NAME_TYPES[param] or 'any'
-          params[#params+1] = {param, t}
-        end
-      else
-        print('error parsing', l)
-      end
-
-      funcs[last_f].signature = sig
-      funcs[last_f].params = params
-
-      lines = {}
-    else
-      lines[#lines+1] = l:gsub('^(
-  local sfx = 1
-
-  for _, p in ipairs(fun.params) do
-    if LUA_KEYWORDS[p[1]] then
-      p[1] = p[1]..'_'
-    end
-    if seen[p[1]] then
-      p[1] = p[1]..sfx
-      sfx = sfx + 1
-    else
-      seen[p[1]] = true
-    end
-  end
-end
-
---- @param funname string
---- @param fun vim.EvalFn2
---- @param write fun(line: string)
-local function render_fun(funname, fun, write)
-  if fun.deprecated then
-    write('')
-    write('--- @deprecated')
-    for _, l in ipairs(fun.deprecated) do
-      write('--- '.. l)
-    end
-    write(render_fun_sig(funname, true))
-    return
-  end
-
-  if fun.desc and fun.signature then
-    write('')
-    for _, l in ipairs(fun.desc) do
-      write('--- '.. l:gsub('@', '\\@'))
-    end
-
-    local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
-
-    for i, param in ipairs(fun.params) do
-      if i <= req_args then
-        write('--- @param '..param[1]..' '..param[2])
-      else
-        write('--- @param '..param[1]..'? '..param[2])
-      end
-    end
-    if fun.returns ~= false then
-      write('--- @return '..(fun.returns or 'any'))
-    end
-    write(render_fun_sig(funname, fun.params))
-    return
-  end
-
-  print('no doc for', funname)
-end
-
-local function main(outfile)
-  local o = assert(io.open(outfile, 'w'))
-
-  local function write(l)
-    local l1 = l:gsub('%s+$', '')
-    o:write(l1)
-    o:write('\n')
-  end
-
-  for _, source in ipairs(SOURCES) do
-    process_source(source)
-  end
-
-  --- @type string[]
-  local fnames = vim.tbl_keys(funcs)
-  table.sort(fnames)
-
-  write('--- @meta')
-  write('-- THIS FILE IS GENERATED')
-  write('-- DO NOT EDIT')
-
-  for _, f in ipairs(fnames) do
-    local fun = funcs[f]
-    process_params(fun)
-    render_fun(f, fun, write)
-  end
-end
-
-main('runtime/lua/vim/_meta/vimfn.lua')
-
-- 
cgit 


From 9b5f58185e1ff0597c7e95b7205d9ec11be1848c Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 1 Aug 2023 09:57:52 +0100
Subject: docs(builtin): fix and annotate language blocks (#24506)

---
 scripts/gen_eval_files.lua | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 7193346758..ee8bbe48a3 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -217,14 +217,14 @@ local CONFIG = {
       'same way.  The difference is that a String is handled like it is one line.',
       'When it contains a "\\n" character, this is not seen as a line break for the',
       'pattern.  It can be matched with a "\\n" in the pattern, or with ".".  Example:',
-      '>',
-      '\t:let a = "aaaa\\nxxxx"',
-      '\t:echo matchstr(a, "..\\n..")',
-      '\taa',
-      '\txx',
-      '\t:echo matchstr(a, "a.x")',
-      '\ta',
-      '\tx',
+      '>vim',
+      '\tlet a = "aaaa\\nxxxx"',
+      '\techo matchstr(a, "..\\n..")',
+      '\t" aa',
+      '\t" xx',
+      '\techo matchstr(a, "a.x")',
+      '\t" a',
+      '\t" x',
       '',
       'Don\'t forget that "^" will only match at the first character of the String and',
       '"$" at the last character of the string.  They don\'t match after or before a',
-- 
cgit 


From 20bfdbe83253cf5ec0a42bd75bd4ed7df945ab37 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 1 Aug 2023 11:12:00 +0100
Subject: docs(builtin): right align tags (#24522)

---
 scripts/gen_eval_files.lua | 43 +++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index ee8bbe48a3..0b845fb246 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -113,6 +113,31 @@ end
 --- @type table
 local rendered_tags = {}
 
+--- @param name string
+--- @param fun vim.EvalFn
+--- @param write fun(line: string)
+local function render_sig_and_tag(name, fun, write)
+  local tags = { '*' .. name .. '()*' }
+
+  if fun.tags then
+    for _, t in ipairs(fun.tags) do
+      tags[#tags + 1] = '*' .. t .. '*'
+    end
+  end
+
+  local tag = table.concat(tags, ' ')
+  local siglen = #fun.signature
+  local conceal_offset = 2*(#tags - 1)
+  local tag_pad_len = math.max(1, 80 - #tag + conceal_offset)
+
+  if siglen + #tag > 80 then
+    write(string.rep(' ', tag_pad_len) .. tag)
+    write(fun.signature)
+  else
+    write(string.format('%s%s%s', fun.signature, string.rep(' ', tag_pad_len - siglen), tag))
+  end
+end
+
 --- @param f string
 --- @param fun vim.EvalFn
 --- @param write fun(line: string)
@@ -133,27 +158,13 @@ local function render_eval_doc(f, fun, write)
   end
 
   local name = fun.name or f
-  local tags = { '*' .. name .. '()*' }
-  if fun.tags then
-    for _, t in ipairs(fun.tags) do
-      tags[#tags + 1] = '*' .. t .. '*'
-    end
-  end
-  local tag = table.concat(tags, ' ')
 
-  local siglen = #fun.signature
   if rendered_tags[name] then
     write(fun.signature)
   else
-    if siglen + #tag > 80 then
-      write(string.rep('\t', 6) .. tag)
-      write(fun.signature)
-    else
-      local tt = math.max(1, (76 - siglen - #tag) / 8)
-      write(string.format('%s%s%s', fun.signature, string.rep('\t', tt), tag))
-    end
+    render_sig_and_tag(name, fun, write)
+    rendered_tags[name] = true
   end
-  rendered_tags[name] = true
 
   desc = vim.trim(desc)
   local desc_l = vim.split(desc, '\n', { plain = true })
-- 
cgit 


From 48d533272e57e91e4d14c93b26d4922957f40cd7 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 1 Aug 2023 14:20:44 +0100
Subject: feat(lua-types): types for vim.api.* (#24523)

---
 scripts/gen_eval_files.lua | 263 +++++++++++++++++++++++++++++++++++++++++++--
 scripts/gen_vimdoc.py      |   4 +-
 2 files changed, 257 insertions(+), 10 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 0b845fb246..7e470a3105 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -1,7 +1,35 @@
 #!/usr/bin/env -S nvim -l
 -- Generator for src/nvim/eval.lua
 
-local funcs = require('src/nvim/eval').funcs
+--- @class vim.api.metadata
+--- @field name string
+--- @field parameters {[1]:string,[2]:string}[]
+--- @field return_type string
+--- @field deprecated_since integer
+--- @field eval boolean
+--- @field fast boolean
+--- @field handler_id integer
+--- @field impl_name string
+--- @field lua boolean
+--- @field method boolean
+--- @field remote boolean
+--- @field since integer
+
+local LUA_META_HEADER = {
+  '--- @meta',
+  '-- THIS FILE IS GENERATED',
+  '-- DO NOT EDIT',
+  "error('Cannot require a meta file')",
+}
+
+local LUA_API_META_HEADER = {
+  '--- @meta',
+  '-- THIS FILE IS GENERATED',
+  '-- DO NOT EDIT',
+  "error('Cannot require a meta file')",
+  '',
+  'vim.api = {}',
+}
 
 local LUA_KEYWORDS = {
   ['and'] = true,
@@ -13,6 +41,47 @@ local LUA_KEYWORDS = {
   ['repeat'] = true,
 }
 
+local API_TYPES = {
+  Window = 'integer',
+  Tabpage = 'integer',
+  Buffer = 'integer',
+  Boolean = 'boolean',
+  Object = 'any',
+  Integer = 'integer',
+  String = 'string',
+  Array = 'any[]',
+  LuaRef = 'function',
+  Dictionary = 'table',
+  Float = 'number',
+  void = '',
+}
+
+--- Convert an API type to Lua
+--- @param t string
+--- @return string
+local function api_type(t)
+  if t:match('^ArrayOf%(([z-aA-Z]+), %d+%') then
+    print(t:match('^ArrayOf%(([z-aA-Z]+), %d+%'))
+  end
+  local as0 = t:match('^ArrayOf%((.*)%)')
+  if as0 then
+    local as = vim.split(as0, ', ', { plain = true })
+    return api_type(as[1]) .. '[]'
+  end
+
+  local d = t:match('^Dict%((.*)%)')
+  if d then
+    return 'vim.api.keyset.' .. d
+  end
+
+  local d0 = t:match('^DictionaryOf%((.*)%)')
+  if d0 then
+    return 'table'
+  end
+
+  return API_TYPES[t] or t
+end
+
 --- @param f string
 --- @param params {[1]:string,[2]:string}[]|true
 local function render_fun_sig(f, params)
@@ -41,8 +110,8 @@ end
 
 --- Uniquify names
 --- Fix any names that are lua keywords
---- @param params {[1]:string,[2]:string}[]
---- @return {[1]:string,[2]:string}[]
+--- @param params {[1]:string,[2]:string,[3]:string}[]
+--- @return {[1]:string,[2]:string,[3]:string}[]
 local function process_params(params)
   local seen = {} --- @type table
   local sfx = 1
@@ -62,6 +131,170 @@ local function process_params(params)
   return params
 end
 
+--- @class vim.gen_vim_doc_fun
+--- @field signature string
+--- @field doc string[]
+--- @field parameters_doc table
+--- @field return string[]
+--- @field seealso string[]
+--- @field annotations string[]
+
+--- @return table
+local function get_api_funcs()
+  local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
+  local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]]
+  local ret = {} --- @type table
+
+  local doc_mpack_f = assert(io.open('runtime/doc/api.mpack', 'rb'))
+  local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]]
+
+  for _, fun in ipairs(metadata) do
+    local fdoc = doc_metadata[fun.name]
+
+    local params = {} --- @type {[1]:string,[2]:string}[]
+    for _, p in ipairs(fun.parameters) do
+      local ptype, pname = p[1], p[2]
+      params[#params + 1] = {
+        pname,
+        api_type(ptype),
+        fdoc and fdoc.parameters_doc[pname] or nil,
+      }
+    end
+
+    local r = {
+      signature = 'NA',
+      name = fun.name,
+      params = params,
+      returns = api_type(fun.return_type),
+      deprecated = fun.deprecated_since ~= nil,
+    }
+
+    if fdoc then
+      if #fdoc.doc > 0 then
+        r.desc = table.concat(fdoc.doc, '\n')
+      end
+      r.return_desc = (fdoc['return'] or {})[1]
+    end
+
+    ret[fun.name] = r
+  end
+  return ret
+end
+
+--- Convert vimdoc references to markdown literals
+--- Convert vimdoc codeblocks to markdown codeblocks
+--- @param x string
+--- @return string
+local function norm_text(x)
+  return (
+    x:gsub('|([^ ]+)|', '`%1`')
+      :gsub('>lua', '\n```lua')
+      :gsub('>vim', '\n```vim')
+      :gsub('\n<$', '\n```')
+      :gsub('\n<\n', '\n```\n')
+  )
+end
+
+--- @param _f string
+--- @param fun vim.EvalFn
+--- @param write fun(line: string)
+local function render_api_fun(_f, fun, write)
+  if not vim.startswith(fun.name, 'nvim_') then
+    return
+  end
+
+  write('')
+
+  if vim.startswith(fun.name, 'nvim__') then
+    write('--- @private')
+  end
+
+  if fun.deprecated then
+    write('--- @deprecated')
+  end
+
+  local desc = fun.desc
+  if desc then
+    for _, l in ipairs(vim.split(norm_text(desc), '\n', { plain = true })) do
+      write('--- ' .. l)
+    end
+    write('---')
+  end
+
+  local param_names = {} --- @type string[]
+  local params = process_params(fun.params)
+  for _, p in ipairs(params) do
+    param_names[#param_names + 1] = p[1]
+    local pdesc = p[3]
+    if pdesc then
+      local pdesc_a = vim.split(norm_text(pdesc), '\n', { plain = true })
+      write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1])
+      for i = 2, #pdesc_a do
+        if not pdesc_a[i] then
+          break
+        end
+        write('--- ' .. pdesc_a[i])
+      end
+    else
+      write('--- @param ' .. p[1] .. ' ' .. p[2])
+    end
+  end
+  if fun.returns ~= '' then
+    if fun.returns_desc then
+      write('--- @return ' .. fun.returns .. ' : ' .. fun.returns_desc)
+    else
+      write('--- @return ' .. fun.returns)
+    end
+  end
+  local param_str = table.concat(param_names, ', ')
+
+  write(string.format('function vim.api.%s(%s) end', fun.name, param_str))
+end
+
+--- @return table
+local function get_api_keysets()
+  local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
+
+  --- @diagnostic disable-next-line:no-unknown
+  local metadata = assert(vim.mpack.decode(mpack_f:read('*all')))
+
+  local ret = {} --- @type table
+
+  --- @type {[1]: string, [2]: {[1]: string, [2]: string}[] }[]
+  local keysets = metadata.keysets
+
+  for _, keyset in ipairs(keysets) do
+    local kname = keyset[1]
+    local kdef = keyset[2]
+    for _, field in ipairs(kdef) do
+      field[2] = api_type(field[2])
+    end
+    ret[kname] = {
+      signature = 'NA',
+      name = kname,
+      params = kdef,
+    }
+  end
+
+  return ret
+end
+
+--- @param _f string
+--- @param fun vim.EvalFn
+--- @param write fun(line: string)
+local function render_api_keyset(_f, fun, write)
+  write('')
+  write('--- @class vim.api.keyset.' .. fun.name)
+  for _, p in ipairs(fun.params) do
+    write('--- @field ' .. p[1] .. ' ' .. p[2])
+  end
+end
+
+--- @return table
+local function get_eval_funcs()
+  return require('src/nvim/eval').funcs
+end
+
 --- @param f string
 --- @param fun vim.EvalFn
 --- @param write fun(line: string)
@@ -83,6 +316,7 @@ local function render_vimfn(f, fun, write)
     local desc = fun.desc
 
     if desc then
+      --- @type string
       desc = desc:gsub('\n%s*\n%s*$', '\n')
       for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do
         l = l:gsub('^      ', ''):gsub('\t', '  '):gsub('@', '\\@')
@@ -184,6 +418,7 @@ end
 
 --- @class nvim.gen_eval_files.elem
 --- @field path string
+--- @field funcs fun(): table
 --- @field render fun(f:string,fun:vim.EvalFn,write:fun(line:string))
 --- @field header? string[]
 --- @field footer? string[]
@@ -192,15 +427,25 @@ end
 local CONFIG = {
   {
     path = 'runtime/lua/vim/_meta/vimfn.lua',
+    header = LUA_META_HEADER,
+    funcs = get_eval_funcs,
     render = render_vimfn,
-    header = {
-      '--- @meta',
-      '-- THIS FILE IS GENERATED',
-      '-- DO NOT EDIT',
-    },
+  },
+  {
+    path = 'runtime/lua/vim/_meta/api.lua',
+    header = LUA_API_META_HEADER,
+    funcs = get_api_funcs,
+    render = render_api_fun,
+  },
+  {
+    path = 'runtime/lua/vim/_meta/api_keysets.lua',
+    header = LUA_META_HEADER,
+    funcs = get_api_keysets,
+    render = render_api_keyset,
   },
   {
     path = 'runtime/doc/builtin.txt',
+    funcs = get_eval_funcs,
     render = render_eval_doc,
     header = {
       '*builtin.txt*	Nvim',
@@ -261,6 +506,8 @@ local function render(elem)
     write(l)
   end
 
+  local funcs = elem.funcs()
+
   --- @type string[]
   local fnames = vim.tbl_keys(funcs)
   table.sort(fnames)
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 61f18ad794..9a1316a328 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -1359,7 +1359,7 @@ if __name__ == "__main__":
     else:
         main(Doxyfile, args)
 
-    print('Running ./scripts/gen_eval_files.lua')
-    subprocess.call(['./scripts/gen_eval_files.lua'])
+        print('Running ./scripts/gen_eval_files.lua')
+        subprocess.call(['./scripts/gen_eval_files.lua'])
 
 # vim: set ft=python ts=4 sw=4 tw=79 et :
-- 
cgit 


From da09f9b551badfb3fd363589009168560ae607f6 Mon Sep 17 00:00:00 2001
From: mathew 
Date: Fri, 28 Jul 2023 15:24:18 +0800
Subject: feat(gen_lsp.lua): protocol.Methods #24504

---
 scripts/lsp_types.lua | 133 +++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 115 insertions(+), 18 deletions(-)

(limited to 'scripts')

diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua
index 4a089bd76d..61ee6ad309 100644
--- a/scripts/lsp_types.lua
+++ b/scripts/lsp_types.lua
@@ -2,8 +2,9 @@
 Generates lua-ls annotations for lsp
 USAGE:
 nvim -l scripts/lsp_types.lua gen  # this will overwrite runtime/lua/vim/lsp/types/protocol.lua
-nvim -l scripts/lsp_types.lua gen --build/new_lsp_types.lua
-nvim -l scripts/lsp_types.lua gen --out runtime/lua/vim/lsp/types/protocol.lua --ref 2023.0.0a2 # specify a git reference from microsoft/lsprotocol
+nvim -l scripts/lsp_types.lua gen --version 3.1x --build/new_lsp_types.lua
+nvim -l scripts/lsp_types.lua gen --version 3.1x --out runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/lsp_types.lua gen --version 3.1x --methods
 --]]
 
 local M = {}
@@ -18,24 +19,117 @@ local function tofile(fname, text)
   end
 end
 
-function M.gen(opt)
-  if vim.uv.fs_stat('./lsp.json') then
-    vim.fn.delete('./lsp.json')
+local function sort_by_method(tbl)
+  local single, client, textD, workspace, others = {}, {}, {}, {}, {}
+  for _, item in ipairs(tbl) do
+    local parts = vim.split(item.method, '/', { trimempty = true })
+    if #parts == 1 then
+      single[#single + 1] = item
+    elseif parts[1] == 'textDocument' then
+      textD[#textD + 1] = item
+    elseif parts[1] == 'client' then
+      client[#client + 1] = item
+    elseif parts[1] == 'workspace' then
+      workspace[#workspace + 1] = item
+    else
+      others[#others + 1] = item
+    end
+  end
+
+  local res = {}
+  for _, item in ipairs({ single, client, textD, workspace, others }) do
+    res = vim.list_extend(res, item)
   end
-  vim.fn.system({
-    'curl',
-    'https://raw.githubusercontent.com/microsoft/lsprotocol/' .. opt.ref .. '/generator/lsp.json',
-    '-o',
-    './lsp.json',
+  return res
+end
+
+local function read_json(opt)
+  local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/'
+    .. opt.version
+    .. '/metaModel/metaModel.json'
+
+  local res = vim.system({ 'curl', uri, '-o', '-' }):wait()
+
+  if res.code ~= 0 then
+    io.write(res.stderr)
+    return
+  end
+  return vim.json.decode(res.stdout)
+end
+
+local function gen_methods(protocol)
+  local output = {
+    '-- Generated by lsp_types.lua, keep at end of file.',
+    '--- LSP method names.',
+    '---',
+    '---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel',
+    'protocol.Methods = {',
+  }
+  local indent = (' '):rep(2)
+
+  for _, item in ipairs(sort_by_method(protocol.requests)) do
+    if item.method then
+      local name = item.method:gsub('/', '_', 3)
+      if item.documentation then
+        local document = vim.split(item.documentation, '\n?\n', { trimempty = true })
+        for _, docstring in ipairs(document) do
+          output[#output + 1] = indent .. '--- ' .. docstring
+        end
+      end
+      output[#output + 1] = indent .. name .. " = '" .. item.method .. "',"
+    end
+  end
+  output[#output + 1] = '}'
+  output = vim.list_extend(
+    output,
+    vim.split(
+      [[
+local function freeze(t)
+  return setmetatable({}, {
+    __index = t,
+    __newindex = function()
+      error('cannot modify immutable table')
+    end,
   })
-  local protocol = vim.fn.json_decode(vim.fn.readfile('./lsp.json'))
-  vim.fn.delete('./lsp.json')
-  protocol = protocol or {}
+end
+protocol.Methods = freeze(protocol.Methods)
+
+return protocol
+]],
+      '\n',
+      { trimempty = true }
+    )
+  )
+
+  local fname = './runtime/lua/vim/lsp/protocol.lua'
+  local bufnr = vim.fn.bufadd(fname)
+  vim.fn.bufload(bufnr)
+  vim.api.nvim_set_current_buf(bufnr)
+  local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+  local index = vim.iter(ipairs(lines)):find(function(key, item)
+    return vim.startswith(item, '-- Generated by') and key or nil
+  end)
+  index = index and index - 1 or vim.api.nvim_buf_line_count(bufnr) - 1
+  vim.api.nvim_buf_set_lines(bufnr, index, -1, true, output)
+  vim.cmd.write()
+end
+
+function M.gen(opt)
+  local protocol = read_json(opt)
+  if not protocol then
+    os.exit(1)
+    return
+  end
+
+  if opt.methods then
+    gen_methods(protocol)
+  end
+
   local output = {
     '--[[',
     'This file is autogenerated from scripts/lsp_types.lua',
     'Regenerate:',
-    [=[nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua]=],
+    [=[nvim -l scripts/lsp_types.lua gen --version 3.1x --runtime/lua/vim/lsp/types/protocol.lua]=],
     '--]]',
     '',
     '---@alias lsp.null nil',
@@ -190,14 +284,17 @@ end
 
 local opt = {
   output_file = 'runtime/lua/vim/lsp/types/protocol.lua',
-  ref = 'main',
+  version = nil,
+  methods = nil,
 }
 
 for i = 1, #_G.arg do
   if _G.arg[i] == '--out' then
-    opt.output_file = _G.arg[i+1]
-  elseif _G.arg[i] == '--ref' then
-    opt.ref = _G.arg[i+1]
+    opt.output_file = _G.arg[i + 1]
+  elseif _G.arg[i] == '--version' then
+    opt.version = _G.arg[i + 1]
+  elseif _G.arg[i] == '--methods' then
+    opt.methods = true
   elseif vim.startswith(_G.arg[i], '--') then
     opt.output_file = _G.arg[i]:sub(3)
   end
-- 
cgit 


From f41496ce74fb30c18bb9a03027a172800b269643 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Tue, 1 Aug 2023 15:52:53 +0200
Subject: feat(gen_lsp.lua): sort by name, handle failure #24504

---
 scripts/gen_lsp.lua   | 288 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/lsp_types.lua | 309 --------------------------------------------------
 2 files changed, 288 insertions(+), 309 deletions(-)
 create mode 100644 scripts/gen_lsp.lua
 delete mode 100644 scripts/lsp_types.lua

(limited to 'scripts')

diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua
new file mode 100644
index 0000000000..ef9d6c41df
--- /dev/null
+++ b/scripts/gen_lsp.lua
@@ -0,0 +1,288 @@
+--[[
+Generates lua-ls annotations for lsp
+USAGE:
+nvim -l scripts/gen_lsp.lua gen  # this will overwrite runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/gen_lsp.lua gen --version 3.18 --build/new_lsp_types.lua
+nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/gen_lsp.lua gen --version 3.18 --methods
+--]]
+
+local M = {}
+
+local function tofile(fname, text)
+  local f = io.open(fname, 'w')
+  if not f then
+    error(('failed to write: %s'):format(f))
+  else
+    f:write(text)
+    f:close()
+  end
+end
+
+local function read_json(opt)
+  local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/'
+    .. opt.version
+    .. '/metaModel/metaModel.json'
+
+  local res = vim.system({ 'curl', '--no-progress-meter', uri, '-o', '-' }):wait()
+  if res.code ~= 0 or (res.stdout or ''):len() < 999 then
+    print(('URL failed: %s'):format(uri))
+    vim.print(res)
+    error(res.stdout)
+  end
+  return vim.json.decode(res.stdout)
+end
+
+-- Gets the Lua symbol for a given fully-qualified LSP method name.
+local function name(s)
+  return s:gsub('/', '_', 3)
+end
+
+local function gen_methods(protocol)
+  local output = {
+    '-- Generated by gen_lsp.lua, keep at end of file.',
+    '--- LSP method names.',
+    '---',
+    '---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel',
+    'protocol.Methods = {',
+  }
+  local indent = (' '):rep(2)
+
+  table.sort(protocol.requests, function(a, b)
+    return name(a.method) < name(b.method)
+  end)
+  for _, item in ipairs(protocol.requests) do
+    if item.method then
+      if item.documentation then
+        local document = vim.split(item.documentation, '\n?\n', { trimempty = true })
+        for _, docstring in ipairs(document) do
+          output[#output + 1] = indent .. '--- ' .. docstring
+        end
+      end
+      output[#output + 1] = ("%s%s = '%s',"):format(indent, name(item.method), item.method)
+    end
+  end
+  output[#output + 1] = '}'
+  output = vim.list_extend(
+    output,
+    vim.split(
+      [[
+local function freeze(t)
+  return setmetatable({}, {
+    __index = t,
+    __newindex = function()
+      error('cannot modify immutable table')
+    end,
+  })
+end
+protocol.Methods = freeze(protocol.Methods)
+
+return protocol
+]],
+      '\n',
+      { trimempty = true }
+    )
+  )
+
+  local fname = './runtime/lua/vim/lsp/protocol.lua'
+  local bufnr = vim.fn.bufadd(fname)
+  vim.fn.bufload(bufnr)
+  vim.api.nvim_set_current_buf(bufnr)
+  local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+  local index = vim.iter(ipairs(lines)):find(function(key, item)
+    return vim.startswith(item, '-- Generated by') and key or nil
+  end)
+  index = index and index - 1 or vim.api.nvim_buf_line_count(bufnr) - 1
+  vim.api.nvim_buf_set_lines(bufnr, index, -1, true, output)
+  vim.cmd.write()
+end
+
+function M.gen(opt)
+  local protocol = read_json(opt)
+
+  if opt.methods then
+    gen_methods(protocol)
+  end
+
+  local output = {
+    '--[[',
+    'This file is autogenerated from scripts/gen_lsp.lua',
+    'Regenerate:',
+    [=[nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/types/protocol.lua]=],
+    '--]]',
+    '',
+    '---@alias lsp.null nil',
+    '---@alias uinteger integer',
+    '---@alias lsp.decimal number',
+    '---@alias lsp.DocumentUri string',
+    '---@alias lsp.URI string',
+    '---@alias lsp.LSPObject table',
+    '---@alias lsp.LSPArray lsp.LSPAny[]',
+    '---@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil',
+    '',
+  }
+
+  local anonymous_num = 0
+
+  local anonym_classes = {}
+
+  local simple_types = {
+    'string',
+    'boolean',
+    'integer',
+    'uinteger',
+    'decimal',
+  }
+
+  local function parse_type(type)
+    if type.kind == 'reference' or type.kind == 'base' then
+      if vim.tbl_contains(simple_types, type.name) then
+        return type.name
+      end
+      return 'lsp.' .. type.name
+    elseif type.kind == 'array' then
+      return parse_type(type.element) .. '[]'
+    elseif type.kind == 'or' then
+      local val = ''
+      for _, item in ipairs(type.items) do
+        val = val .. parse_type(item) .. '|'
+      end
+      val = val:sub(0, -2)
+      return val
+    elseif type.kind == 'stringLiteral' then
+      return '"' .. type.value .. '"'
+    elseif type.kind == 'map' then
+      return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>'
+    elseif type.kind == 'literal' then
+      -- can I use ---@param disabled? {reason: string}
+      -- use | to continue the inline class to be able to add docs
+      -- https://github.com/LuaLS/lua-language-server/issues/2128
+      anonymous_num = anonymous_num + 1
+      local anonym = { '---@class anonym' .. anonymous_num }
+      for _, field in ipairs(type.value.properties) do
+        if field.documentation then
+          field.documentation = field.documentation:gsub('\n', '\n---')
+          anonym[#anonym + 1] = '---' .. field.documentation
+        end
+        anonym[#anonym + 1] = '---@field '
+          .. field.name
+          .. (field.optional and '?' or '')
+          .. ' '
+          .. parse_type(field.type)
+      end
+      anonym[#anonym + 1] = ''
+      for _, line in ipairs(anonym) do
+        anonym_classes[#anonym_classes + 1] = line
+      end
+      return 'anonym' .. anonymous_num
+    elseif type.kind == 'tuple' then
+      local tuple = '{ '
+      for i, value in ipairs(type.items) do
+        tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value) .. ', '
+      end
+      -- remove , at the end
+      tuple = tuple:sub(0, -3)
+      return tuple .. ' }'
+    end
+    vim.print(type)
+    return ''
+  end
+
+  for _, structure in ipairs(protocol.structures) do
+    if structure.documentation then
+      structure.documentation = structure.documentation:gsub('\n', '\n---')
+      output[#output + 1] = '---' .. structure.documentation
+    end
+    if structure.extends then
+      local class_string = '---@class lsp.'
+        .. structure.name
+        .. ': '
+        .. parse_type(structure.extends[1])
+      for _, mixin in ipairs(structure.mixins or {}) do
+        class_string = class_string .. ', ' .. parse_type(mixin)
+      end
+      output[#output + 1] = class_string
+    else
+      output[#output + 1] = '---@class lsp.' .. structure.name
+    end
+    for _, field in ipairs(structure.properties or {}) do
+      if field.documentation then
+        field.documentation = field.documentation:gsub('\n', '\n---')
+        output[#output + 1] = '---' .. field.documentation
+      end
+      output[#output + 1] = '---@field '
+        .. field.name
+        .. (field.optional and '?' or '')
+        .. ' '
+        .. parse_type(field.type)
+    end
+    output[#output + 1] = ''
+  end
+
+  for _, enum in ipairs(protocol.enumerations) do
+    if enum.documentation then
+      enum.documentation = enum.documentation:gsub('\n', '\n---')
+      output[#output + 1] = '---' .. enum.documentation
+    end
+    local enum_type = '---@alias lsp.' .. enum.name
+    for _, value in ipairs(enum.values) do
+      enum_type = enum_type
+        .. '\n---| '
+        .. (type(value.value) == 'string' and '"' .. value.value .. '"' or value.value)
+        .. ' # '
+        .. value.name
+    end
+    output[#output + 1] = enum_type
+    output[#output + 1] = ''
+  end
+
+  for _, alias in ipairs(protocol.typeAliases) do
+    if alias.documentation then
+      alias.documentation = alias.documentation:gsub('\n', '\n---')
+      output[#output + 1] = '---' .. alias.documentation
+    end
+    if alias.type.kind == 'or' then
+      local alias_type = '---@alias lsp.' .. alias.name .. ' '
+      for _, item in ipairs(alias.type.items) do
+        alias_type = alias_type .. parse_type(item) .. '|'
+      end
+      alias_type = alias_type:sub(0, -2)
+      output[#output + 1] = alias_type
+    else
+      output[#output + 1] = '---@alias lsp.' .. alias.name .. ' ' .. parse_type(alias.type)
+    end
+    output[#output + 1] = ''
+  end
+
+  for _, line in ipairs(anonym_classes) do
+    output[#output + 1] = line
+  end
+
+  tofile(opt.output_file, table.concat(output, '\n'))
+end
+
+local opt = {
+  output_file = 'runtime/lua/vim/lsp/types/protocol.lua',
+  version = nil,
+  methods = nil,
+}
+
+for i = 1, #_G.arg do
+  if _G.arg[i] == '--out' then
+    opt.output_file = _G.arg[i + 1]
+  elseif _G.arg[i] == '--version' then
+    opt.version = _G.arg[i + 1]
+  elseif _G.arg[i] == '--methods' then
+    opt.methods = true
+  elseif vim.startswith(_G.arg[i], '--') then
+    opt.output_file = _G.arg[i]:sub(3)
+  end
+end
+
+for _, a in ipairs(arg) do
+  if M[a] then
+    M[a](opt)
+  end
+end
+
+return M
diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua
deleted file mode 100644
index 61ee6ad309..0000000000
--- a/scripts/lsp_types.lua
+++ /dev/null
@@ -1,309 +0,0 @@
---[[
-Generates lua-ls annotations for lsp
-USAGE:
-nvim -l scripts/lsp_types.lua gen  # this will overwrite runtime/lua/vim/lsp/types/protocol.lua
-nvim -l scripts/lsp_types.lua gen --version 3.1x --build/new_lsp_types.lua
-nvim -l scripts/lsp_types.lua gen --version 3.1x --out runtime/lua/vim/lsp/types/protocol.lua
-nvim -l scripts/lsp_types.lua gen --version 3.1x --methods
---]]
-
-local M = {}
-
-local function tofile(fname, text)
-  local f = io.open(fname, 'w')
-  if not f then
-    error(('failed to write: %s'):format(f))
-  else
-    f:write(text)
-    f:close()
-  end
-end
-
-local function sort_by_method(tbl)
-  local single, client, textD, workspace, others = {}, {}, {}, {}, {}
-  for _, item in ipairs(tbl) do
-    local parts = vim.split(item.method, '/', { trimempty = true })
-    if #parts == 1 then
-      single[#single + 1] = item
-    elseif parts[1] == 'textDocument' then
-      textD[#textD + 1] = item
-    elseif parts[1] == 'client' then
-      client[#client + 1] = item
-    elseif parts[1] == 'workspace' then
-      workspace[#workspace + 1] = item
-    else
-      others[#others + 1] = item
-    end
-  end
-
-  local res = {}
-  for _, item in ipairs({ single, client, textD, workspace, others }) do
-    res = vim.list_extend(res, item)
-  end
-  return res
-end
-
-local function read_json(opt)
-  local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/'
-    .. opt.version
-    .. '/metaModel/metaModel.json'
-
-  local res = vim.system({ 'curl', uri, '-o', '-' }):wait()
-
-  if res.code ~= 0 then
-    io.write(res.stderr)
-    return
-  end
-  return vim.json.decode(res.stdout)
-end
-
-local function gen_methods(protocol)
-  local output = {
-    '-- Generated by lsp_types.lua, keep at end of file.',
-    '--- LSP method names.',
-    '---',
-    '---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel',
-    'protocol.Methods = {',
-  }
-  local indent = (' '):rep(2)
-
-  for _, item in ipairs(sort_by_method(protocol.requests)) do
-    if item.method then
-      local name = item.method:gsub('/', '_', 3)
-      if item.documentation then
-        local document = vim.split(item.documentation, '\n?\n', { trimempty = true })
-        for _, docstring in ipairs(document) do
-          output[#output + 1] = indent .. '--- ' .. docstring
-        end
-      end
-      output[#output + 1] = indent .. name .. " = '" .. item.method .. "',"
-    end
-  end
-  output[#output + 1] = '}'
-  output = vim.list_extend(
-    output,
-    vim.split(
-      [[
-local function freeze(t)
-  return setmetatable({}, {
-    __index = t,
-    __newindex = function()
-      error('cannot modify immutable table')
-    end,
-  })
-end
-protocol.Methods = freeze(protocol.Methods)
-
-return protocol
-]],
-      '\n',
-      { trimempty = true }
-    )
-  )
-
-  local fname = './runtime/lua/vim/lsp/protocol.lua'
-  local bufnr = vim.fn.bufadd(fname)
-  vim.fn.bufload(bufnr)
-  vim.api.nvim_set_current_buf(bufnr)
-  local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
-  local index = vim.iter(ipairs(lines)):find(function(key, item)
-    return vim.startswith(item, '-- Generated by') and key or nil
-  end)
-  index = index and index - 1 or vim.api.nvim_buf_line_count(bufnr) - 1
-  vim.api.nvim_buf_set_lines(bufnr, index, -1, true, output)
-  vim.cmd.write()
-end
-
-function M.gen(opt)
-  local protocol = read_json(opt)
-  if not protocol then
-    os.exit(1)
-    return
-  end
-
-  if opt.methods then
-    gen_methods(protocol)
-  end
-
-  local output = {
-    '--[[',
-    'This file is autogenerated from scripts/lsp_types.lua',
-    'Regenerate:',
-    [=[nvim -l scripts/lsp_types.lua gen --version 3.1x --runtime/lua/vim/lsp/types/protocol.lua]=],
-    '--]]',
-    '',
-    '---@alias lsp.null nil',
-    '---@alias uinteger integer',
-    '---@alias lsp.decimal number',
-    '---@alias lsp.DocumentUri string',
-    '---@alias lsp.URI string',
-    '---@alias lsp.LSPObject table',
-    '---@alias lsp.LSPArray lsp.LSPAny[]',
-    '---@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil',
-    '',
-  }
-
-  local anonymous_num = 0
-
-  local anonym_classes = {}
-
-  local simple_types = {
-    'string',
-    'boolean',
-    'integer',
-    'uinteger',
-    'decimal',
-  }
-
-  local function parse_type(type)
-    if type.kind == 'reference' or type.kind == 'base' then
-      if vim.tbl_contains(simple_types, type.name) then
-        return type.name
-      end
-      return 'lsp.' .. type.name
-    elseif type.kind == 'array' then
-      return parse_type(type.element) .. '[]'
-    elseif type.kind == 'or' then
-      local val = ''
-      for _, item in ipairs(type.items) do
-        val = val .. parse_type(item) .. '|'
-      end
-      val = val:sub(0, -2)
-      return val
-    elseif type.kind == 'stringLiteral' then
-      return '"' .. type.value .. '"'
-    elseif type.kind == 'map' then
-      return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>'
-    elseif type.kind == 'literal' then
-      -- can I use ---@param disabled? {reason: string}
-      -- use | to continue the inline class to be able to add docs
-      -- https://github.com/LuaLS/lua-language-server/issues/2128
-      anonymous_num = anonymous_num + 1
-      local anonym = { '---@class anonym' .. anonymous_num }
-      for _, field in ipairs(type.value.properties) do
-        if field.documentation then
-          field.documentation = field.documentation:gsub('\n', '\n---')
-          anonym[#anonym + 1] = '---' .. field.documentation
-        end
-        anonym[#anonym + 1] = '---@field '
-          .. field.name
-          .. (field.optional and '?' or '')
-          .. ' '
-          .. parse_type(field.type)
-      end
-      anonym[#anonym + 1] = ''
-      for _, line in ipairs(anonym) do
-        anonym_classes[#anonym_classes + 1] = line
-      end
-      return 'anonym' .. anonymous_num
-    elseif type.kind == 'tuple' then
-      local tuple = '{ '
-      for i, value in ipairs(type.items) do
-        tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value) .. ', '
-      end
-      -- remove , at the end
-      tuple = tuple:sub(0, -3)
-      return tuple .. ' }'
-    end
-    vim.print(type)
-    return ''
-  end
-
-  for _, structure in ipairs(protocol.structures) do
-    if structure.documentation then
-      structure.documentation = structure.documentation:gsub('\n', '\n---')
-      output[#output + 1] = '---' .. structure.documentation
-    end
-    if structure.extends then
-      local class_string = '---@class lsp.'
-        .. structure.name
-        .. ': '
-        .. parse_type(structure.extends[1])
-      for _, mixin in ipairs(structure.mixins or {}) do
-        class_string = class_string .. ', ' .. parse_type(mixin)
-      end
-      output[#output + 1] = class_string
-    else
-      output[#output + 1] = '---@class lsp.' .. structure.name
-    end
-    for _, field in ipairs(structure.properties or {}) do
-      if field.documentation then
-        field.documentation = field.documentation:gsub('\n', '\n---')
-        output[#output + 1] = '---' .. field.documentation
-      end
-      output[#output + 1] = '---@field '
-        .. field.name
-        .. (field.optional and '?' or '')
-        .. ' '
-        .. parse_type(field.type)
-    end
-    output[#output + 1] = ''
-  end
-
-  for _, enum in ipairs(protocol.enumerations) do
-    if enum.documentation then
-      enum.documentation = enum.documentation:gsub('\n', '\n---')
-      output[#output + 1] = '---' .. enum.documentation
-    end
-    local enum_type = '---@alias lsp.' .. enum.name
-    for _, value in ipairs(enum.values) do
-      enum_type = enum_type
-        .. '\n---| '
-        .. (type(value.value) == 'string' and '"' .. value.value .. '"' or value.value)
-        .. ' # '
-        .. value.name
-    end
-    output[#output + 1] = enum_type
-    output[#output + 1] = ''
-  end
-
-  for _, alias in ipairs(protocol.typeAliases) do
-    if alias.documentation then
-      alias.documentation = alias.documentation:gsub('\n', '\n---')
-      output[#output + 1] = '---' .. alias.documentation
-    end
-    if alias.type.kind == 'or' then
-      local alias_type = '---@alias lsp.' .. alias.name .. ' '
-      for _, item in ipairs(alias.type.items) do
-        alias_type = alias_type .. parse_type(item) .. '|'
-      end
-      alias_type = alias_type:sub(0, -2)
-      output[#output + 1] = alias_type
-    else
-      output[#output + 1] = '---@alias lsp.' .. alias.name .. ' ' .. parse_type(alias.type)
-    end
-    output[#output + 1] = ''
-  end
-
-  for _, line in ipairs(anonym_classes) do
-    output[#output + 1] = line
-  end
-
-  tofile(opt.output_file, table.concat(output, '\n'))
-end
-
-local opt = {
-  output_file = 'runtime/lua/vim/lsp/types/protocol.lua',
-  version = nil,
-  methods = nil,
-}
-
-for i = 1, #_G.arg do
-  if _G.arg[i] == '--out' then
-    opt.output_file = _G.arg[i + 1]
-  elseif _G.arg[i] == '--version' then
-    opt.version = _G.arg[i + 1]
-  elseif _G.arg[i] == '--methods' then
-    opt.methods = true
-  elseif vim.startswith(_G.arg[i], '--') then
-    opt.output_file = _G.arg[i]:sub(3)
-  end
-end
-
-for _, a in ipairs(arg) do
-  if M[a] then
-    M[a](opt)
-  end
-end
-
-return M
-- 
cgit 


From d086bc1e8590a92a70c414bd60e1e988bbdd3c0a Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Tue, 1 Aug 2023 16:17:26 -0700
Subject: docs: drop "Can also be used as a method" #24508

Now that we "own" builtin.txt, we cant remove the repetitive mention of
Vimscript's UFCS syntax. It's noisy to mention this for each function,
and it's also not a Vimscript feature that should be encouraged.

Also change the builtin.txt heading to "NVIM REFERENCE MANUAL", which
indicates when a help file is Nvim-owned.
---
 scripts/gen_eval_files.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 7e470a3105..c3123fd47c 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -451,7 +451,7 @@ local CONFIG = {
       '*builtin.txt*	Nvim',
       '',
       '',
-      '\t\t  VIM REFERENCE MANUAL\t  by Bram Moolenaar',
+      '\t\t  NVIM REFERENCE MANUAL',
       '',
       '',
       'Builtin functions\t\t*vimscript-functions* *builtin-functions*',
-- 
cgit 


From 214b125132778c5d51d4d7e673d31a9be835e150 Mon Sep 17 00:00:00 2001
From: Raphael 
Date: Thu, 3 Aug 2023 17:52:21 +0800
Subject: fix(gen_lsp.lua): no notifications in lsp.Methods #24530

Problem:
- Notifications are missing from `lsp.Methods`.
- Need a way to represent `$/` prefixed methods.

Solution:
- Generate notifications.
- Use "dollar_" prefix for `$/` methods.
---
 scripts/gen_lsp.lua | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua
index ef9d6c41df..a1bcce4135 100644
--- a/scripts/gen_lsp.lua
+++ b/scripts/gen_lsp.lua
@@ -35,7 +35,8 @@ end
 
 -- Gets the Lua symbol for a given fully-qualified LSP method name.
 local function name(s)
-  return s:gsub('/', '_', 3)
+  -- "$/" prefix is special: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#dollarRequests
+  return s:gsub('^%$', 'dollar'):gsub('/', '_')
 end
 
 local function gen_methods(protocol)
@@ -48,10 +49,11 @@ local function gen_methods(protocol)
   }
   local indent = (' '):rep(2)
 
-  table.sort(protocol.requests, function(a, b)
+  local all = vim.list_extend(protocol.requests, protocol.notifications)
+  table.sort(all, function(a, b)
     return name(a.method) < name(b.method)
   end)
-  for _, item in ipairs(protocol.requests) do
+  for _, item in ipairs(all) do
     if item.method then
       if item.documentation then
         local document = vim.split(item.documentation, '\n?\n', { trimempty = true })
-- 
cgit 


From b1fb04475e6fa0c44895cb6fe97b75816d74c297 Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Thu, 3 Aug 2023 13:41:47 +0200
Subject: docs: remove "#" comment char in @return

Everything after a "#" char is a "description" comment, i.e. luals won't
treat it as a type, name, etc. But "#" should not be present in the
generated docs (such as :help docs).
https://github.com/LuaLS/lua-language-server/wiki/Annotations#return
---
 scripts/lua2dox.lua | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 9a666ea629..01bb8ab57a 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -154,6 +154,8 @@ local function removeCommentFromLine(line)
   return line:sub(1, pos_comment - 1), line:sub(pos_comment)
 end
 
+--- Processes "@…" directives in a docstring line.
+---
 --- @param line string
 --- @param generics table
 --- @return string?
@@ -206,6 +208,8 @@ local function process_magic(line, generics)
       magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1')
       magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1')
     end
+    -- Remove first "#" comment char, if any. https://github.com/LuaLS/lua-language-server/wiki/Annotations#return
+    magic = magic:gsub('# ', '', 1)
     -- handle the return of vim.spell.check
     magic = magic:gsub('({.*}%[%])', '`%1`')
     magic_split = vim.split(magic, ' ', { plain = true })
-- 
cgit 


From 6fa17da39b270bf230764859a9537124b18d3ed5 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Fri, 4 Aug 2023 21:26:53 +0100
Subject: docs(options): take ownership of options.txt (#24528)

* docs(options): take ownership of options.txt

- `src/nvim/options.lua` is now the source of truth
- generate runtime/lua/vim/_meta/options.lua

* fixup! zeer comments

* fixup! zeer comments (2)

* fixup! re-enable luacheck

* fixup! regen
---
 scripts/gen_eval_files.lua | 300 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 276 insertions(+), 24 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index c3123fd47c..640d2afb4f 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -31,6 +31,21 @@ local LUA_API_META_HEADER = {
   'vim.api = {}',
 }
 
+local LUA_OPTION_META_HEADER = {
+  '--- @meta',
+  '-- THIS FILE IS GENERATED',
+  '-- DO NOT EDIT',
+  "error('Cannot require a meta file')",
+  '',
+  '---@class vim.bo',
+  '---@field [integer] vim.bo',
+  'vim.bo = vim.bo',
+  '',
+  '---@class vim.wo',
+  '---@field [integer] vim.wo',
+  'vim.wo = vim.wo',
+}
+
 local LUA_KEYWORDS = {
   ['and'] = true,
   ['end'] = true,
@@ -41,6 +56,12 @@ local LUA_KEYWORDS = {
   ['repeat'] = true,
 }
 
+local OPTION_TYPES = {
+  bool = 'boolean',
+  number = 'integer',
+  string = 'string',
+}
+
 local API_TYPES = {
   Window = 'integer',
   Tabpage = 'integer',
@@ -56,16 +77,20 @@ local API_TYPES = {
   void = '',
 }
 
+--- @param x string
+--- @param sep? string
+--- @return string[]
+local function split(x, sep)
+  return vim.split(x, sep or '\n', { plain = true })
+end
+
 --- Convert an API type to Lua
 --- @param t string
 --- @return string
 local function api_type(t)
-  if t:match('^ArrayOf%(([z-aA-Z]+), %d+%') then
-    print(t:match('^ArrayOf%(([z-aA-Z]+), %d+%'))
-  end
   local as0 = t:match('^ArrayOf%((.*)%)')
   if as0 then
-    local as = vim.split(as0, ', ', { plain = true })
+    local as = split(as0, ', ')
     return api_type(as[1]) .. '[]'
   end
 
@@ -84,6 +109,7 @@ end
 
 --- @param f string
 --- @param params {[1]:string,[2]:string}[]|true
+--- @return string
 local function render_fun_sig(f, params)
   local param_str --- @type string
   if params == true then
@@ -92,6 +118,7 @@ local function render_fun_sig(f, params)
     param_str = table.concat(
       vim.tbl_map(
         --- @param v {[1]:string,[2]:string}
+        --- @return string
         function(v)
           return v[1]
         end,
@@ -140,7 +167,7 @@ end
 --- @field annotations string[]
 
 --- @return table
-local function get_api_funcs()
+local function get_api_meta()
   local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
   local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]]
   local ret = {} --- @type table
@@ -192,13 +219,15 @@ local function norm_text(x)
       :gsub('>vim', '\n```vim')
       :gsub('\n<$', '\n```')
       :gsub('\n<\n', '\n```\n')
+      :gsub('%s+>\n', '\n```\n')
+      :gsub('\n<%s+\n?', '\n```\n')
   )
 end
 
 --- @param _f string
 --- @param fun vim.EvalFn
 --- @param write fun(line: string)
-local function render_api_fun(_f, fun, write)
+local function render_api_meta(_f, fun, write)
   if not vim.startswith(fun.name, 'nvim_') then
     return
   end
@@ -215,7 +244,7 @@ local function render_api_fun(_f, fun, write)
 
   local desc = fun.desc
   if desc then
-    for _, l in ipairs(vim.split(norm_text(desc), '\n', { plain = true })) do
+    for _, l in ipairs(split(norm_text(desc))) do
       write('--- ' .. l)
     end
     write('---')
@@ -227,7 +256,7 @@ local function render_api_fun(_f, fun, write)
     param_names[#param_names + 1] = p[1]
     local pdesc = p[3]
     if pdesc then
-      local pdesc_a = vim.split(norm_text(pdesc), '\n', { plain = true })
+      local pdesc_a = split(norm_text(pdesc))
       write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1])
       for i = 2, #pdesc_a do
         if not pdesc_a[i] then
@@ -252,7 +281,7 @@ local function render_api_fun(_f, fun, write)
 end
 
 --- @return table
-local function get_api_keysets()
+local function get_api_keysets_meta()
   local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
 
   --- @diagnostic disable-next-line:no-unknown
@@ -282,7 +311,7 @@ end
 --- @param _f string
 --- @param fun vim.EvalFn
 --- @param write fun(line: string)
-local function render_api_keyset(_f, fun, write)
+local function render_api_keyset_meta(_f, fun, write)
   write('')
   write('--- @class vim.api.keyset.' .. fun.name)
   for _, p in ipairs(fun.params) do
@@ -291,14 +320,14 @@ local function render_api_keyset(_f, fun, write)
 end
 
 --- @return table
-local function get_eval_funcs()
+local function get_eval_meta()
   return require('src/nvim/eval').funcs
 end
 
 --- @param f string
 --- @param fun vim.EvalFn
 --- @param write fun(line: string)
-local function render_vimfn(f, fun, write)
+local function render_eval_meta(f, fun, write)
   if fun.lua == false then
     return
   end
@@ -318,7 +347,7 @@ local function render_vimfn(f, fun, write)
     if desc then
       --- @type string
       desc = desc:gsub('\n%s*\n%s*$', '\n')
-      for _, l in ipairs(vim.split(desc, '\n', { plain = true })) do
+      for _, l in ipairs(split(desc)) do
         l = l:gsub('^      ', ''):gsub('\t', '  '):gsub('@', '\\@')
         write('--- ' .. l)
       end
@@ -401,10 +430,10 @@ local function render_eval_doc(f, fun, write)
   end
 
   desc = vim.trim(desc)
-  local desc_l = vim.split(desc, '\n', { plain = true })
+  local desc_l = split(desc)
   for _, l in ipairs(desc_l) do
     l = l:gsub('^      ', '')
-    if vim.startswith(l, '<') and not l:match('^<[A-Z][A-Z]') then
+    if vim.startswith(l, '<') and not l:match('^<[^ \t]+>') then
       write('<\t\t' .. l:sub(2))
     else
       write('\t\t' .. l)
@@ -416,10 +445,201 @@ local function render_eval_doc(f, fun, write)
   end
 end
 
+--- @param d vim.option_defaults
+--- @param vimdoc? boolean
+--- @return string
+local function render_option_default(d, vimdoc)
+  local dt --- @type integer|boolean|string|fun(): string
+  if d.if_false ~= nil then
+    dt = d.if_false
+  else
+    dt = d.if_true
+  end
+
+  if vimdoc then
+    if d.doc then
+      return d.doc
+    end
+    if type(dt) == 'boolean' then
+      return dt and 'on' or 'off'
+    end
+  end
+
+  if dt == "" or dt == nil or type(dt) == 'function' then
+    dt = d.meta
+  end
+
+  local v --- @type string
+  if not vimdoc then
+    v = vim.inspect(dt) --[[@as string]]
+  else
+    v = type(dt) == 'string' and '"'..dt..'"' or tostring(dt)
+  end
+
+  --- @type table
+  local envvars = {
+    TMPDIR = false,
+    VIMRUNTIME = false,
+    XDG_CONFIG_HOME = vim.env.HOME..'/.local/config',
+    XDG_DATA_HOME = vim.env.HOME..'/.local/share',
+    XDG_STATE_HOME = vim.env.HOME..'/.local/state',
+  }
+
+  for name, default in pairs(envvars) do
+    local value = vim.env[name] or default
+    if value then
+      v = v:gsub(vim.pesc(value), '$'..name)
+    end
+  end
+
+  return v
+end
+
+--- @param _f string
+--- @param opt vim.option_meta
+--- @param write fun(line: string)
+local function render_option_meta(_f, opt, write)
+  write('')
+  for _, l in ipairs(split(norm_text(opt.desc))) do
+    write('--- '..l)
+  end
+
+  write('--- @type '..OPTION_TYPES[opt.type])
+  write('vim.o.'..opt.full_name..' = '..render_option_default(opt.defaults))
+  if opt.abbreviation then
+    write('vim.o.'..opt.abbreviation..' = vim.o.'..opt.full_name)
+  end
+
+  for _, s in pairs {
+    {'wo', 'window'},
+    {'bo', 'buffer'},
+    {'go', 'global'},
+  } do
+    local id, scope = s[1], s[2]
+    if vim.list_contains(opt.scope, scope) or (id == 'go' and #opt.scope > 1) then
+      local pfx = 'vim.'..id..'.'
+      write(pfx..opt.full_name..' = vim.o.'..opt.full_name)
+      if opt.abbreviation then
+        write(pfx..opt.abbreviation..' = '..pfx..opt.full_name)
+      end
+    end
+  end
+end
+
+--- @param s string[]
+--- @return string
+local function scope_to_doc(s)
+  local m = {
+    global = 'global',
+    buffer = 'local to buffer',
+    window = 'local to window',
+    tab = 'local to tab page'
+  }
+
+  if #s == 1 then
+    return m[s[1]]
+  end
+  assert(s[1] == 'global')
+  return 'global or '..m[s[2]]..' |global-local|'
+end
+
+--- @return table
+local function get_option_meta()
+  local opts = require('src/nvim/options').options
+  local optinfo = vim.api.nvim_get_all_options_info()
+  local ret = {} --- @type table
+  for _, o in ipairs(opts) do
+    if o.desc then
+      if o.full_name == 'cmdheight' then
+        table.insert(o.scope, 'tab')
+      end
+      local r = vim.deepcopy(o) --[[@as vim.option_meta]]
+      r.desc = o.desc:gsub('^        ', ''):gsub('\n        ', '\n')
+      r.defaults = r.defaults or {}
+      if r.defaults.meta == nil then
+        r.defaults.meta = optinfo[o.full_name].default
+      end
+      ret[o.full_name] = r
+    end
+  end
+  return ret
+end
+
+--- @param opt vim.option_meta
+--- @return string[]
+local function build_option_tags(opt)
+  --- @type string[]
+  local tags = { opt.full_name }
+
+  tags[#tags+1] = opt.abbreviation
+  if opt.type == 'bool' then
+    for i = 1, #tags do
+      tags[#tags+1] = 'no'..tags[i]
+    end
+  end
+
+  for i, t in ipairs(tags) do
+    tags[i] = "'"..t.."'"
+  end
+
+  for _, t in ipairs(opt.tags or {}) do
+    tags[#tags+1] = t
+  end
+
+  for i, t in ipairs(tags) do
+    tags[i] = "*"..t.."*"
+  end
+
+  return tags
+end
+
+--- @param _f string
+--- @param opt vim.option_meta
+--- @param write fun(line: string)
+local function render_option_doc(_f, opt, write)
+  local tags = build_option_tags(opt)
+  local tag_str = table.concat(tags, ' ')
+  local conceal_offset = 2*(#tags - 1)
+  local tag_pad = string.rep('\t', math.ceil((64 - #tag_str + conceal_offset) / 8))
+  -- local pad = string.rep(' ', 80 - #tag_str + conceal_offset)
+  write(tag_pad..tag_str)
+
+  local name_str --- @type string
+  if opt.abbreviation then
+    name_str = string.format("'%s' '%s'", opt.full_name, opt.abbreviation)
+  else
+    name_str = string.format("'%s'", opt.full_name)
+  end
+
+  local otype = opt.type == 'bool' and 'boolean' or opt.type
+  if opt.defaults.doc or opt.defaults.if_true ~= nil or opt.defaults.meta ~= nil then
+    local v = render_option_default(opt.defaults, true)
+    local pad = string.rep('\t', math.max(1, math.ceil((24 - #name_str) / 8)))
+    if opt.defaults.doc then
+      local deflen = #string.format('%s%s%s (', name_str, pad, otype)
+      --- @type string
+      v = v:gsub('\n', '\n'..string.rep(' ', deflen - 2))
+    end
+    write(string.format('%s%s%s\t(default %s)', name_str, pad, otype, v))
+  else
+    write(string.format('%s\t%s', name_str, otype))
+  end
+
+  write('\t\t\t'..scope_to_doc(opt.scope))
+  for _, l in ipairs(split(opt.desc)) do
+    if l == '<' or l:match('^<%s') then
+      write(l)
+    else
+      write('\t'..l:gsub('\\<', '<'))
+    end
+  end
+end
+
 --- @class nvim.gen_eval_files.elem
 --- @field path string
---- @field funcs fun(): table
---- @field render fun(f:string,fun:vim.EvalFn,write:fun(line:string))
+--- @field from? string Skip lines in path until this pattern is reached.
+--- @field funcs fun(): table
+--- @field render fun(f:string,obj:table,write:fun(line:string))
 --- @field header? string[]
 --- @field footer? string[]
 
@@ -428,24 +648,24 @@ local CONFIG = {
   {
     path = 'runtime/lua/vim/_meta/vimfn.lua',
     header = LUA_META_HEADER,
-    funcs = get_eval_funcs,
-    render = render_vimfn,
+    funcs = get_eval_meta,
+    render = render_eval_meta,
   },
   {
     path = 'runtime/lua/vim/_meta/api.lua',
     header = LUA_API_META_HEADER,
-    funcs = get_api_funcs,
-    render = render_api_fun,
+    funcs = get_api_meta,
+    render = render_api_meta,
   },
   {
     path = 'runtime/lua/vim/_meta/api_keysets.lua',
     header = LUA_META_HEADER,
-    funcs = get_api_keysets,
-    render = render_api_keyset,
+    funcs = get_api_keysets_meta,
+    render = render_api_keyset_meta,
   },
   {
     path = 'runtime/doc/builtin.txt',
-    funcs = get_eval_funcs,
+    funcs = get_eval_meta,
     render = render_eval_doc,
     header = {
       '*builtin.txt*	Nvim',
@@ -489,10 +709,38 @@ local CONFIG = {
       ' vim:tw=78:ts=8:noet:ft=help:norl:',
     },
   },
+  {
+    path = 'runtime/lua/vim/_meta/options.lua',
+    header = LUA_OPTION_META_HEADER,
+    funcs = get_option_meta,
+    render = render_option_meta,
+  },
+  {
+    path = 'runtime/doc/options.txt',
+    header = { '' },
+    from = 'A jump table for the options with a short description can be found at |Q_op|.',
+    footer = {
+      ' vim:tw=78:ts=8:noet:ft=help:norl:'
+    },
+    funcs = get_option_meta,
+    render = render_option_doc,
+  }
 }
 
 --- @param elem nvim.gen_eval_files.elem
 local function render(elem)
+  print('Rendering '..elem.path)
+  local from_lines = {}  --- @type string[]
+  local from = elem.from
+  if from then
+    for line in io.lines(elem.path) do
+      from_lines[#from_lines+1] = line
+      if line:match(from) then
+        break
+      end
+    end
+  end
+
   local o = assert(io.open(elem.path, 'w'))
 
   --- @param l string
@@ -502,6 +750,10 @@ local function render(elem)
     o:write('\n')
   end
 
+  for _, l in ipairs(from_lines) do
+    write(l)
+  end
+
   for _, l in ipairs(elem.header or {}) do
     write(l)
   end
-- 
cgit 


From 7bc93e0e2f246dd78026a3472d929a0fe450f70d Mon Sep 17 00:00:00 2001
From: bfredl 
Date: Tue, 1 Aug 2023 14:01:19 +0200
Subject: refactor(api): use typed keysets

Initially this is just for geting rid of boilerplate,
but eventually the types could get exposed as metadata
---
 scripts/gen_eval_files.lua | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index c3123fd47c..eea76958ae 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -260,19 +260,18 @@ local function get_api_keysets()
 
   local ret = {} --- @type table
 
-  --- @type {[1]: string, [2]: {[1]: string, [2]: string}[] }[]
+  --- @type {name: string, keys: string[], types: table}[]
   local keysets = metadata.keysets
 
-  for _, keyset in ipairs(keysets) do
-    local kname = keyset[1]
-    local kdef = keyset[2]
-    for _, field in ipairs(kdef) do
-      field[2] = api_type(field[2])
+  for _, k in ipairs(keysets) do
+    local params = {}
+    for _, key in ipairs(k.keys) do
+      table.insert(params, {key, api_type(k.types[key] or 'any')})
     end
-    ret[kname] = {
+    ret[k.name] = {
       signature = 'NA',
-      name = kname,
-      params = kdef,
+      name = k.name,
+      params = params,
     }
   end
 
-- 
cgit 


From 628763fbd82d0fab292b7e92b553c6b1ed53e556 Mon Sep 17 00:00:00 2001
From: bfredl 
Date: Tue, 8 Aug 2023 10:40:43 +0200
Subject: docs(lua): the keyset nilocalypse

This is needed to give recent LuaLS the right idea about optional fields.
---
 scripts/gen_eval_files.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index d29691dfe8..9bc9e99c46 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -295,7 +295,7 @@ local function get_api_keysets_meta()
   for _, k in ipairs(keysets) do
     local params = {}
     for _, key in ipairs(k.keys) do
-      table.insert(params, {key, api_type(k.types[key] or 'any')})
+      table.insert(params, {key..'?', api_type(k.types[key] or 'any')})
     end
     ret[k.name] = {
       signature = 'NA',
-- 
cgit 


From c6c21db82b31ea43ce878ab3725dcd901db1e7a1 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Tue, 8 Aug 2023 16:36:06 +0100
Subject: fix(filetype): add typing and dry (#24573)

---
 scripts/lua2dox.lua | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 01bb8ab57a..7594a0e7df 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -58,7 +58,11 @@ local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func
 local TAGGED_TYPES = { 'TSNode', 'LanguageTree' }
 
 -- Document these as 'table'
-local ALIAS_TYPES = { 'Range', 'Range4', 'Range6', 'TSMetadata' }
+local ALIAS_TYPES = {
+  'Range', 'Range4', 'Range6', 'TSMetadata',
+  'vim.filetype.add.filetypes',
+  'vim.filetype.match.args'
+}
 
 local debug_outfile = nil --- @type string?
 local debug_output = {}
-- 
cgit 


From c43c745a14dced87a23227d7be4f1c33d4455193 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Wed, 9 Aug 2023 11:06:13 +0200
Subject: fix(lua): improve annotations for stricter luals diagnostics (#24609)

Problem: luals returns stricter diagnostics with bundled luarc.json
Solution: Improve some function and type annotations:

* use recognized uv.* types
* disable diagnostic for global `vim` in shared.lua
* docs: don't start comment lines with taglink (otherwise LuaLS will interpret it as a type)
* add type alias for lpeg pattern
* fix return annotation for `vim.secure.trust`
* rename local Range object in vim.version (shadows `Range` in vim.treesitter)
* fix some "missing fields" warnings
* add missing required fields for test functions in eval.lua
* rename lsp meta files for consistency
---
 scripts/gen_lsp.lua | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua
index a1bcce4135..66369a8446 100644
--- a/scripts/gen_lsp.lua
+++ b/scripts/gen_lsp.lua
@@ -1,9 +1,9 @@
 --[[
 Generates lua-ls annotations for lsp
 USAGE:
-nvim -l scripts/gen_lsp.lua gen  # this will overwrite runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/gen_lsp.lua gen  # this will overwrite runtime/lua/vim/lsp/_meta/protocol.lua
 nvim -l scripts/gen_lsp.lua gen --version 3.18 --build/new_lsp_types.lua
-nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/types/protocol.lua
+nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/_meta/protocol.lua
 nvim -l scripts/gen_lsp.lua gen --version 3.18 --methods
 --]]
 
@@ -110,7 +110,7 @@ function M.gen(opt)
     '--[[',
     'This file is autogenerated from scripts/gen_lsp.lua',
     'Regenerate:',
-    [=[nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/types/protocol.lua]=],
+    [=[nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/_meta/protocol.lua]=],
     '--]]',
     '',
     '---@alias lsp.null nil',
@@ -264,7 +264,7 @@ function M.gen(opt)
 end
 
 local opt = {
-  output_file = 'runtime/lua/vim/lsp/types/protocol.lua',
+  output_file = 'runtime/lua/vim/lsp/_meta/protocol.lua',
   version = nil,
   methods = nil,
 }
-- 
cgit 


From 3ce3218fb4b6acd45bc94c1cf4ccfe48bb1f7fa9 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Sun, 13 Aug 2023 10:34:25 +0800
Subject: build(vim-patch.sh): group co-authors together (#24686)

---
 scripts/vim-patch.sh | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 7af055640b..0fae27a3bf 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -119,10 +119,10 @@ get_vim_sources() {
 }
 
 commit_message() {
-  if [[ -n "$vim_tag" ]]; then
-    printf '%s\n\n%s\n\n%s' "${vim_message}" "${vim_commit_url}" "${vim_coauthor}"
+  if [[ "${vim_message}" == "vim-patch:${vim_version}:"* ]]; then
+    printf '%s\n\n%s\n\n%s' "${vim_message}" "${vim_commit_url}" "${vim_coauthors}"
   else
-    printf 'vim-patch:%s\n\n%s\n\n%s\n\n%s' "$vim_version" "$vim_message" "$vim_commit_url" "$vim_coauthor"
+    printf 'vim-patch:%s\n\n%s\n\n%s\n\n%s' "$vim_version" "$vim_message" "$vim_commit_url" "$vim_coauthors"
   fi
 }
 
@@ -175,7 +175,13 @@ assign_commit_details() {
   vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
   vim_message="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:%B' "${vim_commit}" \
       | sed -e 's/\(#[0-9]\{1,\}\)/vim\/vim\1/g')"
-  vim_coauthor="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
+  local coauthor0
+  coauthor0="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
+  # Extract co-authors from the commit message.
+  vim_coauthors="$(echo "${vim_message}" | (grep -E '^Co-authored-by: ' || true) | (grep -Fxv "${coauthor0}" || true))"
+  vim_coauthors="$(echo "${coauthor0}"; echo "${vim_coauthors}")"
+  # Remove Co-authored-by and Signed-off-by lines from the commit message.
+  vim_message="$(echo "${vim_message}" | sed -e '/\(Co-authored\|Signed-off\)-by: /d')"
   if [[ ${munge_commit_line} == "true" ]]; then
     # Remove first line of commit message.
     vim_message="$(echo "${vim_message}" | sed -e '1s/^patch /vim-patch:/')"
-- 
cgit 


From e551d623d207685dafbfdf950477bad5b0fa876d Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Sun, 13 Aug 2023 11:27:31 +0800
Subject: build(vim-patch.sh): rename locale.c to os/lang.c (#24687)

---
 scripts/vim-patch.sh | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 0fae27a3bf..94ecc23413 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -175,13 +175,13 @@ assign_commit_details() {
   vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
   vim_message="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:%B' "${vim_commit}" \
       | sed -e 's/\(#[0-9]\{1,\}\)/vim\/vim\1/g')"
-  local coauthor0
-  coauthor0="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
+  local vim_coauthor0
+  vim_coauthor0="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
   # Extract co-authors from the commit message.
-  vim_coauthors="$(echo "${vim_message}" | (grep -E '^Co-authored-by: ' || true) | (grep -Fxv "${coauthor0}" || true))"
-  vim_coauthors="$(echo "${coauthor0}"; echo "${vim_coauthors}")"
+  vim_coauthors="$(echo "${vim_message}" | (grep -E '^Co-authored-by: ' || true) | (grep -Fxv "${vim_coauthor0}" || true))"
+  vim_coauthors="$(echo "${vim_coauthor0}"; echo "${vim_coauthors}")"
   # Remove Co-authored-by and Signed-off-by lines from the commit message.
-  vim_message="$(echo "${vim_message}" | sed -e '/\(Co-authored\|Signed-off\)-by: /d')"
+  vim_message="$(echo "${vim_message}" | sed -e '/^\(Co-authored\|Signed-off\)-by: /d')"
   if [[ ${munge_commit_line} == "true" ]]; then
     # Remove first line of commit message.
     vim_message="$(echo "${vim_message}" | sed -e '1s/^patch /vim-patch:/')"
@@ -241,43 +241,47 @@ preprocess_patch() {
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalfunc.c to eval/funcs.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalfunc\.c/\1\/eval\/funcs\.c/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalfunc\.c/\1\/eval\/funcs.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalvars.c to eval/vars.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalvars\.c/\1\/eval\/vars\.c/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalvars\.c/\1\/eval\/vars.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename userfunc.c to eval/userfunc.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/userfunc\.c/\1\/eval\/userfunc\.c/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/userfunc\.c/\1\/eval\/userfunc.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalbuffer.c to eval/buffer.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalbuffer\.c/\1\/eval\/buffer\.c/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalbuffer\.c/\1\/eval\/buffer.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalwindow.c to eval/window.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalwindow\.c/\1\/eval\/window\.c/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalwindow\.c/\1\/eval\/window.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename map.c to mapping.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/map\(\.[ch]\)/\1\/mapping\2/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/map\.c/\1\/mapping.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename profiler.c to profile.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/profiler\(\.[ch]\)/\1\/profile\2/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/profiler\.c/\1\/profile.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename scriptfile.c to runtime.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/scriptfile\(\.[ch]\)/\1\/runtime\2/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/scriptfile\.c/\1\/runtime.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename session.c to ex_session.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\(\.[ch]\)/\1\/ex_session\2/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\.c/\1\/ex_session.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename highlight.c to highlight_group.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/highlight\(\.[ch]\)/\1\/highlight_group\2/g' \
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/highlight\.c/\1\/highlight_group.c/g' \
+    "$file" > "$file".tmp && mv "$file".tmp "$file"
+
+  # Rename locale.c to os/lang.c
+  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/locale\.c/\1\/os\/lang.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename keymap.h to keycodes.h
@@ -289,11 +293,11 @@ preprocess_patch() {
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename test_urls.vim to check_urls.vim
-  LC_ALL=C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls\.vim\)@\1/scripts/check\2@g' \
+  LC_ALL=C sed -e 's/\( [ab]\)\/runtime\/doc\/test\(_urls\.vim\)/\1\/scripts\/check\2/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename path to check_colors.vim
-  LC_ALL=C sed -e 's@\( [ab]/runtime\)/colors/\(tools/check_colors\.vim\)@\1/\2@g' \
+  LC_ALL=C sed -e 's/\( [ab]\/runtime\)\/colors\/\(tools\/check_colors\.vim\)/\1\/\2/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 }
 
-- 
cgit 


From c0ac53e0d6a1e1fab38738e549200975ac0128a3 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Wed, 16 Aug 2023 08:50:11 +0800
Subject: build(vim-patch.sh): use sed -E for portable regexp (#24734)

Also always use -e for consistency.
---
 scripts/vim-patch.sh | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 94ecc23413..3f411dac49 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -174,17 +174,17 @@ assign_commit_details() {
 
   vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
   vim_message="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:%B' "${vim_commit}" \
-      | sed -e 's/\(#[0-9]\{1,\}\)/vim\/vim\1/g')"
+      | sed -Ee 's/(#[0-9]{1,})/vim\/vim\1/g')"
   local vim_coauthor0
   vim_coauthor0="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
   # Extract co-authors from the commit message.
   vim_coauthors="$(echo "${vim_message}" | (grep -E '^Co-authored-by: ' || true) | (grep -Fxv "${vim_coauthor0}" || true))"
   vim_coauthors="$(echo "${vim_coauthor0}"; echo "${vim_coauthors}")"
   # Remove Co-authored-by and Signed-off-by lines from the commit message.
-  vim_message="$(echo "${vim_message}" | sed -e '/^\(Co-authored\|Signed-off\)-by: /d')"
+  vim_message="$(echo "${vim_message}" | grep -Ev '^(Co-authored|Signed-off)-by: ')"
   if [[ ${munge_commit_line} == "true" ]]; then
     # Remove first line of commit message.
-    vim_message="$(echo "${vim_message}" | sed -e '1s/^patch /vim-patch:/')"
+    vim_message="$(echo "${vim_message}" | sed -Ee '1s/^patch /vim-patch:/')"
   fi
   patch_file="vim-${vim_version}.patch"
 }
@@ -233,71 +233,71 @@ preprocess_patch() {
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
 
   # Rename src/testdir/ paths to test/old/testdir/
-  LC_ALL=C sed -e 's/\( [ab]\)\/src\/testdir/\1\/test\/old\/testdir/g' \
+  LC_ALL=C sed -Ee 's/( [ab])\/src\/testdir/\1\/test\/old\/testdir/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename src/ paths to src/nvim/
-  LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src)/\1\/nvim/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalfunc.c to eval/funcs.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalfunc\.c/\1\/eval\/funcs.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/evalfunc\.c/\1\/eval\/funcs.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalvars.c to eval/vars.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalvars\.c/\1\/eval\/vars.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/evalvars\.c/\1\/eval\/vars.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename userfunc.c to eval/userfunc.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/userfunc\.c/\1\/eval\/userfunc.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/userfunc\.c/\1\/eval\/userfunc.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalbuffer.c to eval/buffer.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalbuffer\.c/\1\/eval\/buffer.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/evalbuffer\.c/\1\/eval\/buffer.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename evalwindow.c to eval/window.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/evalwindow\.c/\1\/eval\/window.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/evalwindow\.c/\1\/eval\/window.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename map.c to mapping.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/map\.c/\1\/mapping.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/map\.c/\1\/mapping.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename profiler.c to profile.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/profiler\.c/\1\/profile.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/profiler\.c/\1\/profile.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename scriptfile.c to runtime.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/scriptfile\.c/\1\/runtime.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/scriptfile\.c/\1\/runtime.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename session.c to ex_session.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\.c/\1\/ex_session.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/session\.c/\1\/ex_session.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename highlight.c to highlight_group.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/highlight\.c/\1\/highlight_group.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/highlight\.c/\1\/highlight_group.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename locale.c to os/lang.c
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/locale\.c/\1\/os\/lang.c/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/locale\.c/\1\/os\/lang.c/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename keymap.h to keycodes.h
-  LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/keymap\.h/\1\/keycodes.h/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/keymap\.h/\1\/keycodes.h/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename terminal.txt to nvim_terminal_emulator.txt
-  LC_ALL=C sed -e 's/\( [ab]\/runtime\/doc\)\/terminal\.txt/\1\/nvim_terminal_emulator.txt/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/runtime\/doc)\/terminal\.txt/\1\/nvim_terminal_emulator.txt/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename test_urls.vim to check_urls.vim
-  LC_ALL=C sed -e 's/\( [ab]\)\/runtime\/doc\/test\(_urls\.vim\)/\1\/scripts\/check\2/g' \
+  LC_ALL=C sed -Ee 's/( [ab])\/runtime\/doc\/test(_urls\.vim)/\1\/scripts\/check\2/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
   # Rename path to check_colors.vim
-  LC_ALL=C sed -e 's/\( [ab]\/runtime\)\/colors\/\(tools\/check_colors\.vim\)/\1\/\2/g' \
+  LC_ALL=C sed -Ee 's/( [ab]\/runtime)\/colors\/(tools\/check_colors\.vim)/\1\/\2/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 }
 
@@ -536,7 +536,7 @@ list_vimpatch_tokens() {
     | grep -oE 'vim-patch:[^ ,{:]{7,}' \
     | sort \
     | uniq \
-    | sed -nE 's/^(vim-patch:([0-9]+\.[^ ]+|[0-9a-z]{7,7})).*/\1/p'
+    | sed -nEe 's/^(vim-patch:([0-9]+\.[^ ]+|[0-9a-z]{7,7})).*/\1/p'
 }
 
 # Prints all patch-numbers (for the current v:version) for which there is
@@ -544,7 +544,7 @@ list_vimpatch_tokens() {
 list_vimpatch_numbers() {
   # Transform "vim-patch:X.Y.ZZZZ" to "ZZZZ".
   list_vimpatch_tokens | while read -r vimpatch_token; do
-    echo "$vimpatch_token" | grep '8\.1\.' | sed -E 's/.*vim-patch:8\.1\.([0-9a-z]+).*/\1/'
+    echo "$vimpatch_token" | grep -F '8.1.' | sed -Ee 's/.*vim-patch:8\.1\.([0-9a-z]+).*/\1/'
   done
 }
 
@@ -669,7 +669,7 @@ show_vimpatches() {
   printf "Vim patches missing from Neovim:\n"
 
   local -A runtime_commits
-  for commit in $(git -C "${VIM_SOURCE_DIR}" log --format="%H %D" -- runtime | sed 's/,\? tag: / /g'); do
+  for commit in $(git -C "${VIM_SOURCE_DIR}" log --format="%H %D" -- runtime | sed -Ee 's/,\? tag: / /g'); do
     runtime_commits[$commit]=1
   done
 
@@ -763,7 +763,7 @@ review_commit() {
   local nvim_patch
   nvim_patch="$(curl -Ssf "${nvim_patch_url}")"
   local vim_version
-  vim_version="$(head -n 4 <<< "${nvim_patch}" | sed -n 's/'"${git_patch_prefix}"'vim-patch:\([a-z0-9.]*\)\(:.*\)\{0,1\}$/\1/p')"
+  vim_version="$(head -n 4 <<< "${nvim_patch}" | sed -nEe 's/'"${git_patch_prefix}"'vim-patch:([a-z0-9.]*)(:.*){0,1}$/\1/p')"
 
   echo
   if [[ -n "${vim_version}" ]]; then
-- 
cgit 


From 0ba27bb51d3297aec43e78050cc3adcf6879db22 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Wed, 23 Aug 2023 16:32:15 +0800
Subject: vim-patch:9.0.1710: scrolloff options work slightly different

Problem: sidescrolloff and scrolloff options work slightly
         different than other global-local options
Solution: Make it behave consistent for all global-local options

It was noticed, that sidescrolloff and scrolloff options behave
differently in comparison to other global-local window options like
'listchars'

So make those two behave like other global-local options. Also add some
extra documentation for a few special local-window options.

Add a few tests to make sure all global-local window options behave
similar

closes: vim/vim#12956
closes: vim/vim#12643

https://github.com/vim/vim/commit/4a8eb6e7a9df10f79bf95301ced012f0d6a13088

Co-authored-by: Christian Brabandt 
---
 scripts/gen_eval_files.lua | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 9bc9e99c46..2990eef069 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -542,6 +542,36 @@ local function scope_to_doc(s)
   return 'global or '..m[s[2]]..' |global-local|'
 end
 
+-- @param o vim.option_meta
+-- @return string
+local function scope_more_doc(o)
+  if
+    vim.list_contains({
+      'previewwindow',
+      'scroll',
+      'winfixheight',
+      'winfixwidth',
+    }, o.full_name)
+  then
+    return '  |special-local-window-option|'
+  end
+
+  if
+    vim.list_contains({
+      'bufhidden',
+      'buftype',
+      'filetype',
+      'modified',
+      'readonly',
+      'syntax',
+    }, o.full_name)
+  then
+    return '  |special-local-buffer-option|'
+  end
+
+  return ''
+end
+
 --- @return table
 local function get_option_meta()
   local opts = require('src/nvim/options').options
@@ -624,7 +654,7 @@ local function render_option_doc(_f, opt, write)
     write(string.format('%s\t%s', name_str, otype))
   end
 
-  write('\t\t\t'..scope_to_doc(opt.scope))
+  write('\t\t\t'..scope_to_doc(opt.scope)..scope_more_doc(opt))
   for _, l in ipairs(split(opt.desc)) do
     if l == '<' or l:match('^<%s') then
       write(l)
-- 
cgit 


From 2234b84a1b85832667ad4a23fd5dee0bd1c92b72 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Thu, 17 Aug 2023 11:14:58 +0100
Subject: docs(generators): bake into cmake

---
 scripts/gen_eval_files.lua | 11 +++++++----
 scripts/gen_vimdoc.py      |  3 ---
 2 files changed, 7 insertions(+), 7 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 2990eef069..e41054ed65 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -1,5 +1,8 @@
 #!/usr/bin/env -S nvim -l
--- Generator for src/nvim/eval.lua
+-- Generator for various vimdoc and Lua type files
+
+local DEP_API_METADATA = 'build/api_metadata.mpack'
+local DEP_API_DOC  = 'runtime/doc/api.mpack'
 
 --- @class vim.api.metadata
 --- @field name string
@@ -168,11 +171,11 @@ end
 
 --- @return table
 local function get_api_meta()
-  local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
+  local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
   local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]]
   local ret = {} --- @type table
 
-  local doc_mpack_f = assert(io.open('runtime/doc/api.mpack', 'rb'))
+  local doc_mpack_f = assert(io.open(DEP_API_DOC, 'rb'))
   local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]]
 
   for _, fun in ipairs(metadata) do
@@ -282,7 +285,7 @@ end
 
 --- @return table
 local function get_api_keysets_meta()
-  local mpack_f = assert(io.open('build/api_metadata.mpack', 'rb'))
+  local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
 
   --- @diagnostic disable-next-line:no-unknown
   local metadata = assert(vim.mpack.decode(mpack_f:read('*all')))
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 9a1316a328..dfad1f000c 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -1359,7 +1359,4 @@ if __name__ == "__main__":
     else:
         main(Doxyfile, args)
 
-        print('Running ./scripts/gen_eval_files.lua')
-        subprocess.call(['./scripts/gen_eval_files.lua'])
-
 # vim: set ft=python ts=4 sw=4 tw=79 et :
-- 
cgit 


From 08fa71fd274530be23b6ae6b10222afee0b57522 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Wed, 23 Aug 2023 19:32:11 +0800
Subject: vim-patch:9.0.1773: cannot distinguish Forth and Fortran *.f files
 (#24841)

Problem:  cannot distinguish Forth and Fortran *.f files
Solution: Add Filetype detection Code

Also add *.4th as a Forth filetype

closes: vim/vim#12251

https://github.com/vim/vim/commit/19a3bc3addf9b4aa8150a01b11b4249c67d15d3b

Don't remove filetype files from Vim patches:
- filetype.vim, script.vim, ft.vim usually contain useful changes
- script.vim and ft.vim don't even have their paths spelled correctly

Co-authored-by: Doug Kearns 
---
 scripts/vim-patch.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 3f411dac49..af73a8006a 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -202,9 +202,9 @@ preprocess_patch() {
   local na_src='auto\|configure.*\|GvimExt\|hardcopy.*\|libvterm\|proto\|tee\|VisVim\|xpm\|xxd\|Make.*\|INSTALL.*\|beval.*\|gui.*\|if_cscop\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@@norm! d/\v(^diff)|%$
' +w +q "$file"
 
-  # Remove runtime files ported to Lua.
-  local na_rt='filetype\.vim\|scripts\.vim\|autoload\/ft\/dist\.vim\|print\/.*'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  # Remove runtime/print/
+  local na_rt='print\/.*'
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@norm! d/\v(^diff)|%$' +w +q "$file"
 
   # Remove unwanted Vim doc files.
   local na_doc='channel\.txt\|if_cscop\.txt\|netbeans\.txt\|os_\w\+\.txt\|print\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|vim9\.txt\|sponsor\.txt\|intro\.txt\|tags'
-- 
cgit 


From daf7abbc4238dc269e22dd431bc4b1627ef9b6a1 Mon Sep 17 00:00:00 2001
From: Sean Dewar 
Date: Thu, 24 Aug 2023 13:29:40 +0100
Subject: docs(builtin): small fixes (#24861)

Also make gen_eval_files.lua render vimdoc helpExamples properly if the line
begins with the `>` marker.
---
 scripts/gen_eval_files.lua | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index e41054ed65..f8d69ce313 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -437,6 +437,8 @@ local function render_eval_doc(f, fun, write)
     l = l:gsub('^      ', '')
     if vim.startswith(l, '<') and not l:match('^<[^ \t]+>') then
       write('<\t\t' .. l:sub(2))
+    elseif l:match('^>[a-z0-9]*$') then
+      write(l)
     else
       write('\t\t' .. l)
     end
-- 
cgit 


From acb868bf84246982883b9fc43fee6487be7c7c60 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Fri, 8 Sep 2023 06:56:57 +0800
Subject: build(vim-patch.sh): dereference annotated tags when listing (#25042)

---
 scripts/vim-patch.sh | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index af73a8006a..42b54d6c05 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -565,10 +565,8 @@ _set_tokens_and_tags() {
 
   # Create an associative array mapping Vim commits to tags.
   eval "vim_commit_tags=(
-    $(git -C "${VIM_SOURCE_DIR}" for-each-ref refs/tags \
-      --format '[%(objectname)]=%(refname:strip=2)' \
-      --sort='-*authordate' \
-      --shell)
+    $(git -C "${VIM_SOURCE_DIR}" show-ref --tags --dereference \
+      | sed -nEe 's/^([0-9a-f]+) refs\/tags\/(v[0-9.]+)(\^\{\})?$/\1 \2/p')
   )"
   # Exit in case of errors from the above eval (empty vim_commit_tags).
   if ! (( "${#vim_commit_tags[@]}" )); then
-- 
cgit 


From 3d2c9102e90ed2cb5d9d344ffb2777f98e2e37f1 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Fri, 8 Sep 2023 07:28:46 +0800
Subject: build(vim-patch.sh): use older associative array syntax

---
 scripts/vim-patch.sh | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 42b54d6c05..e7eaa0b830 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -196,11 +196,13 @@ preprocess_patch() {
 
   # Remove Filelist, README
   local na_files='Filelist\|README.*'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/\<\%('"${na_files}"'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/\<\%('"${na_files}"'\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove *.proto, Make*, INSTALL*, gui_*, beval.*, some if_*, gvim, libvterm, tee, VisVim, xpm, xxd
   local na_src='auto\|configure.*\|GvimExt\|hardcopy.*\|libvterm\|proto\|tee\|VisVim\|xpm\|xxd\|Make.*\|INSTALL.*\|beval.*\|gui.*\|if_cscop\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove runtime/print/
   local na_rt='print\/.*'
@@ -208,29 +210,35 @@ preprocess_patch() {
 
   # Remove unwanted Vim doc files.
   local na_doc='channel\.txt\|if_cscop\.txt\|netbeans\.txt\|os_\w\+\.txt\|print\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|vim9\.txt\|sponsor\.txt\|intro\.txt\|tags'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove "Last change ..." changes in doc files.
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'%s/^@@.*\n.*For Vim version.*Last change.*\n.*For Vim version.*Last change.*//' +w +q "$file"
 
   # Remove gui, option, setup, screen dumps, testdir/Make_*.mak files
   local na_src_testdir='gen_opt_test\.vim\|gui_.*\|Make_amiga\.mak\|Make_dos\.mak\|Make_ming\.mak\|Make_vms\.mms\|dumps/.*\.dump\|setup_gui\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove testdir/test_*.vim files
   local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove version.c #7555
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(version\.c\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(version\.c\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove some *.po files. #5622
   local na_po='sjiscorr\.c\|ja\.sjis\.po\|ko\.po\|pl\.cp1250\.po\|pl\.po\|ru\.cp1251\.po\|uk\.cp1251\.po\|zh_CN\.cp936\.po\|zh_CN\.po\|zh_TW\.po'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Remove vimrc_example.vim
   local na_vimrcexample='vimrc_example\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@norm! d/\v(^diff)|%$
+' +w +q "$file"
 
   # Rename src/testdir/ paths to test/old/testdir/
   LC_ALL=C sed -Ee 's/( [ab])\/src\/testdir/\1\/test\/old\/testdir/g' \
@@ -566,7 +574,7 @@ _set_tokens_and_tags() {
   # Create an associative array mapping Vim commits to tags.
   eval "vim_commit_tags=(
     $(git -C "${VIM_SOURCE_DIR}" show-ref --tags --dereference \
-      | sed -nEe 's/^([0-9a-f]+) refs\/tags\/(v[0-9.]+)(\^\{\})?$/\1 \2/p')
+      | sed -nEe 's/^([0-9a-f]+) refs\/tags\/(v[0-9.]+)(\^\{\})?$/["\1"]="\2"/p')
   )"
   # Exit in case of errors from the above eval (empty vim_commit_tags).
   if ! (( "${#vim_commit_tags[@]}" )); then
-- 
cgit 


From 6a8b48e24cbe070846dd1d234553b3fdeb19460e Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Fri, 8 Sep 2023 07:51:53 +0800
Subject: build(vim-patch.sh): don't use control chars in command (#25044)

---
 scripts/vim-patch.sh | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index e7eaa0b830..8b061add0d 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -196,49 +196,41 @@ preprocess_patch() {
 
   # Remove Filelist, README
   local na_files='Filelist\|README.*'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/\<\%('"${na_files}"'\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/\<\%('"${na_files}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove *.proto, Make*, INSTALL*, gui_*, beval.*, some if_*, gvim, libvterm, tee, VisVim, xpm, xxd
   local na_src='auto\|configure.*\|GvimExt\|hardcopy.*\|libvterm\|proto\|tee\|VisVim\|xpm\|xxd\|Make.*\|INSTALL.*\|beval.*\|gui.*\|if_cscop\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove runtime/print/
   local na_rt='print\/.*'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@norm! d/\v(^diff)|%$' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove unwanted Vim doc files.
   local na_doc='channel\.txt\|if_cscop\.txt\|netbeans\.txt\|os_\w\+\.txt\|print\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|vim9\.txt\|sponsor\.txt\|intro\.txt\|tags'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove "Last change ..." changes in doc files.
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'%s/^@@.*\n.*For Vim version.*Last change.*\n.*For Vim version.*Last change.*//' +w +q "$file"
 
   # Remove gui, option, setup, screen dumps, testdir/Make_*.mak files
   local na_src_testdir='gen_opt_test\.vim\|gui_.*\|Make_amiga\.mak\|Make_dos\.mak\|Make_ming\.mak\|Make_vms\.mms\|dumps/.*\.dump\|setup_gui\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove testdir/test_*.vim files
   local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove version.c #7555
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(version\.c\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(version\.c\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove some *.po files. #5622
   local na_po='sjiscorr\.c\|ja\.sjis\.po\|ko\.po\|pl\.cp1250\.po\|pl\.po\|ru\.cp1251\.po\|uk\.cp1251\.po\|zh_CN\.cp936\.po\|zh_CN\.po\|zh_TW\.po'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@exe "norm! d/\\v(^diff)|%$\r"+' +w +q "$file"
 
   # Remove vimrc_example.vim
   local na_vimrcexample='vimrc_example\.vim'
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@norm! d/\v(^diff)|%$
-' +w +q "$file"
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('${na_vimrcexample}'\)\>@exe "norm! d/\\v(^diff)|%$\r"+' +w +q "$file"
 
   # Rename src/testdir/ paths to test/old/testdir/
   LC_ALL=C sed -Ee 's/( [ab])\/src\/testdir/\1\/test\/old\/testdir/g' \
-- 
cgit 


From 4b6023be7c2b132e7e6994adc73a7b79fbf40946 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Tue, 12 Sep 2023 07:37:05 +0800
Subject: vim-patch:596ad66d1ddb (#25102)

runtime(doc): documentation updates

This is a collection of various improvements to the help pages

closes vim/vim#12790

https://github.com/vim/vim/commit/596ad66d1ddb742ef349e98eb06b8e4052f68f51

Co-authored-by: Christian Brabandt 
Co-authored-by: Houl 
Co-authored-by: Doug Kearns 
Co-authored-by: Adri Verhoef 
---
 scripts/gen_eval_files.lua | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index f8d69ce313..5d726315bd 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -550,28 +550,21 @@ end
 -- @param o vim.option_meta
 -- @return string
 local function scope_more_doc(o)
-  if
-    vim.list_contains({
-      'previewwindow',
-      'scroll',
-      'winfixheight',
-      'winfixwidth',
-    }, o.full_name)
-  then
-    return '  |special-local-window-option|'
-  end
-
   if
     vim.list_contains({
       'bufhidden',
       'buftype',
       'filetype',
       'modified',
+      'previewwindow',
       'readonly',
+      'scroll',
       'syntax',
+      'winfixheight',
+      'winfixwidth',
     }, o.full_name)
   then
-    return '  |special-local-buffer-option|'
+    return '  |local-noglobal|'
   end
 
   return ''
-- 
cgit 


From bc67cf3ccdf935a0e2974fbbe5557a3d24931c54 Mon Sep 17 00:00:00 2001
From: Sergey Slipchenko 
Date: Tue, 12 Sep 2023 15:51:38 +0400
Subject: feat(gen_help_html): add anchors to help tags #25112

Fixes #21911

Co-authored by: wispl
---
 scripts/gen_help_html.lua | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 5e06830336..c8e004e2ab 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -574,14 +574,15 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
       return ''
     end
     local el = in_heading and 'span' or 'code'
-    local s = ('%s<%s id="%s" class="%s">%s'):format(ws(), el, url_encode(tagname), cssclass, trimmed, el)
+    local encoded_tagname = url_encode(tagname)
+    local s = ('%s<%s id="%s" class="%s">%s'):format(ws(), el, encoded_tagname, cssclass, encoded_tagname, trimmed, el)
     if opt.old then
         s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
     end
 
     if in_heading and prev ~= 'tag' then
       -- Don't set "id", let the heading use the tag as its "id" (used by search engines).
-      s = ('%s<%s class="%s">%s'):format(ws(), el, cssclass, trimmed, el)
+      s = ('%s<%s class="%s">%s'):format(ws(), el, cssclass, encoded_tagname, trimmed, el)
       -- Start the  container for tags in a heading.
       -- This makes "justify-content:space-between" right-align the tags.
       --    

foo bartag1 tag2

@@ -963,6 +964,7 @@ local function gen_css(fname) margin-bottom: 0; } + /* TODO: should this rule be deleted? help tags are rendered as or , not */ a.help-tag, a.help-tag:focus, a.help-tag:hover { color: inherit; text-decoration: none; @@ -977,6 +979,14 @@ local function gen_css(fname) margin-right: 0; float: right; } + .help-tag a, + .help-tag-right a { + color: inherit; + } + .help-tag a:not(:hover), + .help-tag-right a:not(:hover) { + text-decoration: none; + } h1 .help-tag, h2 .help-tag, h3 .help-tag { font-size: smaller; } -- cgit From 27a566f3f8e07a4cebb426674800bdf9a7f4f222 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 13 Sep 2023 08:38:28 -0500 Subject: feat(vimdoc): support Markdown code blocks (#25127) Support Markdown code blocks in addition to
 blocks in Doxygen doc
comments.

Update doc comments in iter.lua as a test.
---
 scripts/gen_vimdoc.py | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index dfad1f000c..d485e68e2f 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -440,7 +440,7 @@ def is_blank(text):
     return '' == clean_lines(text)
 
 
-def get_text(n, preformatted=False):
+def get_text(n):
     """Recursively concatenates all text in a node tree."""
     text = ''
     if n.nodeType == n.TEXT_NODE:
@@ -449,11 +449,13 @@ def get_text(n, preformatted=False):
         for node in n.childNodes:
             text += get_text(node)
         return '`{}`'.format(text)
+    if n.nodeName == 'sp': # space, used in "programlisting" nodes
+        return ' '
     for node in n.childNodes:
         if node.nodeType == node.TEXT_NODE:
             text += node.data
         elif node.nodeType == node.ELEMENT_NODE:
-            text += get_text(node, preformatted)
+            text += get_text(node)
     return text
 
 
@@ -571,7 +573,7 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation,
     # text += (int(not space_preceding) * ' ')
 
     if n.nodeName == 'preformatted':
-        o = get_text(n, preformatted=True)
+        o = get_text(n)
         ensure_nl = '' if o[-1] == '\n' else '\n'
         if o[0:4] == 'lua\n':
             text += '>lua{}{}\n<'.format(ensure_nl, o[3:-1])
@@ -581,7 +583,15 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation,
             text += o[4:-1]
         else:
             text += '>{}{}\n<'.format(ensure_nl, o)
+    elif n.nodeName == 'programlisting': # codeblock (```)
+        o = get_text(n)
+        filename = n.attributes['filename'].value
+        if filename:
+            text += '>{}'.format(filename.lstrip('.'))
+        else:
+            text += '>'
 
+        text += '\n\n{}\n<'.format(textwrap.indent(o, ' ' * 4))
     elif is_inline(n):
         text = doc_wrap(get_text(n), prefix=prefix, indent=indent, width=width)
     elif n.nodeName == 'verbatim':
@@ -786,6 +796,18 @@ def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent=
     for child in parent.childNodes:
         para, _ = para_as_map(child, indent, width, fmt_vimhelp)
 
+        # 'programlisting' blocks are Markdown code blocks. Do not include
+        # these as a separate paragraph, but append to the last non-empty line
+        # in the text
+        if (
+            len(child.childNodes) == 1
+            and child.childNodes[0].nodeName == 'programlisting'
+        ):
+            while rendered_blocks and rendered_blocks[-1] == '':
+                rendered_blocks.pop()
+            rendered_blocks[-1] += ' ' + para['text']
+            continue
+
         # Generate text from the gathered items.
         chunks = [para['text']]
         if len(para['note']) > 0:
-- 
cgit 


From 2e92065686f62851318150a315591c30b8306a4b Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 14 Sep 2023 08:23:01 -0500
Subject: docs: replace 
 with ``` (#25136)

---
 scripts/gen_eval_files.lua | 15 +++++++++------
 scripts/gen_vimdoc.py      | 37 +++++++++++++++++++++++++++----------
 2 files changed, 36 insertions(+), 16 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 5d726315bd..1afe3d5f46 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -213,17 +213,20 @@ end
 
 --- Convert vimdoc references to markdown literals
 --- Convert vimdoc codeblocks to markdown codeblocks
+---
+--- Ensure code blocks have one empty line before the start fence and after the closing fence.
+---
 --- @param x string
 --- @return string
 local function norm_text(x)
   return (
     x:gsub('|([^ ]+)|', '`%1`')
-      :gsub('>lua', '\n```lua')
-      :gsub('>vim', '\n```vim')
-      :gsub('\n<$', '\n```')
-      :gsub('\n<\n', '\n```\n')
-      :gsub('%s+>\n', '\n```\n')
-      :gsub('\n<%s+\n?', '\n```\n')
+      :gsub('\n*>lua', '\n\n```lua')
+      :gsub('\n*>vim', '\n\n```vim')
+      :gsub('\n+<$', '\n```')
+      :gsub('\n+<\n+', '\n```\n\n')
+      :gsub('%s+>\n+', '\n```\n')
+      :gsub('\n+<%s+\n?', '\n```\n')
   )
 end
 
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index d485e68e2f..ed156e1422 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -585,13 +585,12 @@ def render_node(n, text, prefix='', indent='', width=text_width - indentation,
             text += '>{}{}\n<'.format(ensure_nl, o)
     elif n.nodeName == 'programlisting': # codeblock (```)
         o = get_text(n)
-        filename = n.attributes['filename'].value
-        if filename:
-            text += '>{}'.format(filename.lstrip('.'))
-        else:
-            text += '>'
+        text += '>'
+        if 'filename' in n.attributes:
+            filename = n.attributes['filename'].value
+            text += filename.lstrip('.')
 
-        text += '\n\n{}\n<'.format(textwrap.indent(o, ' ' * 4))
+        text += '\n{}\n<'.format(textwrap.indent(o, ' ' * 4))
     elif is_inline(n):
         text = doc_wrap(get_text(n), prefix=prefix, indent=indent, width=width)
     elif n.nodeName == 'verbatim':
@@ -768,6 +767,27 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
 
     return chunks, xrefs
 
+def is_program_listing(para):
+    """
+    Return True if `para` contains a "programlisting" (i.e. a Markdown code
+    block ```).
+
+    Sometimes a  element will have only a single "programlisting" child
+    node, but othertimes it will have extra whitespace around the
+    "programlisting" node.
+
+    @param para XML  node
+    @return True if  is a programlisting
+    """
+
+    # Remove any child text nodes that are only whitespace
+    children = [
+        n for n in para.childNodes
+        if n.nodeType != n.TEXT_NODE or n.data.strip() != ''
+    ]
+
+    return len(children) == 1 and children[0].nodeName == 'programlisting'
+
 def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent='',
                         fmt_vimhelp=False):
     """Renders (nested) Doxygen  nodes as Vim :help text.
@@ -799,10 +819,7 @@ def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent=
         # 'programlisting' blocks are Markdown code blocks. Do not include
         # these as a separate paragraph, but append to the last non-empty line
         # in the text
-        if (
-            len(child.childNodes) == 1
-            and child.childNodes[0].nodeName == 'programlisting'
-        ):
+        if is_program_listing(child):
             while rendered_blocks and rendered_blocks[-1] == '':
                 rendered_blocks.pop()
             rendered_blocks[-1] += ' ' + para['text']
-- 
cgit 


From 877d04d0fb83b5fc602dbab22b58f26a793ec236 Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Sat, 16 Sep 2023 23:10:30 +0100
Subject: feat(lua): add vim.func._memoize

Memoizes a function, using a custom function to hash the arguments.

Private for now until:

- There are other places in the codebase that could benefit from this
  (e.g. LSP), but might require other changes to accommodate.
- Invalidation of the cache needs to be controllable. Using weak tables
  is an acceptable invalidation policy, but it shouldn't be the only
  one.
- I don't think the story around `hash_fn` is completely thought out. We
  may be able to have a good default hash_fn by hashing each argument,
  so basically a better 'concat'.
---
 scripts/lua2dox.lua | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'scripts')

diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
index 7594a0e7df..1c8bc5a3cb 100644
--- a/scripts/lua2dox.lua
+++ b/scripts/lua2dox.lua
@@ -361,6 +361,12 @@ local function process_line(line, in_stream, generics)
     return process_block_comment(line:sub(5), in_stream)
   end
 
+  -- Hax... I'm sorry
+  -- M.fun = vim.memoize(function(...)
+  --   ->
+  -- function M.fun(...)
+  line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)')
+
   if line:find('^function') or line:find('^local%s+function') then
     return process_function_header(line)
   end
-- 
cgit 


From dc6d0d2daf69e2fdadda81feb97906dbc962a239 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Sat, 30 Sep 2023 14:41:34 +0800
Subject: refactor: reorganize option header files (#25437)

- Move vimoption_T to option.h
- option_defs.h is for option-related types
- option_vars.h corresponds to Vim's option.h
- option_defs.h and option_vars.h don't include each other
---
 scripts/vim-patch.sh | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 8b061add0d..478415376a 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -288,6 +288,10 @@ preprocess_patch() {
   LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/keymap\.h/\1\/keycodes.h/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
 
+  # Rename option.h to option_vars.h
+  LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/option\.h/\1\/option_vars.h/g' \
+    "$file" > "$file".tmp && mv "$file".tmp "$file"
+
   # Rename terminal.txt to nvim_terminal_emulator.txt
   LC_ALL=C sed -Ee 's/( [ab]\/runtime\/doc)\/terminal\.txt/\1\/nvim_terminal_emulator.txt/g' \
     "$file" > "$file".tmp && mv "$file".tmp "$file"
-- 
cgit 


From 6823fdb20b1330142506410a62474166f646bf13 Mon Sep 17 00:00:00 2001
From: dundargoc 
Date: Sat, 7 Oct 2023 22:00:29 +0200
Subject: build(PVS): exclude build directory

This is to prevent reports on generated files.
---
 scripts/pvscheck.sh | 1 +
 1 file changed, 1 insertion(+)

(limited to 'scripts')

diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh
index 97757c0848..81f309aeb3 100755
--- a/scripts/pvscheck.sh
+++ b/scripts/pvscheck.sh
@@ -375,6 +375,7 @@ run_analysis() {(
       --threads "$(get_jobs_num)" \
       --exclude-path src/cjson \
       --exclude-path src/xdiff \
+      --exclude-path build \
       --output-file PVS-studio.log \
       --file build/compile_commands.json \
       --sourcetree-root . || true
-- 
cgit 


From c80a3976cb34c2b3c7f6f01e9ad2db41a4f67796 Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Mon, 9 Oct 2023 15:34:48 -0700
Subject: docs: miscellaneous doc and type fixes (#25554)

---
 scripts/gen_eval_files.lua | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 1afe3d5f46..bf243e96fd 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -19,14 +19,14 @@ local DEP_API_DOC  = 'runtime/doc/api.mpack'
 --- @field since integer
 
 local LUA_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
 }
 
 local LUA_API_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
@@ -35,7 +35,7 @@ local LUA_API_META_HEADER = {
 }
 
 local LUA_OPTION_META_HEADER = {
-  '--- @meta',
+  '--- @meta _',
   '-- THIS FILE IS GENERATED',
   '-- DO NOT EDIT',
   "error('Cannot require a meta file')",
-- 
cgit 


From c46a6c065e8d830adb8a2f410d3c92cf5bd4455b Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Mon, 16 Oct 2023 08:13:37 -0700
Subject: docs: do not hardcode LSP version in URL #25648

---
 scripts/gen_lsp.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua
index 66369a8446..6ff8dcb3f4 100644
--- a/scripts/gen_lsp.lua
+++ b/scripts/gen_lsp.lua
@@ -35,7 +35,7 @@ end
 
 -- Gets the Lua symbol for a given fully-qualified LSP method name.
 local function name(s)
-  -- "$/" prefix is special: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#dollarRequests
+  -- "$/" prefix is special: https://microsoft.github.io/language-server-protocol/specification/#dollarRequests
   return s:gsub('^%$', 'dollar'):gsub('/', '_')
 end
 
@@ -44,7 +44,7 @@ local function gen_methods(protocol)
     '-- Generated by gen_lsp.lua, keep at end of file.',
     '--- LSP method names.',
     '---',
-    '---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel',
+    '---@see https://microsoft.github.io/language-server-protocol/specification/#metaModel',
     'protocol.Methods = {',
   }
   local indent = (' '):rep(2)
-- 
cgit 


From f1775da07fe48da629468bcfcc2a8a6c4c3f40ed Mon Sep 17 00:00:00 2001
From: Maria José Solano 
Date: Fri, 20 Oct 2023 23:51:26 -0700
Subject: feat(lsp): add snippet API (#25301)

---
 scripts/gen_vimdoc.py | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index ed156e1422..13f64c44a3 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -165,6 +165,7 @@ CONFIG = {
             'secure.lua',
             'version.lua',
             'iter.lua',
+            'snippet.lua',
         ],
         'files': [
             'runtime/lua/vim/iter.lua',
@@ -181,6 +182,7 @@ CONFIG = {
             'runtime/lua/vim/secure.lua',
             'runtime/lua/vim/version.lua',
             'runtime/lua/vim/_inspector.lua',
+            'runtime/lua/vim/snippet.lua',
             'runtime/lua/vim/_meta/builtin.lua',
             'runtime/lua/vim/_meta/diff.lua',
             'runtime/lua/vim/_meta/mpack.lua',
-- 
cgit 


From 224f303ee54c54d2147f03010385e8cc48e42869 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Tue, 31 Oct 2023 09:15:32 -0500
Subject: feat(stdlib): add vim.base64 module (#25843)

Add base64 encode() and decode() functions to a vim.base64 module.
---
 scripts/gen_vimdoc.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 13f64c44a3..1f10a39e35 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -150,6 +150,7 @@ CONFIG = {
             'diff.lua',
             'mpack.lua',
             'json.lua',
+            'base64.lua',
             'spell.lua',
             'builtin.lua',
             '_options.lua',
@@ -187,6 +188,7 @@ CONFIG = {
             'runtime/lua/vim/_meta/diff.lua',
             'runtime/lua/vim/_meta/mpack.lua',
             'runtime/lua/vim/_meta/json.lua',
+            'runtime/lua/vim/_meta/base64.lua',
             'runtime/lua/vim/_meta/regex.lua',
             'runtime/lua/vim/_meta/spell.lua',
         ],
@@ -206,7 +208,7 @@ CONFIG = {
         'section_fmt': lambda name: (
             'Lua module: vim' if name.lower() == '_editor' else
             'LUA-VIMSCRIPT BRIDGE' if name.lower() == '_options' else
-            f'VIM.{name.upper()}' if name.lower() in [ 'highlight', 'mpack', 'json', 'diff', 'spell', 'regex' ] else
+            f'VIM.{name.upper()}' if name.lower() in [ 'highlight', 'mpack', 'json', 'base64', 'diff', 'spell', 'regex' ] else
             'VIM' if name.lower() == 'builtin' else
             f'Lua module: vim.{name.lower()}'),
         'helptag_fmt': lambda name: (
@@ -241,6 +243,7 @@ CONFIG = {
             'builtin': 'vim',
             'mpack': 'vim.mpack',
             'json': 'vim.json',
+            'base64': 'vim.base64',
             'regex': 'vim.regex',
             'spell': 'vim.spell',
         },
-- 
cgit 


From e0d97d264f83d45472e6cdd1051893db1083eefb Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 2 Nov 2023 11:12:38 -0700
Subject: build: use built nvim artifact to generate eval files (#25875)

In cases where the generated files depend on changes to Nvim itself,
generating the files with an older version of Nvim will fail because
those changes are not present in the older version.

For example, if a new option is added then the generator script should
be run with the version of Nvim that contains the new option, or else
the generation will fail.

Co-authored-by: dundargoc 
---
 scripts/gen_eval_files.lua | 1 -
 1 file changed, 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index bf243e96fd..714358e488 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -1,4 +1,3 @@
-#!/usr/bin/env -S nvim -l
 -- Generator for various vimdoc and Lua type files
 
 local DEP_API_METADATA = 'build/api_metadata.mpack'
-- 
cgit 


From 5a2543c1598a0cf97b8eca0573139c9c20d6c93a Mon Sep 17 00:00:00 2001
From: dundargoc <33953936+dundargoc@users.noreply.github.com>
Date: Fri, 3 Nov 2023 00:22:02 +0100
Subject: docs: small fixes (#25831)

Co-authored-by: Peter Aronoff 
---
 scripts/gen_help_html.lua | 8 --------
 1 file changed, 8 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index c8e004e2ab..633207e018 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -60,18 +60,10 @@ local new_layout = {
 
 -- TODO: These known invalid |links| require an update to the relevant docs.
 local exclude_invalid = {
-  ["'previewpopup'"] = "quickref.txt",
-  ["'pvp'"] = "quickref.txt",
   ["'string'"] = "eval.txt",
   Query = 'treesitter.txt',
-  ['eq?'] = 'treesitter.txt',
   matchit = 'vim_diff.txt',
-  ['matchit.txt'] = 'help.txt',
   ["set!"] = "treesitter.txt",
-  ['v:_null_blob'] = 'builtin.txt',
-  ['v:_null_dict'] = 'builtin.txt',
-  ['v:_null_list'] = 'builtin.txt',
-  ['v:_null_string'] = 'builtin.txt',
 }
 
 -- False-positive "invalid URLs".
-- 
cgit 


From 3294d654166ec26cac58037a0358b9f7ea75b2d6 Mon Sep 17 00:00:00 2001
From: dundargoc <33953936+dundargoc@users.noreply.github.com>
Date: Fri, 10 Nov 2023 17:48:45 +0100
Subject: PVS fixes

* build(PVS): exclude mpack and klib as they are external dependencies

* build(PVS): suppress warning V601

See https://pvs-studio.com/en/docs/warnings/v601/

* fix(PVS/V009): add top-level message

* fix(PVS/V547): expression 'p != NULL' is always true

* fix(PVS/V547): expression '* termpp == NULL' is always false
---
 scripts/pvscheck.sh | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'scripts')

diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh
index 81f309aeb3..5334dd2fb7 100755
--- a/scripts/pvscheck.sh
+++ b/scripts/pvscheck.sh
@@ -374,6 +374,8 @@ run_analysis() {(
       --lic-file PVS-Studio.lic \
       --threads "$(get_jobs_num)" \
       --exclude-path src/cjson \
+      --exclude-path src/klib \
+      --exclude-path src/mpack \
       --exclude-path src/xdiff \
       --exclude-path build \
       --output-file PVS-studio.log \
@@ -381,7 +383,7 @@ run_analysis() {(
       --sourcetree-root . || true
 
   rm -rf PVS-studio.{xml,err,tsk,html.d}
-  local plog_args="PVS-studio.log --srcRoot . --excludedCodes V002,V011,V1028,V1042,V1051,V1074"
+  local plog_args="PVS-studio.log --srcRoot . --excludedCodes V002,V011,V601,V1028,V1042,V1051,V1074"
   plog-converter $plog_args --renderTypes xml       --output PVS-studio.xml
   plog-converter $plog_args --renderTypes errorfile --output PVS-studio.err
   plog-converter $plog_args --renderTypes tasklist  --output PVS-studio.tsk
-- 
cgit 


From 448907f65d6709fa234d8366053e33311a01bdb9 Mon Sep 17 00:00:00 2001
From: LW 
Date: Sun, 12 Nov 2023 04:54:27 -0800
Subject: feat(lsp)!: vim.lsp.inlay_hint.get(), enable(), is_enabled() #25512

refactor!: `vim.lsp.inlay_hint()` -> `vim.lsp.inlay_hint.enable()`

Problem:
The LSP specification allows inlay hints to include tooltips, clickable
label parts, and code actions; but Neovim provides no API to query for
these.

Solution:
Add minimal viable extension point from which plugins can query for
inlay hints in a range, in order to build functionality on top of.

Possible Next Steps
---

- Add `virt_text_idx` field to `vim.fn.getmousepos()` return value, for
  usage in mappings of ``, ``, etc
---
 scripts/gen_vimdoc.py | 1 +
 1 file changed, 1 insertion(+)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 1f10a39e35..c738242c5d 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -259,6 +259,7 @@ CONFIG = {
             'buf.lua',
             'diagnostic.lua',
             'codelens.lua',
+            'inlay_hint.lua',
             'tagfunc.lua',
             'semantic_tokens.lua',
             'handlers.lua',
-- 
cgit 


From 353a4be7e84fdc101318215bdcc8a7e780d737fe Mon Sep 17 00:00:00 2001
From: dundargoc 
Date: Sun, 12 Nov 2023 13:13:58 +0100
Subject: build: remove PVS

We already have an extensive suite of static analysis tools we use,
which causes a fair bit of redundancy as we get duplicate warnings. PVS
is also prone to give false warnings which creates a lot of work to
identify and disable.
---
 scripts/pvscheck.sh        | 498 ---------------------------------------------
 scripts/update_terminfo.sh |   3 -
 2 files changed, 501 deletions(-)
 delete mode 100755 scripts/pvscheck.sh

(limited to 'scripts')

diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh
deleted file mode 100755
index 5334dd2fb7..0000000000
--- a/scripts/pvscheck.sh
+++ /dev/null
@@ -1,498 +0,0 @@
-#!/bin/sh
-
-# Assume that "local" is available.
-# shellcheck disable=SC2039
-
-set -e
-# Note: -u causes problems with posh, it barks at “undefined” $@ when no
-# arguments provided.
-test -z "$POSH_VERSION" && set -u
-
-log_info() {
-  >&2 printf "pvscheck.sh: %s\n" "$@"
-}
-
-get_jobs_num() {
-  if [ -n "${TRAVIS:-}" ] ; then
-    # HACK: /proc/cpuinfo on Travis CI is misleading, so hardcode 1.
-    echo 1
-  else
-    echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 ))
-  fi
-}
-
-help() {
-  echo 'Usage:'
-  echo '  pvscheck.sh [--pvs URL] [--deps] [--environment-cc]'
-  echo '              [target-directory [branch]]'
-  echo '  pvscheck.sh [--pvs URL] [--recheck] [--environment-cc] [--update]'
-  echo '              [target-directory]'
-  echo '  pvscheck.sh [--pvs URL] --only-analyse [target-directory]'
-  echo '  pvscheck.sh [--pvs URL] --pvs-install {target-directory}'
-  echo '  pvscheck.sh --patch [--only-build]'
-  echo
-  echo '    --pvs: Fetch pvs-studio from URL.'
-  echo
-  echo '    --pvs detect: Auto-detect latest version (by scraping viva64.com).'
-  echo
-  echo '    --deps: (for regular run) Use top-level Makefile and build deps.'
-  echo '            Without this it assumes all dependencies are already'
-  echo '            installed.'
-  echo
-  echo '    --environment-cc: (for regular run and --recheck) Do not export'
-  echo '                      CC=clang. Build is still run with CFLAGS=-O0.'
-  echo
-  echo '    --only-build: (for --patch) Only patch files in ./build directory.'
-  echo
-  echo '    --pvs-install: Only install PVS-studio to the specified location.'
-  echo
-  echo '    --patch: patch sources in the current directory.'
-  echo '             Does not patch already patched files.'
-  echo '             Does not run analysis.'
-  echo
-  echo '    --recheck: run analysis on a prepared target directory.'
-  echo
-  echo '    --update: when rechecking first do a pull.'
-  echo
-  echo '    --only-analyse: run analysis on a prepared target directory '
-  echo '                    without building Neovim.'
-  echo
-  echo '    target-directory: Directory where build should occur.'
-  echo '                      Default: ../neovim-pvs'
-  echo
-  echo '    branch: Branch to check.'
-  echo '            Default: master.'
-}
-
-getopts_error() {
-  local msg="$1" ; shift
-  local do_help=
-  if test "$msg" = "--help" ; then
-    msg="$1" ; shift
-    do_help=1
-  fi
-  printf '%s\n' "$msg" >&2
-  if test -n "$do_help" ; then
-    printf '\n' >&2
-    help >&2
-  fi
-  echo 'return 1'
-  return 1
-}
-
-# Usage `eval "$(getopts_long long_defs -- positionals_defs -- "$@")"`
-#
-# long_defs: list of pairs of arguments like `longopt action`.
-# positionals_defs: list of arguments like `action`.
-#
-# `action` is a space-separated commands:
-#
-#   store_const [const] [varname] [default]
-#     Store constant [const] (default 1) (note: eval’ed) if argument is present
-#     (long options only). Assumes long option accepts no arguments.
-#   store [varname] [default]
-#     Store value. Assumes long option needs an argument.
-#   run {func} [varname] [default]
-#     Run function {func} and store its output to the [varname]. Assumes no
-#     arguments accepted (long options only).
-#   modify {func} [varname] [default]
-#     Like run, but assumes a single argument, passed to function {func} as $1.
-#
-#   All actions stores empty value if neither [varname] nor [default] are
-#   present. [default] is evaled by top-level `eval`, so be careful. Also note
-#   that no arguments may contain spaces, including [default] and [const].
-getopts_long() {
-  local positional=
-  local opt_bases=""
-  while test $# -gt 0 ; do
-    local arg="$1" ; shift
-    local opt_base=
-    local act=
-    local opt_name=
-    if test -z "$positional" ; then
-      if test "$arg" = "--" ; then
-        positional=0
-        continue
-      fi
-      act="$1" ; shift
-      opt_name="$(echo "$arg" | tr '-' '_')"
-      opt_base="longopt_$opt_name"
-    else
-      if test "$arg" = "--" ; then
-        break
-      fi
-      : $(( positional+=1 ))
-      act="$arg"
-      opt_name="arg_$positional"
-      opt_base="positional_$positional"
-    fi
-    opt_bases="$opt_bases $opt_base"
-    eval "local varname_$opt_base=$opt_name"
-    local i=0
-    for act_subarg in $act ; do
-      eval "local act_$(( i+=1 ))_$opt_base=\"\$act_subarg\""
-    done
-  done
-  # Process options
-  local positional=0
-  local force_positional=
-  while test $# -gt 0 ; do
-    local argument="$1" ; shift
-    local opt_base=
-    local has_equal=
-    local equal_arg=
-    local is_positional=
-    if test "$argument" = "--" ; then
-      force_positional=1
-      continue
-    elif test -z "$force_positional" && test "${argument#--}" != "$argument"
-    then
-      local opt_name="${argument#--}"
-      local opt_name_striparg="${opt_name%%=*}"
-      if test "$opt_name" = "$opt_name_striparg" ; then
-        has_equal=0
-      else
-        has_equal=1
-        equal_arg="${argument#*=}"
-        opt_name="$opt_name_striparg"
-      fi
-      # Use trailing x to prevent stripping newlines
-      opt_name="$(printf '%sx' "$opt_name" | tr '-' '_')"
-      opt_name="${opt_name%x}"
-      if test -n "$(printf '%sx' "$opt_name" | tr -d 'a-z_')" ; then
-        getopts_error "Option contains invalid characters: $opt_name"
-      fi
-      opt_base="longopt_$opt_name"
-    else
-      : $(( positional+=1 ))
-      opt_base="positional_$positional"
-      is_positional=1
-    fi
-    if test -n "$opt_base" ; then
-      eval "local occurred_$opt_base=1"
-
-      eval "local act_1=\"\${act_1_$opt_base:-}\""
-      eval "local varname=\"\${varname_$opt_base:-}\""
-      local need_val=
-      local func=
-      case "$act_1" in
-        (store_const)
-          eval "local const=\"\${act_2_${opt_base}:-1}\""
-          eval "local varname=\"\${act_3_${opt_base}:-$varname}\""
-          printf 'local %s=%s\n' "$varname" "$const"
-          ;;
-        (store)
-          eval "varname=\"\${act_2_${opt_base}:-$varname}\""
-          need_val=1
-          ;;
-        (run)
-          eval "func=\"\${act_2_${opt_base}}\""
-          eval "varname=\"\${act_3_${opt_base}:-$varname}\""
-          printf 'local %s="$(%s)"\n' "$varname" "$func"
-          ;;
-        (modify)
-          eval "func=\"\${act_2_${opt_base}}\""
-          eval "varname=\"\${act_3_${opt_base}:-$varname}\""
-          need_val=1
-          ;;
-        ("")
-          getopts_error --help "Wrong argument: $argument"
-          ;;
-      esac
-      if test -n "$need_val" ; then
-        local val=
-        if test -z "$is_positional" ; then
-          if test $has_equal = 1 ; then
-            val="$equal_arg"
-          else
-            if test $# -eq 0 ; then
-              getopts_error "Missing argument for $opt_name"
-            fi
-            val="$1" ; shift
-          fi
-        else
-          val="$argument"
-        fi
-        local escaped_val="'$(printf "%s" "$val" | sed "s/'/'\\\\''/g")'"
-        case "$act_1" in
-          (store)
-            printf 'local %s=%s\n' "$varname" "$escaped_val"
-            ;;
-          (modify)
-            printf 'local %s="$(%s %s)"\n' "$varname" "$func" "$escaped_val"
-            ;;
-        esac
-      fi
-    fi
-  done
-  # Print default values when no values were provided
-  local opt_base=
-  for opt_base in $opt_bases ; do
-    eval "local occurred=\"\${occurred_$opt_base:-}\""
-    if test -n "$occurred" ; then
-      continue
-    fi
-    eval "local act_1=\"\$act_1_$opt_base\""
-    eval "local varname=\"\$varname_$opt_base\""
-    case "$act_1" in
-      (store)
-        eval "local varname=\"\${act_2_${opt_base}:-$varname}\""
-        eval "local default=\"\${act_3_${opt_base}:-}\""
-        printf 'local %s=%s\n' "$varname" "$default"
-        ;;
-      (store_const|run|modify)
-        eval "local varname=\"\${act_3_${opt_base}:-$varname}\""
-        eval "local default=\"\${act_4_${opt_base}:-}\""
-        printf 'local %s=%s\n' "$varname" "$default"
-        ;;
-    esac
-  done
-}
-
-get_pvs_comment() {
-  local tgt="$1" ; shift
-
-  cat > "$tgt/pvs-comment" << EOF
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
-EOF
-}
-
-install_pvs() {(
-  local tgt="$1" ; shift
-  local pvs_url="$1" ; shift
-
-  cd "$tgt"
-
-  if test -d pvs-studio ; then
-    log_info 'install_pvs: "pvs-studio" directory already exists, skipping install'
-    return 0
-  fi
-
-  mkdir pvs-studio
-  cd pvs-studio
-
-  curl -L -o pvs-studio.tar.gz "$pvs_url"
-  tar xzf pvs-studio.tar.gz
-  rm pvs-studio.tar.gz
-  local pvsdir="$(find . -maxdepth 1 -mindepth 1)"
-  find "$pvsdir" -maxdepth 1 -mindepth 1 -exec mv '{}' . \;
-  rmdir "$pvsdir"
-)}
-
-create_compile_commands() {(
-  local tgt="$1" ; shift
-  local deps="$1" ; shift
-  local environment_cc="$1" ; shift
-
-  if test -z "$environment_cc" ; then
-    export CC=clang
-  fi
-  export CFLAGS=' -O0 '
-
-  if test -z "$deps" ; then
-    mkdir -p "$tgt/build"
-    (
-      cd "$tgt/build"
-
-      cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root"
-      make -j"$(get_jobs_num)"
-    )
-  else
-    (
-      cd "$tgt"
-
-      make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug "
-    )
-  fi
-  find "$tgt/build/src/nvim/auto" -name '*.test-include.c' -delete
-)}
-
-# Warning: realdir below only cares about directories unlike realpath.
-#
-# realpath is not available in Ubuntu trusty yet.
-realdir() {(
-  local dir="$1"
-  local add=""
-  while ! cd "$dir" 2>/dev/null ; do
-    add="${dir##*/}/$add"
-    local new_dir="${dir%/*}"
-    if test "$new_dir" = "$dir" ; then
-      return 1
-    fi
-    dir="$new_dir"
-  done
-  printf '%s\n' "$PWD/$add"
-)}
-
-patch_sources() {(
-  local tgt="$1" ; shift
-  local only_build="${1}" ; shift
-
-  get_pvs_comment "$tgt"
-
-  local sh_script='
-    pvs_comment="$(cat pvs-comment ; echo -n EOS)"
-    filehead="$(head -c $(( ${#pvs_comment} - 3 )) "$1" ; echo -n EOS)"
-    if test "x$filehead" != "x$pvs_comment" ; then
-      cat pvs-comment "$1" > "$1.tmp"
-      mv "$1.tmp" "$1"
-    fi
-  '
-
-  cd "$tgt"
-
-  if test "$only_build" != "--only-build" ; then
-    find \
-      src/nvim test/functional/fixtures test/unit/fixtures \
-      \( -name '*.c' -a '!' -path '*xdiff*' \) \
-      -exec /bin/sh -c "$sh_script" - '{}' \;
-  fi
-
-  find \
-    build/src/nvim/auto build/config \
-    -name '*.c' -not -name '*.test-include.c' \
-    -exec /bin/sh -c "$sh_script" - '{}' \;
-
-  rm pvs-comment
-)}
-
-run_analysis() {(
-  local tgt="$1" ; shift
-
-  cd "$tgt"
-
-  if [ ! -r PVS-Studio.lic ]; then
-    pvs-studio-analyzer credentials -o PVS-Studio.lic 'PVS-Studio Free' 'FREE-FREE-FREE-FREE'
-  fi
-
-  # pvs-studio-analyzer exits with a non-zero exit code when there are detected
-  # errors, so ignore its return
-  pvs-studio-analyzer \
-    analyze \
-      --lic-file PVS-Studio.lic \
-      --threads "$(get_jobs_num)" \
-      --exclude-path src/cjson \
-      --exclude-path src/klib \
-      --exclude-path src/mpack \
-      --exclude-path src/xdiff \
-      --exclude-path build \
-      --output-file PVS-studio.log \
-      --file build/compile_commands.json \
-      --sourcetree-root . || true
-
-  rm -rf PVS-studio.{xml,err,tsk,html.d}
-  local plog_args="PVS-studio.log --srcRoot . --excludedCodes V002,V011,V601,V1028,V1042,V1051,V1074"
-  plog-converter $plog_args --renderTypes xml       --output PVS-studio.xml
-  plog-converter $plog_args --renderTypes errorfile --output PVS-studio.err
-  plog-converter $plog_args --renderTypes tasklist  --output PVS-studio.tsk
-  plog-converter $plog_args --renderTypes fullhtml  --output PVS-studio.html.d
-)}
-
-detect_url() {
-  local url="${1:-detect}"
-  if test "$url" = detect ; then
-    curl --silent -L 'https://pvs-studio.com/en/pvs-studio/download-all/' \
-    | grep -o 'https\{0,1\}://[^"<>]\{1,\}/pvs-studio[^/"<>]*-x86_64\.tgz' \
-    || echo FAILED
-  else
-    printf '%s' "$url"
-  fi
-}
-
-do_check() {
-  local tgt="$1" ; shift
-  local branch="$1" ; shift
-  local pvs_url="$1" ; shift
-  local deps="$1" ; shift
-  local environment_cc="$1" ; shift
-
-  if test -z "$pvs_url" || test "$pvs_url" = FAILED ; then
-    pvs_url="$(detect_url detect)"
-    if test -z "$pvs_url" || test "$pvs_url" = FAILED ; then
-      echo "failed to auto-detect PVS URL"
-      exit 1
-    fi
-    echo "Auto-detected PVS URL: ${pvs_url}"
-  fi
-
-  git clone --branch="$branch" . "$tgt"
-
-  install_pvs "$tgt" "$pvs_url"
-
-  do_recheck "$tgt" "$deps" "$environment_cc" ""
-}
-
-do_recheck() {
-  local tgt="$1" ; shift
-  local deps="$1" ; shift
-  local environment_cc="$1" ; shift
-  local update="$1" ; shift
-
-  if test -n "$update" ; then
-    (
-      cd "$tgt"
-      local branch="$(git rev-parse --abbrev-ref HEAD)"
-      git checkout --detach
-      git fetch -f origin "${branch}:${branch}"
-      git checkout -f "$branch"
-    )
-  fi
-
-  create_compile_commands "$tgt" "$deps" "$environment_cc"
-
-  do_analysis "$tgt"
-}
-
-do_analysis() {
-  local tgt="$1" ; shift
-
-  if test -d "$tgt/pvs-studio" ; then
-    local saved_pwd="$PWD"
-    cd "$tgt/pvs-studio"
-    export PATH="$PWD/bin${PATH+:}${PATH}"
-    cd "$saved_pwd"
-  fi
-
-  run_analysis "$tgt"
-}
-
-main() {
-  eval "$(
-    getopts_long \
-      help store_const \
-      pvs 'modify detect_url pvs_url' \
-      patch store_const \
-      only-build 'store_const --only-build' \
-      recheck store_const \
-      only-analyse store_const \
-      pvs-install store_const \
-      deps store_const \
-      environment-cc store_const \
-      update store_const \
-      -- \
-      'modify realdir tgt "$PWD/../neovim-pvs"' \
-      'store branch master' \
-      -- "$@"
-  )"
-
-  if test -n "$help" ; then
-    help
-    return 0
-  fi
-
-  if test -n "$patch" ; then
-    patch_sources "$tgt" "$only_build"
-  elif test -n "$pvs_install" ; then
-    install_pvs "$tgt" "$pvs_url"
-  elif test -n "$recheck" ; then
-    do_recheck "$tgt" "$deps" "$environment_cc" "$update"
-  elif test -n "$only_analyse" ; then
-    do_analysis "$tgt"
-  else
-    do_check "$tgt" "$branch" "$pvs_url" "$deps" "$environment_cc"
-  fi
-}
-
-main "$@"
diff --git a/scripts/update_terminfo.sh b/scripts/update_terminfo.sh
index 775048f246..2840334e99 100755
--- a/scripts/update_terminfo.sh
+++ b/scripts/update_terminfo.sh
@@ -61,9 +61,6 @@ print_bold "[*] Writing $target... "
 sorted_terms="$(echo "${!entries[@]}" | tr ' ' '\n' | sort | xargs)"
 
 cat > "$target" <
Date: Fri, 10 Nov 2023 12:23:42 +0100
Subject: refactor: replace manual header guards with #pragma once

It is less error-prone than manually defining header guards. Pretty much
all compilers support it even if it's not part of the C standard.
---
 scripts/update_terminfo.sh | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

(limited to 'scripts')

diff --git a/scripts/update_terminfo.sh b/scripts/update_terminfo.sh
index 2840334e99..e12365ba8f 100755
--- a/scripts/update_terminfo.sh
+++ b/scripts/update_terminfo.sh
@@ -63,12 +63,9 @@ sorted_terms="$(echo "${!entries[@]}" | tr ' ' '\n' | sort | xargs)"
 cat > "$target" <
 EOF
@@ -87,7 +84,4 @@ for term in $sorted_terms; do
   printf '};\n'
 done >> "$target"
 
-cat >> "$target" <
Date: Mon, 13 Nov 2023 00:40:34 -0800
Subject: vim-patch: mark N/A 8.1 patches #26008

Problem:
Numerous Vim 8.1 patches are listed by `vim-patch.sh -l`.

Solution:
Mark the following patches as N/A:

obviated by $NVIM env var:
vim-patch:8.1.0049 shell cannot tell running in a terminal window
vim-patch:8.1.0050 $VIM_TERMINAL is also set when not in a terminal window

'termwinkey' is not supported by Nvim:
vim-patch:8.1.0072 use of 'termwinkey' is inconsistent

Nvim handles STOP signal via libuv:
vim-patch:8.1.0304 no redraw when using a STOP signal on Vim and then CONT
vim-patch:8.1.0312 wrong type for flags used in signal handlers

Nvim does not have `parse_queued_messages`:
vim-patch:8.1.0367 getchar(1) no longer processes pending messages

N/A various:
vim-patch:8.1.1396 'wincolor' does not apply to lines below the buffer
vim-patch:8.1.1502 cannot play any sound
vim-patch:8.1.1515 memory leak reported for sound when build with EXITFREE

Nvim has extmarks instead of textprops:
vim-patch:8.1.0579 cannot attach properties to text
vim-patch:8.1.0582 text properties are not enabled
vim-patch:8.1.0634 text properties cannot cross line boundaries
vim-patch:8.1.0638 text property highlighting is off by one column
vim-patch:8.1.0639 text properties test fails on MS-Windows
vim-patch:8.1.0643 computing byte offset wrong
vim-patch:8.1.0654 when deleting a line text property flags are not adjusted
vim-patch:8.1.0655 when appending a line text property flags are not added
vim-patch:8.1.0663 text property display wrong when 'number' is set
vim-patch:8.1.0665 text property display wrong when 'spell' is set
vim-patch:8.1.0667 textprop test leaves file behind
vim-patch:8.1.0675 text property column in screen columns is not practical
vim-patch:8.1.0676 textprop screendump test fails
vim-patch:8.1.0681 text properties as not adjusted for deleted text
vim-patch:8.1.0682 text properties not adjusted when backspacing replaced text
vim-patch:8.1.0688 text properties are not restored by undo
vim-patch:8.1.0689 undo with text properties not tested
vim-patch:8.1.0690 setline() and setbufline() do not clear text properties
vim-patch:8.1.0691 text properties are not adjusted for :substitute
vim-patch:8.1.0694 when using text props may free memory that is not allocated
vim-patch:8.1.0703 compiler warnings with 64-bit compiler
vim-patch:8.1.0707 text property columns are not adjusted for changed indent
vim-patch:8.1.0970 text properties test fails when 'encoding' is not utf-8
vim-patch:8.1.1035 prop_remove() second argument is not optional
vim-patch:8.1.1276 cannot combine text properties with syntax highlighting
vim-patch:8.1.1278 missing change for "combine" field
vim-patch:8.1.1333 text properties don't always move after changes
vim-patch:8.1.1337 get empty text prop when splitting line just after text prop
vim-patch:8.1.1341 text properties are lost when joining lines
vim-patch:8.1.1343 text properties not adjusted for Visual block mode delete
vim-patch:8.1.1340 attributes from 'cursorline' overwrite textprop
vim-patch:8.1.1351 text property wrong after :substitute
vim-patch:8.1.1359 text property wrong after :substitute with backslash
vim-patch:8.1.1387 calling prop_add() in an empty buffer doesn't work
vim-patch:8.1.1388 errors when calling prop_remove() for an unloaded buffer
vim-patch:8.1.1463 gcc warns for uninitialized variable

N/A Nvim has buf_attach instead of "listeners":
vim-patch:8.1.1320 it is not possible to track changes to a buffer
vim-patch:8.1.1321 no docs or tests for listener functions
vim-patch:8.1.1326 no test for listener with partial
vim-patch:8.1.1328 no test for listener with undo operation
vim-patch:8.1.1332 cannot flush listeners without redrawing, mix of changes
vim-patch:8.1.1335 listener callback is called after inserting text
vim-patch:8.1.1419 listener callbacks may be called recursively
vim-patch:8.1.1486 a listener change is merged even when it adds a line

N/A build issues:
vim-patch:8.1.0601 a few compiler warnings
vim-patch:8.1.0612 cannot use two global runtime dirs with configure
vim-patch:8.1.0684 warnings from 64-bit compiler
vim-patch:8.1.1344 Coverity complains about possibly using a NULL pointer
vim-patch:8.1.1376 warnings for size_t/int mixups
vim-patch:8.1.1414 alloc() returning "char_u *" causes a lot of type casts
vim-patch:8.1.1508 sound keeps failing on Travis
vim-patch:8.1.1494 build failure

N/A terminal / job control patches:
vim-patch:8.1.0761 default value for brief_wait is wrong
vim-patch:8.1.0824 SunOS/Solaris has a problem with ttys
vim-patch:8.1.0845 having job_status() free the job causes problems
vim-patch:8.1.0870 Vim doesn't use the new ConPTY support in Windows 10
vim-patch:8.1.0880 MS-Windows: inconsistent selection of winpty/conpty
vim-patch:8.1.0890 pty allocation wrong if using file for out channel
vim-patch:8.1.0906 using clumsy way to get console window handle
vim-patch:8.1.0909 MS-Windows: using ConPTY even though it is not stable
vim-patch:8.1.0928 stray log function call
vim-patch:8.1.0940 MS-Windows console resizing not handled properly
vim-patch:8.1.1028 MS-Windows: memory leak when creating terminal fails
vim-patch:8.1.1265 when GPM mouse support is enabled double clicks do not work
vim-patch:8.1.1267 cannot check if GPM mouse support is working

N/A encoding patches:
vim-patch:8.1.0879 MS-Windows: temp name encoding can be wrong
vim-patch:8.1.0895 MS-Windows: dealing with temp name encoding not quite right
vim-patch:8.1.0918 MS-Windows: startup messages are not converted
vim-patch:8.1.1090 MS-Windows: modify_fname() has problems with some 'encoding'

N/A platform patches:
vim-patch:8.1.1103 MS-Windows: old API calls are no longer needed

N/A Lua patches:
vim-patch:8.1.1019 Lua: may garbage collect function reference in use

N/A Nvim has floating windows instead of popup window:
vim-patch:8.1.1329 plans for popup window support are spread out
vim-patch:8.1.1364 design for popup window support needs more details
vim-patch:8.1.1391 no popup window support
vim-patch:8.1.1400 using global pointer for tab-local popups is clumsy
vim-patch:8.1.1399 popup windows not adjusted when switching tabs
vim-patch:8.1.0062 popup menu broken if a callback changes the window layout
vim-patch:8.1.1405 "highlight" option of popup windows not supported
vim-patch:8.1.1406 popup_hide() and popup_show() not implemented yet
vim-patch:8.1.1407 popup_create() does not support text properties
vim-patch:8.1.1410 popup_move() is not implemented yet
vim-patch:8.1.1402 "timer" option of popup windows not supported
vim-patch:8.1.1408 PFL_HIDDEN conflicts with system header file
vim-patch:8.1.1420 popup window size only uses first line length
vim-patch:8.1.1421 drawing "~" line in popup window
vim-patch:8.1.1422 popup_getoptions() not implemented yet
vim-patch:8.1.1423 popup windows use options from current window and buffer
vim-patch:8.1.1426 no test for syntax highlight in popup window
vim-patch:8.1.1427 popup window screenshot test fails
vim-patch:8.1.1428 popup_atcursor() not implemented yet
vim-patch:8.1.1429 "pos" option of popup window not supported yet
vim-patch:8.1.1430 popup window option "wrap" not supported
vim-patch:8.1.1431 popup window listed as "Scratch"
vim-patch:8.1.1432 can't build with eval feature
vim-patch:8.1.1438 some commands cause trouble in a popup window
vim-patch:8.1.1441 popup window filter not yet implemented
vim-patch:8.1.1442 popup windows not considered when the Vim window is resized
vim-patch:8.1.1443 popup window padding and border not implemented yet
vim-patch:8.1.1444 not using double line characters for popup border
vim-patch:8.1.1445 popup window border highlight not implemented yet
vim-patch:8.1.1446 popup window callback not implemented yet
vim-patch:8.1.1447 not allowed to create an empty popup
vim-patch:8.1.1448 statusline is sometimes drawn on top of popup
vim-patch:8.1.1449 popup text truncated at end of screen
vim-patch:8.1.1450 popup window positioning wrong when using padding or borders
vim-patch:8.1.1451 CTRL-L does not clear screen with a popup window
vim-patch:8.1.1452 line and col property of popup windows not properly checked
vim-patch:8.1.1453 popup window "moved" property not implemented yet
vim-patch:8.1.1455 popup_atcursor() not completely implemented
vim-patch:8.1.1459 popup window border looks bad when 'ambiwidth' is "double"
vim-patch:8.1.1460 popup window border characters may be wrong
vim-patch:8.1.1416 popup_getposition() not implemented yet
vim-patch:8.1.1493 redrawing with popups is slow and causes flicker
vim-patch:8.1.1496 popup window height is not recomputed
vim-patch:8.1.1499 ruler not updated after popup window was removed
vim-patch:8.1.1511 matches in a popup window are not displayed properly
vim-patch:8.1.1513 all popup functionality is in functions, except :popupclear
vim-patch:8.1.1517 when a popup changes all windows are redrawn
vim-patch:8.1.1518 crash when setting 'columns' while a popup is visible
vim-patch:8.1.1520 popup windows are ignored when dealing with mouse position
vim-patch:8.1.1521 when a popup window is closed the buffer remains
vim-patch:8.1.1522 poup_notification() not implemented yet
vim-patch:8.1.1495 memory access error
vim-patch:8.1.1497 accessing memory beyond allocated space

N/A already applied:
vim-patch:8.1.1226 {not in Vi} remarks get in the way of useful help text
vim-patch:8.1.1280 remarks about functionality not in Vi clutters the help
---
 scripts/vim-patch.sh | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 478415376a..47c6d293bc 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -218,11 +218,12 @@ preprocess_patch() {
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('"${na_src_testdir}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove testdir/test_*.vim files
-  local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
+  local na_src_testdir='balloon.*\|behave\.vim\|channel.*\|crypt\.vim\|cscope\.vim\|gui.*\|hardcopy\.vim\|job_fails\.vim\|json\.vim\|listener\.vim\|mzscheme\.vim\|netbeans.*\|paste\.vim\|popupwin.*\|python2\.vim\|pyx2\.vim\|restricted\.vim\|shortpathname\.vim\|sound\.vim\|tcl\.vim\|terminal.*\|xxd\.vim'
   2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
-  # Remove version.c #7555
-  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(version\.c\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
+  # Remove N/A src/*.[ch] files: sound.c, version.c
+  local na_src_c='sound\|version'
+  2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%('"${na_src_c}"'\)\.[ch]\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
 
   # Remove some *.po files. #5622
   local na_po='sjiscorr\.c\|ja\.sjis\.po\|ko\.po\|pl\.cp1250\.po\|pl\.po\|ru\.cp1251\.po\|uk\.cp1251\.po\|zh_CN\.cp936\.po\|zh_CN\.po\|zh_TW\.po'
-- 
cgit 


From d50274812b275edff58418b3d17868385599fc14 Mon Sep 17 00:00:00 2001
From: rsynnest 
Date: Tue, 14 Nov 2023 09:33:18 -0800
Subject: docs: adjust help-tag-right CSS for HTML #25858

---
 scripts/gen_help_html.lua | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 633207e018..706335342d 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -967,13 +967,16 @@ local function gen_css(fname)
     /* Tag pseudo-header common in :help docs. */
     .help-tag-right {
       color: var(--tag-color);
-      margin-left: auto;
-      margin-right: 0;
-      float: right;
+      background-color: inherit;
+      display: flex;
+      justify-content: right;
+      margin-top: 1.5em;
+      margin-bottom: 1em;
     }
     .help-tag a,
     .help-tag-right a {
       color: inherit;
+      background-color: var(--accent-bg-color);
     }
     .help-tag a:not(:hover),
     .help-tag-right a:not(:hover) {
-- 
cgit 


From 1a4db51d064e1ef6925e3545f80a13da4b92d4ef Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Tue, 14 Nov 2023 09:55:54 -0800
Subject: Revert "docs: adjust help-tag-right CSS for HTML" #26046

The style change is mostly a regression.

Reverts #25858 d50274812b275edff58418b3d17868385599fc14
---
 scripts/gen_help_html.lua | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 706335342d..633207e018 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -967,16 +967,13 @@ local function gen_css(fname)
     /* Tag pseudo-header common in :help docs. */
     .help-tag-right {
       color: var(--tag-color);
-      background-color: inherit;
-      display: flex;
-      justify-content: right;
-      margin-top: 1.5em;
-      margin-bottom: 1em;
+      margin-left: auto;
+      margin-right: 0;
+      float: right;
     }
     .help-tag a,
     .help-tag-right a {
       color: inherit;
-      background-color: var(--accent-bg-color);
     }
     .help-tag a:not(:hover),
     .help-tag-right a:not(:hover) {
-- 
cgit 


From dc3f84bf4f94d0389f74991c555c3e76c2ea67f6 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 16 Nov 2023 10:53:25 -0600
Subject: docs: fix vim.snippet help tags (#26068)

---
 scripts/gen_vimdoc.py | 1 +
 1 file changed, 1 insertion(+)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index c738242c5d..3566d52f6e 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -246,6 +246,7 @@ CONFIG = {
             'base64': 'vim.base64',
             'regex': 'vim.regex',
             'spell': 'vim.spell',
+            'snippet': 'vim.snippet',
         },
         'append_only': [
             'shared.lua',
-- 
cgit 


From 4bf47222c973c4bc935d6fde106329f8a0e103e3 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 16 Nov 2023 11:35:54 -0600
Subject: feat: add vim.text module (#26069)

---
 scripts/gen_vimdoc.py | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 3566d52f6e..925e6f98e6 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -167,6 +167,7 @@ CONFIG = {
             'version.lua',
             'iter.lua',
             'snippet.lua',
+            'text.lua',
         ],
         'files': [
             'runtime/lua/vim/iter.lua',
@@ -184,6 +185,7 @@ CONFIG = {
             'runtime/lua/vim/version.lua',
             'runtime/lua/vim/_inspector.lua',
             'runtime/lua/vim/snippet.lua',
+            'runtime/lua/vim/text.lua',
             'runtime/lua/vim/_meta/builtin.lua',
             'runtime/lua/vim/_meta/diff.lua',
             'runtime/lua/vim/_meta/mpack.lua',
@@ -247,6 +249,7 @@ CONFIG = {
             'regex': 'vim.regex',
             'spell': 'vim.spell',
             'snippet': 'vim.snippet',
+            'text': 'vim.text',
         },
         'append_only': [
             'shared.lua',
-- 
cgit 


From 9fa9b3cad94a1ea7fced128fed2cd5ac3ff7bc44 Mon Sep 17 00:00:00 2001
From: LW 
Date: Mon, 27 Nov 2023 08:23:04 -0800
Subject: docs: support @since for api level #25574

close #25416
---
 scripts/gen_vimdoc.py | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 925e6f98e6..8ed88cb8f5 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -42,6 +42,7 @@ import subprocess
 import collections
 import msgpack
 import logging
+from typing import Tuple
 from pathlib import Path
 
 from xml.dom import minidom
@@ -363,6 +364,30 @@ annotation_map = {
 }
 
 
+def nvim_api_info() -> Tuple[int, bool]:
+    """Returns NVIM_API_LEVEL, NVIM_API_PRERELEASE from CMakeLists.txt"""
+    if not hasattr(nvim_api_info, 'LEVEL'):
+        script_dir = os.path.dirname(os.path.abspath(__file__))
+        cmake_file_path = os.path.join(script_dir, '..', 'CMakeLists.txt')
+        with open(cmake_file_path, 'r') as cmake_file:
+            cmake_content = cmake_file.read()
+
+        api_level_match = re.search(r'set\(NVIM_API_LEVEL (\d+)\)', cmake_content)
+        api_prerelease_match = re.search(
+            r'set\(NVIM_API_PRERELEASE (\w+)\)', cmake_content
+        )
+
+        if not api_level_match or not api_prerelease_match:
+            raise RuntimeError(
+                'Could not find NVIM_API_LEVEL or NVIM_API_PRERELEASE in CMakeLists.txt'
+            )
+
+        nvim_api_info.LEVEL = int(api_level_match.group(1))
+        nvim_api_info.PRERELEASE = api_prerelease_match.group(1).lower() == 'true'
+
+    return nvim_api_info.LEVEL, nvim_api_info.PRERELEASE
+
+
 # Raises an error with details about `o`, if `cond` is in object `o`,
 # or if `cond()` is callable and returns True.
 def debug_this(o, cond=True):
@@ -691,6 +716,7 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
         'params': collections.OrderedDict(),
         'return': [],
         'seealso': [],
+        'prerelease': False,
         'xrefs': []
     }
 
@@ -729,6 +755,14 @@ def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=F
                 elif kind == 'warning':
                     text += render_node(child, text, indent=indent,
                                         width=width, fmt_vimhelp=fmt_vimhelp)
+                elif kind == 'since':
+                    since_match = re.match(r'^(\d+)', get_text(child))
+                    since = int(since_match.group(1)) if since_match else 0
+                    NVIM_API_LEVEL, NVIM_API_PRERELEASE = nvim_api_info()
+                    if since > NVIM_API_LEVEL or (
+                        since == NVIM_API_LEVEL and NVIM_API_PRERELEASE
+                    ):
+                        chunks['prerelease'] = True
                 else:
                     raise RuntimeError('unhandled simplesect: {}\n{}'.format(
                         child.nodeName, child.toprettyxml(indent='  ', newl='\n')))
@@ -837,9 +871,11 @@ def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent=
 
         # Generate text from the gathered items.
         chunks = [para['text']]
-        if len(para['note']) > 0:
+        notes = ["    This API is pre-release (unstable)."] if para['prerelease'] else []
+        notes += para['note']
+        if len(notes) > 0:
             chunks.append('\nNote: ~')
-            for s in para['note']:
+            for s in notes:
                 chunks.append(s)
         if len(para['params']) > 0 and has_nonexcluded_params(para['params']):
             chunks.append('\nParameters: ~')
-- 
cgit 


From 570367ac83cdceeee7d43dadcff7652bd5cc93c5 Mon Sep 17 00:00:00 2001
From: zeertzjq 
Date: Tue, 28 Nov 2023 13:52:17 +0800
Subject: docs(lua): don't include remote-only API functions (#26266)

---
 scripts/gen_eval_files.lua | 50 ++++++++++++++++++++++++----------------------
 1 file changed, 26 insertions(+), 24 deletions(-)

(limited to 'scripts')

diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index 714358e488..e331dd996e 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -178,34 +178,36 @@ local function get_api_meta()
   local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table]]
 
   for _, fun in ipairs(metadata) do
-    local fdoc = doc_metadata[fun.name]
-
-    local params = {} --- @type {[1]:string,[2]:string}[]
-    for _, p in ipairs(fun.parameters) do
-      local ptype, pname = p[1], p[2]
-      params[#params + 1] = {
-        pname,
-        api_type(ptype),
-        fdoc and fdoc.parameters_doc[pname] or nil,
-      }
-    end
+    if fun.lua then
+      local fdoc = doc_metadata[fun.name]
+
+      local params = {} --- @type {[1]:string,[2]:string}[]
+      for _, p in ipairs(fun.parameters) do
+        local ptype, pname = p[1], p[2]
+        params[#params + 1] = {
+          pname,
+          api_type(ptype),
+          fdoc and fdoc.parameters_doc[pname] or nil,
+        }
+      end
 
-    local r = {
-      signature = 'NA',
-      name = fun.name,
-      params = params,
-      returns = api_type(fun.return_type),
-      deprecated = fun.deprecated_since ~= nil,
-    }
+      local r = {
+        signature = 'NA',
+        name = fun.name,
+        params = params,
+        returns = api_type(fun.return_type),
+        deprecated = fun.deprecated_since ~= nil,
+      }
 
-    if fdoc then
-      if #fdoc.doc > 0 then
-        r.desc = table.concat(fdoc.doc, '\n')
+      if fdoc then
+        if #fdoc.doc > 0 then
+          r.desc = table.concat(fdoc.doc, '\n')
+        end
+        r.return_desc = (fdoc['return'] or {})[1]
       end
-      r.return_desc = (fdoc['return'] or {})[1]
-    end
 
-    ret[fun.name] = r
+      ret[fun.name] = r
+    end
   end
   return ret
 end
-- 
cgit