mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #11605 'gen_vimdoc.py: fix formatting; sort by name'
This commit is contained in:
commit
22a92a59a6
2142
runtime/doc/api.txt
2142
runtime/doc/api.txt
File diff suppressed because it is too large
Load Diff
@ -861,6 +861,9 @@ schedule_wrap({cb}) *vim.schedule_wrap()*
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
deep_equal({a}, {b}) *vim.deep_equal()*
|
||||||
|
TODO: Documentation
|
||||||
|
|
||||||
deepcopy({orig}) *vim.deepcopy()*
|
deepcopy({orig}) *vim.deepcopy()*
|
||||||
Returns a deep copy of the given object. Non-table objects are
|
Returns a deep copy of the given object. Non-table objects are
|
||||||
copied as in a typical Lua assignment, whereas table objects
|
copied as in a typical Lua assignment, whereas table objects
|
||||||
@ -889,6 +892,45 @@ gsplit({s}, {sep}, {plain}) *vim.gsplit()*
|
|||||||
https://www.lua.org/pil/20.2.html
|
https://www.lua.org/pil/20.2.html
|
||||||
http://lua-users.org/wiki/StringLibraryTutorial
|
http://lua-users.org/wiki/StringLibraryTutorial
|
||||||
|
|
||||||
|
is_callable({f}) *vim.is_callable()*
|
||||||
|
Returns true if object `f` can be called as a function.
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{f} Any object
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
true if `f` is callable, else false
|
||||||
|
|
||||||
|
list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
|
||||||
|
Extends a list-like table with the values of another list-like
|
||||||
|
table.
|
||||||
|
|
||||||
|
NOTE: This mutates dst!
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{dst} list which will be modified and appended to.
|
||||||
|
{src} list from which values will be inserted.
|
||||||
|
{start} Start index on src. defaults to 1
|
||||||
|
{finish} Final index on src. defaults to #src
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
dst
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
|vim.tbl_extend()|
|
||||||
|
|
||||||
|
pesc({s}) *vim.pesc()*
|
||||||
|
Escapes magic chars in a Lua pattern string.
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{s} String to escape
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
%-escaped pattern string
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
https://github.com/rxi/lume
|
||||||
|
|
||||||
split({s}, {sep}, {plain}) *vim.split()*
|
split({s}, {sep}, {plain}) *vim.split()*
|
||||||
Splits a string at each instance of a separator.
|
Splits a string at each instance of a separator.
|
||||||
|
|
||||||
@ -910,6 +952,62 @@ split({s}, {sep}, {plain}) *vim.split()*
|
|||||||
See also: ~
|
See also: ~
|
||||||
|vim.gsplit()|
|
|vim.gsplit()|
|
||||||
|
|
||||||
|
tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
|
||||||
|
Add the reverse lookup values to an existing table. For
|
||||||
|
example: `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A =
|
||||||
|
1 }`
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{o} table The table to add the reverse to.
|
||||||
|
|
||||||
|
tbl_contains({t}, {value}) *vim.tbl_contains()*
|
||||||
|
Checks if a list-like (vector) table contains `value` .
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{t} Table to check
|
||||||
|
{value} Value to compare
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
true if `t` contains `value`
|
||||||
|
|
||||||
|
tbl_extend({behavior}, {...}) *vim.tbl_extend()*
|
||||||
|
Merges two or more map-like tables.
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{behavior} Decides what to do if a key is found in more
|
||||||
|
than one map:
|
||||||
|
• "error": raise an error
|
||||||
|
• "keep": use value from the leftmost map
|
||||||
|
• "force": use value from the rightmost map
|
||||||
|
{...} Two or more map-like tables.
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
|extend()|
|
||||||
|
|
||||||
|
tbl_flatten({t}) *vim.tbl_flatten()*
|
||||||
|
Creates a copy of a list-like table such that any nested
|
||||||
|
tables are "unrolled" and appended to the result.
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
{t} List-like table
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
Flattened copy of the given list-like table.
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua
|
||||||
|
|
||||||
|
tbl_isempty({t}) *vim.tbl_isempty()*
|
||||||
|
See also: ~
|
||||||
|
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua@paramt Table to check
|
||||||
|
|
||||||
|
tbl_islist({t}) *vim.tbl_islist()*
|
||||||
|
Table
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
true: A non-empty array, false: A non-empty table, nil: An
|
||||||
|
empty table
|
||||||
|
|
||||||
tbl_keys({t}) *vim.tbl_keys()*
|
tbl_keys({t}) *vim.tbl_keys()*
|
||||||
Return a list of all keys used in a table. However, the order
|
Return a list of all keys used in a table. However, the order
|
||||||
of the return table of keys is not guaranteed.
|
of the return table of keys is not guaranteed.
|
||||||
@ -933,83 +1031,6 @@ tbl_values({t}) *vim.tbl_values()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
list of values
|
list of values
|
||||||
|
|
||||||
tbl_contains({t}, {value}) *vim.tbl_contains()*
|
|
||||||
Checks if a list-like (vector) table contains `value` .
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{t} Table to check
|
|
||||||
{value} Value to compare
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
true if `t` contains `value`
|
|
||||||
|
|
||||||
tbl_isempty({t}) *vim.tbl_isempty()*
|
|
||||||
See also: ~
|
|
||||||
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua@paramt Table to check
|
|
||||||
|
|
||||||
tbl_extend({behavior}, {...}) *vim.tbl_extend()*
|
|
||||||
Merges two or more map-like tables.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{behavior} Decides what to do if a key is found in more
|
|
||||||
than one map:
|
|
||||||
• "error": raise an error
|
|
||||||
• "keep": use value from the leftmost map
|
|
||||||
• "force": use value from the rightmost map
|
|
||||||
{...} Two or more map-like tables.
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
|extend()|
|
|
||||||
|
|
||||||
deep_equal({a}, {b}) *vim.deep_equal()*
|
|
||||||
TODO: Documentation
|
|
||||||
|
|
||||||
tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
|
|
||||||
Add the reverse lookup values to an existing table. For
|
|
||||||
example: `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A =
|
|
||||||
1 }`
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{o} table The table to add the reverse to.
|
|
||||||
|
|
||||||
list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
|
|
||||||
Extends a list-like table with the values of another list-like
|
|
||||||
table.
|
|
||||||
|
|
||||||
NOTE: This mutates dst!
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{dst} list which will be modified and appended to.
|
|
||||||
{src} list from which values will be inserted.
|
|
||||||
{start} Start index on src. defaults to 1
|
|
||||||
{finish} Final index on src. defaults to #src
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
dst
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
|vim.tbl_extend()|
|
|
||||||
|
|
||||||
tbl_flatten({t}) *vim.tbl_flatten()*
|
|
||||||
Creates a copy of a list-like table such that any nested
|
|
||||||
tables are "unrolled" and appended to the result.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{t} List-like table
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
Flattened copy of the given list-like table.
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
Fromhttps://github.com/premake/premake-core/blob/master/src/base/table.lua
|
|
||||||
|
|
||||||
tbl_islist({t}) *vim.tbl_islist()*
|
|
||||||
Table
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
true: A non-empty array, false: A non-empty table, nil: An
|
|
||||||
empty table
|
|
||||||
|
|
||||||
trim({s}) *vim.trim()*
|
trim({s}) *vim.trim()*
|
||||||
Trim whitespace (Lua pattern "%s") from both sides of a
|
Trim whitespace (Lua pattern "%s") from both sides of a
|
||||||
string.
|
string.
|
||||||
@ -1023,18 +1044,6 @@ trim({s}) *vim.trim()*
|
|||||||
See also: ~
|
See also: ~
|
||||||
https://www.lua.org/pil/20.2.html
|
https://www.lua.org/pil/20.2.html
|
||||||
|
|
||||||
pesc({s}) *vim.pesc()*
|
|
||||||
Escapes magic chars in a Lua pattern string.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{s} String to escape
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
%-escaped pattern string
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
https://github.com/rxi/lume
|
|
||||||
|
|
||||||
validate({opt}) *vim.validate()*
|
validate({opt}) *vim.validate()*
|
||||||
Validates a parameter specification (types and values).
|
Validates a parameter specification (types and values).
|
||||||
|
|
||||||
@ -1085,13 +1094,4 @@ validate({opt}) *vim.validate()*
|
|||||||
• msg: (optional) error string if validation
|
• msg: (optional) error string if validation
|
||||||
fails
|
fails
|
||||||
|
|
||||||
is_callable({f}) *vim.is_callable()*
|
|
||||||
Returns true if object `f` can be called as a function.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
{f} Any object
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
true if `f` is callable, else false
|
|
||||||
|
|
||||||
vim:tw=78:ts=8:ft=help:norl:
|
vim:tw=78:ts=8:ft=help:norl:
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Generates Nvim help docs from C/Lua docstrings, using Doxygen.
|
"""Generates Nvim :help docs from C/Lua docstrings, using Doxygen.
|
||||||
|
|
||||||
Also generates *.mpack files. To inspect the *.mpack structure:
|
Also generates *.mpack files. To inspect the *.mpack structure:
|
||||||
|
|
||||||
:new | put=json_encode(msgpackparse(readfile('runtime/doc/api.mpack')))
|
:new | put=v:lua.vim.inspect(msgpackparse(readfile('runtime/doc/api.mpack')))
|
||||||
|
|
||||||
|
|
||||||
Flow:
|
Flow:
|
||||||
gen_docs
|
main
|
||||||
extract_from_xml
|
extract_from_xml
|
||||||
fmt_node_as_vimhelp
|
fmt_node_as_vimhelp \
|
||||||
fmt_params_map_as_vimhelp
|
para_as_map } recursive
|
||||||
render_node
|
update_params_map /
|
||||||
para_as_map
|
render_node
|
||||||
render_node
|
|
||||||
|
|
||||||
This would be easier using lxml and XSLT, but:
|
This would be easier using lxml and XSLT, but:
|
||||||
|
|
||||||
@ -58,6 +58,7 @@ DEBUG = ('DEBUG' in os.environ)
|
|||||||
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
|
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
|
||||||
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
|
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
|
||||||
|
|
||||||
|
fmt_vimhelp = False # HACK
|
||||||
text_width = 78
|
text_width = 78
|
||||||
script_path = os.path.abspath(__file__)
|
script_path = os.path.abspath(__file__)
|
||||||
base_dir = os.path.dirname(os.path.dirname(script_path))
|
base_dir = os.path.dirname(os.path.dirname(script_path))
|
||||||
@ -144,6 +145,7 @@ def debug_this(cond, o):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
if ((callable(cond) and cond())
|
if ((callable(cond) and cond())
|
||||||
|
or (not callable(cond) and cond)
|
||||||
or (not callable(cond) and cond in o)):
|
or (not callable(cond) and cond in o)):
|
||||||
raise RuntimeError('xxx: {}\n{}'.format(name, o))
|
raise RuntimeError('xxx: {}\n{}'.format(name, o))
|
||||||
|
|
||||||
@ -156,20 +158,27 @@ def find_first(parent, name):
|
|||||||
return sub[0]
|
return sub[0]
|
||||||
|
|
||||||
|
|
||||||
def get_children(parent, name):
|
def iter_children(parent, name):
|
||||||
"""Yield matching child nodes within parent."""
|
"""Yields matching child nodes within parent."""
|
||||||
for child in parent.childNodes:
|
for child in parent.childNodes:
|
||||||
if child.nodeType == child.ELEMENT_NODE and child.nodeName == name:
|
if child.nodeType == child.ELEMENT_NODE and child.nodeName == name:
|
||||||
yield child
|
yield child
|
||||||
|
|
||||||
|
|
||||||
def get_child(parent, name):
|
def get_child(parent, name):
|
||||||
"""Get the first matching child node."""
|
"""Gets the first matching child node."""
|
||||||
for child in get_children(parent, name):
|
for child in iter_children(parent, name):
|
||||||
return child
|
return child
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def self_or_child(n):
|
||||||
|
"""Gets the first child node, or self."""
|
||||||
|
if len(n.childNodes) == 0:
|
||||||
|
return n
|
||||||
|
return n.childNodes[0]
|
||||||
|
|
||||||
|
|
||||||
def clean_text(text):
|
def clean_text(text):
|
||||||
"""Cleans text.
|
"""Cleans text.
|
||||||
|
|
||||||
@ -190,18 +199,21 @@ def is_blank(text):
|
|||||||
return '' == clean_lines(text)
|
return '' == clean_lines(text)
|
||||||
|
|
||||||
|
|
||||||
def get_text(parent, preformatted=False):
|
def get_text(n, preformatted=False):
|
||||||
"""Combine all text in a node."""
|
"""Recursively concatenates all text in a node tree."""
|
||||||
if parent.nodeType == parent.TEXT_NODE:
|
text = ''
|
||||||
return parent.data
|
if n.nodeType == n.TEXT_NODE:
|
||||||
|
return n.data
|
||||||
out = ''
|
if n.nodeName == 'computeroutput':
|
||||||
for node in parent.childNodes:
|
for node in n.childNodes:
|
||||||
|
text += get_text(node)
|
||||||
|
return '`{}` '.format(text)
|
||||||
|
for node in n.childNodes:
|
||||||
if node.nodeType == node.TEXT_NODE:
|
if node.nodeType == node.TEXT_NODE:
|
||||||
out += node.data if preformatted else clean_text(node.data)
|
text += node.data if preformatted else clean_text(node.data)
|
||||||
elif node.nodeType == node.ELEMENT_NODE:
|
elif node.nodeType == node.ELEMENT_NODE:
|
||||||
out += ' ' + get_text(node, preformatted)
|
text += ' ' + get_text(node, preformatted)
|
||||||
return out
|
return text
|
||||||
|
|
||||||
|
|
||||||
# Gets the length of the last line in `text`, excluding newline ("\n") char.
|
# Gets the length of the last line in `text`, excluding newline ("\n") char.
|
||||||
@ -221,6 +233,8 @@ def len_lastline_withoutindent(text, indent):
|
|||||||
|
|
||||||
# Returns True if node `n` contains only inline (not block-level) elements.
|
# Returns True if node `n` contains only inline (not block-level) elements.
|
||||||
def is_inline(n):
|
def is_inline(n):
|
||||||
|
# if len(n.childNodes) == 0:
|
||||||
|
# return n.nodeType == n.TEXT_NODE or n.nodeName == 'computeroutput'
|
||||||
for c in n.childNodes:
|
for c in n.childNodes:
|
||||||
if c.nodeType != c.TEXT_NODE and c.nodeName != 'computeroutput':
|
if c.nodeType != c.TEXT_NODE and c.nodeName != 'computeroutput':
|
||||||
return False
|
return False
|
||||||
@ -271,11 +285,17 @@ def doc_wrap(text, prefix='', width=70, func=False, indent=None):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def max_name(names):
|
||||||
|
if len(names) == 0:
|
||||||
|
return 0
|
||||||
|
return max(len(name) for name in names)
|
||||||
|
|
||||||
|
|
||||||
def update_params_map(parent, ret_map, width=62):
|
def update_params_map(parent, ret_map, width=62):
|
||||||
"""Updates `ret_map` with name:desc key-value pairs extracted
|
"""Updates `ret_map` with name:desc key-value pairs extracted
|
||||||
from Doxygen XML node `parent`.
|
from Doxygen XML node `parent`.
|
||||||
"""
|
"""
|
||||||
params = []
|
params = collections.OrderedDict()
|
||||||
for node in parent.childNodes:
|
for node in parent.childNodes:
|
||||||
if node.nodeType == node.TEXT_NODE:
|
if node.nodeType == node.TEXT_NODE:
|
||||||
continue
|
continue
|
||||||
@ -285,48 +305,36 @@ def update_params_map(parent, ret_map, width=62):
|
|||||||
name = get_text(name_node)
|
name = get_text(name_node)
|
||||||
if name in param_exclude:
|
if name in param_exclude:
|
||||||
continue
|
continue
|
||||||
params.append((name.strip(), node))
|
params[name.strip()] = node
|
||||||
|
max_name_len = max_name(params.keys()) + 8
|
||||||
# `ret_map` is a name:desc map.
|
# `ret_map` is a name:desc map.
|
||||||
for name, node in params:
|
for name, node in params.items():
|
||||||
desc = ''
|
desc = ''
|
||||||
desc_node = get_child(node, 'parameterdescription')
|
desc_node = get_child(node, 'parameterdescription')
|
||||||
if desc_node:
|
if desc_node:
|
||||||
desc = fmt_node_as_vimhelp(desc_node, width=width, indent=(" " * len(name)))
|
desc = fmt_node_as_vimhelp(
|
||||||
|
desc_node, width=width, indent=(' ' * max_name_len))
|
||||||
ret_map[name] = desc
|
ret_map[name] = desc
|
||||||
return ret_map
|
return ret_map
|
||||||
|
|
||||||
|
|
||||||
def fmt_params_map_as_vimhelp(m, width=62):
|
|
||||||
"""Renders a params map as Vim :help text."""
|
|
||||||
max_name_len = 0
|
|
||||||
for name, desc in m.items():
|
|
||||||
max_name_len = max(max_name_len, len(name) + 4)
|
|
||||||
out = ''
|
|
||||||
for name, desc in m.items():
|
|
||||||
name = ' {}'.format('{{{}}}'.format(name).ljust(max_name_len))
|
|
||||||
out += '{}{}\n'.format(name, desc)
|
|
||||||
return out.rstrip()
|
|
||||||
|
|
||||||
|
|
||||||
def render_node(n, text, prefix='', indent='', width=62):
|
def render_node(n, text, prefix='', indent='', width=62):
|
||||||
"""Renders a node as Vim help text, recursively traversing all descendants."""
|
"""Renders a node as Vim help text, recursively traversing all descendants."""
|
||||||
|
global fmt_vimhelp
|
||||||
|
|
||||||
|
def ind(s):
|
||||||
|
return s if fmt_vimhelp else ''
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
# space_preceding = (len(text) > 0 and ' ' == text[-1][-1])
|
# space_preceding = (len(text) > 0 and ' ' == text[-1][-1])
|
||||||
# text += (int(not space_preceding) * ' ')
|
# text += (int(not space_preceding) * ' ')
|
||||||
|
|
||||||
if n.nodeType == n.TEXT_NODE:
|
if n.nodeName == 'preformatted':
|
||||||
# `prefix` is NOT sent to doc_wrap, it was already handled by now.
|
|
||||||
text += doc_wrap(n.data, indent=indent, width=width)
|
|
||||||
elif n.nodeName == 'computeroutput':
|
|
||||||
text += ' `{}` '.format(get_text(n))
|
|
||||||
elif n.nodeName == 'preformatted':
|
|
||||||
o = get_text(n, preformatted=True)
|
o = get_text(n, preformatted=True)
|
||||||
ensure_nl = '' if o[-1] == '\n' else '\n'
|
ensure_nl = '' if o[-1] == '\n' else '\n'
|
||||||
text += ' >{}{}\n<'.format(ensure_nl, o)
|
text += '>{}{}\n<'.format(ensure_nl, o)
|
||||||
elif is_inline(n):
|
elif is_inline(n):
|
||||||
for c in n.childNodes:
|
text = doc_wrap(get_text(n), indent=indent, width=width)
|
||||||
text += render_node(c, text)
|
|
||||||
text = doc_wrap(text, indent=indent, width=width)
|
|
||||||
elif n.nodeName == 'verbatim':
|
elif n.nodeName == 'verbatim':
|
||||||
# TODO: currently we don't use this. The "[verbatim]" hint is there as
|
# 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.
|
# a reminder that we must decide how to format this if we do use it.
|
||||||
@ -341,8 +349,6 @@ def render_node(n, text, prefix='', indent='', width=62):
|
|||||||
elif n.nodeName in ('para', 'heading'):
|
elif n.nodeName in ('para', 'heading'):
|
||||||
for c in n.childNodes:
|
for c in n.childNodes:
|
||||||
text += render_node(c, text, indent=indent, width=width)
|
text += render_node(c, text, indent=indent, width=width)
|
||||||
if is_inline(n):
|
|
||||||
text = doc_wrap(text, indent=indent, width=width)
|
|
||||||
elif n.nodeName == 'itemizedlist':
|
elif n.nodeName == 'itemizedlist':
|
||||||
for c in n.childNodes:
|
for c in n.childNodes:
|
||||||
text += '{}\n'.format(render_node(c, text, prefix='• ',
|
text += '{}\n'.format(render_node(c, text, prefix='• ',
|
||||||
@ -368,7 +374,7 @@ def render_node(n, text, prefix='', indent='', width=62):
|
|||||||
text += '\n'
|
text += '\n'
|
||||||
elif (n.nodeName == 'simplesect'
|
elif (n.nodeName == 'simplesect'
|
||||||
and n.getAttribute('kind') in ('return', 'see')):
|
and n.getAttribute('kind') in ('return', 'see')):
|
||||||
text += ' '
|
text += ind(' ')
|
||||||
for c in n.childNodes:
|
for c in n.childNodes:
|
||||||
text += render_node(c, text, indent=' ', width=width)
|
text += render_node(c, text, indent=' ', width=width)
|
||||||
else:
|
else:
|
||||||
@ -395,11 +401,6 @@ def para_as_map(parent, indent='', width=62):
|
|||||||
'xrefs': []
|
'xrefs': []
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_inline(parent):
|
|
||||||
chunks["text"] = clean_lines(
|
|
||||||
doc_wrap(render_node(parent, ""), indent=indent, width=width).strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
# Ordered dict of ordered lists.
|
# Ordered dict of ordered lists.
|
||||||
groups = collections.OrderedDict([
|
groups = collections.OrderedDict([
|
||||||
('params', []),
|
('params', []),
|
||||||
@ -413,27 +414,39 @@ def para_as_map(parent, indent='', width=62):
|
|||||||
text = ''
|
text = ''
|
||||||
kind = ''
|
kind = ''
|
||||||
last = ''
|
last = ''
|
||||||
for child in parent.childNodes:
|
if is_inline(parent):
|
||||||
if child.nodeName == 'parameterlist':
|
# Flatten inline text from a tree of non-block nodes.
|
||||||
groups['params'].append(child)
|
text = doc_wrap(render_node(parent, ""), indent=indent, width=width)
|
||||||
elif child.nodeName == 'xrefsect':
|
else:
|
||||||
groups['xrefs'].append(child)
|
prev = None # Previous node
|
||||||
elif child.nodeName == 'simplesect':
|
for child in parent.childNodes:
|
||||||
last = kind
|
if child.nodeName == 'parameterlist':
|
||||||
kind = child.getAttribute('kind')
|
groups['params'].append(child)
|
||||||
if kind == 'return' or (kind == 'note' and last == 'return'):
|
elif child.nodeName == 'xrefsect':
|
||||||
groups['return'].append(child)
|
groups['xrefs'].append(child)
|
||||||
elif kind == 'see':
|
elif child.nodeName == 'simplesect':
|
||||||
groups['seealso'].append(child)
|
last = kind
|
||||||
elif kind in ('note', 'warning'):
|
kind = child.getAttribute('kind')
|
||||||
text += render_node(child, text, indent=indent, width=width)
|
if kind == 'return' or (kind == 'note' and last == 'return'):
|
||||||
|
groups['return'].append(child)
|
||||||
|
elif kind == 'see':
|
||||||
|
groups['seealso'].append(child)
|
||||||
|
elif kind in ('note', 'warning'):
|
||||||
|
text += render_node(child, text, indent=indent, width=width)
|
||||||
|
else:
|
||||||
|
raise RuntimeError('unhandled simplesect: {}\n{}'.format(
|
||||||
|
child.nodeName, child.toprettyxml(indent=' ', newl='\n')))
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('unhandled simplesect: {}\n{}'.format(
|
if (prev is not None
|
||||||
child.nodeName, child.toprettyxml(indent=' ', newl='\n')))
|
and is_inline(self_or_child(prev))
|
||||||
else:
|
and is_inline(self_or_child(child))
|
||||||
text += render_node(child, text, indent=indent, width=width)
|
and '' != get_text(self_or_child(child)).strip()
|
||||||
|
and ' ' != text[-1]):
|
||||||
|
text += ' '
|
||||||
|
text += render_node(child, text, indent=indent, width=width)
|
||||||
|
prev = child
|
||||||
|
|
||||||
chunks['text'] = text
|
chunks['text'] += text
|
||||||
|
|
||||||
# Generate map from the gathered items.
|
# Generate map from the gathered items.
|
||||||
if len(groups['params']) > 0:
|
if len(groups['params']) > 0:
|
||||||
@ -441,7 +454,7 @@ def para_as_map(parent, indent='', width=62):
|
|||||||
update_params_map(child, ret_map=chunks['params'], width=width)
|
update_params_map(child, ret_map=chunks['params'], width=width)
|
||||||
for child in groups['return']:
|
for child in groups['return']:
|
||||||
chunks['return'].append(render_node(
|
chunks['return'].append(render_node(
|
||||||
child, '', indent=indent, width=width).lstrip())
|
child, '', indent=indent, width=width))
|
||||||
for child in groups['seealso']:
|
for child in groups['seealso']:
|
||||||
chunks['seealso'].append(render_node(
|
chunks['seealso'].append(render_node(
|
||||||
child, '', indent=indent, width=width))
|
child, '', indent=indent, width=width))
|
||||||
@ -463,20 +476,30 @@ def fmt_node_as_vimhelp(parent, width=62, indent=''):
|
|||||||
NB: Blank lines in a docstring manifest as <para> tags.
|
NB: Blank lines in a docstring manifest as <para> tags.
|
||||||
"""
|
"""
|
||||||
rendered_blocks = []
|
rendered_blocks = []
|
||||||
|
|
||||||
|
def fmt_param_doc(m):
|
||||||
|
"""Renders a params map as Vim :help text."""
|
||||||
|
max_name_len = max_name(m.keys()) + 4
|
||||||
|
out = ''
|
||||||
|
for name, desc in m.items():
|
||||||
|
name = ' {}'.format('{{{}}}'.format(name).ljust(max_name_len))
|
||||||
|
out += '{}{}\n'.format(name, desc)
|
||||||
|
return out.rstrip()
|
||||||
|
|
||||||
|
def has_nonexcluded_params(m):
|
||||||
|
"""Returns true if any of the given params has at least
|
||||||
|
one non-excluded item."""
|
||||||
|
if fmt_param_doc(m) != '':
|
||||||
|
return True
|
||||||
|
|
||||||
for child in parent.childNodes:
|
for child in parent.childNodes:
|
||||||
para = para_as_map(child, indent, width)
|
para = para_as_map(child, indent, width)
|
||||||
|
|
||||||
def has_nonexcluded_params(m):
|
|
||||||
"""Returns true if any of the given params has at least
|
|
||||||
one non-excluded item."""
|
|
||||||
if fmt_params_map_as_vimhelp(m) != '':
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Generate text from the gathered items.
|
# Generate text from the gathered items.
|
||||||
chunks = [para['text']]
|
chunks = [para['text']]
|
||||||
if len(para['params']) > 0 and has_nonexcluded_params(para['params']):
|
if len(para['params']) > 0 and has_nonexcluded_params(para['params']):
|
||||||
chunks.append('\nParameters: ~')
|
chunks.append('\nParameters: ~')
|
||||||
chunks.append(fmt_params_map_as_vimhelp(para['params'], width=width))
|
chunks.append(fmt_param_doc(para['params']))
|
||||||
if len(para['return']) > 0:
|
if len(para['return']) > 0:
|
||||||
chunks.append('\nReturn: ~')
|
chunks.append('\nReturn: ~')
|
||||||
for s in para['return']:
|
for s in para['return']:
|
||||||
@ -493,20 +516,21 @@ def fmt_node_as_vimhelp(parent, width=62, indent=''):
|
|||||||
return clean_lines('\n'.join(rendered_blocks).strip())
|
return clean_lines('\n'.join(rendered_blocks).strip())
|
||||||
|
|
||||||
|
|
||||||
def extract_from_xml(filename, mode, fmt_vimhelp):
|
def extract_from_xml(filename, mode, width):
|
||||||
"""Extracts Doxygen info as maps without formatting the text.
|
"""Extracts Doxygen info as maps without formatting the text.
|
||||||
|
|
||||||
Returns two maps:
|
Returns two maps:
|
||||||
1. Functions
|
1. Functions
|
||||||
2. Deprecated functions
|
2. Deprecated functions
|
||||||
|
|
||||||
The `fmt_vimhelp` parameter controls some special cases for use by
|
The `fmt_vimhelp` global controls some special cases for use by
|
||||||
fmt_doxygen_xml_as_vimhelp(). (TODO: ugly :)
|
fmt_doxygen_xml_as_vimhelp(). (TODO: ugly :)
|
||||||
"""
|
"""
|
||||||
global xrefs
|
global xrefs
|
||||||
|
global fmt_vimhelp
|
||||||
xrefs.clear()
|
xrefs.clear()
|
||||||
functions = {} # Map of func_name:docstring.
|
fns = {} # Map of func_name:docstring.
|
||||||
deprecated_functions = {} # Map of func_name:docstring.
|
deprecated_fns = {} # Map of func_name:docstring.
|
||||||
|
|
||||||
dom = minidom.parse(filename)
|
dom = minidom.parse(filename)
|
||||||
compoundname = get_text(dom.getElementsByTagName('compoundname')[0])
|
compoundname = get_text(dom.getElementsByTagName('compoundname')[0])
|
||||||
@ -553,7 +577,7 @@ def extract_from_xml(filename, mode, fmt_vimhelp):
|
|||||||
params = []
|
params = []
|
||||||
type_length = 0
|
type_length = 0
|
||||||
|
|
||||||
for param in get_children(member, 'param'):
|
for param in iter_children(member, 'param'):
|
||||||
param_type = get_text(get_child(param, 'type')).strip()
|
param_type = get_text(get_child(param, 'type')).strip()
|
||||||
param_name = ''
|
param_name = ''
|
||||||
declname = get_child(param, 'declname')
|
declname = get_child(param, 'declname')
|
||||||
@ -590,15 +614,15 @@ def extract_from_xml(filename, mode, fmt_vimhelp):
|
|||||||
' ')
|
' ')
|
||||||
|
|
||||||
# Minimum 8 chars between signature and vimtag
|
# Minimum 8 chars between signature and vimtag
|
||||||
lhs = (text_width - 8) - len(prefix)
|
lhs = (width - 8) - len(prefix)
|
||||||
|
|
||||||
if len(prefix) + len(suffix) > lhs:
|
if len(prefix) + len(suffix) > lhs:
|
||||||
signature = vimtag.rjust(text_width) + '\n'
|
signature = vimtag.rjust(width) + '\n'
|
||||||
signature += doc_wrap(suffix, width=text_width-8, prefix=prefix,
|
signature += doc_wrap(suffix, width=width-8, prefix=prefix,
|
||||||
func=True)
|
func=True)
|
||||||
else:
|
else:
|
||||||
signature = prefix + suffix
|
signature = prefix + suffix
|
||||||
signature += vimtag.rjust(text_width - len(signature))
|
signature += vimtag.rjust(width - len(signature))
|
||||||
|
|
||||||
paras = []
|
paras = []
|
||||||
desc = find_first(member, 'detaileddescription')
|
desc = find_first(member, 'detaileddescription')
|
||||||
@ -637,26 +661,30 @@ def extract_from_xml(filename, mode, fmt_vimhelp):
|
|||||||
if INCLUDE_C_DECL:
|
if INCLUDE_C_DECL:
|
||||||
fn['c_decl'] = c_decl
|
fn['c_decl'] = c_decl
|
||||||
|
|
||||||
if 'Deprecated' in xrefs:
|
if 'Deprecated' in str(xrefs):
|
||||||
deprecated_functions[name] = fn
|
deprecated_fns[name] = fn
|
||||||
elif name.startswith(CONFIG[mode]['func_name_prefix']):
|
elif name.startswith(CONFIG[mode]['func_name_prefix']):
|
||||||
functions[name] = fn
|
fns[name] = fn
|
||||||
|
|
||||||
xrefs.clear()
|
xrefs.clear()
|
||||||
|
|
||||||
return (functions, deprecated_functions)
|
fns = collections.OrderedDict(sorted(fns.items()))
|
||||||
|
deprecated_fns = collections.OrderedDict(sorted(deprecated_fns.items()))
|
||||||
|
return (fns, deprecated_fns)
|
||||||
|
|
||||||
|
|
||||||
def fmt_doxygen_xml_as_vimhelp(filename, mode):
|
def fmt_doxygen_xml_as_vimhelp(filename, mode):
|
||||||
"""Formats functions from doxygen XML into Vim :help format.
|
"""Entrypoint for generating Vim :help from from Doxygen XML.
|
||||||
|
|
||||||
Returns two strings:
|
Returns 3 items:
|
||||||
1. Functions in Vim :help format
|
1. Vim help text for functions found in `filename`.
|
||||||
2. Deprecated functions (handled by caller, or ignored)
|
2. Vim help text for deprecated functions.
|
||||||
"""
|
"""
|
||||||
functions = {} # Map of func_name:docstring.
|
global fmt_vimhelp
|
||||||
deprecated_functions = {} # Map of func_name:docstring.
|
fmt_vimhelp = True
|
||||||
fns, deprecated_fns = extract_from_xml(filename, mode, True)
|
fns_txt = {} # Map of func_name:vim-help-text.
|
||||||
|
deprecated_fns_txt = {} # Map of func_name:vim-help-text.
|
||||||
|
fns, _ = extract_from_xml(filename, mode, width=text_width)
|
||||||
|
|
||||||
for name, fn in fns.items():
|
for name, fn in fns.items():
|
||||||
# Generate Vim :help for parameters.
|
# Generate Vim :help for parameters.
|
||||||
@ -685,15 +713,15 @@ def fmt_doxygen_xml_as_vimhelp(filename, mode):
|
|||||||
func_doc = re.sub(r'^\s+([<>])$', r'\1', func_doc, flags=re.M)
|
func_doc = re.sub(r'^\s+([<>])$', r'\1', func_doc, flags=re.M)
|
||||||
|
|
||||||
if 'Deprecated' in xrefs:
|
if 'Deprecated' in xrefs:
|
||||||
deprecated_functions.append(func_doc)
|
deprecated_fns_txt[name] = func_doc
|
||||||
elif name.startswith(CONFIG[mode]['func_name_prefix']):
|
elif name.startswith(CONFIG[mode]['func_name_prefix']):
|
||||||
functions[name] = func_doc
|
fns_txt[name] = func_doc
|
||||||
|
|
||||||
xrefs.clear()
|
xrefs.clear()
|
||||||
|
|
||||||
return ('\n\n'.join(list(functions.values())),
|
fmt_vimhelp = False
|
||||||
'\n\n'.join(deprecated_fns),
|
return ('\n\n'.join(list(fns_txt.values())),
|
||||||
functions)
|
'\n\n'.join(list(deprecated_fns_txt.values())))
|
||||||
|
|
||||||
|
|
||||||
def delete_lines_below(filename, tokenstr):
|
def delete_lines_below(filename, tokenstr):
|
||||||
@ -710,14 +738,15 @@ def delete_lines_below(filename, tokenstr):
|
|||||||
fp.writelines(lines[0:i])
|
fp.writelines(lines[0:i])
|
||||||
|
|
||||||
|
|
||||||
def gen_docs(config):
|
def main(config):
|
||||||
"""Generate formatted Vim :help docs and unformatted *.mpack files for use
|
"""Generates:
|
||||||
by API clients.
|
|
||||||
|
1. Vim :help docs
|
||||||
|
2. *.mpack files for use by API clients
|
||||||
|
|
||||||
Doxygen is called and configured through stdin.
|
Doxygen is called and configured through stdin.
|
||||||
"""
|
"""
|
||||||
for mode in CONFIG:
|
for mode in CONFIG:
|
||||||
functions = {} # Map of func_name:docstring.
|
|
||||||
mpack_file = os.path.join(
|
mpack_file = os.path.join(
|
||||||
base_dir, 'runtime', 'doc',
|
base_dir, 'runtime', 'doc',
|
||||||
CONFIG[mode]['filename'].replace('.txt', '.mpack'))
|
CONFIG[mode]['filename'].replace('.txt', '.mpack'))
|
||||||
@ -766,14 +795,13 @@ def gen_docs(config):
|
|||||||
|
|
||||||
filename = get_text(find_first(compound, 'name'))
|
filename = get_text(find_first(compound, 'name'))
|
||||||
if filename.endswith('.c') or filename.endswith('.lua'):
|
if filename.endswith('.c') or filename.endswith('.lua'):
|
||||||
|
# Extract unformatted (*.mpack).
|
||||||
fn_map, _ = extract_from_xml(os.path.join(base, '{}.xml'.format(
|
fn_map, _ = extract_from_xml(os.path.join(base, '{}.xml'.format(
|
||||||
compound.getAttribute('refid'))), mode, False)
|
compound.getAttribute('refid'))), mode, width=9999)
|
||||||
|
# Extract formatted (:help).
|
||||||
functions_text, deprecated_text, fns = fmt_doxygen_xml_as_vimhelp(
|
functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp(
|
||||||
os.path.join(base, '{}.xml'.format(
|
os.path.join(base, '{}.xml'.format(
|
||||||
compound.getAttribute('refid'))), mode)
|
compound.getAttribute('refid'))), mode)
|
||||||
# Collect functions from all modules (for the current `mode`).
|
|
||||||
functions = {**functions, **fns}
|
|
||||||
|
|
||||||
if not functions_text and not deprecated_text:
|
if not functions_text and not deprecated_text:
|
||||||
continue
|
continue
|
||||||
@ -840,6 +868,7 @@ def gen_docs(config):
|
|||||||
with open(doc_file, 'ab') as fp:
|
with open(doc_file, 'ab') as fp:
|
||||||
fp.write(docs.encode('utf8'))
|
fp.write(docs.encode('utf8'))
|
||||||
|
|
||||||
|
fn_map_full = collections.OrderedDict(sorted(fn_map_full.items()))
|
||||||
with open(mpack_file, 'wb') as fp:
|
with open(mpack_file, 'wb') as fp:
|
||||||
fp.write(msgpack.packb(fn_map_full, use_bin_type=True))
|
fp.write(msgpack.packb(fn_map_full, use_bin_type=True))
|
||||||
|
|
||||||
@ -900,6 +929,6 @@ if __name__ == "__main__":
|
|||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
filter_source(sys.argv[1])
|
filter_source(sys.argv[1])
|
||||||
else:
|
else:
|
||||||
gen_docs(Doxyfile)
|
main(Doxyfile)
|
||||||
|
|
||||||
# vim: set ft=python ts=4 sw=4 tw=79 et :
|
# vim: set ft=python ts=4 sw=4 tw=79 et :
|
||||||
|
@ -457,6 +457,7 @@ Object nvim_eval(String expr, Error *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @deprecated Use nvim_exec_lua() instead.
|
/// @deprecated Use nvim_exec_lua() instead.
|
||||||
|
/// @see nvim_exec_lua
|
||||||
Object nvim_execute_lua(String code, Array args, Error *err)
|
Object nvim_execute_lua(String code, Array args, Error *err)
|
||||||
FUNC_API_SINCE(3)
|
FUNC_API_SINCE(3)
|
||||||
FUNC_API_DEPRECATED_SINCE(7)
|
FUNC_API_DEPRECATED_SINCE(7)
|
||||||
|
Loading…
Reference in New Issue
Block a user