fix(extui): translate <Tab> in cmdline text (#34055)

Problem:  <Tab> is not translated on the cmdline, and exposes a wrong
          assumption in search messages that may contain multiple chunks.
Solution: Translate unprintable characters in the cmdline content.
          Extract the 'search_count' from the last chunk and route
          'search_cmd' to cmdline to handle multiple chunks.
This commit is contained in:
luukvbaal
2025-05-17 11:24:05 +02:00
committed by GitHub
parent f40e140083
commit 8e8f4523c6
2 changed files with 10 additions and 8 deletions

View File

@ -30,6 +30,7 @@ local function win_config(win, hide, height)
end
end
local cmdbuff ---@type string Stored cmdline used to calculate translation offset.
local promptlen = 0 -- Current length of the prompt, stored for use in "cmdline_pos"
--- Concatenate content chunks and set the text for the current row in the cmdline buffer.
---
@ -42,7 +43,8 @@ local function set_text(content, prompt)
for _, chunk in ipairs(content) do
prompt = prompt .. chunk[2]
end
api.nvim_buf_set_lines(ext.bufs.cmd, M.row, -1, false, { prompt .. ' ' })
cmdbuff = prompt
api.nvim_buf_set_lines(ext.bufs.cmd, M.row, -1, false, { fn.strtrans(cmdbuff) .. ' ' })
end
--- Set the cmdline buffer text and cursor position.
@ -93,6 +95,7 @@ local curpos = { 0, 0 } -- Last drawn cursor position.
---@param pos integer
--@param level integer
function M.cmdline_pos(pos)
pos = #fn.strtrans(cmdbuff:sub(1, pos + 1)) - 1
if curpos[1] ~= M.row + 1 or curpos[2] ~= promptlen + pos then
curpos[1], curpos[2] = M.row + 1, promptlen + pos
-- Add matchparen highlighting to non-prompt part of cmdline.

View File

@ -311,14 +311,10 @@ local replace_bufwrite = false
---@alias MsgContent MsgChunk[]
---@param content MsgContent
function M.msg_show(kind, content)
if kind == 'search_cmd' then
-- Set the entered search command in the cmdline.
api.nvim_buf_set_lines(ext.bufs.cmd, 0, -1, false, { content[1][2] })
M.virt.msg = ext.cfg.msg.pos == 'cmd' and { {}, {} } or M.virt.msg
M.prev_msg = ext.cfg.msg.pos == 'cmd' and '' or M.prev_msg
elseif kind == 'search_count' then
if kind == 'search_count' then
-- Extract only the search_count, not the entered search command.
-- Match any of search.c:cmdline_search_stat():' [(x | >x | ?)/(y | >y | ??)]'
content = { content[#content] }
content[1][2] = content[1][2]:match('W? %[>?%d*%??/>?%d*%?*%]') .. ' '
M.virt.last[M.virt.idx.search] = content
M.virt.last[M.virt.idx.cmd] = { { 0, (' '):rep(11) } }
@ -336,7 +332,8 @@ function M.msg_show(kind, content)
M.show_msg('prompt', content, true)
M.set_pos('prompt')
else
local tar = ext.cfg.msg.pos
-- Set the entered search command in the cmdline.
local tar = kind == 'search_cmd' and 'cmd' or ext.cfg.msg.pos
if tar == 'cmd' then
if ext.cmd.level > 0 then
return -- Do not overwrite an active cmdline.
@ -352,6 +349,8 @@ function M.msg_show(kind, content)
M.show_msg(tar, content, replace_bufwrite, more)
-- Replace message for every second bufwrite message.
replace_bufwrite = not replace_bufwrite and kind == 'bufwrite'
-- Don't remember search_cmd message as actual mesage.
M.prev_msg = kind == 'search_cmd' and '' or M.prev_msg
end
end