Merge #9993 from justinmk/ui-message-kinds

UI/ext_messages: learn more message kinds
This commit is contained in:
Justin M. Keyes
2019-05-12 00:11:57 +02:00
committed by GitHub
13 changed files with 324 additions and 173 deletions

View File

@@ -46,7 +46,7 @@ version.api_prerelease Declares the API as unstable/unreleased >
(version.api_prerelease && fn.since == version.api_level)
functions API function signatures
ui_events UI event signatures |ui|
ui_options Supported |ui-options|
ui_options Supported |ui-option|s
{fn}.since API level where function {fn} was introduced
{fn}.deprecated_since API level where function {fn} was deprecated
types Custom handle types defined by Nvim
@@ -766,7 +766,7 @@ nvim_get_color_by_name({name}) *nvim_get_color_by_name()*
Returns the 24-bit RGB value of a |nvim_get_color_map()| color
name or "#rrggbb" hexadecimal string.
Examples: >
Example: >
:echo nvim_get_color_by_name("Pink")
:echo nvim_get_color_by_name("#cbcbcb")
<
@@ -1104,11 +1104,11 @@ nvim_list_uis() *nvim_list_uis()*
Return: ~
Array of UI dictionaries, each with these keys:
- "height" requested height of the UI
- "width" requested width of the UI
- "height" Requested height of the UI
- "width" Requested width of the UI
- "rgb" true if the UI uses RGB colors (false implies
|cterm-colors|)
- "ext_..." Requested UI extensions, see |ui-options|
- "ext_..." Requested UI extensions, see |ui-option|
- "chan" Channel id of remote UI (not present for TUI)
nvim_get_proc_children({pid}) *nvim_get_proc_children()*
@@ -1765,7 +1765,7 @@ nvim_ui_attach({width}, {height}, {options}) *nvim_ui_attach()*
Parameters: ~
{width} Requested screen columns
{height} Requested screen rows
{options} |ui-options| map
{options} |ui-option| map
nvim_ui_detach() *nvim_ui_detach()*
Deactivates UI events on the channel.

View File

@@ -69,7 +69,7 @@ Options ~
UI extensions~
*ui-wildmenu* Use |ui-cmdline| with |ui-popupmenu| instead. Enabled
by `ext_wildmenu` |ui-options|. Emits these events:
by the `ext_wildmenu` |ui-option|. Emits these events:
["wildmenu_show", items]
["wildmenu_select", selected]
["wildmenu_hide"]

View File

@@ -157,28 +157,32 @@ with a {thing} that groups functions under a common concept).
Use existing common {action} names if possible:
add Append to, or insert into, a collection
get Get a thing (or subset of things by some query)
set Set a thing
get Get a thing (or group of things by query)
set Set a thing (or group of things)
del Delete a thing (or group of things)
list Get all things
Use consistent names for {thing} in all API functions. E.g. a buffer is called
"buf" everywhere, not "buffer" in some places and "buf" in others.
Example: `nvim_get_current_line` acts on the global editor state; the common
{action} "get" is used but {thing} is omitted.
Example:
`nvim_get_current_line` acts on the global editor state; the common
{action} "get" is used but {thing} is omitted.
Example: `nvim_buf_add_highlight` acts on a `Buffer` object (the first
parameter) and uses the common {action} "add".
Example:
`nvim_buf_add_highlight` acts on a `Buffer` object (the first parameter)
and uses the common {action} "add".
Example: `nvim_list_bufs` operates in a global context (first parameter is
_not_ a Buffer). The common {action} "list" indicates that it lists all
bufs (plural) in the global context.
Example:
`nvim_list_bufs` operates in a global context (first parameter is not
a Buffer). The common {action} "list" indicates that it lists all bufs
(plural) in the global context.
Use this template to name new API events:
nvim_{thing}_{event}_event
Example: `nvim_buf_changedtick_event`.
Example:
`nvim_buf_changedtick_event`
API-CLIENT *dev-api-client*

View File

@@ -11,22 +11,23 @@ Nvim UI protocol *ui*
==============================================================================
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").
UIs can be implemented as external client processes communicating with Nvim
over the RPC API. The default UI model is a terminal-like grid with a single,
monospace font. The UI can opt-in to have windows drawn on separate grids, and
have some elements ("widgets") presented 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*
*ui-option*
Call |nvim_ui_attach()| 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 at startup (see |ui-startup|), but UIs can also connect to a running
Nvim instance and invoke nvim_ui_attach(). The `options` parameter is a map
with these (optional) keys:
*ui-rgb*
`rgb` Decides the color format.
true: (default) 24-bit RGB colors
false: Terminal colors (8-bit, max 256)
*ui-override*
`override` Decides how UI capabilities are resolved.
true: Enable requested UI capabilities, even
if not supported by all connected UIs
@@ -34,54 +35,74 @@ a dictionary with these (optional) keys:
false: (default) Disable UI capabilities not
supported by all connected UIs
(including TUI).
*ui-ext-options*
*ui-ext-options*
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
`ext_hlstate` Detailed highlight state. |ui-hlstate|
Sets `ext_linegrid` implicitly.
`ext_linegrid` Line-based grid events. |ui-linegrid|
Deactivates |ui-grid-old| implicitly.
`ext_messages` Externalize messages. |ui-messages|
Sets `ext_linegrid` and `ext_cmdline` implicitly.
`ext_multigrid` Per-window grid events. |ui-multigrid|
Sets `ext_linegrid` implicitly.
`ext_popupmenu` Externalize |popupmenu-completion| and
'wildmenu'. |ui-popupmenu|
`ext_tabline` Externalize the tabline. |ui-tabline|
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
`ext_messages` Externalize messages. |ui-messages|
`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|
`ext_termcolors` Use external default colors.
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.
Specifying an unknown option is an error; UIs can check the |api-metadata|
`ui_options` key for supported options.
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.
By default Nvim requires all connected UIs to support the same capabilities,
thus the active capabilities are the intersection of those requested. UIs may
specify |ui-override| to invert this behavior (useful for debugging). The
"option_set" event announces which capabilities are active.
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".
Nvim sends 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. Thus multiple events of the same kind can
be sent contiguously without repeating the event name.
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 efficient representation of text (especially
highlighted text), and allows extensions that use multiple grids.
Example of a typical "redraw" batch in a single RPC notification: >
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.
['notification', 'redraw',
[
['grid_resize', [2, 77, 36]],
['grid_line',
[2, 0, 0, [[' ' , 0, 77]]],
[2, 1, 0, [['~', 7], [' ', 7, 76]]],
[2, 9, 0, [['~', 7], [' ', 7, 76]]],
...
[2, 35, 0, [['~', 7], [' ', 7, 76]]],
[1, 36, 0, [['[', 9], ['N'], ['o'], [' '], ['N'], ['a'], ['m'], ['e'], [']']]],
[1, 36, 9, [[' ', 9, 50]]],
[1, 36, 59, [['0', 9], [','], ['0'], ['-' ], ['1'], [' ', 9, 10], ['A'], ['l', 9, 2]]]
],
['msg_showmode', [[]]],
['win_pos', [2, 1000, 0, 0, 77, 36]],
['grid_cursor_goto', [2, 0, 0]],
['flush', []]
]
]
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.
Events must be handled in-order. Nvim sends a "flush" event when it has
completed a redraw of the entire screen (so all windows have a consistent view
of buffer state, options, etc.). Multiple "redraw" batches may be sent before
the entire screen has been redrawn, with "flush" following only the last
batch. The user should only see the final state (when "flush" is sent), not
any intermediate state while processing part of the batch array, nor after
a batch not ending with "flush".
By default, Nvim sends |ui-global| and |ui-grid-old| events (for backwards
compatibility); these suffice to implement a terminal-like interface. However
the new |ui-linegrid| represents text more efficiently (especially highlighted
text), and allows UI capabilities requiring multiple grids. New UIs should
implement |ui-linegrid| instead of |ui-grid-old|.
Nvim optionally sends various screen elements "semantically" as structured
events instead of raw grid-lines, as specified by |ui-ext-options|. The UI
must present such elements itself, Nvim will not draw them 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,
@@ -99,7 +120,7 @@ continue as soon as the UI invokes |nvim_ui_attach()|.
A simple UI only needs to do a single |nvim_ui_attach()| request and then
prepare to handle any UI event. A more featureful UI, which might need
additional configuration of the nvim process, should use the following startup
additional configuration of the Nvim process, should use the following startup
procedure:
1. Invoke |nvim_get_api_info()|, if needed to setup the client library and/or
@@ -119,7 +140,7 @@ procedure:
==============================================================================
Global Events *ui-global*
The following events will always be available, and describe global state of
The following UI events are always emitted, and describe global state of
the editor.
["set_title", title]
@@ -192,7 +213,7 @@ the editor.
["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
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.
@@ -221,17 +242,17 @@ the editor.
==============================================================================
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
`grid_line` event to update the contents of a screen line (where the old
protocol used a combination of cursor, highlight and text events)
Activated by the `ext_linegrid` |ui-option|. Recommended for all new UIs.
Deactivates |ui-grid-old| implicitly.
The biggest change compared to |ui-grid-old| is to use a single `grid_line`
event to update the contents of a screen line (whereas 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|).
global grid used by default for the entire editor screen state. The
`ext_linegrid` capability by itself will never cause any additional grids to
be created; to enable per-window grids, activate |ui-multigrid|.
Highlight attribute groups are predefined. UIs should maintain a table to map
numerical highlight ids to the actual attributes.
@@ -375,10 +396,10 @@ numerical highlight ids to the actual attributes.
part of handling the scroll event.
==============================================================================
Legacy Grid Events (cell based) *ui-grid-old*
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|.
This is the legacy representation of the screen grid, emitted if |ui-linegrid|
is not active. New UIs should implement |ui-linegrid| instead.
["resize", width, height]
The grid is resized to `width` and `height` cells.
@@ -465,8 +486,8 @@ option is not set. New UIs should use |ui-linegrid|.
==============================================================================
Detailed highlight state Extension *ui-hlstate*
Only sent if `ext_hlstate` option is set in |ui-options|. `ext_hlstate` implies
`ext_linegrid`.
Activated by the `ext_hlstate` |ui-option|.
Activates |ui-linegrid| implicitly.
By default Nvim will only describe grid cells using the final calculated
highlight attributes, as described by the dict keys in |ui-event-highlight_set|.
@@ -499,30 +520,32 @@ 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.
Activated by the `ext_multigrid` |ui-option|.
Activates |ui-linegrid| 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.
See |ui-linegrid| for grid events.
See |nvim_ui_try_resize_grid()| to request changing the grid size.
See |nvim_input_mouse()| for sending mouse events to Nvim.
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 multigrid extension gives UIs more control over how windows are displayed:
- UIs receive updates on a separate grid for each window.
- UIs can set the grid size independently of how much space the window
occupies on the global layout. So the UI could use a different font size
per-window. Or reserve space around the border of the window for its own
elements, such as 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).
delegate grid-size handling back to Nvim, 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
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.
@@ -553,15 +576,13 @@ tabs.
["win_close", grid]
Close the window.
See |ui-linegrid| for grid events.
See |nvim_ui_try_resize_grid| in |api-ui| to request changing the grid size.
See |nvim_input_mouse| for sending mouse events to Nvim.
==============================================================================
Popupmenu Events *ui-popupmenu*
Only sent if `ext_popupmenu` option is set in |ui-options|.
Events for |popupmenu-completion| and command-line 'wildmenu'.
Activated by the `ext_popupmenu` |ui-option|.
This UI extension delegates presentation of the |popupmenu-completion| and
command-line 'wildmenu'.
["popupmenu_show", items, selected, row, col, grid]
Show |popupmenu-completion|. `items` is an array of completion items
@@ -586,7 +607,7 @@ Events for |popupmenu-completion| and command-line 'wildmenu'.
==============================================================================
Tabline Events *ui-tabline*
Only sent if `ext_tabline` option is set in |ui-options|
Activated by the `ext_tabline` |ui-option|.
["tabline_update", curtab, tabs]
Tabline was updated. UIs should present this data in a custom tabline
@@ -597,8 +618,10 @@ Only sent if `ext_tabline` option is set in |ui-options|
==============================================================================
Cmdline Events *ui-cmdline*
Only sent if `ext_cmdline` option is set in |ui-options|. To handle
command-line 'wildmenu', enable |ui-popupmenu| and handle its events.
Activated by the `ext_cmdline` |ui-option|.
This UI extension delegates presentation of the |cmdline| (except 'wildmenu').
For command-line 'wildmenu' UI events, activate |ui-popupmenu|.
["cmdline_show", content, pos, firstc, prompt, indent, level]
content: List of [attrs, string]
@@ -654,47 +677,49 @@ command-line 'wildmenu', enable |ui-popupmenu| and handle its events.
Hide the block.
==============================================================================
Message Events *ui-messages*
Message/Dialog Events *ui-messages*
Only sent if `ext_messages` option is set in |ui-options|. This option
implicitly enables `ext_linegrid` and `ext_cmdline`. |ui-linegrid| and
|ui-cmdline| events will thus also be sent.
Activated by the `ext_messages` |ui-option|.
Activates |ui-linegrid| and |ui-cmdline| implicitly.
This extension allows the UI to control the display of messages that otherwise
would have been displayed in the message/cmdline area in the bottom of the
screen.
This UI extension delegates presentation of messages and dialogs. Messages
that would otherwise render in the message/cmdline screen space, are emitted
as UI events.
Activating this extension means that Nvim will not allocate screen space for
the cmdline or messages, 'cmdheight' will be zero. Attempting to change
'cmdheight' will be silently ignored. |ui-cmdline| events represent the state
of the cmdline.
Nvim will not allocate screen space for the cmdline or messages, and
'cmdheight' will be forced zero. Cmdline state is emitted as |ui-cmdline|
events, which the UI must handle.
["msg_show", kind, content, replace_last]
Display a message to the user.
`kind` will be one of the following
`emsg`: Internal error message
`echo`: temporary message from plugin (|:echo|)
`echomsg`: ordinary message from plugin (|:echomsg|)
`echoerr`: error message from plugin (|:echoerr|)
`return_prompt`: |press-enter| prompt after a group of messages
`quickfix`: Quickfix navigation message
`kind` can also be the empty string. The message is then some internal
informative or warning message, that hasn't yet been assigned a kind.
New message kinds can be added in later versions; clients should
handle messages of an unknown kind just like empty kind.
kind
Name indicating the message kind:
"" (empty) Unknown, report a |feature-request|
"confirm" |confirm()| or |:confirm| dialog
"confirm_sub" |:substitute| confirm dialog |:s_c|
"emsg" Error (|errors|, internal error, |:throw|, …)
"echo" |:echo| message
"echomsg" |:echomsg| message
"echoerr" |:echoerr| message
"return_prompt" |press-enter| prompt after a multiple messages
"quickfix" Quickfix navigation message
"wmsg" Warning ("search hit BOTTOM", |W10|, …)
New kinds may be added in the future; clients should treat unknown
kinds as the empty kind.
`content` will be an array of `[attr_id, text_chunk]` tuples,
building up the message text of chunks of different highlights.
No extra spacing should be added between chunks, the `text_chunk` by
itself should contain any necessary whitespace. Messages can contain
line breaks `"\n"`.
content
Array of `[attr_id, text_chunk]` tuples, building up the message
text of chunks of different highlights. No extra spacing should be
added between chunks, the `text_chunk` by itself contains any
necessary whitespace. Messages can contain line breaks "\n".
`replace_last` controls how multiple messages should be displayed.
If `replace_last` is false, this message should be displayed together
with all previous messages that are still visible. If `replace_last`
is true, this message should replace the message in the most recent
`msg_show` call, but any other visible message should still remain.
replace_last
Decides how multiple messages should be displayed:
false: Display the message together with all previous messages
that are still visible.
true: Replace the message in the most-recent `msg_show` call,
but any other visible message should still remain.
["msg_clear"]
Clear all messages currently displayed by "msg_show". (Messages sent

View File

@@ -89,7 +89,7 @@ void remote_ui_wait_for_attach(void)
/// @param channel_id
/// @param width Requested screen columns
/// @param height Requested screen rows
/// @param options |ui-options| map
/// @param options |ui-option| map
/// @param[out] err Error details, if any
void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
Dictionary options, Error *err)

View File

@@ -2048,10 +2048,10 @@ Dictionary nvim__stats(void)
/// Gets a list of dictionaries representing attached UIs.
///
/// @return Array of UI dictionaries, each with these keys:
/// - "height" requested height of the UI
/// - "width" requested width of the UI
/// - "height" Requested height of the UI
/// - "width" Requested width of the UI
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-options|
/// - "ext_..." Requested UI extensions, see |ui-option|
/// - "chan" Channel id of remote UI (not present for TUI)
Array nvim_list_uis(void)
FUNC_API_SINCE(4)

View File

@@ -3692,10 +3692,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
i = msg_scroll;
msg_scroll = 0; /* truncate msg when
needed */
msg_no_more = TRUE;
/* write message same highlighting as for
* wait_return */
smsg_attr(HL_ATTR(HLF_R),
msg_no_more = true;
msg_ext_set_kind("confirm_sub");
smsg_attr(HL_ATTR(HLF_R), // Same highlight as wait_return().
_("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
msg_no_more = FALSE;
msg_scroll = i;

View File

@@ -839,9 +839,10 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
sourcing_lnum = current_exception->throw_lnum;
current_exception->throw_name = NULL;
discard_current_exception(); /* uses IObuff if 'verbose' */
suppress_errthrow = TRUE;
force_abort = TRUE;
discard_current_exception(); // uses IObuff if 'verbose'
suppress_errthrow = true;
force_abort = true;
msg_ext_set_kind("emsg"); // kind=emsg for :throw, exceptions. #9993
if (messages != NULL) {
do {

View File

@@ -3008,6 +3008,8 @@ void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1)
} else {
keep_msg_attr = 0;
}
msg_ext_set_kind("wmsg");
if (msg_attr((const char *)message, keep_msg_attr) && msg_scrolled == 0) {
set_keep_msg(message, keep_msg_attr);
}
@@ -3348,6 +3350,7 @@ void display_confirm_msg(void)
// Avoid that 'q' at the more prompt truncates the message here.
confirm_msg_used++;
if (confirm_msg != NULL) {
msg_ext_set_kind("confirm");
msg_puts_attr((const char *)confirm_msg, HL_ATTR(HLF_M));
}
confirm_msg_used--;

View File

@@ -2248,6 +2248,7 @@ change_warning (
if (msg_row == Rows - 1)
msg_col = col;
msg_source(HL_ATTR(HLF_W));
msg_ext_set_kind("wmsg");
MSG_PUTS_ATTR(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST);
set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1);
msg_clr_eos();

View File

@@ -277,7 +277,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
// Enums need a typecast to be used as array index (for Ultrix).
#define HL_ATTR(n) highlight_attr[(int)(n)]
#define TERM_STR(n) term_strings[(int)(n)]
/// Maximum number of bytes in a multi-byte character. It can be one 32-bit
/// character of up to 6 bytes, or one 16-bit character of up to three bytes

View File

@@ -22,8 +22,129 @@ describe('ui/ext_messages', function()
[6] = {bold = true, reverse = true},
})
end)
after_each(function()
os.remove('Xtest')
end)
it('supports :echoerr', function()
it('msg_show kind=confirm,confirm_sub,emsg,wmsg', function()
feed('iline 1\nline 2<esc>')
-- kind=confirm
feed(':echo confirm("test")<cr>')
screen:expect{grid=[[
line 1 |
line ^2 |
{1:~ }|
{1:~ }|
{1:~ }|
]], messages={ {
content = {{"\ntest\n[O]k: ", 4}},
kind = 'confirm',
}}}
feed('<cr><cr>')
screen:expect{grid=[[
line 1 |
line ^2 |
{1:~ }|
{1:~ }|
{1:~ }|
]], messages={ {
content = { { "\ntest\n[O]k: ", 4 } },
kind = "confirm"
}, {
content = { { "1" } },
kind = "echo"
}, {
content = { { "Press ENTER or type command to continue", 4 } },
kind = "return_prompt"
} }}
feed('<cr><cr>')
-- kind=confirm_sub
feed(':%s/i/X/gc<cr>')
screen:expect{grid=[[
l{7:i}ne 1 |
l{8:i}ne ^2 |
{1:~ }|
{1:~ }|
{1:~ }|
]], attr_ids={
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[3] = {bold = true},
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
[5] = {foreground = Screen.colors.Blue1},
[6] = {bold = true, reverse = true},
[7] = {reverse = true},
[8] = {background = Screen.colors.Yellow},
}, messages={ {
content = { { "replace with X (y/n/a/q/l/^E/^Y)?", 4 } },
kind = "confirm_sub"
} }}
feed('nq')
-- kind=wmsg (editing readonly file)
command('write Xtest')
command('set readonly nohls')
feed('G$x')
screen:expect{grid=[[
line 1 |
{IGNORE}|
{1:~ }|
{1:~ }|
{1:~ }|
]], attr_ids={
[1] = {bold = true, foreground = Screen.colors.Blue1},
[7] = {foreground = Screen.colors.Red},
}, messages={ {
content = { { "W10: Warning: Changing a readonly file", 7 } },
kind = "wmsg"
}
}}
-- kind=wmsg ('wrapscan' after search reaches EOF)
feed('uG$/i<cr>')
screen:expect{grid=[[
l^ine 1 |
line 2 |
{1:~ }|
{1:~ }|
{1:~ }|
]], attr_ids={
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[3] = {bold = true},
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
[5] = {foreground = Screen.colors.Blue1},
[6] = {bold = true, reverse = true},
[7] = {foreground = Screen.colors.Red},
}, messages={ {
content = { { "search hit BOTTOM, continuing at TOP", 7 } },
kind = "wmsg"
} }}
-- kind=emsg after :throw
feed(':throw "foo"<cr>')
screen:expect{grid=[[
l^ine 1 |
line 2 |
{1:~ }|
{1:~ }|
{1:~ }|
]], messages={ {
content = { { "Error detected while processing :", 2 } },
kind = "emsg"
}, {
content = { { "E605: Exception not caught: foo", 2 } },
kind = ""
}, {
content = { { "Press ENTER or type command to continue", 4 } },
kind = "return_prompt"
} }
}
end)
it(':echoerr', function()
feed(':echoerr "raa"<cr>')
screen:expect{grid=[[
^ |
@@ -142,7 +263,7 @@ describe('ui/ext_messages', function()
}}
end)
it('supports showmode', function()
it('&showmode', function()
command('imap <f2> <cmd>echomsg "stuff"<cr>')
feed('i')
screen:expect{grid=[[
@@ -230,7 +351,7 @@ describe('ui/ext_messages', function()
}}
end)
it('supports showmode with recording message', function()
it('&showmode with macro-recording message', function()
feed('qq')
screen:expect{grid=[[
^ |
@@ -268,7 +389,7 @@ describe('ui/ext_messages', function()
]])
end)
it('shows recording message with noshowmode', function()
it('shows macro-recording message with &noshowmode', function()
command("set noshowmode")
feed('qq')
-- also check mode to avoid immediate success
@@ -308,7 +429,7 @@ describe('ui/ext_messages', function()
]], mode="normal"}
end)
it('supports showcmd and ruler', function()
it('supports &showcmd and &ruler', function()
command('set showcmd ruler')
screen:expect{grid=[[
^ |

View File

@@ -74,6 +74,7 @@
local global_helpers = require('test.helpers')
local deepcopy = global_helpers.deepcopy
local shallowcopy = global_helpers.shallowcopy
local concat_tables = global_helpers.concat_tables
local helpers = require('test.functional.helpers')(nil)
local request, run_session = helpers.request, helpers.run_session
local eq = helpers.eq
@@ -413,26 +414,23 @@ screen:redraw_debug() to show all intermediate screen states. ]])
end
end
-- Extension features. The default expectations should cover the case of
-- UI extensions. The default expectations should cover the case of
-- the ext_ feature being disabled, or the feature currently not activated
-- (for instance no external cmdline visible). Some extensions require
-- (e.g. no external cmdline visible). Some extensions require
-- preprocessing to represent highlights in a reproducible way.
local extstate = self:_extstate_repr(attr_state)
-- convert assertion errors into invalid screen state descriptions
local status, res = pcall(function()
for _, k in ipairs(ext_keys) do
-- Empty states is considered the default and need not be mentioned
if not (expected[k] == nil and isempty(extstate[k])) then
eq(expected[k], extstate[k], k)
if expected['mode'] ~= nil then
extstate['mode'] = self.mode
end
-- Convert assertion errors into invalid screen state descriptions.
for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do
-- Empty states are considered the default and need not be mentioned.
if (not (expected[k] == nil and isempty(extstate[k]))) then
local status, res = pcall(eq, expected[k], extstate[k], k)
if not status then
return (tostring(res)..'\nHint: full state of "'..k..'":\n '..inspect(extstate[k]))
end
end
if expected.mode ~= nil then
eq(expected.mode, self.mode, "mode")
end
end)
if not status then
return tostring(res)
end
end, expected)
end