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/gen_vimdoc.py') 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/gen_vimdoc.py') 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/gen_vimdoc.py') 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': [], } -- 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 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'scripts/gen_vimdoc.py') 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) -- 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 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/gen_vimdoc.py') 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 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts/gen_vimdoc.py') 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. -- 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/gen_vimdoc.py') 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 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 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'scripts/gen_vimdoc.py') 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)) -- cgit From 42333ea98dfcd2994ee128a3467dfe68205154cd Mon Sep 17 00:00:00 2001 From: Lewis Russell 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_vimdoc.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts/gen_vimdoc.py') 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 : -- 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_vimdoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/gen_vimdoc.py') 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 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_vimdoc.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'scripts/gen_vimdoc.py') 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 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/gen_vimdoc.py')

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_vimdoc.py | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)

(limited to 'scripts/gen_vimdoc.py')

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 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/gen_vimdoc.py')

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/gen_vimdoc.py')

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 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/gen_vimdoc.py')

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 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/gen_vimdoc.py')

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/gen_vimdoc.py')

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/gen_vimdoc.py')

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