diff options
Diffstat (limited to 'scripts/gen_vimdoc.py')
-rwxr-xr-x | scripts/gen_vimdoc.py | 81 |
1 files changed, 64 insertions, 17 deletions
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index a61690e99f..b1a7f92854 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -39,6 +39,7 @@ Each function :help block is formatted as follows: parameter is marked as [out]. - Each function documentation is separated by a single line. """ +import argparse import os import re import sys @@ -57,7 +58,6 @@ if sys.version_info < MIN_PYTHON_VERSION: sys.exit(1) DEBUG = ('DEBUG' in os.environ) -TARGET = os.environ.get('TARGET', None) INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ) INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ) @@ -68,6 +68,7 @@ base_dir = os.path.dirname(os.path.dirname(script_path)) out_dir = os.path.join(base_dir, 'tmp-{target}-doc') filter_cmd = '%s %s' % (sys.executable, script_path) seen_funcs = set() +msgs = [] # Messages to show on exit. lua2dox_filter = os.path.join(base_dir, 'scripts', 'lua2dox_filter') CONFIG = { @@ -112,10 +113,12 @@ CONFIG = { 'section_order': [ 'vim.lua', 'shared.lua', + 'uri.lua', ], 'files': ' '.join([ os.path.join(base_dir, 'src/nvim/lua/vim.lua'), os.path.join(base_dir, 'runtime/lua/vim/shared.lua'), + os.path.join(base_dir, 'runtime/lua/vim/uri.lua'), ]), 'file_patterns': '*.lua', 'fn_name_prefix': '', @@ -128,6 +131,7 @@ CONFIG = { 'module_override': { # `shared` functions are exposed on the `vim` module. 'shared': 'vim', + 'uri': 'vim', }, 'append_only': [ 'shared.lua', @@ -139,12 +143,13 @@ CONFIG = { 'section_start_token': '*lsp-core*', 'section_order': [ 'lsp.lua', - 'protocol.lua', 'buf.lua', - 'callbacks.lua', + 'diagnostic.lua', + 'handlers.lua', + 'util.lua', 'log.lua', 'rpc.lua', - 'util.lua' + 'protocol.lua', ], 'files': ' '.join([ os.path.join(base_dir, 'runtime/lua/vim/lsp'), @@ -191,7 +196,7 @@ xrefs = set() # Raises an error with details about `o`, if `cond` is in object `o`, # or if `cond()` is callable and returns True. -def debug_this(cond, o): +def debug_this(o, cond=True): name = '' if not isinstance(o, str): try: @@ -205,6 +210,23 @@ def debug_this(cond, o): raise RuntimeError('xxx: {}\n{}'.format(name, o)) +# Appends a message to a list which will be printed on exit. +def msg(s): + msgs.append(s) + + +# Print all collected messages. +def msg_report(): + for m in msgs: + print(f' {m}') + + +# Print collected messages, then throw an exception. +def fail(s): + msg_report() + raise RuntimeError(s) + + def find_first(parent, name): """Finds the first matching node within parent.""" sub = parent.getElementsByTagName(name) @@ -426,7 +448,7 @@ def render_node(n, text, prefix='', indent='', width=62): indent=indent, width=width)) i = i + 1 elif n.nodeName == 'simplesect' and 'note' == n.getAttribute('kind'): - text += 'Note:\n ' + text += '\nNote:\n ' for c in n.childNodes: text += render_node(c, text, indent=' ', width=width) text += '\n' @@ -440,6 +462,8 @@ def render_node(n, text, prefix='', indent='', width=62): text += ind(' ') for c in n.childNodes: text += render_node(c, text, indent=' ', width=width) + elif n.nodeName == 'computeroutput': + return get_text(n) else: raise RuntimeError('unhandled node type: {}\n{}'.format( n.nodeName, n.toprettyxml(indent=' ', newl='\n'))) @@ -505,6 +529,7 @@ def para_as_map(parent, indent='', width=62): and is_inline(self_or_child(prev)) and is_inline(self_or_child(child)) and '' != get_text(self_or_child(child)).strip() + and text and ' ' != text[-1]): text += ' ' @@ -684,7 +709,7 @@ def extract_from_xml(filename, target, width): if len(prefix) + len(suffix) > lhs: signature = vimtag.rjust(width) + '\n' - signature += doc_wrap(suffix, width=width-8, prefix=prefix, + signature += doc_wrap(suffix, width=width, prefix=prefix, func=True) else: signature = prefix + suffix @@ -841,7 +866,7 @@ def delete_lines_below(filename, tokenstr): fp.writelines(lines[0:i]) -def main(config): +def main(config, args): """Generates: 1. Vim :help docs @@ -850,7 +875,7 @@ def main(config): Doxygen is called and configured through stdin. """ for target in CONFIG: - if TARGET is not None and target != TARGET: + if args.target is not None and target != args.target: continue mpack_file = os.path.join( base_dir, 'runtime', 'doc', @@ -915,9 +940,10 @@ def main(config): 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'))) # Extract unformatted (*.mpack). - fn_map, _ = extract_from_xml(os.path.join(base, '{}.xml'.format( - compound.getAttribute('refid'))), target, width=9999) + fn_map, _ = extract_from_xml(xmlfile, target, width=9999) # Extract formatted (:help). functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp( os.path.join(base, '{}.xml'.format( @@ -950,7 +976,8 @@ def main(config): sections[filename] = (title, helptag, doc) fn_map_full.update(fn_map) - assert sections + if len(sections) == 0: + fail(f'no sections for target: {target}') if len(sections) > len(CONFIG[target]['section_order']): raise RuntimeError( 'found new modules "{}"; update the "section_order" map'.format( @@ -960,7 +987,11 @@ def main(config): i = 0 for filename in CONFIG[target]['section_order']: - title, helptag, section_doc = sections.pop(filename) + try: + title, helptag, section_doc = sections.pop(filename) + except KeyError: + msg(f'warning: empty docs, skipping (target={target}): {filename}') + continue i += 1 if filename not in CONFIG[target]['append_only']: docs += sep @@ -983,7 +1014,10 @@ def main(config): with open(mpack_file, 'wb') as fp: fp.write(msgpack.packb(fn_map_full, use_bin_type=True)) - shutil.rmtree(output_dir) + if not args.keep_tmpfiles: + shutil.rmtree(output_dir) + + msg_report() def filter_source(filename): @@ -1001,6 +1035,18 @@ def filter_source(filename): fp.read(), flags=re.M)) +def parse_args(): + targets = ', '.join(CONFIG.keys()) + ap = argparse.ArgumentParser() + ap.add_argument('source_filter', nargs='*', + help="Filter source file(s)") + ap.add_argument('-k', '--keep-tmpfiles', action='store_true', + help="Keep temporary files") + ap.add_argument('-t', '--target', + help=f'One of ({targets}), defaults to "all"') + return ap.parse_args() + + Doxyfile = textwrap.dedent(''' OUTPUT_DIRECTORY = {output} INPUT = {input} @@ -1037,9 +1083,10 @@ Doxyfile = textwrap.dedent(''' ''') if __name__ == "__main__": - if len(sys.argv) > 1: - filter_source(sys.argv[1]) + args = parse_args() + if len(args.source_filter) > 0: + filter_source(args.source_filter[0]) else: - main(Doxyfile) + main(Doxyfile, args) # vim: set ft=python ts=4 sw=4 tw=79 et : |