#!/usr/bin/env python3
"""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')))
Flow:
main
extract_from_xml
fmt_node_as_vimhelp \
para_as_map } recursive
update_params_map /
render_node
TODO: eliminate this script and use Lua+treesitter (requires parsers for C and
Lua markdown-style docstrings).
The generated :help text for each function is formatted as follows:
- Max width of 78 columns (`text_width`).
- Indent with spaces (not tabs).
- Indent of 4 columns for body text (`indentation`).
- Function signature and helptag (right-aligned) on the same line.
- Signature and helptag must have a minimum of 8 spaces between them.
- If the signature is too long, it is placed on the line after the helptag.
Signature wraps at `text_width - 8` characters with subsequent
lines indented to the open parenthesis.
- Subsection bodies are indented an additional 4 spaces.
- Body consists of function description, parameters, return description, and
C declaration (`INCLUDE_C_DECL`).
- Parameters are omitted for the `void` and `Error *` types, or if the
parameter is marked as [out].
- Each function documentation is separated by a single line.
"""
import argparse
import os
import re
import sys
import shutil
import textwrap
import subprocess
import collections
import msgpack
import logging
from pathlib import Path
from xml.dom import minidom
MIN_PYTHON_VERSION = (3, 6)
MIN_DOXYGEN_VERSION = (1, 9, 0)
if sys.version_info < MIN_PYTHON_VERSION:
print("requires Python {}.{}+".format(*MIN_PYTHON_VERSION))
sys.exit(1)
doxygen_version = tuple((int(i) for i in subprocess.check_output(["doxygen", "-v"],
universal_newlines=True).split()[0].split('.')))
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)
# 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)
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
log = logging.getLogger(__name__)
LOG_LEVELS = {
logging.getLevelName(level): level for level in [
logging.DEBUG, logging.INFO, logging.ERROR
]
}
text_width = 78
indentation = 4
script_path = os.path.abspath(__file__)
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)
msgs = [] # Messages to show on exit.
lua2dox = os.path.join(base_dir, 'scripts', 'lua2dox.lua')
CONFIG = {
'api': {
'mode': 'c',
'filename': 'api.txt',
# Section ordering.
'section_order': [
'vim.c',
'vimscript.c',
'command.c',
'options.c',
'buffer.c',
'extmark.c',
'window.c',
'win_config.c',
'tabpage.c',
'autocmd.c',
'ui.c',
],
# List of files/directories for doxygen to read, relative to `base_dir`
'files': ['src/nvim/api'],
# file patterns used by doxygen
'file_patterns': '*.h *.c',
# Only function with this prefix are considered
'fn_name_prefix': 'nvim_',
# Section name overrides.
'section_name': {
'vim.c': 'Global',
},
# For generated section names.
'section_fmt': lambda name: f'{name} Functions',
# Section helptag.
'helptag_fmt': lambda name: f'*api-{name.lower()}*',
# Per-function helptag.
'fn_helptag_fmt': lambda fstem, name: f'*{name}()*',
# Module name overrides (for Lua).
'module_override': {},
# Append the docs for these modules, do not start a new section.
'append_only': [],
},
'lua': {
'mode': 'lua',
'filename': 'lua.txt',
'section_order': [
'_editor.lua',
'_inspector.lua',
'shared.lua',
'uri.lua',
'ui.lua',
'filetype.lua',
'keymap.lua',
'fs.lua',
'secure.lua',
'version.lua',
],
'files': [
'runtime/lua/vim/_editor.lua',
'runtime/lua/vim/shared.lu
|