From e8d7a40b98ce4062834399f097216213a0088ff3 Mon Sep 17 00:00:00 2001 From: glepnir Date: Mon, 25 May 2026 17:30:22 +0000 Subject: [PATCH] patch 9.2.0538: Cannot keep leading whitespace in %{} statusline expr Problem: A leading space in the result of a %{} item is sometimes stripped, and an all-digit result is converted to a number. Solution: Add %0{} atom which inserts the expression result verbatim (glepnir) fixes: #3898 closes: #20315 Signed-off-by: glepnir Signed-off-by: Christian Brabandt --- runtime/doc/options.txt | 5 ++++- runtime/doc/tags | 1 + runtime/doc/version9.txt | 2 ++ src/buffer.c | 5 +++-- src/testdir/test_statusline.vim | 10 ++++++++++ src/version.c | 2 ++ 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6dc518cc75..0ef255210b 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -8670,7 +8670,8 @@ A jump table for the options with a short description can be found at |Q_op|. { NF Evaluate expression between '%{' and '}' and substitute result. Note that there is no '%' before the closing '}'. The expression cannot contain a '}' character, call a function to - work around that. See |stl-%{| below. + work around that. See |stl-%{| below. Use '%0{' to insert the + result verbatim. {% - This is almost same as { except the result of the expression is re-evaluated as a statusline format string. Thus if the return value of expr contains % items they will get expanded. @@ -8797,6 +8798,8 @@ A jump table for the options with a short description can be found at |Q_op|. A result of all digits is regarded a number for display purposes. Otherwise the result is taken as flag text and applied to the rules described above. + *stl-%0{* + With %0{ neither applies: the result is inserted as a literal string. Watch out for errors in expressions. They may render Vim unusable! If you are stuck, hold down ':' or 'Q' to get a prompt, then quit and diff --git a/runtime/doc/tags b/runtime/doc/tags index 2291864943..714a9b7dbe 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -10562,6 +10562,7 @@ static-tag tagsrch.txt /*static-tag* status-line windows.txt /*status-line* statusmsg-variable eval.txt /*statusmsg-variable* stl-%! options.txt /*stl-%!* +stl-%0{ options.txt /*stl-%0{* stl-%@ options.txt /*stl-%@* stl-%[FuncName] options.txt /*stl-%[FuncName]* stl-%{ options.txt /*stl-%{* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index 2bea93a323..7c2ace84e7 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -52640,6 +52640,8 @@ Other ~ well. - New argument handling for user commands |:command-nargs| using the "-nars=_" attribute to handle completion of single arguments with spaces as expected. +- Support %0{} in 'statusline' to insert the expression result verbatim and + not drop leading spaces |stl-%0{|. Platform specific ~ ----------------- diff --git a/src/buffer.c b/src/buffer.c index a903ab3753..07176fbc43 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5041,7 +5041,8 @@ build_stl_str_hl_local( if (reevaluate) s++; - itemisflag = TRUE; + // %0{} keeps the result verbatim + itemisflag = zeropad ? FALSE : TRUE; t = p; while ((*s != '}' || (reevaluate && s[-1] != '%')) && *s != NUL && p + 1 < out + outlen) @@ -5078,7 +5079,7 @@ build_stl_str_hl_local( do_unlet((char_u *)"g:actual_curbuf", TRUE); do_unlet((char_u *)"g:actual_curwin", TRUE); - if (str != NULL && *str != NUL) + if (!zeropad && str != NULL && *str != NUL) { if (*skipdigits(str) == NUL) { diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim index 34aa94e4c5..48c7bb6696 100644 --- a/src/testdir/test_statusline.vim +++ b/src/testdir/test_statusline.vim @@ -282,6 +282,16 @@ func Test_statusline() call assert_match('^vimLineComment\s*$', s:get_statusline()) syntax off + " %0{: result of expression is inserted verbatim + set statusline=%{'\ x'} + call assert_match('^x\s*$', s:get_statusline()) + set statusline=%0{'\ x'} + call assert_match('^ x\s*$', s:get_statusline()) + set statusline=%{'000'} + call assert_match('^0\s*$', s:get_statusline()) + set statusline=%0{'000'} + call assert_match('^000\s*$', s:get_statusline()) + "%{%expr%}: evaluates expressions present in result of expr func! Inner_eval() return '%n some other text' diff --git a/src/version.c b/src/version.c index f86259cc9e..0707c875de 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 538, /**/ 537, /**/