aboutsummaryrefslogtreecommitdiff
path: root/runtime/doc/ui.txt
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/doc/ui.txt')
-rw-r--r--runtime/doc/ui.txt299
1 files changed, 272 insertions, 27 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index 3ce8ac1d89..c021f236c8 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -16,19 +16,23 @@ RPC API. The UI model consists of a terminal-like grid with a single,
monospace font size. Some elements (UI "widgets") can be drawn separately from
the grid ("externalized").
+
*ui-options*
-After connecting to Nvim (usually a spawned, embedded instance) use the
-|nvim_ui_attach| API method to tell Nvim that your program wants to draw the
-Nvim screen grid with a size of width × height cells. `options` must be
+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.
+ `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-ext-wildmenu|
+ `ext_wildmenu` Externalize the wildmenu. |ui-wildmenu|
+ `ext_linegrid` Use new revision of the grid events. |ui-linegrid|
+ `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
@@ -41,28 +45,74 @@ Nvim sends msgpack-rpc notifications to all attached UIs, with method name
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 "put", because each "put" event puts contents in
-one screen cell, but clients must be prepared for multiple argument sets being
-batched for all event kinds.
-
-Events must be handled in-order. The user should only see the updated screen
-state after all events in the same "redraw" batch are processed (not any
-intermediate state after processing only part of the array).
-
-Nvim sends |ui-global| and |ui-grid| events unconditionally; these suffice to
-implement a terminal-like layout.
+batching is mostly used for "grid_line", because each "grid_line" event puts
+contents in one screen 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 room for futher enhancements that will 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 will require it.
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 |ui-grid|.
+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.
@@ -81,13 +131,18 @@ Global Events *ui-global*
`cursor_shape`: "block", "horizontal", "vertical"
`cell_percentage`: Cell % occupied by the cursor.
`blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|.
- `hl_id`: Cursor highlight group.
- `hl_lm`: Cursor highlight group if 'langmap' is active.
+ `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:
@@ -112,7 +167,7 @@ Global Events *ui-global*
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-ext-cmdline|.
+ sent from Nvim, like for |ui-cmdline|.
["mode_change", mode, mode_idx]
The mode changed. The first parameter `mode` is a string representing
@@ -131,15 +186,15 @@ Global Events *ui-global*
would conflict with other usages of the mouse. It is safe for a client
to ignore this and always send mouse events.
-["busy_on"]
-["busy_off"]
+["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 other
- client where it makes sense) could suspend itself. Other clients can
- safely ignore it.
+ |: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.
@@ -148,8 +203,160 @@ Global Events *ui-global*
["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.
+
+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.
+
==============================================================================
-Grid Events *ui-grid*
+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.
@@ -173,7 +380,7 @@ Grid Events *ui-grid*
Set the default foreground, background and special colors
respectively.
- *ui-event-highlight_set*
+ *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
@@ -197,6 +404,9 @@ Grid Events *ui-grid*
["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
@@ -231,6 +441,41 @@ Grid Events *ui-grid*
+-------------------------+
<
==============================================================================
+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.
+
+==============================================================================
Popupmenu Events *ui-popupmenu*
Only sent if `ext_popupmenu` option is set in |ui-options|
@@ -288,7 +533,7 @@ Only sent if `ext_cmdline` option is set in |ui-options|
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 |cmd-line-window|
+ 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]