aboutsummaryrefslogtreecommitdiff
path: root/runtime/doc/ui.txt
blob: c021f236c8c82d6caf3dfa900f7555292b157908 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
*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 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*
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_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 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 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.

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.

==============================================================================
Popupmenu Events						 *ui-popupmenu*

Only sent if `ext_popupmenu` option is set in |ui-options|

["popupmenu_show", items, selected, row, col]
	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.

["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: