mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 12:28:18 +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);
|
||||||
|
@@ -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