diff options
-rw-r--r-- | runtime/doc/starting.txt | 2 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 113 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 29 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 2 | ||||
-rw-r--r-- | src/nvim/syntax.c | 2 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 2 | ||||
-rw-r--r-- | src/nvim/ui.h | 4 | ||||
-rw-r--r-- | test/functional/api/version_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/terminal/tui_spec.lua | 8 | ||||
-rw-r--r-- | test/functional/ui/cmdline_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/ui/embed_spec.lua | 8 | ||||
-rw-r--r-- | test/functional/ui/options_spec.lua | 10 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 33 | ||||
-rw-r--r-- | test/functional/ui/screen_basic_spec.lua | 4 |
15 files changed, 148 insertions, 79 deletions
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index dd9f9ad0f3..34c4db4047 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -358,6 +358,8 @@ argument. instance a `nvim_get_api_info` call so that UI features can be safely detected by the UI before attaching. + See |ui-startup| for more information about UI startup. + To embed nvim without using the UI protocol, `--headless` should be supplied together with `--embed`. Then initialization is performed without waiting for an UI. This is also equivalent diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 42ce7a5edf..a0f1b0770e 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -16,10 +16,12 @@ 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. *ui-rgb* Set true (default) for 24-bit RGB colors. @@ -29,7 +31,7 @@ a dictionary with these (optional) keys: `ext_tabline` Externalize the tabline. |ui-tabline| `ext_cmdline` Externalize the cmdline. |ui-cmdline| `ext_wildmenu` Externalize the wildmenu. |ui-wildmenu| - `ext_newgrid` Use new revision of the grid events. |ui-newgrid| + `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| @@ -43,22 +45,26 @@ 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). +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-newgrid|, enabled by -`ext_newgrid` option, has some improvements, such as a more efficient -representation of highlighted text, simplified events 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-newgrid|, as further protocol extensions will require it. +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 @@ -69,8 +75,44 @@ 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. @@ -144,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. @@ -161,16 +203,24 @@ 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 (new revision) *ui-newgrid* +Grid Events (line-based) *ui-linegrid* -These events are used if `ext_newgrid` option is set (recommended for all new -UIs). +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_newgrid` -option by itself will never cause any additional grids to be created. +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. @@ -299,10 +349,10 @@ numerical highlight `id`:s to the actual attributes. from `set_scroll_region` which was end-inclusive. ============================================================================== -Grid Events (first revision) *ui-grid-old* +Legacy Grid Events (cell based) *ui-grid-old* -This is an older representation of the screen grid, used if `ext_newgrid` -option is not set. +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. @@ -389,9 +439,8 @@ option is not set. ============================================================================== Detailed highlight state Extension *ui-hlstate* - Only sent if `ext_hlstate` option is set in |ui-options|. `ext_hlstate` implies -`ext_newgrid`. +`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|. diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index b49de7abf3..01f8c9f71c 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -127,7 +127,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, } if (ui->ui_ext[kUIHlState]) { - ui->ui_ext[kUINewgrid] = true; + ui->ui_ext[kUILinegrid] = true; } UIData *data = xmalloc(sizeof(UIData)); @@ -227,11 +227,11 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, return; } bool boolval = value.data.boolean; - if (!init && i == kUINewgrid && boolval != ui->ui_ext[i]) { + if (!init && i == kUILinegrid && boolval != ui->ui_ext[i]) { // There shouldn't be a reason for an UI to do this ever // so explicitly don't support this. api_set_error(error, kErrorTypeValidation, - "ext_newgrid option cannot be changed"); + "ext_linegrid option cannot be changed"); } ui->ui_ext[i] = boolval; if (!init) { @@ -271,10 +271,10 @@ static void push_call(UI *ui, const char *name, Array args) static void remote_ui_grid_clear(UI *ui, Integer grid) { Array args = ARRAY_DICT_INIT; - if (ui->ui_ext[kUINewgrid]) { + if (ui->ui_ext[kUILinegrid]) { ADD(args, INTEGER_OBJ(grid)); } - const char *name = ui->ui_ext[kUINewgrid] ? "grid_clear" : "clear"; + const char *name = ui->ui_ext[kUILinegrid] ? "grid_clear" : "clear"; push_call(ui, name, args); } @@ -282,12 +282,12 @@ static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) { Array args = ARRAY_DICT_INIT; - if (ui->ui_ext[kUINewgrid]) { + if (ui->ui_ext[kUILinegrid]) { ADD(args, INTEGER_OBJ(grid)); } ADD(args, INTEGER_OBJ(width)); ADD(args, INTEGER_OBJ(height)); - const char *name = ui->ui_ext[kUINewgrid] ? "grid_resize" : "resize"; + const char *name = ui->ui_ext[kUILinegrid] ? "grid_resize" : "resize"; push_call(ui, name, args); } @@ -295,7 +295,7 @@ static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows, Integer cols) { - if (ui->ui_ext[kUINewgrid]) { + if (ui->ui_ext[kUILinegrid]) { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(grid)); ADD(args, INTEGER_OBJ(top)); @@ -341,7 +341,7 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, push_call(ui, "default_colors_set", args); // Deprecated - if (!ui->ui_ext[kUINewgrid]) { + if (!ui->ui_ext[kUILinegrid]) { args = (Array)ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(ui->rgb ? rgb_fg : cterm_fg - 1)); push_call(ui, "update_fg", args); @@ -359,7 +359,7 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, Array info) { - if (!ui->ui_ext[kUINewgrid]) { + if (!ui->ui_ext[kUILinegrid]) { return; } Array args = ARRAY_DICT_INIT; @@ -397,7 +397,7 @@ static void remote_ui_highlight_set(UI *ui, int id) static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col) { - if (ui->ui_ext[kUINewgrid]) { + if (ui->ui_ext[kUILinegrid]) { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(grid)); ADD(args, INTEGER_OBJ(row)); @@ -442,7 +442,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, const sattr_T *attrs) { UIData *data = ui->data; - if (ui->ui_ext[kUINewgrid]) { + if (ui->ui_ext[kUILinegrid]) { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(grid)); ADD(args, INTEGER_OBJ(row)); @@ -508,9 +508,10 @@ static void remote_ui_flush(UI *ui) { UIData *data = ui->data; if (data->buffer.size > 0) { - if (!ui->ui_ext[kUINewgrid]) { + if (!ui->ui_ext[kUILinegrid]) { remote_ui_cursor_goto(ui, data->cursor_row, data->cursor_col); } + push_call(ui, "flush", (Array)ARRAY_DICT_INIT); rpc_send_event(data->channel_id, "redraw", data->buffer); data->buffer = (Array)ARRAY_DICT_INIT; } @@ -549,7 +550,7 @@ static Array translate_firstarg(UI *ui, Array args) static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed) { - if (!ui->ui_ext[kUINewgrid]) { + if (!ui->ui_ext[kUILinegrid]) { // the representation of highlights in cmdline changed, translate back // never consumes args if (strequal(name, "cmdline_show")) { diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 456ad0c8cc..9ddf788376 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -63,7 +63,7 @@ void set_scroll_region(Integer top, Integer bot, Integer left, Integer right) void scroll(Integer count) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -// Second revison of the grid protocol, used with ext_newgrid ui option +// Second revison of the grid protocol, used with ext_linegrid ui option void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, Integer cterm_fg, Integer cterm_bg) FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL; diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 4c054dc8e0..e0e1897b88 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6884,7 +6884,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) // "fg", which have been changed now. highlight_attr_set_all(); - if (!ui_is_external(kUINewgrid) && starting == 0) { + if (!ui_is_external(kUILinegrid) && starting == 0) { // Older UIs assume that we clear the screen after normal group is // changed ui_refresh(); diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 575932c7da..bc7d2ca42a 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -156,7 +156,7 @@ UI *tui_start(void) ui->raw_line = tui_raw_line; memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); - ui->ui_ext[kUINewgrid] = true; + ui->ui_ext[kUILinegrid] = true; return ui_bridge_attach(ui, tui_main, tui_scheduler); } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index df489f569f..d89ad60ce7 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -15,7 +15,7 @@ typedef enum { kUITabline, kUIWildmenu, #define kUIGlobalCount (kUIWildmenu+1) - kUINewgrid, + kUILinegrid, kUIHlState, kUIExtCount, } UIExtension; @@ -25,7 +25,7 @@ EXTERN const char *ui_ext_names[] INIT(= { "ext_popupmenu", "ext_tabline", "ext_wildmenu", - "ext_newgrid", + "ext_linegrid", "ext_hlstate", }); diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index e0472977cc..c3b332c8e7 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -156,6 +156,6 @@ describe("ui_options in metadata", function() local api = helpers.call('api_info') local options = api.ui_options eq({'rgb', 'ext_cmdline', 'ext_popupmenu', - 'ext_tabline', 'ext_wildmenu', 'ext_newgrid', 'ext_hlstate'}, options) + 'ext_tabline', 'ext_wildmenu', 'ext_linegrid', 'ext_hlstate'}, options) end) end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5261f57ca7..5ca133267d 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1254,7 +1254,7 @@ describe('API', function() ext_popupmenu = false, ext_tabline = false, ext_wildmenu = false, - ext_newgrid = screen._options.ext_newgrid or false, + ext_linegrid = screen._options.ext_linegrid or false, ext_hlstate=false, height = 4, rgb = true, diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 351038e521..09f80ca849 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -258,10 +258,10 @@ describe('tui', function() feed_data(':echo map(nvim_list_uis(), {k,v -> sort(items(v))})\013') screen:expect([=[ [[['ext_cmdline', v:false], ['ext_hlstate', v:fals| - e], ['ext_newgrid', v:true], ['ext_popupmenu', v:f| - alse], ['ext_tabline', v:false], ['ext_wildmenu', | - v:false], ['height', 6], ['rgb', v:false], ['width| - ', 50]]] | + e], ['ext_linegrid', v:true], ['ext_popupmenu', v:| + false], ['ext_tabline', v:false], ['ext_wildmenu',| + v:false], ['height', 6], ['rgb', v:false], ['widt| + h', 50]]] | {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | ]=]) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index d39b24a00f..af26a6d88f 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -4,13 +4,13 @@ local clear, feed = helpers.clear, helpers.feed local source = helpers.source local command = helpers.command -local function test_cmdline(newgrid) +local function test_cmdline(linegrid) local screen before_each(function() clear() screen = Screen.new(25, 5) - screen:attach({rgb=true, ext_cmdline=true, ext_newgrid=newgrid}) + screen:attach({rgb=true, ext_cmdline=true, ext_linegrid=linegrid}) screen:set_default_attr_ids({ [1] = {bold = true, foreground = Screen.colors.Blue1}, [2] = {reverse = true}, @@ -608,7 +608,7 @@ local function test_cmdline(newgrid) end) end --- the representation of cmdline and cmdline_block contents changed with ext_newgrid +-- the representation of cmdline and cmdline_block contents changed with ext_linegrid -- (which uses indexed highlights) so make sure to test both describe('ui/ext_cmdline', function() test_cmdline(true) end) describe('ui/ext_cmdline (legacy highlights)', function() test_cmdline(false) end) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index 6a5227803d..4fc93c3b63 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -5,14 +5,14 @@ local feed = helpers.feed local eq = helpers.eq local clear = helpers.clear -local function test_embed(ext_newgrid) +local function test_embed(ext_linegrid) local screen local function startup(...) clear{headless=false, args={...}} -- attach immediately after startup, for early UI screen = Screen.new(60, 8) - screen:attach{ext_newgrid=ext_newgrid} + screen:attach{ext_linegrid=ext_linegrid} screen:set_default_attr_ids({ [1] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [2] = {bold = true, foreground = Screen.colors.SeaGreen4}, @@ -77,5 +77,5 @@ local function test_embed(ext_newgrid) end) end -describe('--embed UI on startup (ext_newgrid=true)', function() test_embed(true) end) -describe('--embed UI on startup (ext_newgrid=false)', function() test_embed(false) end) +describe('--embed UI on startup (ext_linegrid=true)', function() test_embed(true) end) +describe('--embed UI on startup (ext_linegrid=false)', function() test_embed(false) end) diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 322a94763f..99aae16183 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -30,15 +30,15 @@ describe('ui receives option updates', function() ext_popupmenu=false, ext_tabline=false, ext_wildmenu=false, - ext_newgrid=false, + ext_linegrid=false, ext_hlstate=false, } it("for defaults", function() screen:attach() - -- NB: UI test suite can be run in both "newgrid" and legacy grid mode. + -- NB: UI test suite can be run in both "linegrid" and legacy grid mode. -- In both cases check that the received value is the one requested. - defaults.ext_newgrid = screen._options.ext_newgrid or false + defaults.ext_linegrid = screen._options.ext_linegrid or false screen:expect(function() eq(defaults, screen.options) end) @@ -46,7 +46,7 @@ describe('ui receives option updates', function() it("when setting options", function() screen:attach() - defaults.ext_newgrid = screen._options.ext_newgrid or false + defaults.ext_linegrid = screen._options.ext_linegrid or false local changed = {} for k,v in pairs(defaults) do changed[k] = v @@ -95,7 +95,7 @@ describe('ui receives option updates', function() end screen:attach({ext_cmdline=true, ext_wildmenu=true}) - defaults.ext_newgrid = screen._options.ext_newgrid or false + defaults.ext_linegrid = screen._options.ext_linegrid or false changed.ext_cmdline = true changed.ext_wildmenu = true screen:expect(function() diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 3831968f5b..691bf9f64c 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -185,11 +185,11 @@ function Screen:attach(options) if options == nil then options = {} end - if options.ext_newgrid == nil then - options.ext_newgrid = true + if options.ext_linegrid == nil then + options.ext_linegrid = true end self._options = options - self._clear_attrs = (options.ext_newgrid and {{},{}}) or {} + self._clear_attrs = (options.ext_linegrid and {{},{}}) or {} uimeths.attach(self._width, self._height, options) if self._options.rgb == nil then -- nvim defaults to rgb=true internally, @@ -386,9 +386,13 @@ function Screen:wait(check, timeout) local err, checked = false local success_seen = false local failure_after_success = false + local did_flush = true local function notification_cb(method, args) assert(method == 'redraw') - self:_redraw(args) + did_flush = self:_redraw(args) + if not did_flush then + return + end err = check() checked = true if not err then @@ -402,7 +406,9 @@ function Screen:wait(check, timeout) return true end run(nil, notification_cb, nil, timeout or self.timeout) - if not checked then + if not did_flush then + err = "no flush received" + elseif not checked then err = check() end @@ -431,7 +437,8 @@ function Screen:sleep(ms) end function Screen:_redraw(updates) - for _, update in ipairs(updates) do + local did_flush = false + for k, update in ipairs(updates) do -- print('--') -- print(require('inspect')(update)) local method = update[1] @@ -446,7 +453,11 @@ function Screen:_redraw(updates) self._on_event(method, update[i]) end end + if k == #updates and method == "flush" then + did_flush = true + end end + return did_flush end function Screen:set_on_event_handler(callback) @@ -472,6 +483,10 @@ function Screen:_handle_resize(width, height) } end +function Screen:_handle_flush() +end + + function Screen:_handle_grid_resize(grid, width, height) assert(grid == 1) self:_handle_resize(width, height) @@ -609,6 +624,7 @@ function Screen:_handle_highlight_set(attrs) end function Screen:_handle_put(str) + assert(not self._options.ext_linegrid) local cell = self._rows[self._cursor.row][self._cursor.col] cell.text = str cell.attrs = self._attrs @@ -617,6 +633,7 @@ function Screen:_handle_put(str) end function Screen:_handle_grid_line(grid, row, col, items) + assert(self._options.ext_linegrid) assert(grid == 1) local line = self._rows[row+1] local colpos = col+1 @@ -764,7 +781,7 @@ function Screen:_row_repr(row, attr_state) local current_attr_id for i = 1, self._width do local attrs = row[i].attrs - if self._options.ext_newgrid then + if self._options.ext_linegrid then attrs = attrs[(self._options.rgb and 1) or 2] end local attr_id = self:_get_attr_id(attr_state, attrs, row[i].hl_id) @@ -820,7 +837,7 @@ function Screen:_chunks_repr(chunks, attr_state) for i, chunk in ipairs(chunks) do local hl, text = unpack(chunk) local attrs - if self._options.ext_newgrid then + if self._options.ext_linegrid then attrs = self._attr_table[hl][1] else attrs = hl diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 957d8c0915..31825bdbf4 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -48,13 +48,13 @@ describe('screen', function() end) end) -local function screen_tests(newgrid) +local function screen_tests(linegrid) local screen before_each(function() clear() screen = Screen.new() - screen:attach({rgb=true,ext_newgrid=newgrid}) + screen:attach({rgb=true,ext_linegrid=linegrid}) screen:set_default_attr_ids( { [0] = {bold=true, foreground=255}, [1] = {bold=true, reverse=true}, |