Skip to content

Commit a3993f1

Browse files
luukvbaaldundargoc
authored andcommitted
fix(ui): forward 'rulerformat' to msg_ruler event neovim#35707
Problem: A 'rulerformat' not part of the statusline is not emitted through msg_ruler events. Solution: Build the message chunks to emit as a msg_ruler event.
1 parent 000f2d7 commit a3993f1

File tree

9 files changed

+121
-88
lines changed

9 files changed

+121
-88
lines changed

runtime/doc/news.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ EVENTS
201201
|CmdlineLeavePre| triggered before preparing to leave the command line.
202202
• New `append` paremeter for |ui-messages| `msg_show` event.
203203
• New `msg_id` paremeter for |ui-messages| `msg_show` event.
204+
'rulerformat' is emitted as `msg_ruler` when not part of the statusline.
204205
• Creating or updating a progress message with |nvim_echo()| triggers a |Progress| event.
205206

206207
HIGHLIGHTS

src/nvim/api/vim.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,8 +2141,8 @@ DictAs(eval_statusline_ret) nvim_eval_statusline(String str, Dict(eval_statuslin
21412141
if (opts->use_winbar) {
21422142
fillchar = wp->w_p_fcs_chars.wbr;
21432143
} else {
2144-
int attr;
2145-
fillchar = fillchar_status(&attr, wp);
2144+
hlf_T group;
2145+
fillchar = fillchar_status(&group, wp);
21462146
}
21472147
}
21482148

src/nvim/cmdexpand.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -513,17 +513,13 @@ static int wildmenu_match_len(expand_T *xp, char *s)
513513
/// @param matches list of matches
514514
static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, bool showtail)
515515
{
516-
int len;
517-
int clen; // length in screen cells
518-
int attr;
519-
int i;
520516
bool highlight = true;
521517
char *selstart = NULL;
522518
int selstart_col = 0;
523519
char *selend = NULL;
524520
static int first_match = 0;
525521
bool add_left = false;
526-
int l;
522+
int i, l;
527523

528524
if (matches == NULL) { // interrupted completion?
529525
return;
@@ -536,7 +532,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
536532
highlight = false;
537533
}
538534
// count 1 for the ending ">"
539-
clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3;
535+
int clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3; // length in screen cells
540536
if (match == 0) {
541537
first_match = 0;
542538
} else if (match < first_match) {
@@ -577,7 +573,10 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
577573
}
578574
}
579575

580-
schar_T fillchar = fillchar_status(&attr, curwin);
576+
int len;
577+
hlf_T group;
578+
schar_T fillchar = fillchar_status(&group, curwin);
579+
int attr = win_hl_attr(curwin, (int)group);
581580

582581
if (first_match == 0) {
583582
*buf = NUL;

src/nvim/option.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,6 +2094,7 @@ static const char *did_set_laststatus(optset_T *args)
20942094
win_comp_pos();
20952095
}
20962096

2097+
status_redraw_curbuf();
20972098
last_status(false); // (re)set last window status line.
20982099
return NULL;
20992100
}

src/nvim/statusline.c

Lines changed: 83 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ typedef enum {
6666
/// If inversion is possible we use it. Else '=' characters are used.
6767
void win_redr_status(win_T *wp)
6868
{
69-
int attr;
7069
bool is_stl_global = global_stl_height() > 0;
7170
static bool busy = false;
7271

@@ -92,15 +91,16 @@ void win_redr_status(win_T *wp)
9291
redraw_custom_statusline(wp);
9392
}
9493

94+
hlf_T group = HLF_C;
9595
// May need to draw the character below the vertical separator.
9696
if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) {
9797
schar_T fillchar;
9898
if (stl_connected(wp)) {
99-
fillchar = fillchar_status(&attr, wp);
99+
fillchar = fillchar_status(&group, wp);
100100
} else {
101-
attr = win_hl_attr(wp, HLF_C);
102101
fillchar = wp->w_p_fcs_chars.vert;
103102
}
103+
int attr = win_hl_attr(wp, (int)group);
104104
grid_line_start(&default_gridview, W_ENDROW(wp));
105105
grid_line_put_schar(W_ENDCOL(wp), fillchar, attr);
106106
grid_line_flush();
@@ -208,15 +208,17 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
208208
}
209209
}
210210

211-
/// Redraw the status line, window bar or ruler of window "wp".
212-
/// When "wp" is NULL redraw the tab pages line from 'tabline'.
213-
static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
211+
/// Redraw the status line, window bar, ruler or tabline.
212+
/// @param wp target window, NULL for 'tabline'
213+
/// @param draw_winbar redraw 'winbar'
214+
/// @param draw_ruler redraw 'rulerformat'
215+
/// @param ui_event emit UI-event instead of drawing
216+
static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool ui_event)
214217
{
215218
static bool entered = false;
216-
int attr;
217-
int row;
218219
int col = 0;
219-
int maxwidth;
220+
int attr, row, maxwidth;
221+
hlf_T group;
220222
schar_T fillchar;
221223
char buf[MAXPATHL];
222224
char transbuf[MAXPATHL];
@@ -243,7 +245,8 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
243245
stl = p_tal;
244246
row = 0;
245247
fillchar = schar_from_ascii(' ');
246-
attr = HL_ATTR(HLF_TPF);
248+
group = HLF_TPF;
249+
attr = HL_ATTR(group);
247250
maxwidth = Columns;
248251
opt_idx = kOptTabline;
249252
} else if (draw_winbar) {
@@ -259,14 +262,15 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
259262
}
260263

261264
fillchar = wp->w_p_fcs_chars.wbr;
262-
attr = (wp == curwin) ? win_hl_attr(wp, HLF_WBR) : win_hl_attr(wp, HLF_WBRNC);
265+
group = (wp == curwin) ? HLF_WBR : HLF_WBRNC;
266+
attr = win_hl_attr(wp, (int)group);
263267
maxwidth = wp->w_view_width;
264268
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
265269
wp->w_winbar_click_defs = stl_alloc_click_defs(wp->w_winbar_click_defs, maxwidth,
266270
&wp->w_winbar_click_defs_size);
267271
} else {
268272
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
269-
fillchar = fillchar_status(&attr, wp);
273+
fillchar = fillchar_status(&group, wp);
270274
const bool in_status_line = wp->w_status_height != 0 || is_stl_global;
271275
maxwidth = in_status_line && !is_stl_global ? wp->w_width : Columns;
272276
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
@@ -297,14 +301,15 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
297301
grid = grid_adjust(&msg_grid_adj, &row, &col);
298302
maxwidth--; // writing in last column may cause scrolling
299303
fillchar = schar_from_ascii(' ');
300-
attr = HL_ATTR(HLF_MSG);
304+
group = HLF_MSG;
301305
}
302306
} else {
303307
opt_idx = kOptStatusline;
304308
stl = ((*wp->w_p_stl != NUL) ? wp->w_p_stl : p_stl);
305309
opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
306310
}
307311

312+
attr = win_hl_attr(wp, (int)group);
308313
if (in_status_line && !is_stl_global) {
309314
col += wp->w_wincol;
310315
}
@@ -332,31 +337,57 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
332337
int len = (int)strlen(buf);
333338
int start_col = col;
334339

335-
// Draw each snippet with the specified highlighting.
336-
screengrid_line_start(grid, row, 0);
340+
if (!ui_event) {
341+
// Draw each snippet with the specified highlighting.
342+
screengrid_line_start(grid, row, 0);
343+
}
337344

338-
int curattr = attr;
339345
char *p = buf;
340-
for (int n = 0; hltab[n].start != NULL; n++) {
341-
int textlen = (int)(hltab[n].start - p);
342-
// Make all characters printable.
343-
size_t tsize = transstr_buf(p, textlen, transbuf, sizeof transbuf, true);
344-
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
345-
p = hltab[n].start;
346-
347-
if (hltab[n].userhl == 0) {
346+
int curattr = attr;
347+
int curgroup = (int)group;
348+
Array content = ARRAY_DICT_INIT;
349+
for (stl_hlrec_t *sp = hltab;; sp++) {
350+
int textlen = (int)(sp->start ? sp->start - p : buf + len - p);
351+
// Make all characters printable. Use an empty string instead of p, if p is beyond buf + len.
352+
size_t tsize = transstr_buf(p >= buf + len ? "" : p, textlen, transbuf, sizeof transbuf, true);
353+
if (!ui_event) {
354+
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
355+
} else {
356+
Array chunk = ARRAY_DICT_INIT;
357+
ADD(chunk, INTEGER_OBJ(curattr));
358+
ADD(chunk, STRING_OBJ(cbuf_as_string(xmemdupz(transbuf, tsize), tsize)));
359+
ADD(chunk, INTEGER_OBJ(curgroup));
360+
ADD(content, ARRAY_OBJ(chunk));
361+
}
362+
p = sp->start;
363+
364+
if (p == NULL) {
365+
break;
366+
} else if (sp->userhl == 0) {
348367
curattr = attr;
349-
} else if (hltab[n].userhl < 0) {
350-
curattr = hl_combine_attr(attr, syn_id2attr(-hltab[n].userhl));
351-
} else if (wp != NULL && wp != curwin && wp->w_status_height != 0) {
352-
curattr = highlight_stlnc[hltab[n].userhl - 1];
368+
curgroup = (int)group;
369+
} else if (sp->userhl < 0) {
370+
curattr = syn_id2attr(-sp->userhl);
371+
curgroup = -sp->userhl;
353372
} else {
354-
curattr = highlight_user[hltab[n].userhl - 1];
373+
int *userhl = (wp != NULL && wp != curwin && wp->w_status_height != 0)
374+
? highlight_stlnc : highlight_user;
375+
char userbuf[5] = "User";
376+
userbuf[4] = (char)sp->userhl + '0';
377+
curattr = userhl[sp->userhl - 1];
378+
curgroup = syn_name2id_len(userbuf, 5);
379+
}
380+
if (curattr != attr) {
381+
curattr = hl_combine_attr(attr, curattr);
355382
}
356383
}
357-
// Make sure to use an empty string instead of p, if p is beyond buf + len.
358-
size_t tsize = transstr_buf(p >= buf + len ? "" : p, -1, transbuf, sizeof transbuf, true);
359-
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
384+
385+
if (ui_event) {
386+
ui_call_msg_ruler(content);
387+
api_free_array(content);
388+
goto theend;
389+
}
390+
360391
int maxcol = start_col + maxwidth;
361392

362393
// fill up with "fillchar"
@@ -389,7 +420,7 @@ void win_redr_winbar(win_T *wp)
389420
if (wp->w_winbar_height == 0 || !redrawing()) {
390421
// Do nothing.
391422
} else if (*p_wbr != NUL || *wp->w_p_wbr != NUL) {
392-
win_redr_custom(wp, true, false);
423+
win_redr_custom(wp, true, false, false);
393424
}
394425
entered = false;
395426
}
@@ -423,43 +454,21 @@ void redraw_ruler(void)
423454

424455
// Don't draw the ruler while doing insert-completion, it might overwrite
425456
// the (long) mode message.
426-
if (wp->w_status_height == 0 && !is_stl_global) {
427-
if (edit_submode != NULL) {
428-
return;
429-
}
457+
if (wp->w_status_height == 0 && !is_stl_global && edit_submode != NULL) {
458+
return;
430459
}
431460

432-
if (*p_ruf && p_ch > 0 && !ui_has(kUIMessages)) {
433-
win_redr_custom(wp, false, true);
461+
bool part_of_status = wp->w_status_height || is_stl_global;
462+
if (*p_ruf && (p_ch > 0 || (ui_has(kUIMessages) && !part_of_status))) {
463+
win_redr_custom(wp, false, true, ui_has(kUIMessages));
434464
return;
435465
}
436466

437-
// Check if not in Insert mode and the line is empty (will show "0-1").
438-
int empty_line = (State & MODE_INSERT) == 0
439-
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
440-
441-
int width;
442-
schar_T fillchar;
443-
int attr;
444-
int off;
445-
bool part_of_status = false;
446-
447-
if (wp->w_status_height) {
448-
fillchar = fillchar_status(&attr, wp);
449-
off = wp->w_wincol;
450-
width = wp->w_width;
451-
part_of_status = true;
452-
} else if (is_stl_global) {
453-
fillchar = fillchar_status(&attr, wp);
454-
off = 0;
455-
width = Columns;
456-
part_of_status = true;
457-
} else {
458-
fillchar = schar_from_ascii(' ');
459-
attr = HL_ATTR(HLF_MSG);
460-
width = Columns;
461-
off = 0;
462-
}
467+
hlf_T group = HLF_MSG;
468+
int off = wp->w_status_height ? wp->w_wincol : 0;
469+
int width = wp->w_status_height ? wp->w_width : Columns;
470+
schar_T fillchar = part_of_status ? fillchar_status(&group, wp) : schar_from_ascii(' ');
471+
int attr = win_hl_attr(wp, (int)group);
463472

464473
// In list mode virtcol needs to be recomputed
465474
colnr_T virtcol = wp->w_virtcol;
@@ -469,6 +478,10 @@ void redraw_ruler(void)
469478
wp->w_p_list = true;
470479
}
471480

481+
// Check if not in Insert mode and the line is empty (will show "0-1").
482+
int empty_line = (State & MODE_INSERT) == 0
483+
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
484+
472485
#define RULER_BUF_LEN 70
473486
char buffer[RULER_BUF_LEN];
474487

@@ -542,13 +555,13 @@ void redraw_ruler(void)
542555
}
543556

544557
/// Get the character to use in a status line. Get its attributes in "*attr".
545-
schar_T fillchar_status(int *attr, win_T *wp)
558+
schar_T fillchar_status(hlf_T *group, win_T *wp)
546559
{
547560
if (wp == curwin) {
548-
*attr = win_hl_attr(wp, HLF_S);
561+
*group = HLF_S;
549562
return wp->w_p_fcs_chars.stl;
550563
} else {
551-
*attr = win_hl_attr(wp, HLF_SNC);
564+
*group = HLF_SNC;
552565
return wp->w_p_fcs_chars.stlnc;
553566
}
554567
}
@@ -566,7 +579,7 @@ void redraw_custom_statusline(win_T *wp)
566579
}
567580
entered = true;
568581

569-
win_redr_custom(wp, false, false);
582+
win_redr_custom(wp, false, false, false);
570583
entered = false;
571584
}
572585

@@ -644,7 +657,7 @@ void draw_tabline(void)
644657

645658
// Use the 'tabline' option if it's set.
646659
if (*p_tal != NUL) {
647-
win_redr_custom(NULL, false, false);
660+
win_redr_custom(NULL, false, false, false);
648661
} else {
649662
int tabcount = 0;
650663
int col = 0;

src/nvim/statusline.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <stddef.h>
44

5+
#include "nvim/highlight_defs.h"
56
#include "nvim/macros_defs.h"
67
#include "nvim/option_defs.h" // IWYU pragma: keep
78
#include "nvim/statusline_defs.h" // IWYU pragma: keep

test/functional/legacy/statusline_spec.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ describe('statusline', function()
1212

1313
before_each(function()
1414
screen = Screen.new(50, 7)
15+
screen:add_extra_attr_ids({
16+
[100] = {
17+
background = Screen.colors.Red,
18+
foreground = Screen.colors.Gray100,
19+
reverse = true,
20+
bold = true,
21+
},
22+
[101] = { foreground = Screen.colors.Blue, reverse = true, bold = true },
23+
})
1524
end)
1625

1726
it('is updated in cmdline mode when using window-local statusline vim-patch:8.2.2737', function()
@@ -51,7 +60,7 @@ describe('statusline', function()
5160
screen:expect([[
5261
^ |
5362
{1:~ }|*4
54-
{9:<F}{18:GHI }|
63+
{100:<F}{101:GHI }|
5564
|
5665
]])
5766
end)

0 commit comments

Comments
 (0)