feat(api): add nvim_win_get_view

Problem: lack of access to view-related data such as leftcol at the lua api.

Solution: add nvim_win_get_view api function
This commit is contained in:
glepnir 2024-11-03 18:06:58 +08:00
parent 8f9401f5c8
commit 0be85a9556
5 changed files with 131 additions and 0 deletions

View File

@ -2985,6 +2985,21 @@ nvim_win_get_var({window}, {name}) *nvim_win_get_var()*
Return: ~
Variable value
nvim_win_get_view({window}, {opts}) *nvim_win_get_view()*
Retrieves view-related information for a specified window.
Parameters: ~
• {window} Window handle, or 0 for current window
• {opts} Optional parameters. Currently unused.
Return: ~
Dict containing text height information, with these keys:
• lnum: cursor line number in the given window.
• topline: first line in the given window.
• botline: bottom line in the given window.
• leftcol: first column displayed; only used when 'wrap' is off.
• skipcol: columns skipped.
nvim_win_get_width({window}) *nvim_win_get_width()*
Gets the window width

View File

@ -150,6 +150,7 @@ The following new features were added.
API
• |nvim__ns_set()| can set properties for a namespace
• add api |nvim_win_get_view()| for get view information for a specified window.
DEFAULTS

View File

@ -2423,6 +2423,18 @@ function vim.api.nvim_win_get_tabpage(window) end
--- @return any # Variable value
function vim.api.nvim_win_get_var(window, name) end
--- Retrieves view-related information for a specified window.
---
--- @param window integer Window handle, or 0 for current window
--- @param opts vim.api.keyset.empty Optional parameters. Currently unused.
--- @return table<string,any> # Dict containing text height information, with these keys:
--- - lnum: cursor line number in the given window.
--- - topline: first line in the given window.
--- - botline: bottom line in the given window.
--- - leftcol: first column displayed; only used when 'wrap' is off.
--- - skipcol: columns skipped.
function vim.api.nvim_win_get_view(window, opts) end
--- Gets the window width
---
--- @param window integer Window handle, or 0 for current window

View File

@ -581,3 +581,43 @@ Dict nvim_win_text_height(Window window, Dict(win_text_height) *opts, Arena *are
PUT_C(rv, "fill", INTEGER_OBJ(fill));
return rv;
}
/// Retrieves view-related information for a specified window.
///
/// @param window Window handle, or 0 for current window
/// @param opts Optional parameters. Currently unused.
/// @param[out] err Error details, if any
///
/// @return Dict containing text height information, with these keys:
/// - lnum: cursor line number in the given window.
/// - topline: first line in the given window.
/// - botline: bottom line in the given window.
/// - leftcol: first column displayed; only used when 'wrap' is off.
/// - skipcol: columns skipped.
Dict nvim_win_get_view(Window window, Dict(empty) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(13)
{
Dict rv = arena_dict(arena, 5);
win_T *wp = find_window_by_handle(window, err);
if (!wp) {
return rv;
}
bool need_swicth = curwin != wp;
switchwin_T switchwin;
tabpage_T *tp = NULL;
if (need_swicth && switch_win_noblock(&switchwin, wp, tp, true)) {
check_cursor(curwin);
update_topline(curwin);
}
// In silent Ex mode topline is zero, use one instead.
PUT_C(rv, "topline", INTEGER_OBJ(wp->w_topline > 0 ? wp->w_topline : 1));
PUT_C(rv, "lnum", INTEGER_OBJ(wp->w_cursor.lnum));
PUT_C(rv, "leftcol", INTEGER_OBJ(wp->w_leftcol));
// In silent Ex mode botline is zero, return zero then.
PUT_C(rv, "botline", INTEGER_OBJ(wp->w_botline > 0 ? wp->w_botline - 1 : 0));
PUT_C(rv, "skipcol", INTEGER_OBJ(wp->w_skipcol));
if (need_swicth) {
restore_win_noblock(&switchwin, true);
}
return rv;
}

View File

@ -2877,4 +2877,67 @@ describe('API/win', function()
end)
end)
end)
describe('get_view', function()
local win
before_each(function()
win = api.nvim_open_win(0, false, {
relative = 'editor',
row = 1,
col = 1,
height = 3,
width = 3,
})
end)
it('errors on invalid window', function()
eq('Invalid window id: 9999', pcall_err(api.nvim_win_get_view, 9999, {}))
end)
it('on empty buffer', function()
eq(
{ lnum = 1, leftcol = 0, topline = 1, botline = 1, skipcol = 0 },
api.nvim_win_get_view(win, {})
)
end)
it('topline botline cursorline in view range', function()
api.nvim_buf_set_lines(0, 0, -1, false, { 'a', 'b', 'c', 'd' })
eq(
{ lnum = 1, leftcol = 0, topline = 1, botline = 3, skipcol = 0 },
api.nvim_win_get_view(win, {})
)
api.nvim_win_set_cursor(win, { 2, 1 })
eq(
{ lnum = 2, leftcol = 0, topline = 1, botline = 3, skipcol = 0 },
api.nvim_win_get_view(win, {})
)
feed('<C-w>wGzz<C-w>p')
eq(
{ lnum = 4, leftcol = 0, topline = 3, botline = 4, skipcol = 0 },
api.nvim_win_get_view(win, {})
)
end)
it('leftcol bigger than zero', function()
api.nvim_set_option_value('wrap', false, { scope = 'local', win = win })
api.nvim_buf_set_lines(0, 0, -1, false, { 'looooooooooooooong' })
feed('<C-w>wlllllll<C-w>p')
eq(
{ lnum = 1, leftcol = 6, topline = 1, botline = 1, skipcol = 0 },
api.nvim_win_get_view(win, {})
)
end)
it('get skipcol', function()
api.nvim_buf_set_lines(0, 0, -1, true, { ('foo'):rep(8) })
api.nvim_win_set_cursor(win, { 1, 7 })
api.nvim_set_current_win(win)
feed('gj')
eq(
{ lnum = 1, leftcol = 0, topline = 1, botline = 1, skipcol = 3 },
api.nvim_win_get_view(win, {})
)
end)
end)
end)