fix(statusline): "%.0" renders garbage #41685

Problem:
`getdigits_int(pp, strict, def)` returns `def` only when the number
fails to parse or overflows, never when the text parses to a literal
`0`, so `%.0` leaves `maxwid` at 0. Both render paths then break down:
`l > maxwid` is always true and `while (l >= maxwid)` consumes the whole
string, so `%.0f` comes out as `<` and `%.0l` as `0>3`.

Vim guards for this right after the same call. Nvim had the guard too
until 3344cffe7b ("getdigits: introduce `strict`, `def` parameters"),
which folded it into the new `def` argument and so changed what a
literal zero means. The neighbouring `minwid` call was translated
correctly.

Solution:
Fall back to 50 when the parsed width is not positive, as Vim does.

AI-assisted
This commit is contained in:
Volodymyr Chernetskyi
2026-09-06 17:24:52 +02:00
committed by GitHub
parent bd43394d4e
commit e8a0b400d8
2 changed files with 10 additions and 0 deletions

View File

@@ -1377,6 +1377,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
fmt_p++;
if (ascii_isdigit(*fmt_p)) {
maxwid = getdigits_int(&fmt_p, false, 50);
if (maxwid <= 0) { // overflow or an explicit zero
maxwid = 50;
}
}
}

View File

@@ -4537,6 +4537,13 @@ describe('API', function()
}, api.nvim_eval_statusline('Should be truncated%<', { maxwidth = 15 }))
end)
it('does not take a zero item width literally', function()
command('file some/dir/testfile.txt')
eq({ str = 'abc', width = 3 }, api.nvim_eval_statusline('%.0(abc%)', {}))
eq(api.nvim_eval_statusline('%.50f', {}), api.nvim_eval_statusline('%.0f', {}))
eq(api.nvim_eval_statusline('%.50l', {}), api.nvim_eval_statusline('%.0l', {}))
end)
it('has correct default fillchar', function()
local oldwin = api.nvim_get_current_win()
command('set fillchars=stl:#,stlnc:$,wbr:%')