mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge #28101 nvim__redraw
This commit is contained in:
		| @@ -1566,6 +1566,35 @@ nvim__invalidate_glyph_cache()                *nvim__invalidate_glyph_cache()* | |||||||
|     For testing. The condition in schar_cache_clear_if_full is hard to reach, |     For testing. The condition in schar_cache_clear_if_full is hard to reach, | ||||||
|     so this function can be used to force a cache clear in a test. |     so this function can be used to force a cache clear in a test. | ||||||
|  |  | ||||||
|  | nvim__redraw({opts})                                          *nvim__redraw()* | ||||||
|  |     EXPERIMENTAL: this API may change in the future. | ||||||
|  |  | ||||||
|  |     Instruct Nvim to redraw various components. | ||||||
|  |  | ||||||
|  |     Parameters: ~ | ||||||
|  |       • {opts}  Optional parameters. | ||||||
|  |                 • win: Target a specific |window-ID| as described below. | ||||||
|  |                 • buf: Target a specific buffer number as described below. | ||||||
|  |                 • flush: Update the screen with pending updates. | ||||||
|  |                 • valid: When present mark `win`, `buf`, or all windows for | ||||||
|  |                   redraw. When `true`, only redraw changed lines (useful for | ||||||
|  |                   decoration providers). When `false`, forcefully redraw. | ||||||
|  |                 • range: Redraw a range in `buf`, the buffer in `win` or the | ||||||
|  |                   current buffer (useful for decoration providers). Expects a | ||||||
|  |                   tuple `[first, last]` with the first and last line number of | ||||||
|  |                   the range, 0-based end-exclusive |api-indexing|. | ||||||
|  |                 • cursor: Immediately update cursor position on the screen in | ||||||
|  |                   `win` or the current window. | ||||||
|  |                 • statuscolumn: Redraw the 'statuscolumn' in `buf`, `win` or | ||||||
|  |                   all windows. | ||||||
|  |                 • statusline: Redraw the 'statusline' in `buf`, `win` or all | ||||||
|  |                   windows. | ||||||
|  |                 • winbar: Redraw the 'winbar' in `buf`, `win` or all windows. | ||||||
|  |                 • tabline: Redraw the 'tabline'. | ||||||
|  |  | ||||||
|  |     See also: ~ | ||||||
|  |       • |:redraw| | ||||||
|  |  | ||||||
| nvim__stats()                                                  *nvim__stats()* | nvim__stats()                                                  *nvim__stats()* | ||||||
|     Gets internal stats. |     Gets internal stats. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ Various commands					*various* | |||||||
| 							*CTRL-L* | 							*CTRL-L* | ||||||
| CTRL-L			Clears and redraws the screen.  The redraw may happen | CTRL-L			Clears and redraws the screen.  The redraw may happen | ||||||
| 			later, after processing typeahead. | 			later, after processing typeahead. | ||||||
|  | 			See also |nvim__redraw()|. | ||||||
| 							*CTRL-L-default* | 							*CTRL-L-default* | ||||||
| 			By default, also clears search highlighting | 			By default, also clears search highlighting | ||||||
| 			|:nohlsearch| and updates diffs |:diffupdate|. | 			|:nohlsearch| and updates diffs |:diffupdate|. | ||||||
| @@ -21,6 +22,7 @@ CTRL-L			Clears and redraws the screen.  The redraw may happen | |||||||
|  |  | ||||||
| 							*:mod* *:mode* | 							*:mod* *:mode* | ||||||
| :mod[e]			Clears and redraws the screen. | :mod[e]			Clears and redraws the screen. | ||||||
|  | 			See also |nvim__redraw()|. | ||||||
|  |  | ||||||
| 							*:redr* *:redraw* | 							*:redr* *:redraw* | ||||||
| :redr[aw][!]		Redraws pending screen updates now, or the entire | :redr[aw][!]		Redraws pending screen updates now, or the entire | ||||||
| @@ -28,6 +30,7 @@ CTRL-L			Clears and redraws the screen.  The redraw may happen | |||||||
| 			|:mode| or |CTRL-L|. | 			|:mode| or |CTRL-L|. | ||||||
| 			Useful to update the screen during a script or | 			Useful to update the screen during a script or | ||||||
| 			function (or a mapping if 'lazyredraw' set). | 			function (or a mapping if 'lazyredraw' set). | ||||||
|  | 			See also |nvim__redraw()|. | ||||||
|  |  | ||||||
| 						*:redraws* *:redrawstatus* | 						*:redraws* *:redrawstatus* | ||||||
| :redraws[tatus][!]	Redraws the status line and window bar of the current | :redraws[tatus][!]	Redraws the status line and window bar of the current | ||||||
| @@ -35,11 +38,12 @@ CTRL-L			Clears and redraws the screen.  The redraw may happen | |||||||
| 			included. Redraws the commandline instead if it contains | 			included. Redraws the commandline instead if it contains | ||||||
| 			the 'ruler'. Useful if 'statusline' or 'winbar' includes | 			the 'ruler'. Useful if 'statusline' or 'winbar' includes | ||||||
| 			an item that doesn't cause automatic updating. | 			an item that doesn't cause automatic updating. | ||||||
|  | 			See also |nvim__redraw()|. | ||||||
|  |  | ||||||
| 						*:redrawt* *:redrawtabline* | 						*:redrawt* *:redrawtabline* | ||||||
| :redrawt[abline]	Redraw the tabline.  Useful to update the tabline when | :redrawt[abline]	Redraw the tabline.  Useful to update the tabline when | ||||||
| 			'tabline' includes an item that doesn't trigger | 			'tabline' includes an item that doesn't trigger | ||||||
| 			automatic updating. | 			automatic updating. See also |nvim__redraw()|. | ||||||
|  |  | ||||||
| 							*N<Del>* | 							*N<Del>* | ||||||
| <Del>			When entering a number: Remove the last digit. | <Del>			When entering a number: Remove the last digit. | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								runtime/lua/vim/_meta/api.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								runtime/lua/vim/_meta/api.lua
									
									
									
										generated
									
									
									
								
							| @@ -12,12 +12,6 @@ vim.api = {} | |||||||
| --- @return string | --- @return string | ||||||
| function vim.api.nvim__buf_debug_extmarks(buffer, keys, dot) end | function vim.api.nvim__buf_debug_extmarks(buffer, keys, dot) end | ||||||
|  |  | ||||||
| --- @private |  | ||||||
| --- @param buffer integer |  | ||||||
| --- @param first integer |  | ||||||
| --- @param last integer |  | ||||||
| function vim.api.nvim__buf_redraw_range(buffer, first, last) end |  | ||||||
|  |  | ||||||
| --- @private | --- @private | ||||||
| --- @param buffer integer | --- @param buffer integer | ||||||
| --- @return table<string,any> | --- @return table<string,any> | ||||||
| @@ -105,6 +99,32 @@ function vim.api.nvim__inspect_cell(grid, row, col) end | |||||||
| --- | --- | ||||||
| function vim.api.nvim__invalidate_glyph_cache() end | function vim.api.nvim__invalidate_glyph_cache() end | ||||||
|  |  | ||||||
|  | --- @private | ||||||
|  | --- EXPERIMENTAL: this API may change in the future. | ||||||
|  | --- | ||||||
|  | --- Instruct Nvim to redraw various components. | ||||||
|  | --- | ||||||
|  | --- @param opts vim.api.keyset.redraw Optional parameters. | ||||||
|  | ---             • win: Target a specific `window-ID` as described below. | ||||||
|  | ---             • buf: Target a specific buffer number as described below. | ||||||
|  | ---             • flush: Update the screen with pending updates. | ||||||
|  | ---             • valid: When present mark `win`, `buf`, or all windows for | ||||||
|  | ---               redraw. When `true`, only redraw changed lines (useful for | ||||||
|  | ---               decoration providers). When `false`, forcefully redraw. | ||||||
|  | ---             • range: Redraw a range in `buf`, the buffer in `win` or the | ||||||
|  | ---               current buffer (useful for decoration providers). Expects a | ||||||
|  | ---               tuple `[first, last]` with the first and last line number of | ||||||
|  | ---               the range, 0-based end-exclusive `api-indexing`. | ||||||
|  | ---             • cursor: Immediately update cursor position on the screen in | ||||||
|  | ---               `win` or the current window. | ||||||
|  | ---             • statuscolumn: Redraw the 'statuscolumn' in `buf`, `win` or | ||||||
|  | ---               all windows. | ||||||
|  | ---             • statusline: Redraw the 'statusline' in `buf`, `win` or all | ||||||
|  | ---               windows. | ||||||
|  | ---             • winbar: Redraw the 'winbar' in `buf`, `win` or all windows. | ||||||
|  | ---             • tabline: Redraw the 'tabline'. | ||||||
|  | function vim.api.nvim__redraw(opts) end | ||||||
|  |  | ||||||
| --- @private | --- @private | ||||||
| --- @return any[] | --- @return any[] | ||||||
| function vim.api.nvim__runtime_inspect() end | function vim.api.nvim__runtime_inspect() end | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								runtime/lua/vim/_meta/api_keysets.lua
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								runtime/lua/vim/_meta/api_keysets.lua
									
									
									
										generated
									
									
									
								
							| @@ -207,6 +207,18 @@ error('Cannot require a meta file') | |||||||
| --- @field buf? integer | --- @field buf? integer | ||||||
| --- @field filetype? string | --- @field filetype? string | ||||||
|  |  | ||||||
|  | --- @class vim.api.keyset.redraw | ||||||
|  | --- @field flush? boolean | ||||||
|  | --- @field cursor? boolean | ||||||
|  | --- @field valid? boolean | ||||||
|  | --- @field statuscolumn? boolean | ||||||
|  | --- @field statusline? boolean | ||||||
|  | --- @field tabline? boolean | ||||||
|  | --- @field winbar? boolean | ||||||
|  | --- @field range? any[] | ||||||
|  | --- @field win? integer | ||||||
|  | --- @field buf? integer | ||||||
|  |  | ||||||
| --- @class vim.api.keyset.runtime | --- @class vim.api.keyset.runtime | ||||||
| --- @field is_lua? boolean | --- @field is_lua? boolean | ||||||
| --- @field do_source? boolean | --- @field do_source? boolean | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ function M.on_inlayhint(err, result, ctx, _) | |||||||
|   if num_unprocessed == 0 then |   if num_unprocessed == 0 then | ||||||
|     client_hints[client_id] = {} |     client_hints[client_id] = {} | ||||||
|     bufstate.version = ctx.version |     bufstate.version = ctx.version | ||||||
|     api.nvim__buf_redraw_range(bufnr, 0, -1) |     api.nvim__redraw({ buf = bufnr, valid = true }) | ||||||
|     return |     return | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -91,7 +91,7 @@ function M.on_inlayhint(err, result, ctx, _) | |||||||
|  |  | ||||||
|   client_hints[client_id] = new_lnum_hints |   client_hints[client_id] = new_lnum_hints | ||||||
|   bufstate.version = ctx.version |   bufstate.version = ctx.version | ||||||
|   api.nvim__buf_redraw_range(bufnr, 0, -1) |   api.nvim__redraw({ buf = bufnr, valid = true }) | ||||||
| end | end | ||||||
|  |  | ||||||
| --- |lsp-handler| for the method `textDocument/inlayHint/refresh` | --- |lsp-handler| for the method `textDocument/inlayHint/refresh` | ||||||
| @@ -224,7 +224,7 @@ local function clear(bufnr) | |||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) |   api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) | ||||||
|   api.nvim__buf_redraw_range(bufnr, 0, -1) |   api.nvim__redraw({ buf = bufnr, valid = true }) | ||||||
| end | end | ||||||
|  |  | ||||||
| --- Disable inlay hints for a buffer | --- Disable inlay hints for a buffer | ||||||
|   | |||||||
| @@ -394,7 +394,7 @@ function STHighlighter:process_response(response, client, version) | |||||||
|   current_result.namespace_cleared = false |   current_result.namespace_cleared = false | ||||||
|  |  | ||||||
|   -- redraw all windows displaying buffer |   -- redraw all windows displaying buffer | ||||||
|   api.nvim__buf_redraw_range(self.bufnr, 0, -1) |   api.nvim__redraw({ buf = self.bufnr, valid = true }) | ||||||
| end | end | ||||||
|  |  | ||||||
| --- on_win handler for the decoration provider (see |nvim_set_decoration_provider|) | --- on_win handler for the decoration provider (see |nvim_set_decoration_provider|) | ||||||
|   | |||||||
| @@ -215,7 +215,7 @@ end | |||||||
| ---@param start_row integer | ---@param start_row integer | ||||||
| ---@param new_end integer | ---@param new_end integer | ||||||
| function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) | function TSHighlighter:on_bytes(_, _, start_row, _, _, _, _, _, new_end) | ||||||
|   api.nvim__buf_redraw_range(self.bufnr, start_row, start_row + new_end + 1) |   api.nvim__redraw({ buf = self.bufnr, range = { start_row, start_row + new_end + 1 } }) | ||||||
| end | end | ||||||
|  |  | ||||||
| ---@package | ---@package | ||||||
| @@ -227,7 +227,7 @@ end | |||||||
| ---@param changes Range6[] | ---@param changes Range6[] | ||||||
| function TSHighlighter:on_changedtree(changes) | function TSHighlighter:on_changedtree(changes) | ||||||
|   for _, ch in ipairs(changes) do |   for _, ch in ipairs(changes) do | ||||||
|     api.nvim__buf_redraw_range(self.bufnr, ch[1], ch[4] + 1) |     api.nvim__redraw({ buf = self.bufnr, range = { ch[1], ch[4] + 1 } }) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -230,20 +230,6 @@ Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err) | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// @nodoc |  | ||||||
| void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err) |  | ||||||
| { |  | ||||||
|   buf_T *buf = find_buffer_by_handle(buffer, err); |  | ||||||
|   if (!buf) { |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|   if (last < 0) { |  | ||||||
|     last = buf->b_ml.ml_line_count; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   redraw_buf_range_later(buf, (linenr_T)first + 1, (linenr_T)last); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Gets a line-range from the buffer. | /// Gets a line-range from the buffer. | ||||||
| /// | /// | ||||||
| /// Indexing is zero-based, end-exclusive. Negative indices are interpreted | /// Indexing is zero-based, end-exclusive. Negative indices are interpreted | ||||||
|   | |||||||
| @@ -373,3 +373,17 @@ typedef struct { | |||||||
|   Boolean ignore_blank_lines; |   Boolean ignore_blank_lines; | ||||||
|   Boolean indent_heuristic; |   Boolean indent_heuristic; | ||||||
| } Dict(xdl_diff); | } Dict(xdl_diff); | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |   OptionalKeys is_set__redraw_; | ||||||
|  |   Boolean flush; | ||||||
|  |   Boolean cursor; | ||||||
|  |   Boolean valid; | ||||||
|  |   Boolean statuscolumn; | ||||||
|  |   Boolean statusline; | ||||||
|  |   Boolean tabline; | ||||||
|  |   Boolean winbar; | ||||||
|  |   Array range; | ||||||
|  |   Window win; | ||||||
|  |   Buffer buf; | ||||||
|  | } Dict(redraw); | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ | |||||||
| #include "nvim/mapping.h" | #include "nvim/mapping.h" | ||||||
| #include "nvim/mark.h" | #include "nvim/mark.h" | ||||||
| #include "nvim/mark_defs.h" | #include "nvim/mark_defs.h" | ||||||
|  | #include "nvim/math.h" | ||||||
| #include "nvim/mbyte.h" | #include "nvim/mbyte.h" | ||||||
| #include "nvim/memline.h" | #include "nvim/memline.h" | ||||||
| #include "nvim/memory.h" | #include "nvim/memory.h" | ||||||
| @@ -2305,3 +2306,158 @@ Dictionary nvim__complete_set(Integer index, Dict(complete_set) *opts, Arena *ar | |||||||
|   } |   } | ||||||
|   return rv; |   return rv; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void redraw_status(win_T *wp, Dict(redraw) *opts, bool *flush) | ||||||
|  | { | ||||||
|  |   if (opts->statuscolumn && *wp->w_p_stc != NUL) { | ||||||
|  |     wp->w_nrwidth_line_count = 0; | ||||||
|  |     changed_window_setting(wp); | ||||||
|  |   } | ||||||
|  |   win_grid_alloc(wp); | ||||||
|  |  | ||||||
|  |   // Flush later in case winbar was just hidden or shown for the first time, or | ||||||
|  |   // statuscolumn is being drawn. | ||||||
|  |   if (wp->w_lines_valid == 0) { | ||||||
|  |     *flush = true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Mark for redraw in case flush will happen, otherwise redraw now. | ||||||
|  |   if (*flush && (opts->statusline || opts->winbar)) { | ||||||
|  |     wp->w_redr_status = true; | ||||||
|  |   } else if (opts->statusline || opts->winbar) { | ||||||
|  |     win_check_ns_hl(wp); | ||||||
|  |     if (opts->winbar) { | ||||||
|  |       win_redr_winbar(wp); | ||||||
|  |     } | ||||||
|  |     if (opts->statusline) { | ||||||
|  |       win_redr_status(wp); | ||||||
|  |     } | ||||||
|  |     win_check_ns_hl(NULL); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// EXPERIMENTAL: this API may change in the future. | ||||||
|  | /// | ||||||
|  | /// Instruct Nvim to redraw various components. | ||||||
|  | /// | ||||||
|  | /// @see |:redraw| | ||||||
|  | /// | ||||||
|  | /// @param opts  Optional parameters. | ||||||
|  | ///               - win: Target a specific |window-ID| as described below. | ||||||
|  | ///               - buf: Target a specific buffer number as described below. | ||||||
|  | ///               - flush: Update the screen with pending updates. | ||||||
|  | ///               - valid: When present mark `win`, `buf`, or all windows for | ||||||
|  | ///                 redraw. When `true`, only redraw changed lines (useful for | ||||||
|  | ///                 decoration providers). When `false`, forcefully redraw. | ||||||
|  | ///               - range: Redraw a range in `buf`, the buffer in `win` or the | ||||||
|  | ///                 current buffer (useful for decoration providers). Expects a | ||||||
|  | ///                 tuple `[first, last]` with the first and last line number | ||||||
|  | ///                 of the range, 0-based end-exclusive |api-indexing|. | ||||||
|  | ///               - cursor: Immediately update cursor position on the screen in | ||||||
|  | ///                 `win` or the current window. | ||||||
|  | ///               - statuscolumn: Redraw the 'statuscolumn' in `buf`, `win` or | ||||||
|  | ///                 all windows. | ||||||
|  | ///               - statusline: Redraw the 'statusline' in `buf`, `win` or all | ||||||
|  | ///                 windows. | ||||||
|  | ///               - winbar: Redraw the 'winbar' in `buf`, `win` or all windows. | ||||||
|  | ///               - tabline: Redraw the 'tabline'. | ||||||
|  | void nvim__redraw(Dict(redraw) *opts, Error *err) | ||||||
|  |   FUNC_API_SINCE(12) | ||||||
|  | { | ||||||
|  |   win_T *win = NULL; | ||||||
|  |   buf_T *buf = NULL; | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts, redraw, win)) { | ||||||
|  |     win = find_window_by_handle(opts->win, err); | ||||||
|  |     if (ERROR_SET(err)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts, redraw, buf)) { | ||||||
|  |     VALIDATE(win == NULL, "%s", "cannot use both 'buf' and 'win'", { | ||||||
|  |       return; | ||||||
|  |     }); | ||||||
|  |     buf = find_buffer_by_handle(opts->buf, err); | ||||||
|  |     if (ERROR_SET(err)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int count = (win != NULL) + (buf != NULL); | ||||||
|  |   VALIDATE(popcount(opts->is_set__redraw_) > count, "%s", "at least one action required", { | ||||||
|  |     return; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts, redraw, valid)) { | ||||||
|  |     // UPD_VALID redraw type does not actually do anything on it's own. Setting | ||||||
|  |     // it here without scrolling or changing buffer text seems pointless but | ||||||
|  |     // the expectation is that this may be called by decoration providers whose | ||||||
|  |     // "on_win" callback may set "w_redr_top/bot". | ||||||
|  |     int type = opts->valid ? UPD_VALID : UPD_NOT_VALID; | ||||||
|  |     if (win != NULL) { | ||||||
|  |       redraw_later(win, type); | ||||||
|  |     } else if (buf != NULL) { | ||||||
|  |       redraw_buf_later(buf, type); | ||||||
|  |     } else { | ||||||
|  |       redraw_all_later(type); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (HAS_KEY(opts, redraw, range)) { | ||||||
|  |     VALIDATE(kv_size(opts->range) == 2 | ||||||
|  |              && kv_A(opts->range, 0).type == kObjectTypeInteger | ||||||
|  |              && kv_A(opts->range, 1).type == kObjectTypeInteger | ||||||
|  |              && kv_A(opts->range, 0).data.integer >= 0 | ||||||
|  |              && kv_A(opts->range, 1).data.integer >= -1, | ||||||
|  |              "%s", "Invalid 'range': Expected 2-tuple of Integers", { | ||||||
|  |       return; | ||||||
|  |     }); | ||||||
|  |     linenr_T first = (linenr_T)kv_A(opts->range, 0).data.integer + 1; | ||||||
|  |     linenr_T last = (linenr_T)kv_A(opts->range, 1).data.integer; | ||||||
|  |     if (last < 0) { | ||||||
|  |       last = buf->b_ml.ml_line_count; | ||||||
|  |     } | ||||||
|  |     redraw_buf_range_later(win ? win->w_buffer : (buf ? buf : curbuf), first, last); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (opts->cursor) { | ||||||
|  |     setcursor_mayforce(win ? win : curwin, true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool flush = opts->flush; | ||||||
|  |   if (opts->tabline) { | ||||||
|  |     // Flush later in case tabline was just hidden or shown for the first time. | ||||||
|  |     if (redraw_tabline && firstwin->w_lines_valid == 0) { | ||||||
|  |       flush = true; | ||||||
|  |     } else { | ||||||
|  |       draw_tabline(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool save_lz = p_lz; | ||||||
|  |   int save_rd = RedrawingDisabled; | ||||||
|  |   RedrawingDisabled = 0; | ||||||
|  |   p_lz = false; | ||||||
|  |   if (opts->statuscolumn || opts->statusline || opts->winbar) { | ||||||
|  |     if (win == NULL) { | ||||||
|  |       FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { | ||||||
|  |         if (buf == NULL || wp->w_buffer == buf) { | ||||||
|  |           redraw_status(wp, opts, &flush); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       redraw_status(win, opts, &flush); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Flush pending screen updates if "flush" or "clear" is true, or when | ||||||
|  |   // redrawing a status component may have changed the grid dimensions. | ||||||
|  |   if (flush && !cmdpreview) { | ||||||
|  |     update_screen(); | ||||||
|  |   } | ||||||
|  |   ui_flush(); | ||||||
|  |  | ||||||
|  |   RedrawingDisabled = save_rd; | ||||||
|  |   p_lz = save_lz; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -821,25 +821,25 @@ static void win_redr_border(win_T *wp) | |||||||
| /// Set cursor to its position in the current window. | /// Set cursor to its position in the current window. | ||||||
| void setcursor(void) | void setcursor(void) | ||||||
| { | { | ||||||
|   setcursor_mayforce(false); |   setcursor_mayforce(curwin, false); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Set cursor to its position in the current window. | /// Set cursor to its position in the current window. | ||||||
| /// @param force  when true, also when not redrawing. | /// @param force  when true, also when not redrawing. | ||||||
| void setcursor_mayforce(bool force) | void setcursor_mayforce(win_T *wp, bool force) | ||||||
| { | { | ||||||
|   if (force || redrawing()) { |   if (force || redrawing()) { | ||||||
|     validate_cursor(curwin); |     validate_cursor(wp); | ||||||
|  |  | ||||||
|     ScreenGrid *grid = &curwin->w_grid; |     ScreenGrid *grid = &wp->w_grid; | ||||||
|     int row = curwin->w_wrow; |     int row = wp->w_wrow; | ||||||
|     int col = curwin->w_wcol; |     int col = wp->w_wcol; | ||||||
|     if (curwin->w_p_rl) { |     if (wp->w_p_rl) { | ||||||
|       // With 'rightleft' set and the cursor on a double-wide character, |       // With 'rightleft' set and the cursor on a double-wide character, | ||||||
|       // position it on the leftmost column. |       // position it on the leftmost column. | ||||||
|       col = curwin->w_width_inner - curwin->w_wcol |       char *cursor = ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) + wp->w_cursor.col; | ||||||
|             - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2 |       col = wp->w_width_inner - wp->w_wcol - ((utf_ptr2cells(cursor) == 2 | ||||||
|                 && vim_isprintc(gchar_cursor())) ? 2 : 1); |                                                && vim_isprintc(utf_ptr2char(cursor))) ? 2 : 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     grid_adjust(&grid, &row, &col); |     grid_adjust(&grid, &row, &col); | ||||||
| @@ -2713,7 +2713,7 @@ void redraw_buf_line_later(buf_T *buf, linenr_T line, bool force) | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void redraw_buf_range_later(buf_T *buf,  linenr_T firstline, linenr_T lastline) | void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline) | ||||||
| { | { | ||||||
|   FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { |   FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { | ||||||
|     if (wp->w_buffer == buf |     if (wp->w_buffer == buf | ||||||
|   | |||||||
| @@ -5886,7 +5886,7 @@ static void ex_equal(exarg_T *eap) | |||||||
| static void ex_sleep(exarg_T *eap) | static void ex_sleep(exarg_T *eap) | ||||||
| { | { | ||||||
|   if (cursor_valid(curwin)) { |   if (cursor_valid(curwin)) { | ||||||
|     setcursor_mayforce(true); |     setcursor_mayforce(curwin, true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int64_t len = eap->line2; |   int64_t len = eap->line2; | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ typedef enum { | |||||||
|   kRetLuaref,  ///< return value becomes a single Luaref, regardless of type (except NIL) |   kRetLuaref,  ///< return value becomes a single Luaref, regardless of type (except NIL) | ||||||
| } LuaRetMode; | } LuaRetMode; | ||||||
|  |  | ||||||
| /// To use with kRetNilBool for quick thuthyness check | /// To use with kRetNilBool for quick truthiness check | ||||||
| #define LUARET_TRUTHY(res) ((res).type == kObjectTypeBoolean && (res).data.boolean == true) | #define LUARET_TRUTHY(res) ((res).type == kObjectTypeBoolean && (res).data.boolean == true) | ||||||
|  |  | ||||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||||
|   | |||||||
| @@ -77,6 +77,23 @@ int xctz(uint64_t x) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Count number of set bits in bit field. | ||||||
|  | int popcount(uint64_t x) | ||||||
|  | { | ||||||
|  |   // Use compiler builtin if possible. | ||||||
|  | #if defined(__clang__) || defined(__GNUC__) | ||||||
|  |   return __builtin_popcountll(x); | ||||||
|  | #else | ||||||
|  |   int count = 0; | ||||||
|  |   for (; x != 0; x >>= 1) { | ||||||
|  |     if (x & 1) { | ||||||
|  |       count++; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return count; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
| /// For overflow detection, add a digit safely to an int value. | /// For overflow detection, add a digit safely to an int value. | ||||||
| int vim_append_digit_int(int *value, int digit) | int vim_append_digit_int(int *value, int digit) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -1281,7 +1281,7 @@ void pum_show_popupmenu(vimmenu_T *menu) | |||||||
|     pum_is_drawn = true; |     pum_is_drawn = true; | ||||||
|     pum_grid.zindex = kZIndexCmdlinePopupMenu;  // show above cmdline area #23275 |     pum_grid.zindex = kZIndexCmdlinePopupMenu;  // show above cmdline area #23275 | ||||||
|     pum_redraw(); |     pum_redraw(); | ||||||
|     setcursor_mayforce(true); |     setcursor_mayforce(curwin, true); | ||||||
|  |  | ||||||
|     int c = vgetc(); |     int c = vgetc(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5016,4 +5016,216 @@ describe('API', function() | |||||||
|       eq(false, exec_lua('return _G.success')) |       eq(false, exec_lua('return _G.success')) | ||||||
|     end) |     end) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   it('nvim__redraw', function() | ||||||
|  |     local screen = Screen.new(60, 5) | ||||||
|  |     screen:attach() | ||||||
|  |     local win = api.nvim_get_current_win() | ||||||
|  |     eq('at least one action required', pcall_err(api.nvim__redraw, {})) | ||||||
|  |     eq('at least one action required', pcall_err(api.nvim__redraw, { buf = 0 })) | ||||||
|  |     eq('at least one action required', pcall_err(api.nvim__redraw, { win = 0 })) | ||||||
|  |     eq("cannot use both 'buf' and 'win'", pcall_err(api.nvim__redraw, { buf = 0, win = 0 })) | ||||||
|  |     feed(':echo getchar()<CR>') | ||||||
|  |     fn.setline(1, 'foobar') | ||||||
|  |     command('vnew') | ||||||
|  |     fn.setline(1, 'foobaz') | ||||||
|  |     -- Can flush pending screen updates | ||||||
|  |     api.nvim__redraw({ flush = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         foobaz                        │foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:[No Name] [+]                  }{2:[No Name] [+]                }| | ||||||
|  |         ^:echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the grid cursor position #20793 | ||||||
|  |     api.nvim__redraw({ cursor = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^foobaz                        │foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:[No Name] [+]                  }{2:[No Name] [+]                }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Also in non-current window | ||||||
|  |     api.nvim__redraw({ cursor = true, win = win }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         foobaz                        │^foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:[No Name] [+]                  }{2:[No Name] [+]                }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the 'statusline' in a single window | ||||||
|  |     api.nvim_set_option_value('statusline', 'statusline1', { win = 0 }) | ||||||
|  |     api.nvim_set_option_value('statusline', 'statusline2', { win = win }) | ||||||
|  |     api.nvim__redraw({ cursor = true, win = 0, statusline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^foobaz                        │foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:statusline1                    }{2:[No Name] [+]                }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     api.nvim__redraw({ win = win, statusline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^foobaz                        │foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:statusline1                    }{2:statusline2                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the 'statusline' in all windows | ||||||
|  |     api.nvim_set_option_value('statusline', '', { win = win }) | ||||||
|  |     api.nvim_set_option_value('statusline', 'statusline3', {}) | ||||||
|  |     api.nvim__redraw({ statusline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^foobaz                        │foobar                       | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:statusline3                    }{2:statusline3                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the 'statuscolumn' | ||||||
|  |     api.nvim_set_option_value('statuscolumn', 'statuscolumn', { win = win }) | ||||||
|  |     api.nvim__redraw({ statuscolumn = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^foobaz                        │{8:statuscolumn}foobar           | | ||||||
|  |         {1:~                             }│{1:~                            }|*2 | ||||||
|  |         {3:statusline3                    }{2:statusline3                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the 'winbar' | ||||||
|  |     api.nvim_set_option_value('winbar', 'winbar', { win = 0 }) | ||||||
|  |     api.nvim__redraw({ win = 0, winbar = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {5:^winbar                        }│{8:statuscolumn}foobar           | | ||||||
|  |         foobaz                        │{1:~                            }| | ||||||
|  |         {1:~                             }│{1:~                            }| | ||||||
|  |         {3:statusline3                    }{2:statusline3                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update the 'tabline' | ||||||
|  |     api.nvim_set_option_value('showtabline', 2, {}) | ||||||
|  |     api.nvim_set_option_value('tabline', 'tabline', {}) | ||||||
|  |     api.nvim__redraw({ tabline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:^tabline                                                     }| | ||||||
|  |         {5:winbar                        }│{8:statuscolumn}foobar           | | ||||||
|  |         foobaz                        │{1:~                            }| | ||||||
|  |         {3:statusline3                    }{2:statusline3                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update multiple status widgets | ||||||
|  |     api.nvim_set_option_value('tabline', 'tabline2', {}) | ||||||
|  |     api.nvim_set_option_value('statusline', 'statusline4', {}) | ||||||
|  |     api.nvim__redraw({ statusline = true, tabline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:^tabline2                                                    }| | ||||||
|  |         {5:winbar                        }│{8:statuscolumn}foobar           | | ||||||
|  |         foobaz                        │{1:~                            }| | ||||||
|  |         {3:statusline4                    }{2:statusline4                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update all status widgets | ||||||
|  |     api.nvim_set_option_value('tabline', 'tabline3', {}) | ||||||
|  |     api.nvim_set_option_value('statusline', 'statusline5', {}) | ||||||
|  |     api.nvim_set_option_value('statuscolumn', 'statuscolumn2', {}) | ||||||
|  |     api.nvim_set_option_value('winbar', 'winbar2', {}) | ||||||
|  |     api.nvim__redraw({ statuscolumn = true, statusline = true, tabline = true, winbar = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:^tabline3                                                    }| | ||||||
|  |         {5:winbar2                       }│{5:winbar2                      }| | ||||||
|  |         {8:statuscolumn2}foobaz           │{8:statuscolumn}foobar           | | ||||||
|  |         {3:statusline5                    }{2:statusline5                  }| | ||||||
|  |         :echo getchar()                                             | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update status widget for a specific window | ||||||
|  |     feed('<CR><CR>') | ||||||
|  |     command('let g:status=0') | ||||||
|  |     api.nvim_set_option_value('statusline', '%{%g:status%}', { win = 0 }) | ||||||
|  |     command('vsplit') | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:tabline3                                                    }| | ||||||
|  |         {5:winbar2             }│{5:winbar2            }│{5:winbar2            }| | ||||||
|  |         {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | | ||||||
|  |         {3:0                    }{2:0                   statusline5        }| | ||||||
|  |         13                                                          | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     command('let g:status=1') | ||||||
|  |     api.nvim__redraw({ win = 0, statusline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:tabline3                                                    }| | ||||||
|  |         {5:winbar2             }│{5:winbar2            }│{5:winbar2            }| | ||||||
|  |         {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | | ||||||
|  |         {3:1                    }{2:0                   statusline5        }| | ||||||
|  |         13                                                          | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- Can update status widget for a specific buffer | ||||||
|  |     command('let g:status=2') | ||||||
|  |     api.nvim__redraw({ buf = 0, statusline = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:tabline3                                                    }| | ||||||
|  |         {5:winbar2             }│{5:winbar2            }│{5:winbar2            }| | ||||||
|  |         {8:statuscolumn2}^foobaz │{8:statuscolumn2}foobaz│{8:statuscolumn}foobar | | ||||||
|  |         {3:2                    }{2:2                   statusline5        }| | ||||||
|  |         13                                                          | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- valid = true does not draw any lines on its own | ||||||
|  |     exec_lua([[ | ||||||
|  |       lines = 0 | ||||||
|  |       ns = vim.api.nvim_create_namespace('') | ||||||
|  |       on_win = function() | ||||||
|  |         if do_win then | ||||||
|  |           vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { hl_group = 'IncSearch', end_col = 6 }) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |       vim.api.nvim_set_decoration_provider(ns, { | ||||||
|  |         on_win = on_win, | ||||||
|  |         on_line = function() | ||||||
|  |           lines = lines + 1 | ||||||
|  |         end, | ||||||
|  |       }) | ||||||
|  |     ]]) | ||||||
|  |     local lines = exec_lua('return lines') | ||||||
|  |     api.nvim__redraw({ buf = 0, valid = true, flush = true }) | ||||||
|  |     eq(lines, exec_lua('return lines')) | ||||||
|  |     -- valid = false does | ||||||
|  |     api.nvim__redraw({ buf = 0, valid = false, flush = true }) | ||||||
|  |     neq(lines, exec_lua('return lines')) | ||||||
|  |     -- valid = true does redraw lines if affected by on_win callback | ||||||
|  |     exec_lua('do_win = true') | ||||||
|  |     api.nvim__redraw({ buf = 0, valid = true, flush = true }) | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {2:tabline3                                                    }| | ||||||
|  |         {5:winbar2             }│{5:winbar2            }│{5:winbar2            }| | ||||||
|  |         {8:statuscolumn2}{2:^foobaz} │{8:statuscolumn2}{2:foobaz}│{8:statuscolumn}foobar | | ||||||
|  |         {3:2                    }{2:2                   statusline5        }| | ||||||
|  |         13                                                          | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |   end) | ||||||
| end) | end) | ||||||
|   | |||||||
| @@ -827,14 +827,14 @@ local function test_cmdline(linegrid) | |||||||
|     ]]) |     ]]) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   -- Needs new API |   it('does not move cursor to curwin #20309', function() | ||||||
|   pending('does not move cursor to curwin #20309', function() |  | ||||||
|     local win = api.nvim_get_current_win() |     local win = api.nvim_get_current_win() | ||||||
|     command('norm icmdlinewin') |     command('norm icmdlinewin') | ||||||
|     command('new') |     command('new') | ||||||
|     command('norm icurwin') |     command('norm icurwin') | ||||||
|     feed(':') |     feed(':') | ||||||
|     api.nvim_win_set_cursor(win, { 1, 7 }) |     api.nvim_win_set_cursor(win, { 1, 7 }) | ||||||
|  |     api.nvim__redraw({ win = win, cursor = true }) | ||||||
|     screen:expect { |     screen:expect { | ||||||
|       grid = [[ |       grid = [[ | ||||||
|       curwin                   | |       curwin                   | | ||||||
|   | |||||||
| @@ -2594,6 +2594,12 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function() | |||||||
|     {2:[Preview]                     }| |     {2:[Preview]                     }| | ||||||
|     :%s/foo/ZZZ^                   | |     :%s/foo/ZZZ^                   | | ||||||
|   ]]) |   ]]) | ||||||
|  |  | ||||||
|  |   -- Also with nvim__redraw() | ||||||
|  |   command('call timer_start(10, {-> nvim__redraw(#{flush:1})}, {"repeat":-1})') | ||||||
|  |   command('call timer_start(10, {-> nvim__redraw(#{statusline:1})}, {"repeat":-1})') | ||||||
|  |   sleep(20) -- Allow some timer activity. | ||||||
|  |   screen:expect_unchanged() | ||||||
| end) | end) | ||||||
|  |  | ||||||
| it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function() | it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function() | ||||||
|   | |||||||
| @@ -918,4 +918,57 @@ describe('statuscolumn', function() | |||||||
|                                        | |                                        | | ||||||
|     ]]) |     ]]) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   it('forces a rebuild with nvim__redraw', function() | ||||||
|  |     screen:try_resize(40, 4) | ||||||
|  |     -- Current window | ||||||
|  |     command([[ | ||||||
|  |       let g:insert = v:false | ||||||
|  |       set nonu stc=%{g:insert?'insert':''} | ||||||
|  |       vsplit | ||||||
|  |       au InsertEnter * let g:insert = v:true | call nvim__redraw(#{statuscolumn:1, win:0}) | ||||||
|  |       au InsertLeave * let g:insert = v:false | call nvim__redraw(#{statuscolumn:1, win:0}) | ||||||
|  |     ]]) | ||||||
|  |     feed('i') | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {8:insert}^aaaaa         │aaaaa              | | ||||||
|  |         {8:insert}aaaaa         │aaaaa              | | ||||||
|  |         {3:[No Name] [+]        }{2:[No Name] [+]      }| | ||||||
|  |         {5:-- INSERT --}                            | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     feed('<esc>') | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^aaaaa               │aaaaa              | | ||||||
|  |         aaaaa               │aaaaa              | | ||||||
|  |         {3:[No Name] [+]        }{2:[No Name] [+]      }| | ||||||
|  |                                                 | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     -- All windows | ||||||
|  |     command([[ | ||||||
|  |       au! InsertEnter * let g:insert = v:true | call nvim__redraw(#{statuscolumn:1}) | ||||||
|  |       au! InsertLeave * let g:insert = v:false | call nvim__redraw(#{statuscolumn:1}) | ||||||
|  |     ]]) | ||||||
|  |     feed('i') | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         {8:insert}^aaaaa         │{8:insert}aaaaa        | | ||||||
|  |         {8:insert}aaaaa         │{8:insert}aaaaa        | | ||||||
|  |         {3:[No Name] [+]        }{2:[No Name] [+]      }| | ||||||
|  |         {5:-- INSERT --}                            | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |     feed('<esc>') | ||||||
|  |     screen:expect({ | ||||||
|  |       grid = [[ | ||||||
|  |         ^aaaaa               │aaaaa              | | ||||||
|  |         aaaaa               │aaaaa              | | ||||||
|  |         {3:[No Name] [+]        }{2:[No Name] [+]      }| | ||||||
|  |                                                 | | ||||||
|  |       ]], | ||||||
|  |     }) | ||||||
|  |   end) | ||||||
| end) | end) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes