From c5be3315027de331bc201c3a4bb69180e33f6360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Hoffmann?= Date: Sun, 28 Jun 2026 14:40:33 +0200 Subject: [PATCH] fix(ui2)!: don't constrain ruler to ru_wid, fix leading item group Problem: ui2's ruler is no longer of fixed width, and the internal width variable `ru_wid` now acts as an arbitrary maximum, which is unnecessary because the same can now be achieved transparently with an item group. Furthermore, the old way of setting `ru_wid` with an overloaded subset of the item group syntax leads to a number of inconsistencies. In particular, when the configured ruler expression is reused for including the ruler into the statusline, where the item group syntax is interpreted in the usual way. The fact that this width is set in the `minwid` position is more confusing now that it is a de-facto maximum. Solution: for ui2, constrain the ruler only by half the screen width, which previously was an additional limit relevant on small screens. Skip the special-case treatment of the ruler's leading item group spec, process it like a normal item group. Example: the current fallback ruler expression in the default statusline now actually works for `rulerformat` itself: set rulerformat=%-14.(%l,%c%V%)\ %P because the result can naturally expand to 18 cells instead of being truncated to the default 17 cells, and removing the period after `minwid` doesn't change the result, whereas before, it would unhelpfully lead to setting the fixed ruler width to 14 cells. BREAKING CHANGE: if the user used to set the ruler's fixed width, it will now be treated as minimum instead of a maximum width, which in practice increases backwards-compatibility with ui1 and vim. The main remaining difference is that item groups are right-aligned by default, but backwards-compatibility can be achieved by setting a negative `minwid`, which ui1 and vim ignore. To restore the previous fixed width, specify `maxwid` as well, but this does not work in ui1 and vim. If `rulerformat` contains a `%=` without enclosing item group, it will now expand to fill half the screen width. But in that case, it will already spread out similarly in the new expression-based statusline, so consistency of the ruler in both positions is increased. To simulate the previous default behaviour, wrap it in `%-17.17(...%)`. For best compatibility and reuse with vim, leave out `maxwid` and make `minwid` negative, e.g. `%-20(...%)`. fix https://github.com/neovim/neovim/issues/40247 --- runtime/doc/news.txt | 6 +++++- runtime/doc/options.txt | 7 +++++++ runtime/lua/vim/_meta/options.gen.lua | 7 +++++++ src/nvim/options.lua | 7 +++++++ src/nvim/optionstr.c | 7 ++++--- src/nvim/statusline.c | 10 +++++++++- 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 9a2cdbbba5..96c20ea290 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -44,7 +44,11 @@ DIAGNOSTICS OPTIONS -• todo +• When |ui2| is enabled, since the ruler is no longer a left-aligned box of + fixed width, there is no longer an inconsistent special handling of item + groups in 'rulerformat' to configure that fixed width. An old-style left- + aligned fixed-width ruler can now be achieved by using item groups exactly + as they are documented, e.g. `%-20.20(...%)`. TREESITTER diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d3a1923d6f..6612af2fbb 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5169,6 +5169,13 @@ A jump table for the options with a short description can be found at |Q_op|. Example: >vim set rulerformat=%15(%c%V\ %p%%%) < + This looks like an item group, but there are some differences in this + particular case. Most notably, the width is fixed and not a minimum, + and the ruler is left-aligned, whereas the alignment of item groups is + configurable and right-aligned by default. + + When |ui2| is enabled, the ruler no longer has a fixed width and the + item group syntax has no special meaning for 'rulerformat'. *'runtimepath'* *'rtp'* *vimfiles* 'runtimepath' 'rtp' string (default "$XDG_CONFIG_HOME/nvim, diff --git a/runtime/lua/vim/_meta/options.gen.lua b/runtime/lua/vim/_meta/options.gen.lua index e7296cea5d..7b76ddbdc4 100644 --- a/runtime/lua/vim/_meta/options.gen.lua +++ b/runtime/lua/vim/_meta/options.gen.lua @@ -5380,6 +5380,13 @@ vim.go.ru = vim.go.ruler --- set rulerformat=%15(%c%V\ %p%%%) --- ``` --- +--- This looks like an item group, but there are some differences in this +--- particular case. Most notably, the width is fixed and not a minimum, +--- and the ruler is left-aligned, whereas the alignment of item groups is +--- configurable and right-aligned by default. +--- +--- When `ui2` is enabled, the ruler no longer has a fixed width and the +--- item group syntax has no special meaning for 'rulerformat'. --- --- @type string vim.o.rulerformat = "" diff --git a/src/nvim/options.lua b/src/nvim/options.lua index ebd1e3048d..cd40fa02cc 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -7073,6 +7073,13 @@ local options = { Example: >vim set rulerformat=%15(%c%V\ %p%%%) < + This looks like an item group, but there are some differences in this + particular case. Most notably, the width is fixed and not a minimum, + and the ruler is left-aligned, whereas the alignment of item groups is + configurable and right-aligned by default. + + When |ui2| is enabled, the ruler no longer has a fixed width and the + item group syntax has no special meaning for 'rulerformat'. ]=], full_name = 'rulerformat', modelineexpr = true, diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 3826f3a5b0..aef2f16eef 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -52,6 +52,7 @@ #include "nvim/tag.h" #include "nvim/terminal.h" #include "nvim/types_defs.h" +#include "nvim/ui.h" #include "nvim/vim_defs.h" #include "nvim/window.h" #include "nvim/winfloat.h" @@ -1917,7 +1918,7 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf win_config_float(win, win->w_config); } - if (rulerformat && *s == '%') { + if (rulerformat && !ui_has(kUIMessages) && *s == '%') { // set ru_wid if 'ruf' starts with "%99(" if (*++s == '-') { // ignore a '-' s++; @@ -1932,8 +1933,8 @@ static const char *did_set_statustabline_rulerformat(optset_T *args, bool rulerf errmsg = check_stl_option(p_ruf); } } - } else if (rulerformat || s[0] != '%' || s[1] != '!') { - // check 'statusline', 'winbar', 'tabline' or 'statuscolumn' + } else if (s[0] != '%' || s[1] != '!') { + // check 'statusline', 'rulerformat', 'winbar', 'tabline' or 'statuscolumn' // only if it doesn't start with "%!" errmsg = check_stl_option(s); } diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 4913dc9a02..cc2a66cdca 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -308,7 +308,15 @@ static void win_redr_stl_expr(win_T *wp, bool draw_winbar, bool draw_ruler, bool wp->w_status_click_defs = stl_alloc_click_defs(wp->w_status_click_defs, maxwidth, &wp->w_status_click_defs_size); - if (draw_ruler) { + if (draw_ruler && ui_event) { + stl = p_ruf; + opt_idx = kOptRulerformat; + maxwidth = Columns / 2; + if (!in_status_line) { + fillchar = schar_from_ascii(' '); + group = HLF_MSG; + } + } else if (draw_ruler) { stl = p_ruf; opt_idx = kOptRulerformat; // advance past any leading group spec - implicit in ru_col