gen_vimdoc.py: render nested lists, etc [ci skip]

- render_node() is now the main rendering function: it traverses a node
  and builds the Vim help text recursively.
- render_para() is weird and ugly, it is the entry-point for rendering
  the help text for one docstring'd function.
This commit is contained in:
Justin M. Keyes
2019-03-03 15:01:16 +01:00
parent eeb19a346a
commit bec4066033
2 changed files with 479 additions and 323 deletions

View File

@@ -293,6 +293,9 @@ nvim_get_hl_by_name({name}, {rgb}) *nvim_get_hl_by_name()*
Return: ~ Return: ~
Highlight definition map Highlight definition map
See also: ~
nvim_get_hl_by_id
nvim_get_hl_by_id({hl_id}, {rgb}) *nvim_get_hl_by_id()* nvim_get_hl_by_id({hl_id}, {rgb}) *nvim_get_hl_by_id()*
Gets a highlight definition by id. |hlID()| Gets a highlight definition by id. |hlID()|
@@ -303,6 +306,9 @@ nvim_get_hl_by_id({hl_id}, {rgb}) *nvim_get_hl_by_id()*
Return: ~ Return: ~
Highlight definition map Highlight definition map
See also: ~
nvim_get_hl_by_name
nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()* nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()*
Sends input-keys to Nvim, subject to various quirks controlled Sends input-keys to Nvim, subject to various quirks controlled
by `mode` flags. This is a blocking call, unlike by `mode` flags. This is a blocking call, unlike
@@ -316,6 +322,10 @@ nvim_feedkeys({keys}, {mode}, {escape_csi}) *nvim_feedkeys()*
{escape_csi} If true, escape K_SPECIAL/CSI bytes in {escape_csi} If true, escape K_SPECIAL/CSI bytes in
`keys` `keys`
See also: ~
feedkeys()
vim_strsave_escape_csi
nvim_input({keys}) *nvim_input()* nvim_input({keys}) *nvim_input()*
Queues raw user-input. Unlike |nvim_feedkeys()|, this uses a Queues raw user-input. Unlike |nvim_feedkeys()|, this uses a
low-level input buffer and the call is non-blocking (input is low-level input buffer and the call is non-blocking (input is
@@ -326,7 +336,6 @@ nvim_input({keys}) *nvim_input()*
Note: Note:
|keycodes| like <CR> are translated, so "<" is special. To |keycodes| like <CR> are translated, so "<" is special. To
input a literal "<", send <LT>. input a literal "<", send <LT>.
Note: Note:
For mouse events use |nvim_input_mouse()|. The pseudokey For mouse events use |nvim_input_mouse()|. The pseudokey
form "<LeftMouse><col,row>" is deprecated since form "<LeftMouse><col,row>" is deprecated since
@@ -346,9 +355,8 @@ nvim_input({keys}) *nvim_input()*
nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col}) nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
Send mouse event from GUI. Send mouse event from GUI.
The call is non-blocking. It doesn't wait on any resulting Non-blocking: does not wait on any result, but queues the
action, but queues the event to be processed soon by the event event to be processed soon by the event loop.
loop.
Note: Note:
Currently this doesn't support "scripting" multiple mouse Currently this doesn't support "scripting" multiple mouse
@@ -392,6 +400,10 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special})
{special} Replace |keycodes|, e.g. <CR> becomes a "\n" {special} Replace |keycodes|, e.g. <CR> becomes a "\n"
char. char.
See also: ~
replace_termcodes
cpoptions
nvim_command_output({command}) *nvim_command_output()* nvim_command_output({command}) *nvim_command_output()*
Executes an ex-command and returns its (non-error) output. Executes an ex-command and returns its (non-error) output.
Shell |:!| output is not captured. Shell |:!| output is not captured.
@@ -420,7 +432,7 @@ nvim_execute_lua({code}, {args}) *nvim_execute_lua()*
inside the chunk. The chunk can return a value. inside the chunk. The chunk can return a value.
Only statements are executed. To evaluate an expression, Only statements are executed. To evaluate an expression,
prefix it with `return`: return my_function(...) prefix it with `return` : return my_function(...)
Parameters: ~ Parameters: ~
{code} lua code to execute {code} lua code to execute
@@ -458,7 +470,7 @@ nvim_call_dict_function({dict}, {fn}, {args}) *nvim_call_dict_function()*
Result of the function call Result of the function call
nvim_strwidth({text}) *nvim_strwidth()* nvim_strwidth({text}) *nvim_strwidth()*
Calculates the number of display cells occupied by `text`. Calculates the number of display cells occupied by `text` .
<Tab> counts as one cell. <Tab> counts as one cell.
Parameters: ~ Parameters: ~
@@ -575,11 +587,14 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
Parameters: ~ Parameters: ~
{str} Message {str} Message
See also: ~
nvim_err_write()
nvim_list_bufs() *nvim_list_bufs()* nvim_list_bufs() *nvim_list_bufs()*
Gets the current list of buffer handles Gets the current list of buffer handles
Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use Includes unlisted (unloaded/deleted) buffers, like `:ls!` .
|nvim_buf_is_loaded()| to check if a buffer is loaded. Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
Return: ~ Return: ~
List of buffer handles List of buffer handles
@@ -618,13 +633,16 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
Creates a new, empty, unnamed buffer. Creates a new, empty, unnamed buffer.
Parameters: ~ Parameters: ~
{listed} Controls 'buflisted' {listed} Sets 'buflisted'
{scratch} Creates a "throwaway" |scratch-buffer| for {scratch} Creates a "throwaway" |scratch-buffer| for
temporary work (always 'nomodified') temporary work (always 'nomodified')
Return: ~ Return: ~
Buffer handle, or 0 on error Buffer handle, or 0 on error
See also: ~
buf_open_scratch
nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Open a new window. Open a new window.
@@ -639,51 +657,6 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
Exactly one of `external` and `relative` must be specified. Exactly one of `external` and `relative` must be specified.
Parameters: ~
{buffer} handle of buffer to be displayed in the window
{enter} whether the window should be entered (made the
current window)
{config} Dictionary for the window configuration accepts
these keys:
`relative`: If set, the window becomes a
floating window. The window will be placed with
row,col coordinates relative to one of the
following:
"editor" the global editor grid
"win" a window. Use `win` to specify window id,
or current window will be used by default.
"cursor" the cursor position in current window.
`win`: when using `relative='win'`, window id of the window
where the position is defined.
`anchor`: the corner of the float that the row,col
position defines
"NW" north-west (default)
"NE" north-east
"SW" south-west
"SE" south-east
`focusable`: Whether window can be focused by wincmds and
mouse events. Defaults to true. Even if set to false,
the window can still be entered using
|nvim_set_current_win()| API call.
`height`: Window height in character cells. Minimum of 1.
`width`: Window width in character cells. Minimum of 2.
`row`: row position. Screen cell height are used as unit.
Can be floating point.
`col`: column position. Screen cell width is used as
unit. Can be floating point.
`external`: GUI should display the window as an external
top-level window. Currently accepts no other
positioning configuration together with this.
With editor positioning row=0, col=0 refers to the top-left With editor positioning row=0, col=0 refers to the top-left
corner of the screen-grid and row=Lines-1, Columns-1 refers to corner of the screen-grid and row=Lines-1, Columns-1 refers to
the bottom-right corner. Floating point values are allowed, the bottom-right corner. Floating point values are allowed,
@@ -698,9 +671,49 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
should not be used to specify arbitrary WM screen positions. should not be used to specify arbitrary WM screen positions.
Parameters: ~ Parameters: ~
{buffer} handle of buffer to be displayed in the window
{enter} whether the window should be entered (made the
current window)
{config} Dictionary for the window configuration accepts
these keys:
- `relative` : If set, the window becomes a floating
window. The window will be placed with row,col
coordinates relative to one of the following:
- "editor" the global editor grid
- "win" a window. Use `win` to specify a
window id, or the current window will be
used by default. "cursor" the cursor
position in current window.
- `win` : When using relative='win', window id
of the window where the position is defined.
- `anchor` : The corner of the float that the row,col
position defines:
- "NW" north-west (default)
- "NE" north-east
- "SW" south-west
- "SE" south-east
- `height` : window height (in character cells).
Minimum of 1.
- `width` : window width (in character cells).
Minimum of 2.
- `row` : row position. Screen cell height are
used as unit. Can be floating point.
- `col` : column position. Screen cell width is
used as unit. Can be floating point.
- `focusable` : Whether window can be focused by
wincmds and mouse events. Defaults to true.
Even if set to false, the window can still be
entered using |nvim_set_current_win()| API
call.
- `external` : GUI should display the window as
an external top-level window. Currently
accepts no other positioning configuration
together with this.
Return: ~ Return: ~
the window handle or 0 when error Window handle, or 0 on error
nvim_list_tabpages() *nvim_list_tabpages()* nvim_list_tabpages() *nvim_list_tabpages()*
Gets the current list of tabpage handles. Gets the current list of tabpage handles.
@@ -808,86 +821,87 @@ nvim_get_api_info() *nvim_get_api_info()*
*nvim_set_client_info()* *nvim_set_client_info()*
nvim_set_client_info({name}, {version}, {type}, {methods}, nvim_set_client_info({name}, {version}, {type}, {methods},
{attributes}) {attributes})
Identify the client for nvim. Can be called more than once, Identifies the client. Can be called more than once;
but subsequent calls will remove earlier info, which should be subsequent calls remove earlier info, which should be included
resent if it is still valid. (This could happen if a library by the caller if it is still valid. (E.g. if a library first
first identifies the channel, and a plugin using that library identifies the channel, then a plugin using that library later
later overrides that info) overrides that info)
Parameters: ~ Parameters: ~
{name} short name for the connected client {name} Short name for the connected client
{version} Dictionary describing the version, with the {version} Dictionary describing the version, with
following possible keys (all optional) these (optional) keys:
"major" major version (defaults to 0 if not - "major" major version (defaults to 0 if
set, for no release yet) "minor" minor not set, for no release yet)
version "patch" patch number "prerelease" - "minor" minor version
string describing a prerelease, like "dev" - "patch" patch number
or "beta1" "commit" hash or similar - "prerelease" string describing a
identifier of commit prerelease, like "dev" or "beta1"
{type} Must be one of the following values. A - "commit" hash or similar identifier of
client library should use "remote" if the commit
library user hasn't specified other value. {type} Must be one of the following values. Client
"remote" remote client that connected to libraries should default to "remote" unless
nvim. "ui" gui frontend "embedder" overridden by the user.
application using nvim as a component, for - "remote" remote client connected to Nvim.
instance IDE/editor implementing a vim mode. - "ui" gui frontend
"host" plugin host, typically started by - "embedder" application using Nvim as a
nvim "plugin" single plugin, started by component (for example, IDE/editor
nvim implementing a vim mode).
- "host" plugin host, typically started by
nvim
- "plugin" single plugin, started by nvim
{methods} Builtin methods in the client. For a host, {methods} Builtin methods in the client. For a host,
this does not include plugin methods which this does not include plugin methods which
will be discovered later. The key should be will be discovered later. The key should be
the method name, the values are dicts with the method name, the values are dicts with
the following (optional) keys: "async" if these (optional) keys (more keys may be
true, send as a notification. If false or added in future versions of Nvim, thus
unspecified, use a blocking request "nargs" unknown keys are ignored. Clients must only
Number of arguments. Could be a single use keys defined in this or later versions
integer or an array two integers, minimum of Nvim):
and maximum inclusive. Further keys might be - "async" if true, send as a notification.
added in later versions of nvim and unknown If false or unspecified, use a blocking
keys are thus ignored. Clients must only use request
keys defined in this or later versions of - "nargs" Number of arguments. Could be a
nvim! single integer or an array of two
{attributes} Informal attributes describing the client. integers, minimum and maximum inclusive.
Clients might define their own keys, but the {attributes} Arbitrary string:string map of informal
following are suggested: "website" Website client properties. Suggested keys:
of client (for instance github repository) - "website": Client homepage URL (e.g.
"license" Informal description of the GitHub repository)
license, such as "Apache 2", "GPLv3" or - "license": License description ("Apache
"MIT" "logo" URI or path to image, 2", "GPLv3", "MIT", …)
preferably small logo or icon. .png or .svg - "logo": URI or path to image, preferably
format is preferred. small logo or icon. .png or .svg format is
preferred.
nvim_get_chan_info({chan}) *nvim_get_chan_info()* nvim_get_chan_info({chan}) *nvim_get_chan_info()*
Get information about a channel. Get information about a channel.
Return: ~ Return: ~
a Dictionary, describing a channel with the following Dictionary describing a channel, with these keys:
keys: - "stream" the stream underlying the channel
- "stdio" stdin and stdout of this Nvim instance
- "stderr" stderr of this Nvim instance
- "socket" TCP/IP socket or named pipe
- "job" job with communication over its stdio
`stream`: the stream underlying the channel: - "mode" how data received on the channel is interpreted
"stdio" stdin and stdout of this Nvim instance. - "bytes" send and receive raw bytes
"stderr" stderr of this Nvim instance. - "terminal" a |terminal| instance interprets ASCII
"socket" TCP/IP socket or named pipe. sequences
"job" job with communication over its stdio. - "rpc" |RPC| communication on the channel is active
`mode`: how data received on the channel is interpreted: - "pty" Name of pseudoterminal, if one is used (optional).
"bytes" send and recieve raw bytes. On a POSIX system, this will be a device path like
"terminal" a |terminal| instance interprets ASCII sequences /dev/pts/1. Even if the name is unknown, the key will
"rpc" |RPC| communication on the channel is active still be present to indicate a pty is used. This is
currently the case when using winpty on windows.
`pty`: Name of pseudoterminal, if one is used (optional). - "buffer" buffer with connected |terminal| instance
On a POSIX system, this will be a device path like (optional)
/dev/pts/1. Even if the name is unknown, the key will - "client" information about the client on the other end
still be present to indicate a pty is used. This is of the RPC channel, if it has added it using
currently the case when using winpty on windows. |nvim_set_client_info()|. (optional)
`buffer`: buffer with connected |terminal|
instance (optional).
`client`: information about the client on the other end of
the RPC channel, if it has added it using
|nvim_set_client_info()| (optional).
nvim_list_chans() *nvim_list_chans()* nvim_list_chans() *nvim_list_chans()*
Get information about all open channels. Get information about all open channels.
@@ -901,12 +915,12 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
This has two main usages: This has two main usages:
1. To perform several requests from an async context 1. To perform several requests from an async context
atomically, i.e. without interleaving redraws, RPC requests atomically, i.e. without interleaving redraws, RPC requests
from other clients, or user interactions (however API methods from other clients, or user interactions (however API
may trigger autocommands or event processing which have such methods may trigger autocommands or event processing which
side-effects, e.g. |:sleep| may wake timers). have such side-effects, e.g. |:sleep| may wake timers).
2. To minimize RPC overhead (roundtrips) of a sequence of many 2. To minimize RPC overhead (roundtrips) of a sequence of many
requests. requests.
Parameters: ~ Parameters: ~
{calls} an array of calls, where each call is described {calls} an array of calls, where each call is described
@@ -914,13 +928,13 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
and an array of arguments. and an array of arguments.
Return: ~ Return: ~
an array with two elements. The first is an array of Array of two elements. The first is an array of return
return values. The second is NIL if all calls succeeded. values. The second is NIL if all calls succeeded. If a
If a call resulted in an error, it is a three-element call resulted in an error, it is a three-element array
array with the zero-based index of the call which resulted with the zero-based index of the call which resulted in an
in an error, the error type and the error message. If an error, the error type and the error message. If an error
error occurred, the values from all preceding calls will occurred, the values from all preceding calls will still
still be returned. be returned.
*nvim_parse_expression()* *nvim_parse_expression()*
nvim_parse_expression({expr}, {flags}, {highlight}) nvim_parse_expression({expr}, {flags}, {highlight})
@@ -930,20 +944,24 @@ nvim_parse_expression({expr}, {flags}, {highlight})
{async} {async}
Parameters: ~ Parameters: ~
{expr} Expression to parse. Is always treated as a {expr} Expression to parse. Always treated as a
single line. single line.
{flags} Flags: - "m" if multiple expressions in a {flags} Flags:
row are allowed (only the first one will be - "m" if multiple expressions in a row are
parsed), - "E" if EOC tokens are not allowed allowed (only the first one will be
(determines whether they will stop parsing parsed),
process or be recognized as an - "E" if EOC tokens are not allowed
operator/space, though also yielding an (determines whether they will stop parsing
error). - "l" when needing to start parsing process or be recognized as an
with lvalues for ":let" or ":for". Common operator/space, though also yielding an
flag sets: - "m" to parse like for ":echo". - error).
"E" to parse like for "<C-r>=". - empty - "l" when needing to start parsing with
string for ":call". - "lm" to parse for lvalues for ":let" or ":for". Common flag
":let". sets:
- "m" to parse like for ":echo".
- "E" to parse like for "<C-r>=".
- empty string for ":call".
- "lm" to parse for ":let".
{highlight} If true, return value will also include {highlight} If true, return value will also include
"highlight" key containing array of 4-tuples "highlight" key containing array of 4-tuples
(arrays) (Integer, Integer, Integer, String), (arrays) (Integer, Integer, Integer, String),
@@ -954,51 +972,66 @@ nvim_parse_expression({expr}, {flags}, {highlight})
[start_col, end_col)). [start_col, end_col)).
Return: ~ Return: ~
AST: top-level dictionary with these keys: "error":
Dictionary with error, present only if parser saw some - AST: top-level dictionary with these keys:
error. Contains the following keys: "message": String, - "error": Dictionary with error, present only if parser
error message in printf format, translated. Must contain saw some error. Contains the following keys:
exactly one "%.*s". "arg": String, error message argument. - "message": String, error message in printf format,
"len": Amount of bytes successfully parsed. With flags translated. Must contain exactly one "%.*s".
equal to "" that should be equal to the length of expr - "arg": String, error message argument.
string. @note: “Sucessfully parsed” here means
“participated in AST creation”, not “till the first - "len": Amount of bytes successfully parsed. With flags
error”. "ast": AST, either nil or a dictionary with these equal to "" that should be equal to the length of expr
keys: "type": node type, one of the value names from string. (“Sucessfully parsed” here means “participated
ExprASTNodeType stringified without "kExprNode" prefix. in AST creation”, not “till the first error”.)
"start": a pair [line, column] describing where node is - "ast": AST, either nil or a dictionary with these
“started” where "line" is always 0 (will not be 0 if you keys:
will be using nvim_parse_viml() on e.g. ":let", but that - "type": node type, one of the value names from
is not present yet). Both elements are Integers. "len": ExprASTNodeType stringified without "kExprNode"
“length” of the node. This and "start" are there for prefix.
debugging purposes primary (debugging parser and providing - "start": a pair [line, column] describing where node
debug information). "children": a list of nodes described is "started" where "line" is always 0 (will not be 0
in top/"ast". There always is zero, one or two children, if you will be using nvim_parse_viml() on e.g.
key will not be present if node has no children. Maximum ":let", but that is not present yet). Both elements
number of children may be found in node_maxchildren array. are Integers.
Local values (present only for certain nodes): "scope": a - "len": “length” of the node. This and "start" are
single Integer, specifies scope for "Option" and there for debugging purposes primary (debugging
"PlainIdentifier" nodes. For "Option" it is one of parser and providing debug information).
ExprOptScope values, for "PlainIdentifier" it is one of - "children": a list of nodes described in top/"ast".
ExprVarScope values. "ident": identifier (without scope, There always is zero, one or two children, key will
if any), present for "Option", "PlainIdentifier", not be present if node has no children. Maximum
"PlainKey" and "Environment" nodes. "name": Integer, number of children may be found in node_maxchildren
register name (one character) or -1. Only present for array.
"Register" nodes. "cmp_type": String, comparison type, one
of the value names from ExprComparisonType, stringified - Local values (present only for certain nodes):
without "kExprCmp" prefix. Only present for "Comparison" - "scope": a single Integer, specifies scope for
nodes. "ccs_strategy": String, case comparison strategy, "Option" and "PlainIdentifier" nodes. For "Option" it
one of the value names from ExprCaseCompareStrategy, is one of ExprOptScope values, for "PlainIdentifier"
stringified without "kCCStrategy" prefix. Only present for it is one of ExprVarScope values.
"Comparison" nodes. "augmentation": String, augmentation - "ident": identifier (without scope, if any), present
type for "Assignment" nodes. Is either an empty string, for "Option", "PlainIdentifier", "PlainKey" and
"Add", "Subtract" or "Concat" for "=", "+=", "-=" or ".=" "Environment" nodes.
respectively. "invert": Boolean, true if result of - "name": Integer, register name (one character) or -1.
comparison needs to be inverted. Only present for Only present for "Register" nodes.
"Comparison" nodes. "ivalue": Integer, integer value for - "cmp_type": String, comparison type, one of the value
"Integer" nodes. "fvalue": Float, floating-point value for names from ExprComparisonType, stringified without
"Float" nodes. "svalue": String, value for "kExprCmp" prefix. Only present for "Comparison"
"SingleQuotedString" and "DoubleQuotedString" nodes. nodes.
- "ccs_strategy": String, case comparison strategy, one
of the value names from ExprCaseCompareStrategy,
stringified without "kCCStrategy" prefix. Only present
for "Comparison" nodes.
- "augmentation": String, augmentation type for
"Assignment" nodes. Is either an empty string, "Add",
"Subtract" or "Concat" for "=", "+=", "-=" or ".="
respectively.
- "invert": Boolean, true if result of comparison needs
to be inverted. Only present for "Comparison" nodes.
- "ivalue": Integer, integer value for "Integer" nodes.
- "fvalue": Float, floating-point value for "Float"
nodes.
- "svalue": String, value for "SingleQuotedString" and
"DoubleQuotedString" nodes.
nvim__id({obj}) *nvim__id()* nvim__id({obj}) *nvim__id()*
Returns object given as argument. Returns object given as argument.
@@ -1058,23 +1091,22 @@ nvim_list_uis() *nvim_list_uis()*
Gets a list of dictionaries representing attached UIs. Gets a list of dictionaries representing attached UIs.
Return: ~ Return: ~
Array of UI dictionaries. Each dictionary has the Array of UI dictionaries, each with these keys:
following keys: - "height" requested height of the UI
`height`: requested height of the UI - "width" requested width of the UI
`width`: requested width of the UI - "rgb" whether the UI uses rgb colors (false implies
`rgb`: whether the UI uses rgb colors cterm colors)
(false implies cterm colors) - "ext_..." Requested UI extensions, see |ui-options|
`ext_...`: Requested UI extensions, see |ui-options| - "chan" Channel id of remote UI (not present for TUI)
`chan`: Channel id of remote UI (not present for TUI)
nvim_get_proc_children({pid}) *nvim_get_proc_children()* nvim_get_proc_children({pid}) *nvim_get_proc_children()*
Gets the immediate children of process `pid`. Gets the immediate children of process `pid` .
Return: ~ Return: ~
Array of child process ids, empty if process not found. Array of child process ids, empty if process not found.
nvim_get_proc({pid}) *nvim_get_proc()* nvim_get_proc({pid}) *nvim_get_proc()*
Gets info describing process `pid`. Gets info describing process `pid` .
Return: ~ Return: ~
Map of process properties, or NIL if process not found. Map of process properties, or NIL if process not found.
@@ -1096,7 +1128,7 @@ nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts})
{insert} Whether the selection should be inserted in the {insert} Whether the selection should be inserted in the
buffer. buffer.
{finish} Finish the completion and dismiss the popupmenu. {finish} Finish the completion and dismiss the popupmenu.
Implies `insert`. Implies `insert` .
{opts} Optional parameters. Reserved for future use. {opts} Optional parameters. Reserved for future use.
nvim__inspect_cell({row}, {col}) *nvim__inspect_cell()* nvim__inspect_cell({row}, {col}) *nvim__inspect_cell()*
@@ -1123,7 +1155,7 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Gets the buffer line count Gets the buffer line count
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
Line count, or 0 for unloaded buffer. |api-buffer| Line count, or 0 for unloaded buffer. |api-buffer|
@@ -1132,11 +1164,11 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activate updates from this buffer to the current channel. Activate updates from this buffer to the current channel.
Parameters: ~ Parameters: ~
{buffer} The buffer handle {buffer} Buffer handle, or 0 for current buffer
{send_buffer} Set to true if the initial notification {send_buffer} Set to true if the initial notification
should contain the whole buffer. If so, the should contain the whole buffer. If so, the
first notification will be a first notification will be a
`nvim_buf_lines_event`. Otherwise, the `nvim_buf_lines_event` . Otherwise, the
first notification will be a first notification will be a
`nvim_buf_changedtick_event` `nvim_buf_changedtick_event`
{opts} Optional parameters. Reserved for future {opts} Optional parameters. Reserved for future
@@ -1144,14 +1176,14 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Return: ~ Return: ~
False when updates couldn't be enabled because the buffer False when updates couldn't be enabled because the buffer
isn't loaded or optscontained an invalid key; otherwise isn't loaded or `opts` contained an invalid key; otherwise
True. True.
nvim_buf_detach({buffer}) *nvim_buf_detach()* nvim_buf_detach({buffer}) *nvim_buf_detach()*
Deactivate updates from this buffer to the current channel. Deactivate updates from this buffer to the current channel.
Parameters: ~ Parameters: ~
{buffer} The buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
False when updates couldn't be disabled because the buffer False when updates couldn't be disabled because the buffer
@@ -1169,7 +1201,7 @@ nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
unless `strict_indexing` is set. unless `strict_indexing` is set.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{start} First line index {start} First line index
{end} Last line index (exclusive) {end} Last line index (exclusive)
{strict_indexing} Whether out-of-bounds should be an {strict_indexing} Whether out-of-bounds should be an
@@ -1196,7 +1228,7 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing},
unless `strict_indexing` is set. unless `strict_indexing` is set.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{start} First line index {start} First line index
{end} Last line index (exclusive) {end} Last line index (exclusive)
{strict_indexing} Whether out-of-bounds should be an {strict_indexing} Whether out-of-bounds should be an
@@ -1216,7 +1248,7 @@ nvim_buf_get_offset({buffer}, {index}) *nvim_buf_get_offset()*
Returns -1 for unloaded buffer. Returns -1 for unloaded buffer.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{index} Line index {index} Line index
Return: ~ Return: ~
@@ -1226,7 +1258,7 @@ nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()*
Gets a buffer-scoped (b:) variable. Gets a buffer-scoped (b:) variable.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Variable name {name} Variable name
Return: ~ Return: ~
@@ -1236,17 +1268,17 @@ nvim_buf_get_changedtick({buffer}) *nvim_buf_get_changedtick()*
Gets a changed tick of a buffer Gets a changed tick of a buffer
Parameters: ~ Parameters: ~
{buffer} Buffer handle. {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
b:changedtickvalue. `b:changedtick` value.
nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()* nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()*
Gets a list of buffer-local |mapping| definitions. Gets a list of buffer-local |mapping| definitions.
Parameters: ~ Parameters: ~
{mode} Mode short-name ("n", "i", "v", ...) {mode} Mode short-name ("n", "i", "v", ...)
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
Array of maparg()-like dictionaries describing mappings. Array of maparg()-like dictionaries describing mappings.
@@ -1256,7 +1288,7 @@ nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()*
Gets a map of buffer-local |user-commands|. Gets a map of buffer-local |user-commands|.
Parameters: ~ Parameters: ~
{buffer} Buffer handle. {buffer} Buffer handle, or 0 for current buffer
{opts} Optional parameters. Currently not used. {opts} Optional parameters. Currently not used.
Return: ~ Return: ~
@@ -1266,7 +1298,7 @@ nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
Sets a buffer-scoped (b:) variable Sets a buffer-scoped (b:) variable
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Variable name {name} Variable name
{value} Variable value {value} Variable value
@@ -1274,14 +1306,14 @@ nvim_buf_del_var({buffer}, {name}) *nvim_buf_del_var()*
Removes a buffer-scoped (b:) variable Removes a buffer-scoped (b:) variable
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Variable name {name} Variable name
nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()* nvim_buf_get_option({buffer}, {name}) *nvim_buf_get_option()*
Gets a buffer option value Gets a buffer option value
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Option name {name} Option name
Return: ~ Return: ~
@@ -1292,7 +1324,7 @@ nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()*
option (only works if there's a global fallback) option (only works if there's a global fallback)
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Option name {name} Option name
{value} Option value {value} Option value
@@ -1300,7 +1332,7 @@ nvim_buf_get_name({buffer}) *nvim_buf_get_name()*
Gets the full file name for the buffer Gets the full file name for the buffer
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
Buffer name Buffer name
@@ -1309,7 +1341,7 @@ nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()*
Sets the full file name for a buffer Sets the full file name for a buffer
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Buffer name {name} Buffer name
nvim_buf_is_loaded({buffer}) *nvim_buf_is_loaded()* nvim_buf_is_loaded({buffer}) *nvim_buf_is_loaded()*
@@ -1317,7 +1349,7 @@ nvim_buf_is_loaded({buffer}) *nvim_buf_is_loaded()*
more info about unloaded buffers. more info about unloaded buffers.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
true if the buffer is valid and loaded, false otherwise. true if the buffer is valid and loaded, false otherwise.
@@ -1330,7 +1362,7 @@ nvim_buf_is_valid({buffer}) *nvim_buf_is_valid()*
|api-buffer| for more info about unloaded buffers. |api-buffer| for more info about unloaded buffers.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
Return: ~ Return: ~
true if the buffer is valid, false otherwise. true if the buffer is valid, false otherwise.
@@ -1340,7 +1372,7 @@ nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
named mark named mark
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{name} Mark name {name} Mark name
Return: ~ Return: ~
@@ -1364,7 +1396,7 @@ nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line},
`ns_id` to add highlights to the namespace. All highlights in `ns_id` to add highlights to the namespace. All highlights in
the same namespace can then be cleared with single call to the same namespace can then be cleared with single call to
|nvim_buf_clear_namespace|. If the highlight never will be |nvim_buf_clear_namespace|. If the highlight never will be
deleted by an API call, pass `ns_id = -1`. deleted by an API call, pass `ns_id = -1` .
As a shorthand, `ns_id = 0` can be used to create a new As a shorthand, `ns_id = 0` can be used to create a new
namespace for the highlight, the allocated id is then namespace for the highlight, the allocated id is then
@@ -1374,7 +1406,7 @@ nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line},
|nvim_create_namespace| to create a new empty namespace. |nvim_create_namespace| to create a new empty namespace.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{ns_id} namespace to use or -1 for ungrouped {ns_id} namespace to use or -1 for ungrouped
highlight highlight
{hl_group} Name of the highlight group to use {hl_group} Name of the highlight group to use
@@ -1396,7 +1428,7 @@ nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end})
to line_start and line_end respectively. to line_start and line_end respectively.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{ns_id} Namespace to clear, or -1 to clear all {ns_id} Namespace to clear, or -1 to clear all
namespaces. namespaces.
{line_start} Start of range of lines to clear {line_start} Start of range of lines to clear
@@ -1420,14 +1452,14 @@ nvim_buf_set_virtual_text({buffer}, {ns_id}, {line}, {chunks}, {opts})
both virtual text and highlights added by both virtual text and highlights added by
|nvim_buf_add_highlight|, both can then be cleared with a |nvim_buf_add_highlight|, both can then be cleared with a
single call to |nvim_buf_clear_namespace|. If the virtual text single call to |nvim_buf_clear_namespace|. If the virtual text
never will be cleared by an API call, pass `ns_id = -1`. never will be cleared by an API call, pass `ns_id = -1` .
As a shorthand, `ns_id = 0` can be used to create a new As a shorthand, `ns_id = 0` can be used to create a new
namespace for the virtual text, the allocated id is then namespace for the virtual text, the allocated id is then
returned. returned.
Parameters: ~ Parameters: ~
{buffer} Buffer handle {buffer} Buffer handle, or 0 for current buffer
{ns_id} Namespace to use or 0 to create a namespace, or {ns_id} Namespace to use or 0 to create a namespace, or
-1 for a ungrouped annotation -1 for a ungrouped annotation
{line} Line to annotate with virtual text {line} Line to annotate with virtual text
@@ -1601,7 +1633,7 @@ nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
parameters. parameters.
When reconfiguring a floating window, absent option keys will When reconfiguring a floating window, absent option keys will
not be changed. The following restriction apply: `row`, `col` not be changed. The following restriction apply: `row` , `col`
and `relative` must be reconfigured together. Only changing a and `relative` must be reconfigured together. Only changing a
subset of these is an error. subset of these is an error.
@@ -1636,9 +1668,6 @@ nvim_win_close({window}, {force}) *nvim_win_close()*
buffer will become hidden, even if 'hidden' is buffer will become hidden, even if 'hidden' is
not set. not set.
Return: ~
Window number
============================================================================== ==============================================================================
Tabpage Functions *api-tabpage* Tabpage Functions *api-tabpage*
@@ -1650,7 +1679,7 @@ nvim_tabpage_list_wins({tabpage}) *nvim_tabpage_list_wins()*
{tabpage} Tabpage {tabpage} Tabpage
Return: ~ Return: ~
List of windows in tabpage List of windows in `tabpage`
nvim_tabpage_get_var({tabpage}, {name}) *nvim_tabpage_get_var()* nvim_tabpage_get_var({tabpage}, {name}) *nvim_tabpage_get_var()*
Gets a tab-scoped (t:) variable Gets a tab-scoped (t:) variable

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Parses Doxygen XML output to generate Neovim's API documentation. """Generates Nvim help docs from C docstrings, by parsing Doxygen XML.
This would be easier using lxml and XSLT, but: This would be easier using lxml and XSLT, but:
@@ -35,6 +35,8 @@ import sys
import shutil import shutil
import textwrap import textwrap
import subprocess import subprocess
import collections
import pprint
from xml.dom import minidom from xml.dom import minidom
@@ -42,6 +44,10 @@ if sys.version_info[0] < 3:
print("use Python 3") print("use Python 3")
sys.exit(1) sys.exit(1)
DEBUG = ('DEBUG' in os.environ)
INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
doc_filename = 'api.txt' doc_filename = 'api.txt'
# String used to find the start of the generated part of the doc. # String used to find the start of the generated part of the doc.
section_start_token = '*api-global*' section_start_token = '*api-global*'
@@ -83,6 +89,12 @@ seen_funcs = set()
# deprecated functions. # deprecated functions.
xrefs = set() xrefs = set()
def debug_this(s, n):
o = n if isinstance(n, str) else n.toprettyxml(indent=' ', newl='\n')
name = '' if isinstance(n, str) else n.nodeName
if s in o:
raise RuntimeError('xxx: {}\n{}'.format(name, o))
# XML Parsing Utilities {{{ # XML Parsing Utilities {{{
def find_first(parent, name): def find_first(parent, name):
@@ -123,6 +135,10 @@ def clean_lines(text):
return re.sub(r'\A\n\s*\n*|\n\s*\n*\Z', '', re.sub(r'(\n\s*\n+)+', '\n\n', text)) return re.sub(r'\A\n\s*\n*|\n\s*\n*\Z', '', re.sub(r'(\n\s*\n+)+', '\n\n', text))
def is_blank(text):
return '' == clean_lines(text)
def get_text(parent): def get_text(parent):
"""Combine all text in a node.""" """Combine all text in a node."""
if parent.nodeType == parent.TEXT_NODE: if parent.nodeType == parent.TEXT_NODE:
@@ -137,16 +153,43 @@ def get_text(parent):
return out return out
def doc_wrap(text, prefix='', width=70, func=False): # Gets the length of the last line in `text`, excluding newline ("\n") char.
def len_lastline(text):
lastnl = text.rfind('\n')
if -1 == lastnl:
return len(text)
if '\n' == text[-1]:
return lastnl - (1+ text.rfind('\n', 0, lastnl))
return len(text) - (1 + lastnl)
def len_lastline_withoutindent(text, indent):
n = len_lastline(text)
return (n - len(indent)) if n > len(indent) else 0
# Returns True if node `n` contains only inline (not block-level) elements.
def is_inline(n):
for c in n.childNodes:
if c.nodeType != c.TEXT_NODE and c.nodeName != 'computeroutput':
return False
if not is_inline(c):
return False
return True
def doc_wrap(text, prefix='', width=70, func=False, indent=None):
"""Wraps text to `width`. """Wraps text to `width`.
The first line is prefixed with `prefix`, and subsequent lines are aligned. First line is prefixed with `prefix`, subsequent lines are aligned.
If `func` is True, only wrap at commas. If `func` is True, only wrap at commas.
""" """
if not width: if not width:
# return prefix + text
return text return text
indent_space = ' ' * len(prefix) # Whitespace used to indent all lines except the first line.
indent = ' ' * len(prefix) if indent is None else indent
indent_only = (prefix == '' and indent is not None)
if func: if func:
lines = [prefix] lines = [prefix]
@@ -154,27 +197,37 @@ def doc_wrap(text, prefix='', width=70, func=False):
if part[-1] not in ');': if part[-1] not in ');':
part += ', ' part += ', '
if len(lines[-1]) + len(part) > width: if len(lines[-1]) + len(part) > width:
lines.append(indent_space) lines.append(indent)
lines[-1] += part lines[-1] += part
return '\n'.join(x.rstrip() for x in lines).rstrip() return '\n'.join(x.rstrip() for x in lines).rstrip()
# XXX: Dummy prefix to force TextWrapper() to wrap the first line.
if indent_only:
prefix = indent
tw = textwrap.TextWrapper(break_long_words = False, tw = textwrap.TextWrapper(break_long_words = False,
break_on_hyphens = False, break_on_hyphens = False,
width=width, width=width,
initial_indent=prefix, initial_indent=prefix,
subsequent_indent=indent_space) subsequent_indent=indent)
return '\n'.join(tw.wrap(text.strip())) result = '\n'.join(tw.wrap(text.strip()))
# XXX: Remove the dummy prefix.
if indent_only:
result = result[len(indent):]
return result
def parse_params(parent, width=62): def render_params(parent, width=62):
"""Parse Doxygen `parameterlist`.""" """Renders Doxygen <parameterlist> tag as Vim help text."""
name_length = 0 name_length = 0
items = [] items = []
for child in parent.childNodes: for node in parent.childNodes:
if child.nodeType == child.TEXT_NODE: if node.nodeType == node.TEXT_NODE:
continue continue
name_node = find_first(child, 'parametername') name_node = find_first(node, 'parametername')
if name_node.getAttribute('direction') == 'out': if name_node.getAttribute('direction') == 'out':
continue continue
@@ -184,79 +237,152 @@ def parse_params(parent, width=62):
name = '{%s}' % name name = '{%s}' % name
name_length = max(name_length, len(name) + 2) name_length = max(name_length, len(name) + 2)
items.append((name.strip(), node))
out = ''
for name, node in items:
name = ' {}'.format(name.ljust(name_length))
desc = '' desc = ''
desc_node = get_child(child, 'parameterdescription') desc_node = get_child(node, 'parameterdescription')
if desc_node: if desc_node:
desc = parse_parblock(desc_node, width=None) desc = parse_parblock(desc_node, width=width,
items.append((name.strip(), desc.strip())) indent=(' ' * len(name)))
out = 'Parameters: ~\n' out += '{}{}\n'.format(name, desc)
for name, desc in items: return out.rstrip()
name = ' %s' % name.ljust(name_length)
out += doc_wrap(desc, prefix=name, width=width) + '\n'
return out.strip()
# Renders a node as Vim help text, recursively traversing all descendants.
def render_node(n, text, prefix='', indent='', width=62):
text = ''
# space_preceding = (len(text) > 0 and ' ' == text[-1][-1])
# text += (int(not space_preceding) * ' ')
def parse_para(parent, width=62): if n.nodeType == n.TEXT_NODE:
"""Parse doxygen `para` tag. # `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 is_inline(n):
for c in n.childNodes:
text += render_node(c, text)
text = doc_wrap(text, 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.
text += ' [verbatim] {}'.format(get_text(n))
elif n.nodeName == 'listitem':
for c in n.childNodes:
text += indent + prefix + render_node(c, text, indent=indent+(' ' * len(prefix)), width=width)
elif n.nodeName == 'para':
for c in n.childNodes:
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':
for c in n.childNodes:
text += '{}\n'.format(render_node(c, text, prefix='- ',
indent=indent, width=width))
elif n.nodeName == 'orderedlist':
i = 1
for c in n.childNodes:
if is_blank(get_text(c)):
text += '\n'
continue
text += '{}\n'.format(render_node(c, text, prefix='{}. '.format(i),
indent=indent, width=width))
i = i + 1
elif n.nodeName == 'simplesect' and 'note' == n.getAttribute('kind'):
text += 'Note:\n '
for c in n.childNodes:
text += render_node(c, text, indent=' ', width=width)
text += '\n'
elif n.nodeName == 'simplesect' and 'warning' == n.getAttribute('kind'):
text += 'Warning:\n '
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')):
text += ' '
for c in n.childNodes:
text += render_node(c, text, indent=' ', width=width)
else:
raise RuntimeError('unhandled node type: {}\n{}'.format(
n.nodeName, n.toprettyxml(indent=' ', newl='\n')))
return text
I assume <para> is a paragraph block or "a block of text". It can contain def render_para(parent, indent='', width=62):
text nodes, or other tags. """Renders Doxygen <para> containing arbitrary nodes.
NB: Blank lines in a docstring manifest as <para> tags.
""" """
line = '' if is_inline(parent):
lines = [] return clean_lines(doc_wrap(render_node(parent, ''),
indent=indent, width=width).strip())
# Ordered dict of ordered lists.
groups = collections.OrderedDict([
('params', []),
('return', []),
('seealso', []),
('xrefs', []),
])
# Gather nodes into groups. Mostly this is because we want "parameterlist"
# nodes to appear together.
text = ''
kind = ''
last = ''
for child in parent.childNodes: for child in parent.childNodes:
if child.nodeType == child.TEXT_NODE: if child.nodeName == 'parameterlist':
line += child.data groups['params'].append(child)
elif child.nodeName == 'computeroutput': elif child.nodeName == 'xrefsect':
line += '`%s`' % get_text(child) groups['xrefs'].append(child)
else: elif child.nodeName == 'simplesect':
if line: last = kind
lines.append(doc_wrap(line, width=width)) kind = child.getAttribute('kind')
line = '' if kind == 'return' or (kind == 'note' and last == 'return'):
groups['return'].append(child)
if child.nodeName == 'parameterlist': elif kind == 'see':
lines.append(parse_params(child, width=width)) groups['seealso'].append(child)
elif child.nodeName == 'xrefsect': elif kind in ('note', 'warning'):
title = get_text(get_child(child, 'xreftitle')) text += render_node(child, text, indent=indent, width=width)
xrefs.add(title)
xrefdesc = parse_para(get_child(child, 'xrefdescription'))
lines.append(doc_wrap(xrefdesc, prefix='%s: ' % title,
width=width) + '\n')
elif child.nodeName == 'simplesect':
kind = child.getAttribute('kind')
if kind == 'note':
lines.append('Note:')
lines.append(doc_wrap(parse_para(child),
prefix=' ',
width=width))
elif kind == 'return':
lines.append('%s: ~' % kind.title())
lines.append(doc_wrap(parse_para(child),
prefix=' ',
width=width))
else: else:
lines.append(get_text(child)) raise RuntimeError('unhandled simplesect: {}\n{}'.format(
child.nodeName, child.toprettyxml(indent=' ', newl='\n')))
else:
text += render_node(child, text, indent=indent, width=width)
if line: chunks = [text]
lines.append(doc_wrap(line, width=width)) # Generate text from the gathered items.
return clean_lines('\n'.join(lines).strip()) if len(groups['params']) > 0:
chunks.append('\nParameters: ~')
for child in groups['params']:
chunks.append(render_params(child, width=width))
if len(groups['return']) > 0:
chunks.append('\nReturn: ~')
for child in groups['return']:
chunks.append(render_node(child, chunks[-1][-1], indent=indent, width=width))
if len(groups['seealso']) > 0:
chunks.append('\nSee also: ~')
for child in groups['seealso']:
chunks.append(render_node(child, chunks[-1][-1], indent=indent, width=width))
for child in groups['xrefs']:
title = get_text(get_child(child, 'xreftitle'))
xrefs.add(title)
xrefdesc = render_para(get_child(child, 'xrefdescription'), width=width)
chunks.append(doc_wrap(xrefdesc, prefix='{}: '.format(title),
width=width) + '\n')
return clean_lines('\n'.join(chunks).strip())
def parse_parblock(parent, width=62): def parse_parblock(parent, prefix='', width=62, indent=''):
"""Parses a nested block of `para` tags. """Renders a nested block of <para> tags as Vim help text."""
Named after the \parblock command, but not directly related.
"""
paragraphs = [] paragraphs = []
for child in parent.childNodes: for child in parent.childNodes:
if child.nodeType == child.TEXT_NODE: paragraphs.append(render_para(child, width=width, indent=indent))
paragraphs.append(doc_wrap(child.data, width=width))
elif child.nodeName == 'para':
paragraphs.append(parse_para(child, width=width))
else:
paragraphs.append(doc_wrap(get_text(child), width=width))
paragraphs.append('') paragraphs.append('')
return clean_lines('\n'.join(paragraphs).strip()) return clean_lines('\n'.join(paragraphs).strip())
# }}} # }}}
@@ -292,7 +418,7 @@ def parse_source_xml(filename):
if return_type.startswith(('ArrayOf', 'DictionaryOf')): if return_type.startswith(('ArrayOf', 'DictionaryOf')):
parts = return_type.strip('_').split('_') parts = return_type.strip('_').split('_')
return_type = '%s(%s)' % (parts[0], ', '.join(parts[1:])) return_type = '{}({})'.format(parts[0], ', '.join(parts[1:]))
name = get_text(get_child(member, 'name')) name = get_text(get_child(member, 'name'))
@@ -306,37 +432,37 @@ def parse_source_xml(filename):
annotations = filter(None, map(lambda x: annotation_map.get(x), annotations = filter(None, map(lambda x: annotation_map.get(x),
annotations.split())) annotations.split()))
vimtag = '*%s()*' % name vimtag = '*{}()*'.format(name)
args = [] params = []
type_length = 0 type_length = 0
for param in get_children(member, 'param'): for param in get_children(member, 'param'):
arg_type = get_text(get_child(param, 'type')).strip() param_type = get_text(get_child(param, 'type')).strip()
arg_name = '' param_name = ''
declname = get_child(param, 'declname') declname = get_child(param, 'declname')
if declname: if declname:
arg_name = get_text(declname).strip() param_name = get_text(declname).strip()
if arg_name in param_exclude: if param_name in param_exclude:
continue continue
if arg_type.endswith('*'): if param_type.endswith('*'):
arg_type = arg_type.strip('* ') param_type = param_type.strip('* ')
arg_name = '*' + arg_name param_name = '*' + param_name
type_length = max(type_length, len(arg_type)) type_length = max(type_length, len(param_type))
args.append((arg_type, arg_name)) params.append((param_type, param_name))
c_args = [] c_args = []
for arg_type, arg_name in args: for param_type, param_name in params:
c_args.append(' ' + ( c_args.append(' ' + (
'%s %s' % (arg_type.ljust(type_length), arg_name)).strip()) '%s %s' % (param_type.ljust(type_length), param_name)).strip())
c_decl = textwrap.indent('%s %s(\n%s\n);' % (return_type, name, c_decl = textwrap.indent('%s %s(\n%s\n);' % (return_type, name,
',\n'.join(c_args)), ',\n'.join(c_args)),
' ') ' ')
prefix = '%s(' % name prefix = '%s(' % name
suffix = '%s)' % ', '.join('{%s}' % a[1] for a in args suffix = '%s)' % ', '.join('{%s}' % a[1] for a in params
if a[0] not in ('void', 'Error')) if a[0] not in ('void', 'Error'))
# Minimum 8 chars between signature and vimtag # Minimum 8 chars between signature and vimtag
@@ -354,7 +480,7 @@ def parse_source_xml(filename):
desc = find_first(member, 'detaileddescription') desc = find_first(member, 'detaileddescription')
if desc: if desc:
doc = parse_parblock(desc) doc = parse_parblock(desc)
if 'DEBUG' in os.environ: if DEBUG:
print(textwrap.indent( print(textwrap.indent(
re.sub(r'\n\s*\n+', '\n', re.sub(r'\n\s*\n+', '\n',
desc.toprettyxml(indent=' ', newl='\n')), ' ' * 16)) desc.toprettyxml(indent=' ', newl='\n')), ' ' * 16))
@@ -372,7 +498,7 @@ def parse_source_xml(filename):
else: else:
doc = doc[:i] + annotations + '\n\n' + doc[i:] doc = doc[:i] + annotations + '\n\n' + doc[i:]
if 'INCLUDE_C_DECL' in os.environ: if INCLUDE_C_DECL:
doc += '\n\nC Declaration: ~\n>\n' doc += '\n\nC Declaration: ~\n>\n'
doc += c_decl doc += c_decl
doc += '\n<' doc += '\n<'
@@ -464,7 +590,7 @@ def gen_docs(config):
if functions: if functions:
doc += '\n\n' + functions doc += '\n\n' + functions
if 'INCLUDE_DEPRECATED' in os.environ and deprecated: if INCLUDE_DEPRECATED and deprecated:
doc += '\n\n\nDeprecated %s Functions: ~\n\n' % name doc += '\n\n\nDeprecated %s Functions: ~\n\n' % name
doc += deprecated doc += deprecated
@@ -551,6 +677,7 @@ XML_PROGRAMLISTING = NO
ENABLE_PREPROCESSING = YES ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO EXPAND_ONLY_PREDEF = NO
MARKDOWN_SUPPORT = YES
''' '''
# }}} # }}}