diff options
Diffstat (limited to 'runtime/doc/ui.txt')
-rw-r--r-- | runtime/doc/ui.txt | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt new file mode 100644 index 0000000000..9acd8b2c5a --- /dev/null +++ b/runtime/doc/ui.txt @@ -0,0 +1,639 @@ +*ui.txt* Nvim + + + NVIM REFERENCE MANUAL + + +Nvim UI protocol *ui* + + Type |gO| to see the table of contents. + +============================================================================== +UI Events *ui-events* + +GUIs can be implemented as external processes communicating with Nvim over the +RPC API. The default UI model consists of a terminal-like grid with a single, +monospace font size. The UI can opt-in to have windows drawn on separate +grids, as well as to have some elements (UI "widgets") be drawn by the UI +itself rather than by nvim ("externalized"). + + + *ui-options* +The |nvim_ui_attach()| API method is used to tell Nvim that your program wants to +draw the Nvim screen grid with a size of width × height cells. This is typically +done by an embedder, see |ui-startup| below for details, but an UI can also +connect to a running nvim instance and invoke this method. `options` must be +a dictionary with these (optional) keys: + `rgb` Decides the color format. *ui-rgb* + Set true (default) for 24-bit RGB colors. + Set false for terminal colors (max of 256). + *ui-ext-options* + `ext_popupmenu` Externalize the popupmenu. |ui-popupmenu| + `ext_tabline` Externalize the tabline. |ui-tabline| + `ext_cmdline` Externalize the cmdline. |ui-cmdline| + `ext_wildmenu` Externalize the wildmenu. |ui-wildmenu| + `ext_linegrid` Use new revision of the grid events. |ui-linegrid| + `ext_multigrid` Use per-window grid based events. |ui-multigrid| + `ext_hlstate` Use detailed highlight state. |ui-hlstate| + +Specifying a non-existent option is an error. UIs can check the |api-metadata| +`ui_options` key for supported options. Additionally Nvim (currently) requires +that all connected UIs use the same set of widgets. Therefore the active +widgets will be the intersection of the requested widget sets of all connected +UIs. The "option_set" event announces which widgets actually are active. + +Nvim sends msgpack-rpc notifications to all attached UIs, with method name +"redraw" and a single argument: an array (batch) of screen "update events". +Each update event is itself an array whose first element is the event name and +remaining elements are event-parameter tuples. This allows multiple events of +the same kind to be sent in a row without the event name being repeated. This +batching is mostly used for "grid_line", because each "grid_line" event puts +contents in one grid line, but clients must be prepared for multiple argument +sets being batched for all event kinds. + +Events must be handled in-order. A "flush" event is sent when nvim is done +redrawing the entire screen (so that all windows have a consistent view of +buffer state, options etc). Clients should be prepared that several "redraw" +batches are sent before the entire screen has been redrawn, and only the last +batch will end in "flush". The user should only see the final state when +"flush" is sent, and not any intermediate state after processing only part of +the batch array, nor after a batch not ending with "flush". + +By default, Nvim sends |ui-global| and |ui-grid-old| events; these suffice to +implement a terminal-like interface. However there are two revisions of the +grid part of the protocol. The newer revision |ui-linegrid|, enabled by +`ext_linegrid` option, has a more effecient representation of text (especially +highlighted text), and allows extensions that use multiple grids. + +The older revision is available and used by default only for backwards +compatibility reasons. New UIs are strongly recommended to use |ui-linegrid|, +as further protocol extensions require it. The |ui-multigrid| extension +enables |ui-linegrid| implicitly. + +Nvim optionally sends screen elements "semantically" as structured events +instead of raw grid-lines, controlled by |ui-ext-options|. The UI must present +those elements itself; Nvim will not draw those elements on the grid. + +Future versions of Nvim may add new update kinds and may append new parameters +to existing update kinds. Clients must be prepared to ignore such extensions, +for forward-compatibility. |api-contract| + +============================================================================== +UI startup *ui-startup* + +Nvim defines a standard procedure for how an embedding UI should interact with +the startup phase of Nvim. When spawning the nvim process, use the |--embed| flag +but not the |--headless| flag. The started Nvim process will pause before loading +startup files and reading buffers, and give the UI a chance to invoke requests +to do early initialization. As soon as the UI invokes |nvim_ui_attach()|, the +startup will continue. + +A simple UI only need to do a single |nvim_ui_attach()| request and then +be prepared to handle any UI event. A more featureful UI, which might need +additional configuration of the nvim process, should use the following startup +procedure: + +1. Invoke |nvim_get_api_info()|, if this is needed to setup the client library + and/or to get the list of supported UI extensions. +2. At this time, any configuration that should be happen before init.vim + loading should be done. Buffers and windows are not available at this + point, but this could be used to set |g:| variables visible to init.vim +3. If the UI wants to do additional setup after the init.vim file was loaded + register an autocmd for VimEnter at this point: > + + nvim_command("autocmd VimEnter * call rpcrequest(1, 'vimenter')") + +<4. Now invoke |nvim_ui_attach()|. The UI will need to handle keyboard input + at this point, as sourcing init.vim and loading buffers might lead to + blocking prompts. +5. If step 3 was used, nvim will send a blocking "vimenter" request to the + UI. Inside this request handler, the UI can safely do any initialization + before entering normal mode, for instance reading variables set by + init.vim. + +============================================================================== +Global Events *ui-global* + +The following events will always be available, and describe global state of +the editor. + +["set_title", title] +["set_icon", icon] + Set the window title, and icon (minimized) window title, respectively. + In windowing systems not distinguishing between the two, "set_icon" + can be ignored. + +["mode_info_set", cursor_style_enabled, mode_info] + `cursor_style_enabled` is a boolean indicating if the UI should set + the cursor style. `mode_info` is a list of mode property maps. The + current mode is given by the `mode_idx` field of the `mode_change` + event. + + Each mode property map may contain these keys: + + KEY DESCRIPTION ~ + `cursor_shape`: "block", "horizontal", "vertical" + `cell_percentage`: Cell % occupied by the cursor. + `blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|. + `attr_id`: Cursor attribute id (defined by `hl_attr_define`) + `attr_id_lm`: Cursor attribute id for when 'langmap' is active. + `short_name`: Mode code name, see 'guicursor'. + `name`: Mode descriptive name. + `mouse_shape`: (To be implemented.) + + Some keys are missing in some modes. + + The following keys are deprecated: + + `hl_id`: Use `attr_id` instead. + `hl_lm`: Use `attr_id_lm` instead. + +["option_set", name, value] + UI-related option changed, where `name` is one of: + + 'arabicshape' + 'ambiwidth' + 'emoji' + 'guifont' + 'guifontset' + 'guifontwide' + 'linespace' + 'showtabline' + 'termguicolors' + "ext_*" (all |ui-ext-options|) + + Triggered when the UI first connects to Nvim, and whenever an option + is changed by the user or a plugin. + + Options are not represented here if their effects are communicated in + other UI events. For example, instead of forwarding the 'mouse' option + value, the "mouse_on" and "mouse_off" UI events directly indicate if + mouse support is active. Some options like 'ambiwidth' have already + taken effect on the grid, where appropriate empty cells are added, + however a UI might still use such options when rendering raw text + sent from Nvim, like for |ui-cmdline|. + +["mode_change", mode, mode_idx] + The mode changed. The first parameter `mode` is a string representing + the current mode. `mode_idx` is an index into the array received in + the `mode_info_set` event. UIs should change the cursor style + according to the properties specified in the corresponding item. The + set of modes reported will change in new versions of Nvim, for + instance more submodes and temporary states might be represented as + separate modes. + +["mouse_on"] +["mouse_off"] + Tells the client whether mouse support, as determined by |'mouse'| + option, is considered to be active in the current mode. This is mostly + useful for a terminal frontend, or other situations where nvim mouse + would conflict with other usages of the mouse. It is safe for a client + to ignore this and always send mouse events. + +["busy_start"] +["busy_stop"] + Nvim started or stopped being busy, and possibly not responsive to + user input. This could be indicated to the user by hiding the cursor. + +["suspend"] + |:suspend| command or |CTRL-Z| mapping is used. A terminal client (or + another client where it makes sense) could suspend itself. Other + clients can safely ignore it. + +["update_menu"] + The menu mappings changed. + +["bell"] +["visual_bell"] + Notify the user with an audible or visual bell, respectively. + +["flush"] + Nvim is done redrawing the screen. For an implementation that renders + to an internal buffer, this is the time to display the redrawn parts + to the user. + +============================================================================== +Grid Events (line-based) *ui-linegrid* + +These events are used if `ext_linegrid` option is set (recommended for all new +UIs). The biggest change compared to previous revision is to use a single +event `grid_line` to update the contents of a screen line (where the old +protocol used a combination of cursor, highlight and text events) + +Most of these events take a `grid` index as first parameter. Grid 1 is the +global grid used by default for the entire editor screen state. Grids other +than that will be defined by future extensions. Just activating the +`ext_linegrid` option by itself will never cause any additional grids to be +created. To enable per-window grids, `ext_multigrid` option should be set (see +|ui-multigrid|). + +Highlight attribute groups are predefined. UIs should maintain a table to map +numerical highlight `id`:s to the actual attributes. + +["grid_resize", grid, width, height] + Resize a `grid`. If `grid` wasn't seen by the client before, a new grid is + being created with this size. + +["default_colors_set", rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg] + The first three arguments set the default foreground, background and + special colors respectively. `cterm_fg` and `cterm_bg` specifies the + default color codes to use in a 256-color terminal. + + Note: unlike the corresponding events in the first revision, the + screen is not always cleared after sending this event. The GUI has to + repaint the screen with changed background color itself. + + *ui-event-hl_attr_define* +["hl_attr_define", id, rgb_attr, cterm_attr, info] + Add a highlight with `id` to the highlight table, with the + attributes specified by the `rgb_attr` and `cterm_attr` dicts, with the + following (all optional) keys. + + `foreground`: foreground color. + `background`: background color. + `special`: color to use for underline and undercurl, when present. + `reverse`: reverse video. Foreground and background colors are + switched. + `italic`: italic text. + `bold`: bold text. + `underline`: underlined text. The line has `special` color. + `undercurl`: undercurled text. The curl has `special` color. + + For absent color keys the default color should be used. Don't store + the default value in the table, rather a sentinel value, so that + a changed default color will take effect. + All boolean keys default to false, and will only be sent when they + are true. + + Highlights are always transmitted both for both the rgb format and as + terminal 256-color codes, as the `rgb_attr` and `cterm_attr` parameters + respectively. The |ui-rgb| option has no effect effect anymore. + Most external UIs will only need to store and use the `rgb_attr` + attributes. + + `id` 0 will always be used for the default highlight with colors defined + by `default_colors_set` and no styles applied. + + Note: `id`:s can be reused if Nvim's internal highlight table is full. + In this case, Nvim will always issue redraws of screen cells that are + affected by redefined `id`:s, so UIs do not need to keep track of this + themselves. + + `info` is an empty array per default, and will be used by the + |ui-hlstate| extension explaned below. + + *ui-event-grid_line* +["grid_line", grid, row, col_start, cells] + Redraw a continous part of a `row` on a `grid`, starting at the column + `col_start`. `cells` is an array of arrays each with 1 to 3 items: + `[text(, hl_id, repeat)]` . `text` is the UTF-8 text that should be put in + a cell, with the highlight `hl_id` defined by a previous `hl_attr_define` + call. If `hl_id` is not present the most recently seen `hl_id` in + the same call should be used (it is always sent for the first + cell in the event). If `repeat` is present, the cell should be + repeated `repeat` times (including the first time), otherwise just + once. + + The right cell of a double-width char will be represented as the empty + string. Double-width chars never use `repeat`. + + If the array of cell changes doesn't reach to the end of the line, the + rest should remain unchanged. A whitespace char, repeated + enough to cover the remaining line, will be sent when the rest of the + line should be cleared. + +["grid_clear", grid] + Clear a `grid`. + +["grid_destroy", grid] + `grid` will not be used anymore and the UI can free any data associated + with it. + +["grid_cursor_goto", grid, row, column] + Makes `grid` the current grid and `row, column` the cursor position on this + grid. This event will be sent at most once in a `redraw` batch and + indicates the visible cursor position. + +["grid_scroll", grid, top, bot, left, right, rows, cols] + Scroll the text in the a region of `grid`. The diagrams below illustrate + what will happen, depending on the scroll direction. "=" is used to + represent the SR(scroll region) boundaries and "-" the moved rectangles. + Note that dst and src share a common region. + + If `rows` is bigger than 0, move a rectangle in the SR up, this can + happen while scrolling down. +> + +-------------------------+ + | (clipped above SR) | ^ + |=========================| dst_top | + | dst (still in SR) | | + +-------------------------+ src_top | + | src (moved up) and dst | | + |-------------------------| dst_bot | + | src (invalid) | | + +=========================+ src_bot +< + If `rows` is less than zero, move a rectangle in the SR down, this can + happen while scrolling up. +> + +=========================+ src_top + | src (invalid) | | + |------------------------ | dst_top | + | src (moved down) and dst| | + +-------------------------+ src_bot | + | dst (still in SR) | | + |=========================| dst_bot | + | (clipped below SR) | v + +-------------------------+ +< + `cols` is always zero in this version of Nvim, and reserved for future + use. + + Note when updating code from |ui-grid-old| events: ranges are + end-exclusive, which is consistent with API conventions, but different + from `set_scroll_region` which was end-inclusive. + + The scrolled-in area will be filled using |ui-event-grid_line| directly + after the scroll event. The UI thus doesn't need to clear this area as + part of handling the scroll event. + +============================================================================== +Legacy Grid Events (cell based) *ui-grid-old* + +This is an older representation of the screen grid, used if `ext_linegrid` +option is not set. New UIs should use |ui-linegrid|. + +["resize", width, height] + The grid is resized to `width` and `height` cells. + +["clear"] + Clear the grid. + +["eol_clear"] + Clear from the cursor position to the end of the current line. + +["cursor_goto", row, col] + Move the cursor to position (row, col). Currently, the same cursor is + used to define the position for text insertion and the visible cursor. + However, only the last cursor position, after processing the entire + array in the "redraw" event, is intended to be a visible cursor + position. + +["update_fg", color] +["update_bg", color] +["update_sp", color] + Set the default foreground, background and special colors + respectively. + + *ui-event-highlight_set* +["highlight_set", attrs] + Set the attributes that the next text put on the grid will have. + `attrs` is a dict with the keys below. Any absent key is reset + to its default value. Color defaults are set by the `update_fg` etc + updates. All boolean keys default to false. + + `foreground`: foreground color. + `background`: backround color. + `special`: color to use for underline and undercurl, when present. + `reverse`: reverse video. Foreground and background colors are + switched. + `italic`: italic text. + `bold`: bold text. + `underline`: underlined text. The line has `special` color. + `undercurl`: undercurled text. The curl has `special` color. + +["put", text] + The (utf-8 encoded) string `text` is put at the cursor position + (and the cursor is advanced), with the highlights as set by the + last `highlight_set` update. + +["set_scroll_region", top, bot, left, right] + Define the scroll region used by `scroll` below. + + Note: ranges are end-inclusive, which is inconsistent with API + conventions. + +["scroll", count] + Scroll the text in the scroll region. The diagrams below illustrate + what will happen, depending on the scroll direction. "=" is used to + represent the SR(scroll region) boundaries and "-" the moved rectangles. + Note that dst and src share a common region. + + If count is bigger than 0, move a rectangle in the SR up, this can + happen while scrolling down. +> + +-------------------------+ + | (clipped above SR) | ^ + |=========================| dst_top | + | dst (still in SR) | | + +-------------------------+ src_top | + | src (moved up) and dst | | + |-------------------------| dst_bot | + | src (cleared) | | + +=========================+ src_bot +< + If count is less than zero, move a rectangle in the SR down, this can + happen while scrolling up. +> + +=========================+ src_top + | src (cleared) | | + |------------------------ | dst_top | + | src (moved down) and dst| | + +-------------------------+ src_bot | + | dst (still in SR) | | + |=========================| dst_bot | + | (clipped below SR) | v + +-------------------------+ +< +============================================================================== +Detailed highlight state Extension *ui-hlstate* + +Only sent if `ext_hlstate` option is set in |ui-options|. `ext_hlstate` implies +`ext_linegrid`. + +By default, nvim will only describe grid cells using the final calculated +higlight attributes, as described by the dict keys in |ui-event-highlight_set|. +The `ext_hlstate` extension allows to the UI to also receive a semantic +describtion of the higlights active in a cell. In this mode highlights will be +predefined in a table, see |ui-event-hl_attr_define| and |ui-event-grid_line|. +The `info` parameter in `hl_attr_define` will contain a semantic description +of the highlights. As highlight groups can be combined, this will be an array +of items, with the item with highest priority last. Each item is a dictionary +with the following possible keys: + + `kind`: always present. One of the following values: + "ui": A builtin ui highlight. + "syntax": highlight applied to a buffer by a syntax declaration or + other runtime/plugin functionallity such as + |nvim_buf_add_highlight()| + "terminal": highlight from a process running in a |terminal-emulator|. + Contains no futher semantic information. + `ui_name`: Name of the builtin highlight. See |highlight-groups| for + possible values. Only present for "ui". + `hi_name`: Name of the final |:highlight| group where the used + attributes are defined. + `id`: Unique numeric id representing this item. + +Note: "ui" items will have both `ui_name` and `hi_name` present. These can +differ, because the builtin group was linked to another group |:hi-link| , or +because 'winhighlight' was used. UI items will be transmitted, even if the +highlight group is cleared, so `ui_name` can always be used to reliably identify +screen elements, even if no attributes have been applied. + +============================================================================== +Multigrid Events *ui-multigrid* + +Only sent if `ext_multigrid` option is set in |ui-options|. Enables the +`ext_linegrid` extension implicitly. + +The multigrid extension gives the UIs more control over how windows are +displayed. The UIs receive updates on a separate grid for each window. The UIs +can set the grid size independently of how much space the window occupies on +the global layout. This enables the UIs to set a different font size for each +window if the UI so desires. The UI can also reserve space around the border +of the window for its own elements, for instance scrollbars from the UI +toolkit. + +By default, the grid size is handled by nvim and set to the outer grid size +(i.e. the size of the window frame in nvim) whenever the split is created. +Once a UI sets a grid size, nvim does not handle the size for that grid and +the UI must change the grid size whenever the outer size is changed. To +delegate the handling of grid size back to nvim, the UIs should request the +size (0, 0). + +A window can be hidden and redisplayed without its grid being deallocated. +This can happen multiple times for the same window, for instance when switching +tabs. + +["win_pos", grid, win, start_row, start_col, width, height] + Set the position and size of the grid in nvim (i.e. the outer grid + size). If the window was previously hidden, it should now be shown + again. + +["win_hide", grid] + Stop displaying the window. + +["win_scroll_over_start"] + Hint that following `grid_scroll` on the default grid should + scroll over windows. This is a temporary workaround to allow + UIs to use the builtin message drawing. Later on, messages will be + drawn on a dedicated grid. + +["win_scroll_over_reset"] + Hint that scrolled over windows should be redrawn again, and not be + overdrawn by default grid scrolling anymore. + +See |ui-linegrid| for grid events. +See |nvim_ui_try_resize_grid| in |api-ui| to request changing the grid size. + +============================================================================== +Popupmenu Events *ui-popupmenu* + +Only sent if `ext_popupmenu` option is set in |ui-options| + +["popupmenu_show", items, selected, row, col, grid] + Show |popupmenu-completion|. `items` is an array of completion items + to show; each item is an array of the form [word, kind, menu, info] as + defined at |complete-items|, except that `word` is replaced by `abbr` + if present. `selected` is the initially-selected item, a zero-based + index into the array of items (-1 if no item is selected). `row` and + `col` give the anchor position, where the first character of the + completed word will be. When |ui-multigrid| is used, `grid` is the + grid for the anchor position. + +["popupmenu_select", selected] + Select an item in the current popupmenu. `selected` is a zero-based + index into the array of items from the last popupmenu_show event, or + -1 if no item is selected. + +["popupmenu_hide"] + Hide the popupmenu. + +============================================================================== +Tabline Events *ui-tabline* + +Only sent if `ext_tabline` option is set in |ui-options| + +["tabline_update", curtab, tabs] + Tabline was updated. UIs should present this data in a custom tabline + widget. + curtab: Current Tabpage + tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...] + +============================================================================== +Cmdline Events *ui-cmdline* + +Only sent if `ext_cmdline` option is set in |ui-options| + +["cmdline_show", content, pos, firstc, prompt, indent, level] + content: List of [attrs, string] + [[{}, "t"], [attrs, "est"], ...] + + Triggered when the cmdline is displayed or changed. + The `content` is the full content that should be displayed in the + cmdline, and the `pos` is the position of the cursor that in the + cmdline. The content is divided into chunks with different highlight + attributes represented as a dict (see |ui-event-highlight_set|). + + `firstc` and `prompt` are text, that if non-empty should be + displayed in front of the command line. `firstc` always indicates + built-in command lines such as `:` (ex command) and `/` `?` (search), + while `prompt` is an |input()| prompt. `indent` tells how many spaces + the content should be indented. + + The Nvim command line can be invoked recursively, for instance by + typing `<c-r>=` at the command line prompt. The `level` field is used + to distinguish different command lines active at the same time. The + first invoked command line has level 1, the next recursively-invoked + prompt has level 2. A command line invoked from the |cmdline-window| + has a higher level than than the edited command line. + +["cmdline_pos", pos, level] + Change the cursor position in the cmdline. + +["cmdline_special_char", c, shift, level] + Display a special char in the cmdline at the cursor position. This is + typically used to indicate a pending state, e.g. after |c_CTRL-V|. If + `shift` is true the text after the cursor should be shifted, otherwise + it should overwrite the char at the cursor. + + Should be hidden at next cmdline_show. + +["cmdline_hide"] + Hide the cmdline. + +["cmdline_block_show", lines] + Show a block of context to the current command line. For example if + the user defines a |:function| interactively: > + :function Foo() + : echo "foo" + : +< + `lines` is a list of lines of highlighted chunks, in the same form as + the "cmdline_show" `contents` parameter. + +["cmdline_block_append", line] + Append a line at the end of the currently shown block. + +["cmdline_block_hide"] + Hide the block. + +============================================================================== +Wildmenu Events *ui-wildmenu* + +Only sent if `ext_wildmenu` option is set in |ui-options| + +["wildmenu_show", items] + Activate the wildmenu (command-line completion). `items` is an array + with the completion items. + +["wildmenu_select", selected] + Select an item in the current wildmenu. `selected` is a zero-based + index into the array of items from the last wildmenu_show event, or -1 + if no item is selected. + +["wildmenu_hide"] + Hide the wildmenu. + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: |