commit cb171ee7cba01dc97f72c5b4c05ce9e9d52f221b
parent 647f11e6ae795901e9bf5d0f4d84f73eab2b836b
Author: glepnir <glephunter@gmail.com>
Date: Mon, 8 Dec 2025 14:52:07 +0800
fix(float): tail truncate long title #28387
Problem:
We truncate the title from start, this is somewhat inconsistent
with the way vim works. Usually we use < to truncate and keep
more trailing characters.
Solution:
Keep more trailing characters.
Diffstat:
2 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
@@ -1085,8 +1085,14 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
}
static void grid_draw_bordertext(VirtText vt, int col, int winbl, const int *hl_attr,
- BorderTextType bt)
+ BorderTextType bt, int over_flow)
{
+ int default_attr = hl_attr[bt == kBorderTextTitle ? HLF_BTITLE : HLF_BFOOTER];
+ if (over_flow > 0) {
+ grid_line_puts(1, "<", -1, hl_apply_winblend(winbl, default_attr));
+ col += 1;
+ }
+
for (size_t i = 0; i < kv_size(vt);) {
int attr = -1;
char *text = next_virt_text_chunk(vt, &i, &attr);
@@ -1094,7 +1100,24 @@ static void grid_draw_bordertext(VirtText vt, int col, int winbl, const int *hl_
break;
}
if (attr == -1) { // No highlight specified.
- attr = hl_attr[bt == kBorderTextTitle ? HLF_BTITLE : HLF_BFOOTER];
+ attr = default_attr;
+ }
+ // Skip characters from the beginning when title overflows available width.
+ // over_flow contains the number of cells to skip.
+ if (over_flow > 0) {
+ int cells = (int)mb_string2cells(text);
+ // Skip entire chunk if overflow is larger than chunk width.
+ if (over_flow >= cells) {
+ over_flow -= cells;
+ continue;
+ }
+ // Skip partial characters within the chunk.
+ char *p = text;
+ while (*p && over_flow > 0) {
+ over_flow -= utf_ptr2cells(p);
+ p += utfc_ptr2len(p);
+ }
+ text = p;
}
attr = hl_apply_winblend(winbl, attr);
col += grid_line_puts(col, text, -1, attr);
@@ -1146,7 +1169,8 @@ void grid_draw_border(ScreenGrid *grid, WinConfig *config, int *adj, int winbl,
if (config->title) {
int title_col = get_bordertext_col(icol, config->title_width, config->title_pos);
- grid_draw_bordertext(config->title_chunks, title_col, winbl, hl_attr, kBorderTextTitle);
+ grid_draw_bordertext(config->title_chunks, title_col, winbl, hl_attr, kBorderTextTitle,
+ config->title_width - icol + 1);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
@@ -1181,7 +1205,8 @@ void grid_draw_border(ScreenGrid *grid, WinConfig *config, int *adj, int winbl,
if (config->footer) {
int footer_col = get_bordertext_col(icol, config->footer_width, config->footer_pos);
- grid_draw_bordertext(config->footer_chunks, footer_col, winbl, hl_attr, kBorderTextFooter);
+ grid_draw_bordertext(config->footer_chunks, footer_col, winbl, hl_attr, kBorderTextFooter,
+ config->footer_width - icol + 1);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
@@ -2047,10 +2047,10 @@ describe('float window', function()
eq('center', footer_pos)
end)
- it('center aligned title longer than window width #25746', function()
+ it('truncates title longer than window width #25746 #23602', function()
local buf = api.nvim_create_buf(false, false)
api.nvim_buf_set_lines(buf, 0, -1, true, { ' halloj! ', ' BORDAA ' })
- local win = api.nvim_open_win(buf, false, {
+ local config = {
relative = 'editor',
width = 9,
height = 2,
@@ -2059,8 +2059,8 @@ describe('float window', function()
border = 'double',
title = 'abcdefghijklmnopqrstuvwxyz',
title_pos = 'center',
- })
-
+ }
+ local win = api.nvim_open_win(buf, false, config)
if multigrid then
screen:expect {
grid = [[
@@ -2073,7 +2073,7 @@ describe('float window', function()
## grid 3
|
## grid 4
- {5:╔}{11:abcdefghi}{5:╗}|
+ {5:╔}{11:<stuvwxyz}{5:╗}|
{5:║}{1: halloj! }{5:║}|
{5:║}{1: BORDAA }{5:║}|
{5:╚═════════╝}|
@@ -2089,7 +2089,7 @@ describe('float window', function()
grid = [[
^ |
{0:~ }|
- {0:~ }{5:╔}{11:abcdefghi}{5:╗}{0: }|
+ {0:~ }{5:╔}{11:<stuvwxyz}{5:╗}{0: }|
{0:~ }{5:║}{1: halloj! }{5:║}{0: }|
{0:~ }{5:║}{1: BORDAA }{5:║}{0: }|
{0:~ }{5:╚═════════╝}{0: }|
@@ -2097,7 +2097,9 @@ describe('float window', function()
]],
}
end
-
+ config.title = { { 'abcd' }, { 'stuvw' }, { 'xyz' } }
+ api.nvim_win_set_config(win, config)
+ screen:expect_unchanged()
api.nvim_win_close(win, false)
assert_alive()
end)