mirror of
https://github.com/neovim/neovim.git
synced 2026-04-02 05:39:26 +00:00
fix(ui): forward 'rulerformat' to msg_ruler event #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.
This commit is contained in:
@@ -201,6 +201,7 @@ EVENTS
|
||||
• |CmdlineLeavePre| triggered before preparing to leave the command line.
|
||||
• New `append` paremeter for |ui-messages| `msg_show` event.
|
||||
• New `msg_id` paremeter for |ui-messages| `msg_show` event.
|
||||
• 'rulerformat' is emitted as `msg_ruler` when not part of the statusline.
|
||||
• Creating or updating a progress message with |nvim_echo()| triggers a |Progress| event.
|
||||
|
||||
HIGHLIGHTS
|
||||
|
||||
@@ -2141,8 +2141,8 @@ DictAs(eval_statusline_ret) nvim_eval_statusline(String str, Dict(eval_statuslin
|
||||
if (opts->use_winbar) {
|
||||
fillchar = wp->w_p_fcs_chars.wbr;
|
||||
} else {
|
||||
int attr;
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
hlf_T group;
|
||||
fillchar = fillchar_status(&group, wp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -513,17 +513,13 @@ static int wildmenu_match_len(expand_T *xp, char *s)
|
||||
/// @param matches list of matches
|
||||
static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, bool showtail)
|
||||
{
|
||||
int len;
|
||||
int clen; // length in screen cells
|
||||
int attr;
|
||||
int i;
|
||||
bool highlight = true;
|
||||
char *selstart = NULL;
|
||||
int selstart_col = 0;
|
||||
char *selend = NULL;
|
||||
static int first_match = 0;
|
||||
bool add_left = false;
|
||||
int l;
|
||||
int i, l;
|
||||
|
||||
if (matches == NULL) { // interrupted completion?
|
||||
return;
|
||||
@@ -536,7 +532,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
|
||||
highlight = false;
|
||||
}
|
||||
// count 1 for the ending ">"
|
||||
clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3;
|
||||
int clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3; // length in screen cells
|
||||
if (match == 0) {
|
||||
first_match = 0;
|
||||
} else if (match < first_match) {
|
||||
@@ -577,7 +573,10 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
|
||||
}
|
||||
}
|
||||
|
||||
schar_T fillchar = fillchar_status(&attr, curwin);
|
||||
int len;
|
||||
hlf_T group;
|
||||
schar_T fillchar = fillchar_status(&group, curwin);
|
||||
int attr = win_hl_attr(curwin, (int)group);
|
||||
|
||||
if (first_match == 0) {
|
||||
*buf = NUL;
|
||||
|
||||
@@ -2094,6 +2094,7 @@ static const char *did_set_laststatus(optset_T *args)
|
||||
win_comp_pos();
|
||||
}
|
||||
|
||||
status_redraw_curbuf();
|
||||
last_status(false); // (re)set last window status line.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ typedef enum {
|
||||
/// If inversion is possible we use it. Else '=' characters are used.
|
||||
void win_redr_status(win_T *wp)
|
||||
{
|
||||
int attr;
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
static bool busy = false;
|
||||
|
||||
@@ -92,15 +91,16 @@ void win_redr_status(win_T *wp)
|
||||
redraw_custom_statusline(wp);
|
||||
}
|
||||
|
||||
hlf_T group = HLF_C;
|
||||
// May need to draw the character below the vertical separator.
|
||||
if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) {
|
||||
schar_T fillchar;
|
||||
if (stl_connected(wp)) {
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
fillchar = fillchar_status(&group, wp);
|
||||
} else {
|
||||
attr = win_hl_attr(wp, HLF_C);
|
||||
fillchar = wp->w_p_fcs_chars.vert;
|
||||
}
|
||||
int attr = win_hl_attr(wp, (int)group);
|
||||
grid_line_start(&default_gridview, W_ENDROW(wp));
|
||||
grid_line_put_schar(W_ENDCOL(wp), fillchar, attr);
|
||||
grid_line_flush();
|
||||
@@ -208,15 +208,17 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
|
||||
}
|
||||
}
|
||||
|
||||
/// Redraw the status line, window bar or ruler of window "wp".
|
||||
/// When "wp" is NULL redraw the tab pages line from 'tabline'.
|
||||
static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
/// Redraw the status line, window bar, ruler or tabline.
|
||||
/// @param wp target window, NULL for 'tabline'
|
||||
/// @param draw_winbar redraw 'winbar'
|
||||
/// @param draw_ruler redraw 'rulerformat'
|
||||
/// @param ui_event emit UI-event instead of drawing
|
||||
static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool ui_event)
|
||||
{
|
||||
static bool entered = false;
|
||||
int attr;
|
||||
int row;
|
||||
int col = 0;
|
||||
int maxwidth;
|
||||
int attr, row, maxwidth;
|
||||
hlf_T group;
|
||||
schar_T fillchar;
|
||||
char buf[MAXPATHL];
|
||||
char transbuf[MAXPATHL];
|
||||
@@ -243,7 +245,8 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
stl = p_tal;
|
||||
row = 0;
|
||||
fillchar = schar_from_ascii(' ');
|
||||
attr = HL_ATTR(HLF_TPF);
|
||||
group = HLF_TPF;
|
||||
attr = HL_ATTR(group);
|
||||
maxwidth = Columns;
|
||||
opt_idx = kOptTabline;
|
||||
} else if (draw_winbar) {
|
||||
@@ -259,14 +262,15 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
}
|
||||
|
||||
fillchar = wp->w_p_fcs_chars.wbr;
|
||||
attr = (wp == curwin) ? win_hl_attr(wp, HLF_WBR) : win_hl_attr(wp, HLF_WBRNC);
|
||||
group = (wp == curwin) ? HLF_WBR : HLF_WBRNC;
|
||||
attr = win_hl_attr(wp, (int)group);
|
||||
maxwidth = wp->w_view_width;
|
||||
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||
wp->w_winbar_click_defs = stl_alloc_click_defs(wp->w_winbar_click_defs, maxwidth,
|
||||
&wp->w_winbar_click_defs_size);
|
||||
} else {
|
||||
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
fillchar = fillchar_status(&group, wp);
|
||||
const bool in_status_line = wp->w_status_height != 0 || is_stl_global;
|
||||
maxwidth = in_status_line && !is_stl_global ? wp->w_width : Columns;
|
||||
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||
@@ -297,7 +301,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
grid = grid_adjust(&msg_grid_adj, &row, &col);
|
||||
maxwidth--; // writing in last column may cause scrolling
|
||||
fillchar = schar_from_ascii(' ');
|
||||
attr = HL_ATTR(HLF_MSG);
|
||||
group = HLF_MSG;
|
||||
}
|
||||
} else {
|
||||
opt_idx = kOptStatusline;
|
||||
@@ -305,6 +309,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
|
||||
}
|
||||
|
||||
attr = win_hl_attr(wp, (int)group);
|
||||
if (in_status_line && !is_stl_global) {
|
||||
col += wp->w_wincol;
|
||||
}
|
||||
@@ -332,31 +337,57 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
int len = (int)strlen(buf);
|
||||
int start_col = col;
|
||||
|
||||
// Draw each snippet with the specified highlighting.
|
||||
screengrid_line_start(grid, row, 0);
|
||||
if (!ui_event) {
|
||||
// Draw each snippet with the specified highlighting.
|
||||
screengrid_line_start(grid, row, 0);
|
||||
}
|
||||
|
||||
int curattr = attr;
|
||||
char *p = buf;
|
||||
for (int n = 0; hltab[n].start != NULL; n++) {
|
||||
int textlen = (int)(hltab[n].start - p);
|
||||
// Make all characters printable.
|
||||
size_t tsize = transstr_buf(p, textlen, transbuf, sizeof transbuf, true);
|
||||
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
|
||||
p = hltab[n].start;
|
||||
|
||||
if (hltab[n].userhl == 0) {
|
||||
curattr = attr;
|
||||
} else if (hltab[n].userhl < 0) {
|
||||
curattr = hl_combine_attr(attr, syn_id2attr(-hltab[n].userhl));
|
||||
} else if (wp != NULL && wp != curwin && wp->w_status_height != 0) {
|
||||
curattr = highlight_stlnc[hltab[n].userhl - 1];
|
||||
int curattr = attr;
|
||||
int curgroup = (int)group;
|
||||
Array content = ARRAY_DICT_INIT;
|
||||
for (stl_hlrec_t *sp = hltab;; sp++) {
|
||||
int textlen = (int)(sp->start ? sp->start - p : buf + len - p);
|
||||
// Make all characters printable. Use an empty string instead of p, if p is beyond buf + len.
|
||||
size_t tsize = transstr_buf(p >= buf + len ? "" : p, textlen, transbuf, sizeof transbuf, true);
|
||||
if (!ui_event) {
|
||||
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
|
||||
} else {
|
||||
curattr = highlight_user[hltab[n].userhl - 1];
|
||||
Array chunk = ARRAY_DICT_INIT;
|
||||
ADD(chunk, INTEGER_OBJ(curattr));
|
||||
ADD(chunk, STRING_OBJ(cbuf_as_string(xmemdupz(transbuf, tsize), tsize)));
|
||||
ADD(chunk, INTEGER_OBJ(curgroup));
|
||||
ADD(content, ARRAY_OBJ(chunk));
|
||||
}
|
||||
p = sp->start;
|
||||
|
||||
if (p == NULL) {
|
||||
break;
|
||||
} else if (sp->userhl == 0) {
|
||||
curattr = attr;
|
||||
curgroup = (int)group;
|
||||
} else if (sp->userhl < 0) {
|
||||
curattr = syn_id2attr(-sp->userhl);
|
||||
curgroup = -sp->userhl;
|
||||
} else {
|
||||
int *userhl = (wp != NULL && wp != curwin && wp->w_status_height != 0)
|
||||
? highlight_stlnc : highlight_user;
|
||||
char userbuf[5] = "User";
|
||||
userbuf[4] = (char)sp->userhl + '0';
|
||||
curattr = userhl[sp->userhl - 1];
|
||||
curgroup = syn_name2id_len(userbuf, 5);
|
||||
}
|
||||
if (curattr != attr) {
|
||||
curattr = hl_combine_attr(attr, curattr);
|
||||
}
|
||||
}
|
||||
// Make sure to use an empty string instead of p, if p is beyond buf + len.
|
||||
size_t tsize = transstr_buf(p >= buf + len ? "" : p, -1, transbuf, sizeof transbuf, true);
|
||||
col += grid_line_puts(col, transbuf, (int)tsize, curattr);
|
||||
|
||||
if (ui_event) {
|
||||
ui_call_msg_ruler(content);
|
||||
api_free_array(content);
|
||||
goto theend;
|
||||
}
|
||||
|
||||
int maxcol = start_col + maxwidth;
|
||||
|
||||
// fill up with "fillchar"
|
||||
@@ -389,7 +420,7 @@ void win_redr_winbar(win_T *wp)
|
||||
if (wp->w_winbar_height == 0 || !redrawing()) {
|
||||
// Do nothing.
|
||||
} else if (*p_wbr != NUL || *wp->w_p_wbr != NUL) {
|
||||
win_redr_custom(wp, true, false);
|
||||
win_redr_custom(wp, true, false, false);
|
||||
}
|
||||
entered = false;
|
||||
}
|
||||
@@ -423,44 +454,22 @@ void redraw_ruler(void)
|
||||
|
||||
// Don't draw the ruler while doing insert-completion, it might overwrite
|
||||
// the (long) mode message.
|
||||
if (wp->w_status_height == 0 && !is_stl_global) {
|
||||
if (edit_submode != NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p_ruf && p_ch > 0 && !ui_has(kUIMessages)) {
|
||||
win_redr_custom(wp, false, true);
|
||||
if (wp->w_status_height == 0 && !is_stl_global && edit_submode != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if not in Insert mode and the line is empty (will show "0-1").
|
||||
int empty_line = (State & MODE_INSERT) == 0
|
||||
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
|
||||
|
||||
int width;
|
||||
schar_T fillchar;
|
||||
int attr;
|
||||
int off;
|
||||
bool part_of_status = false;
|
||||
|
||||
if (wp->w_status_height) {
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
off = wp->w_wincol;
|
||||
width = wp->w_width;
|
||||
part_of_status = true;
|
||||
} else if (is_stl_global) {
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
off = 0;
|
||||
width = Columns;
|
||||
part_of_status = true;
|
||||
} else {
|
||||
fillchar = schar_from_ascii(' ');
|
||||
attr = HL_ATTR(HLF_MSG);
|
||||
width = Columns;
|
||||
off = 0;
|
||||
bool part_of_status = wp->w_status_height || is_stl_global;
|
||||
if (*p_ruf && (p_ch > 0 || (ui_has(kUIMessages) && !part_of_status))) {
|
||||
win_redr_custom(wp, false, true, ui_has(kUIMessages));
|
||||
return;
|
||||
}
|
||||
|
||||
hlf_T group = HLF_MSG;
|
||||
int off = wp->w_status_height ? wp->w_wincol : 0;
|
||||
int width = wp->w_status_height ? wp->w_width : Columns;
|
||||
schar_T fillchar = part_of_status ? fillchar_status(&group, wp) : schar_from_ascii(' ');
|
||||
int attr = win_hl_attr(wp, (int)group);
|
||||
|
||||
// In list mode virtcol needs to be recomputed
|
||||
colnr_T virtcol = wp->w_virtcol;
|
||||
if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) {
|
||||
@@ -469,6 +478,10 @@ void redraw_ruler(void)
|
||||
wp->w_p_list = true;
|
||||
}
|
||||
|
||||
// Check if not in Insert mode and the line is empty (will show "0-1").
|
||||
int empty_line = (State & MODE_INSERT) == 0
|
||||
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
|
||||
|
||||
#define RULER_BUF_LEN 70
|
||||
char buffer[RULER_BUF_LEN];
|
||||
|
||||
@@ -542,13 +555,13 @@ void redraw_ruler(void)
|
||||
}
|
||||
|
||||
/// Get the character to use in a status line. Get its attributes in "*attr".
|
||||
schar_T fillchar_status(int *attr, win_T *wp)
|
||||
schar_T fillchar_status(hlf_T *group, win_T *wp)
|
||||
{
|
||||
if (wp == curwin) {
|
||||
*attr = win_hl_attr(wp, HLF_S);
|
||||
*group = HLF_S;
|
||||
return wp->w_p_fcs_chars.stl;
|
||||
} else {
|
||||
*attr = win_hl_attr(wp, HLF_SNC);
|
||||
*group = HLF_SNC;
|
||||
return wp->w_p_fcs_chars.stlnc;
|
||||
}
|
||||
}
|
||||
@@ -566,7 +579,7 @@ void redraw_custom_statusline(win_T *wp)
|
||||
}
|
||||
entered = true;
|
||||
|
||||
win_redr_custom(wp, false, false);
|
||||
win_redr_custom(wp, false, false, false);
|
||||
entered = false;
|
||||
}
|
||||
|
||||
@@ -644,7 +657,7 @@ void draw_tabline(void)
|
||||
|
||||
// Use the 'tabline' option if it's set.
|
||||
if (*p_tal != NUL) {
|
||||
win_redr_custom(NULL, false, false);
|
||||
win_redr_custom(NULL, false, false, false);
|
||||
} else {
|
||||
int tabcount = 0;
|
||||
int col = 0;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "nvim/highlight_defs.h"
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/option_defs.h" // IWYU pragma: keep
|
||||
#include "nvim/statusline_defs.h" // IWYU pragma: keep
|
||||
|
||||
@@ -12,6 +12,15 @@ describe('statusline', function()
|
||||
|
||||
before_each(function()
|
||||
screen = Screen.new(50, 7)
|
||||
screen:add_extra_attr_ids({
|
||||
[100] = {
|
||||
background = Screen.colors.Red,
|
||||
foreground = Screen.colors.Gray100,
|
||||
reverse = true,
|
||||
bold = true,
|
||||
},
|
||||
[101] = { foreground = Screen.colors.Blue, reverse = true, bold = true },
|
||||
})
|
||||
end)
|
||||
|
||||
it('is updated in cmdline mode when using window-local statusline vim-patch:8.2.2737', function()
|
||||
@@ -51,7 +60,7 @@ describe('statusline', function()
|
||||
screen:expect([[
|
||||
^ |
|
||||
{1:~ }|*4
|
||||
{9:<F}{18:GHI }|
|
||||
{100:<F}{101:GHI }|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
@@ -852,7 +852,7 @@ describe('ui/ext_messages', function()
|
||||
}
|
||||
end)
|
||||
|
||||
it('supports &showcmd and &ruler', function()
|
||||
it("supports 'showcmd' and 'ruler(format)'", function()
|
||||
command('set showcmd ruler')
|
||||
command('hi link MsgArea ErrorMsg')
|
||||
screen:expect({
|
||||
@@ -940,19 +940,26 @@ describe('ui/ext_messages', function()
|
||||
]],
|
||||
ruler = { { '2,0-1 All', 'MsgArea' } },
|
||||
}
|
||||
|
||||
-- when ruler is part of statusline it is not externalized.
|
||||
-- this will be added as part of future ext_statusline support
|
||||
command('set laststatus=2')
|
||||
command('set rulerformat=Foo%#ErrorMsg#Bar')
|
||||
screen:expect({
|
||||
grid = [[
|
||||
abcde |
|
||||
^ |
|
||||
{1:~ }|*2
|
||||
{3:<] [+] 2,0-1 All}|
|
||||
{1:~ }|*3
|
||||
]],
|
||||
ruler = { { '2,0-1 All', 'MsgArea' } },
|
||||
ruler = { { 'Foo', 'MsgArea' }, { 'Bar', 9, 'ErrorMsg' } },
|
||||
})
|
||||
command('set rulerformat=')
|
||||
|
||||
-- when ruler is part of statusline it is not externalized.
|
||||
-- this will be added as part of future ext_statusline support
|
||||
command('set laststatus=2')
|
||||
screen:expect([[
|
||||
abcde |
|
||||
^ |
|
||||
{1:~ }|*2
|
||||
{3:<] [+] 2,0-1 All}|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('keeps history of message of different kinds', function()
|
||||
|
||||
@@ -315,6 +315,8 @@ func Test_statusline()
|
||||
call assert_equal(sa3, screenattr(&lines - 1, 7))
|
||||
|
||||
" %*: Set highlight group to User{N}
|
||||
" Nvim: Combined with hl-StatusLine so needs to be set.
|
||||
hi link User1 ErrorMsg
|
||||
set statusline=a%1*b%0*c
|
||||
call assert_match('^abc\s*$', s:get_statusline())
|
||||
let sa1=screenattr(&lines - 1, 1)
|
||||
|
||||
Reference in New Issue
Block a user