mirror of
https://github.com/neovim/neovim.git
synced 2025-10-09 19:36:40 +00:00
fix(column)!: ensure 'statuscolumn' works with virtual and wrapped lines
Problem: The `'statuscolumn'` was not re-evaluated for wrapped lines, when preceded by virtual/filler lines. There was also no way to distinguish virtual and wrapped lines in the status column. Solution: Make sure to rebuild the statuscolumn, and replace variable `v:wrap` with `v:virtnum`. `v:virtnum` is negative when drawing virtual lines, zero when drawing the actual buffer line, and positive when drawing the wrapped part of a buffer line.
This commit is contained in:
@@ -399,40 +399,45 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
|
||||
|
||||
/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
|
||||
/// Fill "stcp" with the built status column string and attributes.
|
||||
/// This can be called three times per win_line(), once for virt_lines, once for
|
||||
/// the start of the buffer line "lnum" and once for the wrapped lines.
|
||||
///
|
||||
/// @param[out] stcp Status column attributes
|
||||
static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
|
||||
int cul_attr, int sign_num_attr, int sign_cul_attr, char_u *extra,
|
||||
foldinfo_T foldinfo, SignTextAttrs *sattrs, statuscol_T *stcp)
|
||||
int cul_attr, int sign_num_attr, int sign_cul_attr, statuscol_T *stcp,
|
||||
foldinfo_T foldinfo, SignTextAttrs *sattrs)
|
||||
{
|
||||
long relnum = 0;
|
||||
bool wrapped = row != startrow + filler_lines;
|
||||
long relnum = -1;
|
||||
bool use_cul = use_cursor_line_sign(wp, lnum);
|
||||
int virtnum = row - startrow - filler_lines;
|
||||
|
||||
// Set num, fold and sign text and attrs, empty when wrapped
|
||||
set_vim_var_nr(VV_VIRTNUM, virtnum);
|
||||
// When called the first time for line "lnum" set num_attr
|
||||
if (row == startrow) {
|
||||
relnum = labs(get_cursor_rel_lnum(wp, lnum));
|
||||
stcp->num_attr = sign_num_attr ? sign_num_attr
|
||||
: get_line_number_attr(wp, lnum, row, startrow, filler_lines);
|
||||
|
||||
}
|
||||
// When called for the first non-filler row of line "lnum" set num v:vars and fold column
|
||||
if (virtnum == 0) {
|
||||
relnum = labs(get_cursor_rel_lnum(wp, lnum));
|
||||
if (compute_foldcolumn(wp, 0)) {
|
||||
size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum);
|
||||
stcp->fold_text[n] = NUL;
|
||||
stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to clear->set->clear sign column for filler->first->wrapped lines
|
||||
int i = 0;
|
||||
for (; i < wp->w_scwidth; i++) {
|
||||
SignTextAttrs *sattr = wrapped ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
|
||||
SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
|
||||
stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
|
||||
stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id)
|
||||
: win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC);
|
||||
}
|
||||
stcp->sign_text[i] = NULL;
|
||||
|
||||
int width = build_statuscol_str(wp, row == startrow, wrapped, lnum, relnum,
|
||||
stcp->width, ' ', stcp->text, &stcp->hlrec, stcp);
|
||||
int width = build_statuscol_str(wp, lnum, relnum, stcp->width,
|
||||
' ', stcp->text, &stcp->hlrec, stcp);
|
||||
// Force a redraw in case of error or when truncated
|
||||
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
|
||||
if (stcp->truncate) { // Avoid truncating 'statuscolumn'
|
||||
@@ -465,9 +470,8 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i
|
||||
///
|
||||
/// @param stcp Status column attributes
|
||||
/// @param[out] draw_state Current draw state in win_line()
|
||||
static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr, int *n_extrap,
|
||||
int *c_extrap, int *c_finalp, char_u *extra, char **pp_extra,
|
||||
statuscol_T *stcp)
|
||||
static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_state, int *char_attr,
|
||||
int *n_extrap, int *c_extrap, int *c_finalp, char **pp_extra)
|
||||
{
|
||||
*c_extrap = NUL;
|
||||
*c_finalp = NUL;
|
||||
@@ -1326,14 +1330,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
// Draw the 'statuscolumn' if option is set.
|
||||
if (statuscol.draw) {
|
||||
if (statuscol.textp == NULL) {
|
||||
get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, sign_num_attr,
|
||||
sign_cul_attr, extra, foldinfo, sattrs, &statuscol);
|
||||
get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr,
|
||||
sign_num_attr, sign_cul_attr, &statuscol, foldinfo, sattrs);
|
||||
if (wp->w_redr_statuscol) {
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
get_statuscol_display_info(&draw_state, &char_attr, &n_extra, &c_extra,
|
||||
&c_final, extra, &p_extra, &statuscol);
|
||||
get_statuscol_display_info(&statuscol, &draw_state, &char_attr,
|
||||
&n_extra, &c_extra, &c_final, &p_extra);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2818,7 +2822,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|
||||
need_showbreak = true;
|
||||
}
|
||||
if (statuscol.draw) {
|
||||
if (row == startrow + 1 || row == startrow + filler_lines) {
|
||||
if (row == startrow + filler_lines + 1 || row == startrow + filler_lines) {
|
||||
// Re-evaluate 'statuscolumn' for the first wrapped row and non filler line
|
||||
statuscol.textp = NULL;
|
||||
} else { // Otherwise just reset the text/hlrec pointers
|
||||
|
@@ -268,7 +268,7 @@ static struct vimvar {
|
||||
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
|
||||
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
|
||||
VV(VV_RELNUM, "relnum", VAR_NUMBER, VV_RO),
|
||||
VV(VV_WRAP, "wrap", VAR_BOOL, VV_RO),
|
||||
VV(VV_VIRTNUM, "virtnum", VAR_NUMBER, VV_RO),
|
||||
};
|
||||
#undef VV
|
||||
|
||||
|
@@ -166,7 +166,7 @@ typedef enum {
|
||||
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
|
||||
VV_LUA,
|
||||
VV_RELNUM,
|
||||
VV_WRAP,
|
||||
VV_VIRTNUM,
|
||||
} VimVarIndex;
|
||||
|
||||
/// All recognized msgpack types
|
||||
|
@@ -784,7 +784,7 @@ int number_width(win_T *wp)
|
||||
if (*wp->w_p_stc != NUL) {
|
||||
char buf[MAXPATHL];
|
||||
wp->w_nrwidth_width = 0;
|
||||
n = build_statuscol_str(wp, true, false, lnum, 0, 0, NUL, buf, NULL, NULL);
|
||||
n = build_statuscol_str(wp, lnum, 0, 0, NUL, buf, NULL, NULL);
|
||||
n = MAX(n, (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw);
|
||||
wp->w_nrwidth_width = MIN(n, MAX_NUMBERWIDTH);
|
||||
return wp->w_nrwidth_width;
|
||||
|
@@ -876,14 +876,13 @@ void draw_tabline(void)
|
||||
/// @param hlrec HL attributes (can be NULL)
|
||||
/// @param stcp Status column attributes (can be NULL)
|
||||
/// @return The width of the built status column string for line "lnum"
|
||||
int build_statuscol_str(win_T *wp, bool setnum, bool wrap, linenr_T lnum, long relnum, int maxwidth,
|
||||
int fillchar, char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
|
||||
int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int fillchar,
|
||||
char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
|
||||
{
|
||||
if (setnum) {
|
||||
if (relnum >= 0) {
|
||||
set_vim_var_nr(VV_LNUM, lnum);
|
||||
set_vim_var_nr(VV_RELNUM, relnum);
|
||||
}
|
||||
set_vim_var_bool(VV_WRAP, wrap);
|
||||
|
||||
StlClickRecord *clickrec;
|
||||
char *stc = xstrdup(wp->w_p_stc);
|
||||
@@ -1506,13 +1505,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
||||
case STL_LINE:
|
||||
// Overload %l with v:lnum for 'statuscolumn'
|
||||
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
|
||||
if (wp->w_p_nu) {
|
||||
if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
|
||||
num = get_vim_var_nr(VV_LNUM);
|
||||
}
|
||||
} else {
|
||||
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STL_NUMLINES:
|
||||
@@ -1612,7 +1610,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
||||
case STL_ROFLAG_ALT:
|
||||
// Overload %r with v:relnum for 'statuscolumn'
|
||||
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
|
||||
if (wp->w_p_rnu) {
|
||||
if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
|
||||
num = get_vim_var_nr(VV_RELNUM);
|
||||
}
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user