mirror of
https://github.com/neovim/neovim.git
synced 2026-02-18 10:21:26 +10:00
feat(ui2): show active paging keys in dialog float title #37919
Problem: Paging keys being consumed without obvious indicator
in the dialog window can be surprising.
Solution: Display a hint with paging keys in the dialog window title
when paging is active. Recognize <Esc> as mapping to stop
paging.
This commit is contained in:
@@ -501,21 +501,22 @@ end
|
||||
|
||||
--- Adjust visibility and dimensions of the message windows after certain events.
|
||||
---
|
||||
---@param type? 'cmd'|'dialog'|'msg'|'pager' Type of to be positioned window (nil for all).
|
||||
function M.set_pos(type)
|
||||
---@param tar? 'cmd'|'dialog'|'msg'|'pager' To be positioned window (nil for all).
|
||||
function M.set_pos(tar)
|
||||
local function win_set_pos(win)
|
||||
local cfg = { hide = false, relative = 'laststatus', col = 10000 }
|
||||
local texth = type and api.nvim_win_text_height(win, {}) or {}
|
||||
local texth = tar and api.nvim_win_text_height(win, {}) or {}
|
||||
local top = { vim.opt.fcs:get().msgsep or ' ', 'MsgSeparator' }
|
||||
cfg.height = type == 'pager' and texth.all
|
||||
or type and math.min(texth.all, math.ceil(o.lines * 0.5))
|
||||
cfg.height = tar and math.min(texth.all, tar == 'pager' and 10000 or math.ceil(o.lines * 0.5))
|
||||
cfg.border = win ~= ui.wins.msg and { '', top, '', '', '', '', '', '' } or nil
|
||||
cfg.focusable = type == 'cmd' or nil
|
||||
cfg.focusable = tar == 'cmd' or nil
|
||||
cfg.row = (win == ui.wins.msg and 0 or 1) - ui.cmd.wmnumode
|
||||
cfg.row = cfg.row - ((win == ui.wins.pager and o.laststatus == 3) and 1 or 0)
|
||||
local title = { 'f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging', 'MsgSeparator' }
|
||||
cfg.title = tar == 'dialog' and cfg.height < texth.all and { title } or nil
|
||||
api.nvim_win_set_config(win, cfg)
|
||||
|
||||
if type == 'cmd' and not cmd_on_key then
|
||||
if tar == 'cmd' and not cmd_on_key then
|
||||
-- Temporarily expand the cmdline, until next key press.
|
||||
local save_spill = M.virt.msg[M.virt.idx.spill][1]
|
||||
local spill = texth.all > cfg.height and (' [+%d]'):format(texth.all - cfg.height)
|
||||
@@ -551,7 +552,7 @@ function M.set_pos(type)
|
||||
end)
|
||||
vim.on_key(nil, ui.ns)
|
||||
end, ui.ns)
|
||||
elseif type == 'dialog' then
|
||||
elseif tar == 'dialog' then
|
||||
-- Add virtual [+x] text to indicate scrolling is possible.
|
||||
local function set_top_bot_spill()
|
||||
local topspill = fn.line('w0', ui.wins.dialog) - 1
|
||||
@@ -565,10 +566,18 @@ function M.set_pos(type)
|
||||
set_top_bot_spill()
|
||||
|
||||
-- Allow paging in the dialog window, consume the key if the topline changes.
|
||||
M.dialog_on_key = vim.on_key(function(key, typed)
|
||||
M.dialog_on_key = vim.on_key(function(_, typed)
|
||||
typed = typed and fn.keytrans(typed)
|
||||
if not typed then
|
||||
return
|
||||
elseif typed == '<Esc>' then
|
||||
-- Stop paging, redraw empty title to reflect paging is no longer active.
|
||||
api.nvim_win_set_config(ui.wins.dialog, { title = '' })
|
||||
api.nvim__redraw({ flush = true })
|
||||
vim.on_key(nil, M.dialog_on_key)
|
||||
return ''
|
||||
end
|
||||
|
||||
local page_keys = {
|
||||
g = 'gg',
|
||||
G = 'G',
|
||||
@@ -579,18 +588,18 @@ function M.set_pos(type)
|
||||
f = [[\<C-F>]],
|
||||
b = [[\<C-B>]],
|
||||
}
|
||||
local info = page_keys[key] and fn.getwininfo(ui.wins.dialog)[1]
|
||||
if info and (key ~= 'f' or info.botline < api.nvim_buf_line_count(ui.bufs.dialog)) then
|
||||
fn.win_execute(ui.wins.dialog, ('exe "norm! %s"'):format(page_keys[key]))
|
||||
local info = page_keys[typed] and fn.getwininfo(ui.wins.dialog)[1]
|
||||
if info and (typed ~= 'f' or info.botline < api.nvim_buf_line_count(ui.bufs.dialog)) then
|
||||
fn.win_execute(ui.wins.dialog, ('exe "norm! %s"'):format(page_keys[typed]))
|
||||
set_top_bot_spill()
|
||||
return fn.getwininfo(ui.wins.dialog)[1].topline ~= info.topline and '' or nil
|
||||
end
|
||||
end, M.dialog_on_key)
|
||||
elseif type == 'msg' then
|
||||
elseif tar == 'msg' then
|
||||
-- Ensure last line is visible and first line is at top of window.
|
||||
local row = (texth.all > cfg.height and texth.end_row or 0) + 1
|
||||
api.nvim_win_set_cursor(ui.wins.msg, { row, 0 })
|
||||
elseif type == 'pager' then
|
||||
elseif tar == 'pager' then
|
||||
if fn.getcmdwintype() ~= '' then
|
||||
-- Cannot leave the cmdwin to enter the pager, so close it.
|
||||
-- NOTE: regression w.r.t. the message grid, which allowed this.
|
||||
@@ -621,10 +630,10 @@ function M.set_pos(type)
|
||||
end
|
||||
|
||||
for t, win in pairs(ui.wins) do
|
||||
local cfg = (t == type or (type == nil and t ~= 'cmd'))
|
||||
local cfg = (t == tar or (tar == nil and t ~= 'cmd'))
|
||||
and api.nvim_win_is_valid(win)
|
||||
and api.nvim_win_get_config(win)
|
||||
if cfg and (type or not cfg.hide) then
|
||||
if cfg and (tar or not cfg.hide) then
|
||||
win_set_pos(win)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -311,7 +311,7 @@ describe('messages2', function()
|
||||
local top = [[
|
||||
|
|
||||
{1:~ }|*4
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
0 |
|
||||
1 |
|
||||
2 |
|
||||
@@ -327,7 +327,7 @@ describe('messages2', function()
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*4
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
1 [+1] |
|
||||
2 |
|
||||
3 |
|
||||
@@ -343,7 +343,7 @@ describe('messages2', function()
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*4
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
3 [+3] |
|
||||
4 |
|
||||
5 |
|
||||
@@ -359,7 +359,7 @@ describe('messages2', function()
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*4
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
5 [+5] |
|
||||
6 |
|
||||
7 |
|
||||
@@ -375,7 +375,7 @@ describe('messages2', function()
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*4
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
93 [+93] |
|
||||
94 |
|
||||
95 |
|
||||
@@ -390,7 +390,7 @@ describe('messages2', function()
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*3
|
||||
{3: }|
|
||||
{3: f/d/j: screen/page/line down, b/u/k: up, <Esc>: stop paging }|
|
||||
93 [+93] |
|
||||
94 |
|
||||
95 |
|
||||
@@ -403,6 +403,21 @@ describe('messages2', function()
|
||||
]])
|
||||
feed('<Backspace>g')
|
||||
screen:expect(top)
|
||||
feed('<Esc>f')
|
||||
screen:expect([[
|
||||
|
|
||||
{1:~ }|*3
|
||||
{3: }|
|
||||
0 |
|
||||
1 |
|
||||
2 |
|
||||
3 |
|
||||
4 |
|
||||
5 |
|
||||
6 [+93] |
|
||||
Type number and <Enter> or click with the mouse (q or empty cancels): f|
|
||||
^ |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('FileType is fired after default options are set', function()
|
||||
|
||||
Reference in New Issue
Block a user