Merge pull request #22859 from luukvbaal/evalstc

feat(api): evaluate 'statuscolumn' with nvim_eval_statusline()
This commit is contained in:
bfredl 2023-04-05 15:02:22 +02:00 committed by GitHub
commit 63bffae9e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 153 additions and 74 deletions

View File

@ -773,6 +773,8 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
• use_tabline: (boolean) Evaluate tabline instead of • use_tabline: (boolean) Evaluate tabline instead of
statusline. When true, {winid} is ignored. Mutually statusline. When true, {winid} is ignored. Mutually
exclusive with {use_winbar}. exclusive with {use_winbar}.
• use_statuscol: (boolean) Evaluate statuscolumn instead of
statusline.
Return: ~ Return: ~
Dictionary containing statusline information, with these keys: Dictionary containing statusline information, with these keys:

View File

@ -73,6 +73,9 @@ NEW FEATURES *news-features*
The following new APIs or features were added. The following new APIs or features were added.
• |nvim_eval_statusline()| supports evaluating the |'statuscolumn'| through a
new `opts` field: `use_statuscol`.
• |nvim_buf_get_extmarks()| now accepts a -1 `ns_id` to request extmarks from • |nvim_buf_get_extmarks()| now accepts a -1 `ns_id` to request extmarks from
all namespaces and adds the namespace id to the details array. all namespaces and adds the namespace id to the details array.
Other missing properties have been added to the details array and marks can Other missing properties have been added to the details array and marks can

View File

@ -97,6 +97,7 @@ return {
"highlights"; "highlights";
"use_winbar"; "use_winbar";
"use_tabline"; "use_tabline";
"use_statuscol";
}}; }};
{ 'option', { { 'option', {
"scope"; "scope";

View File

@ -959,12 +959,14 @@ bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
} }
/// Get default statusline highlight for window /// Get default statusline highlight for window
const char *get_default_stl_hl(win_T *wp, bool use_winbar) const char *get_default_stl_hl(win_T *wp, bool use_winbar, int stc_hl_id)
{ {
if (wp == NULL) { if (wp == NULL) {
return "TabLineFill"; return "TabLineFill";
} else if (use_winbar) { } else if (use_winbar) {
return (wp == curwin) ? "WinBar" : "WinBarNC"; return (wp == curwin) ? "WinBar" : "WinBarNC";
} else if (stc_hl_id > 0) {
return syn_id2name(stc_hl_id);
} else { } else {
return (wp == curwin) ? "StatusLine" : "StatusLineNC"; return (wp == curwin) ? "StatusLine" : "StatusLineNC";
} }

View File

@ -25,6 +25,7 @@
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/channel.h" #include "nvim/channel.h"
#include "nvim/context.h" #include "nvim/context.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h" #include "nvim/drawscreen.h"
#include "nvim/eval.h" #include "nvim/eval.h"
#include "nvim/eval/typval.h" #include "nvim/eval/typval.h"
@ -59,6 +60,7 @@
#include "nvim/popupmenu.h" #include "nvim/popupmenu.h"
#include "nvim/pos.h" #include "nvim/pos.h"
#include "nvim/runtime.h" #include "nvim/runtime.h"
#include "nvim/sign.h"
#include "nvim/state.h" #include "nvim/state.h"
#include "nvim/statusline.h" #include "nvim/statusline.h"
#include "nvim/strings.h" #include "nvim/strings.h"
@ -2054,6 +2056,7 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// - use_winbar: (boolean) Evaluate winbar instead of statusline. /// - use_winbar: (boolean) Evaluate winbar instead of statusline.
/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid} /// - use_tabline: (boolean) Evaluate tabline instead of statusline. When true, {winid}
/// is ignored. Mutually exclusive with {use_winbar}. /// is ignored. Mutually exclusive with {use_winbar}.
/// - use_statuscol: (boolean) Evaluate statuscolumn instead of statusline.
/// ///
/// @param[out] err Error details, if any. /// @param[out] err Error details, if any.
/// @return Dictionary containing statusline information, with these keys: /// @return Dictionary containing statusline information, with these keys:
@ -2071,9 +2074,11 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
int maxwidth; int maxwidth;
int fillchar = 0; int fillchar = 0;
int use_bools = 0;
Window window = 0; Window window = 0;
bool use_winbar = false; bool use_winbar = false;
bool use_tabline = false; bool use_tabline = false;
bool use_statuscol = false;
bool highlights = false; bool highlights = false;
if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) { if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) {
@ -2111,23 +2116,34 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
} }
if (HAS_KEY(opts->use_winbar)) { if (HAS_KEY(opts->use_winbar)) {
use_winbar = api_object_to_bool(opts->use_winbar, "use_winbar", false, err); use_winbar = api_object_to_bool(opts->use_winbar, "use_winbar", false, err);
use_bools++;
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return result; return result;
} }
} }
if (HAS_KEY(opts->use_tabline)) { if (HAS_KEY(opts->use_tabline)) {
use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err); use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err);
use_bools++;
if (ERROR_SET(err)) { if (ERROR_SET(err)) {
return result; return result;
} }
} }
VALIDATE(!(use_winbar && use_tabline), "%s", "Cannot use both 'use_winbar' and 'use_tabline'", { if (HAS_KEY(opts->use_statuscol)) {
use_statuscol = api_object_to_bool(opts->use_statuscol, "use_statuscol", false, err);
use_bools++;
if (ERROR_SET(err)) {
return result;
}
}
VALIDATE(use_bools <= 1, "%s",
"Can only use one of 'use_winbar', 'use_tabline' and 'use_statuscol'", {
return result; return result;
}); });
win_T *wp, *ewp; win_T *wp, *ewp;
int stc_hl_id = 0;
statuscol_T statuscol = { 0 };
SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 };
if (use_tabline) { if (use_tabline) {
wp = NULL; wp = NULL;
@ -2149,6 +2165,31 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar = fillchar_status(&attr, wp); fillchar = fillchar_status(&attr, wp);
} }
} }
if (use_statuscol) {
HlPriId line = { 0 };
HlPriId cul = { 0 };
HlPriId num = { 0 };
linenr_T lnum = (linenr_T)get_vim_var_nr(VV_LNUM);
int num_signs = buf_get_signattrs(wp->w_buffer, lnum, sattrs, &num, &line, &cul);
decor_redraw_signs(wp->w_buffer, lnum - 1, &num_signs, sattrs, &num, &line, &cul);
statuscol.sattrs = sattrs;
statuscol.foldinfo = fold_info(wp, lnum);
statuscol.use_cul = wp->w_p_cul && lnum == wp->w_cursorline
&& (wp->w_p_culopt_flags & CULOPT_NBR);
statuscol.sign_cul_id = statuscol.use_cul ? cul.hl_id : 0;
if (num.hl_id) {
stc_hl_id = num.hl_id;
} else if (statuscol.use_cul) {
stc_hl_id = HLF_CLN + 1;
} else if (wp->w_p_rnu) {
stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
} else {
stc_hl_id = HLF_N + 1;
}
set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
set_vim_var_nr(VV_VIRTNUM, 0);
}
} }
if (HAS_KEY(opts->maxwidth)) { if (HAS_KEY(opts->maxwidth)) {
@ -2158,12 +2199,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
maxwidth = (int)opts->maxwidth.data.integer; maxwidth = (int)opts->maxwidth.data.integer;
} else { } else {
maxwidth = (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width; maxwidth = use_statuscol ? win_col_off(wp)
: (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
} }
char buf[MAXPATHL]; char buf[MAXPATHL];
stl_hlrec_t *hltab; stl_hlrec_t *hltab;
stl_hlrec_t **hltab_ptr = highlights ? &hltab : NULL;
// Temporarily reset 'cursorbind' to prevent side effects from moving the cursor away and back. // Temporarily reset 'cursorbind' to prevent side effects from moving the cursor away and back.
int p_crb_save = ewp->w_p_crb; int p_crb_save = ewp->w_p_crb;
@ -2177,9 +2218,9 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
0, 0,
fillchar, fillchar,
maxwidth, maxwidth,
hltab_ptr, highlights ? &hltab : NULL,
NULL, NULL,
NULL); use_statuscol ? &statuscol : NULL);
PUT(result, "width", INTEGER_OBJ(width)); PUT(result, "width", INTEGER_OBJ(width));
@ -2195,7 +2236,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
// add the default highlight at the beginning of the highlight list // add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || (hltab->start - buf) != 0) { if (hltab->start == NULL || (hltab->start - buf) != 0) {
Dictionary hl_info = ARRAY_DICT_INIT; Dictionary hl_info = ARRAY_DICT_INIT;
grpname = get_default_stl_hl(wp, use_winbar); grpname = get_default_stl_hl(wp, use_winbar, stc_hl_id);
PUT(hl_info, "start", INTEGER_OBJ(0)); PUT(hl_info, "start", INTEGER_OBJ(0));
PUT(hl_info, "group", CSTR_TO_OBJ(grpname)); PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
@ -2209,7 +2250,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf)); PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf));
if (sp->userhl == 0) { if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp, use_winbar); grpname = get_default_stl_hl(wp, use_winbar, stc_hl_id);
} else if (sp->userhl < 0) { } else if (sp->userhl < 0) {
grpname = syn_id2name(-sp->userhl); grpname = syn_id2name(-sp->userhl);
} else { } else {

View File

@ -386,7 +386,7 @@ next_mark:
} }
void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattrs[], void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattrs[],
HlPriAttr *num_attrs, HlPriAttr *line_attrs, HlPriAttr *cul_attrs) HlPriId *num_id, HlPriId *line_id, HlPriId *cul_id)
{ {
if (!buf->b_signs) { if (!buf->b_signs) {
return; return;
@ -422,23 +422,23 @@ void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattr
if (j < SIGN_SHOW_MAX) { if (j < SIGN_SHOW_MAX) {
sattrs[j] = (SignTextAttrs) { sattrs[j] = (SignTextAttrs) {
.text = decor->sign_text, .text = decor->sign_text,
.hl_attr_id = decor->sign_hl_id == 0 ? 0 : syn_id2attr(decor->sign_hl_id), .hl_id = decor->sign_hl_id,
.priority = decor->priority .priority = decor->priority
}; };
(*num_signs)++; (*num_signs)++;
} }
} }
struct { HlPriAttr *dest; int hl; } cattrs[] = { struct { HlPriId *dest; int hl; } cattrs[] = {
{ line_attrs, decor->line_hl_id }, { line_id, decor->line_hl_id },
{ num_attrs, decor->number_hl_id }, { num_id, decor->number_hl_id },
{ cul_attrs, decor->cursorline_hl_id }, { cul_id, decor->cursorline_hl_id },
{ NULL, -1 }, { NULL, -1 },
}; };
for (int i = 0; cattrs[i].dest; i++) { for (int i = 0; cattrs[i].dest; i++) {
if (cattrs[i].hl != 0 && decor->priority >= cattrs[i].dest->priority) { if (cattrs[i].hl != 0 && decor->priority >= cattrs[i].dest->priority) {
*cattrs[i].dest = (HlPriAttr) { *cattrs[i].dest = (HlPriId) {
.attr_id = syn_id2attr(cattrs[i].hl), .hl_id = cattrs[i].hl,
.priority = decor->priority .priority = decor->priority
}; };
} }

View File

@ -508,31 +508,12 @@ static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int
if (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr > 0) { if (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr > 0) {
wlv->char_attr = sign_cul_attr; wlv->char_attr = sign_cul_attr;
} else { } else {
wlv->char_attr = sattr->hl_attr_id; wlv->char_attr = sattr->hl_id ? syn_id2attr(sattr->hl_id) : 0;
} }
} }
} }
} }
static int get_sign_attrs(buf_T *buf, winlinevars_T *wlv, int *sign_num_attrp, int *sign_cul_attrp)
{
HlPriAttr line_attrs = { wlv->line_attr, 0 };
HlPriAttr num_attrs = { *sign_num_attrp, 0 };
HlPriAttr cul_attrs = { *sign_cul_attrp, 0 };
// TODO(bfredl, vigoux): line_attr should not take priority over decoration!
int num_signs = buf_get_signattrs(buf, wlv->lnum, wlv->sattrs, &num_attrs, &line_attrs,
&cul_attrs);
decor_redraw_signs(buf, wlv->lnum - 1, &num_signs, wlv->sattrs, &num_attrs, &line_attrs,
&cul_attrs);
wlv->line_attr = line_attrs.attr_id;
*sign_num_attrp = num_attrs.attr_id;
*sign_cul_attrp = cul_attrs.attr_id;
return num_signs;
}
/// Returns width of the signcolumn that should be used for the whole window /// Returns width of the signcolumn that should be used for the whole window
/// ///
/// @param wp window we want signcolumn width from /// @param wp window we want signcolumn width from
@ -726,7 +707,7 @@ static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv)
if (stcp->textp + wlv->n_extra < stcp->text_end) { if (stcp->textp + wlv->n_extra < stcp->text_end) {
int hl = stcp->hlrecp->userhl; int hl = stcp->hlrecp->userhl;
stcp->textp = stcp->hlrecp->start; stcp->textp = stcp->hlrecp->start;
stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : hl > 0 ? hl : stcp->num_attr; stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr;
stcp->hlrecp++; stcp->hlrecp++;
wlv->draw_state = WL_STC - 1; wlv->draw_state = WL_STC - 1;
} }
@ -1288,9 +1269,37 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_highlighting = true; area_highlighting = true;
} }
int sign_num_attr = 0; // sign attribute for the number column HlPriId line_id = { 0 };
int sign_cul_attr = 0; // sign attribute for cursorline HlPriId sign_cul = { 0 };
int num_signs = get_sign_attrs(buf, &wlv, &sign_num_attr, &sign_cul_attr); HlPriId sign_num = { 0 };
// TODO(bfredl, vigoux): line_attr should not take priority over decoration!
int num_signs = buf_get_signattrs(buf, wlv.lnum, wlv.sattrs, &sign_num, &line_id, &sign_cul);
decor_redraw_signs(buf, wlv.lnum - 1, &num_signs, wlv.sattrs, &sign_num, &line_id, &sign_cul);
int sign_cul_attr = 0;
int sign_num_attr = 0;
statuscol_T statuscol = { 0 };
if (*wp->w_p_stc != NUL) {
// Draw the 'statuscolumn' if option is set.
statuscol.draw = true;
statuscol.sattrs = wlv.sattrs;
statuscol.foldinfo = foldinfo;
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul.hl_id : 0;
statuscol.num_attr = sign_num.hl_id ? syn_id2attr(sign_num.hl_id)
: get_line_number_attr(wp, &wlv);
} else {
if (sign_cul.hl_id > 0) {
sign_cul_attr = syn_id2attr(sign_cul.hl_id);
}
if (sign_num.hl_id > 0) {
sign_num_attr = syn_id2attr(sign_num.hl_id);
}
}
if (line_id.hl_id > 0) {
wlv.line_attr = syn_id2attr(line_id.hl_id);
}
// Highlight the current line in the quickfix window. // Highlight the current line in the quickfix window.
if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) {
@ -1495,18 +1504,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
extra_check = true; extra_check = true;
} }
statuscol_T statuscol = { 0 };
if (*wp->w_p_stc != NUL) {
// Draw the 'statuscolumn' if option is set.
statuscol.draw = true;
statuscol.sattrs = wlv.sattrs;
statuscol.foldinfo = foldinfo;
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0;
statuscol.num_attr = sign_num_attr ? sign_num_attr : get_line_number_attr(wp, &wlv);
}
int sign_idx = 0; int sign_idx = 0;
int virt_line_index; int virt_line_index;
int virt_line_offset = -1; int virt_line_offset = -1;

View File

@ -247,8 +247,8 @@ typedef struct {
/// highlight attributes with associated priorities /// highlight attributes with associated priorities
typedef struct { typedef struct {
int attr_id; int hl_id;
int priority; int priority;
} HlPriAttr; } HlPriId;
#endif // NVIM_HIGHLIGHT_DEFS_H #endif // NVIM_HIGHLIGHT_DEFS_H

View File

@ -491,8 +491,8 @@ SignTextAttrs *sign_get_attr(int idx, SignTextAttrs sattrs[], int max_signs)
/// @param lnum Line in which to search /// @param lnum Line in which to search
/// @param sattrs Output array for attrs /// @param sattrs Output array for attrs
/// @return Number of signs of which attrs were found /// @return Number of signs of which attrs were found
int buf_get_signattrs(buf_T *buf, linenr_T lnum, SignTextAttrs sattrs[], HlPriAttr *num_attrs, int buf_get_signattrs(buf_T *buf, linenr_T lnum, SignTextAttrs sattrs[], HlPriId *num_id,
HlPriAttr *line_attrs, HlPriAttr *cul_attrs) HlPriId *line_id, HlPriId *cul_id)
{ {
sign_entry_T *sign; sign_entry_T *sign;
@ -517,21 +517,21 @@ int buf_get_signattrs(buf_T *buf, linenr_T lnum, SignTextAttrs sattrs[], HlPriAt
if (sp->sn_text != NULL && sattr_matches < SIGN_SHOW_MAX) { if (sp->sn_text != NULL && sattr_matches < SIGN_SHOW_MAX) {
sattrs[sattr_matches++] = (SignTextAttrs) { sattrs[sattr_matches++] = (SignTextAttrs) {
.text = sp->sn_text, .text = sp->sn_text,
.hl_attr_id = sp->sn_text_hl == 0 ? 0 : syn_id2attr(sp->sn_text_hl), .hl_id = sp->sn_text_hl,
.priority = sign->se_priority .priority = sign->se_priority
}; };
} }
struct { HlPriAttr *dest; int hl; } cattrs[] = { struct { HlPriId *dest; int hl; } cattrs[] = {
{ line_attrs, sp->sn_line_hl }, { line_id, sp->sn_line_hl },
{ num_attrs, sp->sn_num_hl }, { num_id, sp->sn_num_hl },
{ cul_attrs, sp->sn_cul_hl }, { cul_id, sp->sn_cul_hl },
{ NULL, -1 }, { NULL, -1 },
}; };
for (int i = 0; cattrs[i].dest; i++) { for (int i = 0; cattrs[i].dest; i++) {
if (cattrs[i].hl != 0 && sign->se_priority >= cattrs[i].dest->priority) { if (cattrs[i].hl != 0 && sign->se_priority >= cattrs[i].dest->priority) {
*cattrs[i].dest = (HlPriAttr) { *cattrs[i].dest = (HlPriId) {
.attr_id = syn_id2attr(cattrs[i].hl), .hl_id = cattrs[i].hl,
.priority = sign->se_priority .priority = sign->se_priority
}; };
} }

View File

@ -35,7 +35,7 @@ struct sign_entry {
/// Sign attributes. Used by the screen refresh routines. /// Sign attributes. Used by the screen refresh routines.
typedef struct { typedef struct {
char *text; char *text;
int hl_attr_id; int hl_id;
int priority; int priority;
} SignTextAttrs; } SignTextAttrs;

View File

@ -1512,7 +1512,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_LINE: case STL_LINE:
// Overload %l with v:lnum for 'statuscolumn' // Overload %l with v:lnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) { if (stcp != NULL) {
if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) { if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
num = (int)get_vim_var_nr(VV_LNUM); num = (int)get_vim_var_nr(VV_LNUM);
} }
@ -1617,7 +1617,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_ROFLAG: case STL_ROFLAG:
case STL_ROFLAG_ALT: case STL_ROFLAG_ALT:
// Overload %r with v:relnum for 'statuscolumn' // Overload %r with v:relnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) { if (stcp != NULL) {
if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) { if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
num = (int)get_vim_var_nr(VV_RELNUM); num = (int)get_vim_var_nr(VV_RELNUM);
} }
@ -1652,7 +1652,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
char *p; char *p;
if (fold) { if (fold) {
size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM)); size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM));
stl_items[curitem].minwid = win_hl_attr(wp, stcp->use_cul ? HLF_CLF : HLF_FC); stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
p = out_p; p = out_p;
p[n] = NUL; p[n] = NUL;
} }
@ -1668,9 +1668,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
} else if (!fold) { } else if (!fold) {
SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth); SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth);
p = sattr && sattr->text ? sattr->text : " "; p = sattr && sattr->text ? sattr->text : " ";
stl_items[curitem].minwid = sattr ? stcp->sign_cul_attr ? stcp->sign_cul_attr stl_items[curitem].minwid = -(sattr ? stcp->sign_cul_id ? stcp->sign_cul_id
: sattr->hl_attr_id : sattr->hl_id : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
: win_hl_attr(wp, stcp->use_cul ? HLF_CLS : HLF_SC);
} }
stl_items[curitem].type = Highlight; stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p + strlen(buf_tmp); stl_items[curitem].start = out_p + strlen(buf_tmp);

View File

@ -62,8 +62,8 @@ typedef struct statuscol statuscol_T;
struct statuscol { struct statuscol {
int width; ///< width of the status column int width; ///< width of the status column
int cur_attr; ///< current attributes in text int cur_attr; ///< current attributes in text
int num_attr; ///< attributes used for line number int num_attr; ///< default highlight attr
int sign_cul_attr; ///< cursorline sign attr int sign_cul_id; ///< cursorline sign highlight id
int truncate; ///< truncated width int truncate; ///< truncated width
bool draw; ///< whether to draw the statuscolumn bool draw; ///< whether to draw the statuscolumn
bool use_cul; ///< whether to use cursorline attrs bool use_cul; ///< whether to use cursorline attrs

View File

@ -3421,6 +3421,40 @@ describe('API', function()
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
{ use_winbar = true, highlights = true })) { use_winbar = true, highlights = true }))
end) end)
it('works with statuscolumn', function()
command([[
let &stc='%C%s%=%l '
set cul nu nuw=3 scl=yes:2 fdc=2
call setline(1, repeat(['aaaaa'], 5))
let g:ns = nvim_create_namespace('')
call sign_define('a', {'text':'aa', 'texthl':'IncSearch', 'numhl':'Normal'})
call sign_place(2, 1, 'a', bufnr(), {'lnum':4})
call nvim_buf_set_extmark(0, g:ns, 3, 1, { 'sign_text':'bb', 'sign_hl_group':'ErrorMsg' })
1,5fold | 1,5 fold | foldopen!
]])
command('norm 4G')
command('let v:lnum=4')
eq({
str = '││aabb 4 ',
width = 9,
highlights = {
{ group = 'CursorLineFold', start = 0 },
{ group = 'Normal', start = 6 },
{ group = 'IncSearch', start = 6 },
{ group = 'ErrorMsg', start = 8 },
{ group = 'Normal', start = 10 }
}
}, meths.eval_statusline('%C%s%=%l ', { use_statuscol = true, highlights = true }))
command('let v:lnum=3')
eq({
str = '3 ' ,
width = 2,
highlights = {
{ group = 'LineNr', start = 0 },
{ group = 'ErrorMsg', start = 1 }
}
}, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol = true, highlights = true }))
end)
it('no memory leak with click functions', function() it('no memory leak with click functions', function()
meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {})
eq({ eq({