mirror of
https://github.com/neovim/neovim.git
synced 2025-10-21 17:21:49 +00:00
feat(ui2): more predictable routing #35028
Problem: Routing based on message kinds can be perceived as unpredictable. Solution: Implement phase 1 of #34281, always showing the full message in a window dismissed on any user input when it does not fit in the 'cmdheight'. Also show spill "[+n]" indicator if needed.
This commit is contained in:
@@ -67,7 +67,8 @@ local cmd_on_key = nil
|
|||||||
--- Place or delete a virtual text mark in the cmdline or message window.
|
--- Place or delete a virtual text mark in the cmdline or message window.
|
||||||
---
|
---
|
||||||
---@param type 'last'|'msg'
|
---@param type 'last'|'msg'
|
||||||
local function set_virttext(type)
|
---@param tar? 'cmd'|'msg'
|
||||||
|
local function set_virttext(type, tar)
|
||||||
if (type == 'last' and (ext.cmdheight == 0 or M.virt.delayed)) or cmd_on_key then
|
if (type == 'last' and (ext.cmdheight == 0 or M.virt.delayed)) or cmd_on_key then
|
||||||
return -- Don't show virtual text while cmdline, error or full message in cmdline is shown.
|
return -- Don't show virtual text while cmdline, error or full message in cmdline is shown.
|
||||||
end
|
end
|
||||||
@@ -87,7 +88,7 @@ local function set_virttext(type)
|
|||||||
M.virt.ids[type] = nil
|
M.virt.ids[type] = nil
|
||||||
M.cmd.last_col = type == 'last' and o.columns or M.cmd.last_col
|
M.cmd.last_col = type == 'last' and o.columns or M.cmd.last_col
|
||||||
elseif #chunks > 0 then
|
elseif #chunks > 0 then
|
||||||
local tar = type == 'msg' and ext.cfg.msg.target or 'cmd'
|
tar = tar or type == 'msg' and ext.cfg.msg.target or 'cmd'
|
||||||
local win = ext.wins[tar]
|
local win = ext.wins[tar]
|
||||||
local erow = tar == 'cmd' and math.min(M.cmd.msg_row, api.nvim_buf_line_count(ext.bufs.cmd) - 1)
|
local erow = tar == 'cmd' and math.min(M.cmd.msg_row, api.nvim_buf_line_count(ext.bufs.cmd) - 1)
|
||||||
local texth = api.nvim_win_text_height(win, {
|
local texth = api.nvim_win_text_height(win, {
|
||||||
@@ -220,8 +221,7 @@ end
|
|||||||
---@param content MsgContent
|
---@param content MsgContent
|
||||||
---@param replace_last boolean
|
---@param replace_last boolean
|
||||||
---@param append boolean
|
---@param append boolean
|
||||||
---@param full boolean? If true, show messages that exceed target window in full.
|
function M.show_msg(tar, content, replace_last, append)
|
||||||
function M.show_msg(tar, content, replace_last, append, full)
|
|
||||||
local msg, restart, cr, dupe, count = '', false, false, 0, 0
|
local msg, restart, cr, dupe, count = '', false, false, 0, 0
|
||||||
append = append and col > 0
|
append = append and col > 0
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ function M.show_msg(tar, content, replace_last, append, full)
|
|||||||
if tar == 'msg' then
|
if tar == 'msg' then
|
||||||
api.nvim_win_set_width(ext.wins.msg, width)
|
api.nvim_win_set_width(ext.wins.msg, width)
|
||||||
local texth = api.nvim_win_text_height(ext.wins.msg, { start_row = start_row })
|
local texth = api.nvim_win_text_height(ext.wins.msg, { start_row = start_row })
|
||||||
if full and texth.all > 1 then
|
if texth.all > math.ceil(o.lines * 0.5) then
|
||||||
msg_to_full(tar)
|
msg_to_full(tar)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -320,12 +320,11 @@ function M.show_msg(tar, content, replace_last, append, full)
|
|||||||
end
|
end
|
||||||
-- Place [+x] indicator for lines that spill over 'cmdheight'.
|
-- Place [+x] indicator for lines that spill over 'cmdheight'.
|
||||||
local texth = api.nvim_win_text_height(ext.wins.cmd, {})
|
local texth = api.nvim_win_text_height(ext.wins.cmd, {})
|
||||||
local spill = texth.all > ext.cmdheight and ('[+%d]'):format(texth.all - ext.cmdheight)
|
local spill = texth.all > ext.cmdheight and (' [+%d]'):format(texth.all - ext.cmdheight)
|
||||||
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
||||||
M.cmd.msg_row = texth.end_row
|
M.cmd.msg_row = texth.end_row
|
||||||
|
|
||||||
local want_full = full or will_full or not api.nvim_win_get_config(ext.wins.pager).hide
|
if texth.all > ext.cmdheight then
|
||||||
if want_full and texth.all > ext.cmdheight then
|
|
||||||
msg_to_full(tar)
|
msg_to_full(tar)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -387,17 +386,14 @@ function M.msg_show(kind, content, replace_last, _, append)
|
|||||||
if ext.cmdheight == 0 or (ext.cmd.level > 0 and ext.cmd.row == 0) then
|
if ext.cmdheight == 0 or (ext.cmd.level > 0 and ext.cmd.row == 0) then
|
||||||
return -- Do not overwrite an active cmdline unless in block mode.
|
return -- Do not overwrite an active cmdline unless in block mode.
|
||||||
end
|
end
|
||||||
-- Store the time when an error message was emitted in order to not overwrite
|
-- Store the time when an important message was emitted in order to not overwrite
|
||||||
-- it with 'last' virt_text in the cmdline to give the user a chance to read it.
|
-- it with 'last' virt_text in the cmdline so that the user has a chance to read it.
|
||||||
M.cmd.last_emsg = kind == 'emsg' and os.time() or M.cmd.last_emsg
|
M.cmd.last_emsg = kind == 'emsg' or kind == 'wmsg' and os.time() or M.cmd.last_emsg
|
||||||
-- Should clear the search count now, mark itself is cleared by invalidate.
|
-- Should clear the search count now, mark itself is cleared by invalidate.
|
||||||
M.virt.last[M.virt.idx.search][1] = nil
|
M.virt.last[M.virt.idx.search][1] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Typed "inspection" messages should be shown in full.
|
M.show_msg(tar, content, replace_last, append)
|
||||||
local inspect = { 'echo', 'echomsg', 'lua_print' }
|
|
||||||
local full = kind == 'list_cmd' or (ext.cmd.level >= 0 and vim.tbl_contains(inspect, kind))
|
|
||||||
M.show_msg(tar, content, replace_last, append, full)
|
|
||||||
-- Don't remember search_cmd message as actual message.
|
-- Don't remember search_cmd message as actual message.
|
||||||
if kind == 'search_cmd' then
|
if kind == 'search_cmd' then
|
||||||
M.cmd.count, M.prev_msg = 0, ''
|
M.cmd.count, M.prev_msg = 0, ''
|
||||||
@@ -486,9 +482,9 @@ function M.set_pos(type)
|
|||||||
if type == 'cmd' then
|
if type == 'cmd' then
|
||||||
-- Temporarily showing a full message in the cmdline, until next key press.
|
-- Temporarily showing a full message in the cmdline, until next key press.
|
||||||
local save_spill = M.virt.msg[M.virt.idx.spill][1]
|
local save_spill = M.virt.msg[M.virt.idx.spill][1]
|
||||||
local spill = texth.all > height and ('[+%d]'):format(texth.all - height)
|
local spill = texth.all > height and (' [+%d]'):format(texth.all - height)
|
||||||
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
M.virt.msg[M.virt.idx.spill][1] = spill and { 0, spill } or nil
|
||||||
set_virttext('msg')
|
set_virttext('msg', 'cmd')
|
||||||
M.virt.msg[M.virt.idx.spill][1] = save_spill
|
M.virt.msg[M.virt.idx.spill][1] = save_spill
|
||||||
cmd_on_key = vim.on_key(function(_, typed)
|
cmd_on_key = vim.on_key(function(_, typed)
|
||||||
if not typed or fn.keytrans(typed) == '<MouseMove>' then
|
if not typed or fn.keytrans(typed) == '<MouseMove>' then
|
||||||
|
@@ -22,8 +22,10 @@ describe('messages2', function()
|
|||||||
command('echo "foo\nbar"')
|
command('echo "foo\nbar"')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
^ |
|
^ |
|
||||||
{1:~ }|*12
|
{1:~ }|*10
|
||||||
foo[+1] |
|
{3:─────────────────────────────────────────────────────}|
|
||||||
|
foo |
|
||||||
|
bar |
|
||||||
]])
|
]])
|
||||||
command('set ruler showcmd noshowmode')
|
command('set ruler showcmd noshowmode')
|
||||||
feed('g<lt>')
|
feed('g<lt>')
|
||||||
@@ -47,14 +49,14 @@ describe('messages2', function()
|
|||||||
bar |
|
bar |
|
||||||
baz |
|
baz |
|
||||||
bar |
|
bar |
|
||||||
baz[+23] |
|
baz [+23] |
|
||||||
]])
|
]])
|
||||||
-- Any key press resizes the cmdline and updates the spill indicator.
|
-- Any key press resizes the cmdline and updates the spill indicator.
|
||||||
feed('j')
|
feed('j')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
^ |
|
^ |
|
||||||
{1:~ }|*12
|
{1:~ }|*12
|
||||||
foo[+29] 0,0-1 All|
|
foo [+29] 0,0-1 All|
|
||||||
]])
|
]])
|
||||||
command('echo "foo"')
|
command('echo "foo"')
|
||||||
-- New message clears spill indicator.
|
-- New message clears spill indicator.
|
||||||
@@ -177,14 +179,14 @@ describe('messages2', function()
|
|||||||
{16::}^ |
|
{16::}^ |
|
||||||
]])
|
]])
|
||||||
-- Highlighter disabled when message is moved to cmdline #34884
|
-- Highlighter disabled when message is moved to cmdline #34884
|
||||||
feed('ls<CR>')
|
feed([[echo "bar\n"->repeat(&lines)<CR>]])
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
^ |
|
^ |
|
||||||
{1:~ }|*8
|
{1:~ }|*4
|
||||||
{3:─────────────────────────────────────────────────────}|
|
{3:─────────────────────────────────────────────────────}|
|
||||||
foo |
|
foo |
|
||||||
|
|
bar |*5
|
||||||
1 %a "[No Name]" line 1 |
|
bar [+8] |
|
||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -199,4 +201,14 @@ describe('messages2', function()
|
|||||||
command('%bdelete')
|
command('%bdelete')
|
||||||
screen:expect_unchanged()
|
screen:expect_unchanged()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("'readonly' warning can be read", function()
|
||||||
|
command('set readonly')
|
||||||
|
feed('i')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|*12
|
||||||
|
{19:W10: Warning: Changing a readonly file} |
|
||||||
|
]])
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Reference in New Issue
Block a user