mirror of
https://github.com/neovim/neovim.git
synced 2026-08-28 01:51:52 +00:00
feat(column): apply appropriate numhl highlight to virt_lines (#32400)
Problem: Number and statuscolumn highlighting for virtual lines does
not take always take on numhl highlights.
Solution: Apply the appropriate numhl highlight to the number/statuscolumn
of virtual lines, fetching the numhl highlight of the line above
for `virt_line_above == false` lines.
This commit is contained in:
@@ -853,7 +853,7 @@ int sign_item_cmp(const void *p1, const void *p2)
|
||||
static const uint32_t sign_filter[4] = {[kMTMetaSignText] = kMTFilterSelect,
|
||||
[kMTMetaSignHL] = kMTFilterSelect };
|
||||
|
||||
/// Return the sign attributes on the currently refreshed row.
|
||||
/// Return the signs and highest priority sign attributes on a row.
|
||||
///
|
||||
/// @param[out] sattrs Output array for sign text and texthl id
|
||||
/// @param[out] line_id Highest priority linehl id
|
||||
@@ -904,17 +904,17 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
|
||||
|
||||
for (size_t i = 0; i < kv_size(signs); i++) {
|
||||
DecorSignHighlight *sh = kv_A(signs, i).sh;
|
||||
if (idx < len && sh->text[0]) {
|
||||
if (sattrs && idx < len && sh->text[0]) {
|
||||
memcpy(sattrs[idx].text, sh->text, SIGN_WIDTH * sizeof(sattr_T));
|
||||
sattrs[idx++].hl_id = sh->hl_id;
|
||||
}
|
||||
if (*num_id == 0) {
|
||||
if (num_id != NULL && *num_id <= 0) {
|
||||
*num_id = sh->number_hl_id;
|
||||
}
|
||||
if (*line_id == 0) {
|
||||
if (line_id != NULL && *line_id <= 0) {
|
||||
*line_id = sh->line_hl_id;
|
||||
}
|
||||
if (*cul_id == 0) {
|
||||
if (cul_id != NULL && *cul_id <= 0) {
|
||||
*cul_id = sh->cursorline_hl_id;
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +1038,8 @@ bool decor_redraw_eol(win_T *wp, DecorState *state, int *eol_attr, int eol_col)
|
||||
static const uint32_t lines_filter[4] = {[kMTMetaLines] = kMTFilterSelect };
|
||||
|
||||
/// @param apply_folds Only count virtual lines that are not in folds.
|
||||
int decor_virt_lines(win_T *wp, int start_row, int end_row, VirtLines *lines, bool apply_folds)
|
||||
int decor_virt_lines(win_T *wp, int start_row, int end_row, int *num_below, VirtLines *lines,
|
||||
bool apply_folds)
|
||||
{
|
||||
buf_T *buf = wp->w_buffer;
|
||||
if (!buf_meta_total(buf, kMTMetaLines)) {
|
||||
@@ -1071,6 +1072,9 @@ int decor_virt_lines(win_T *wp, int start_row, int end_row, VirtLines *lines, bo
|
||||
if (lines) {
|
||||
kv_splice(*lines, vt->data.virt_lines);
|
||||
}
|
||||
if (num_below && !above) {
|
||||
(*num_below) += (int)kv_size(vt->data.virt_lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
vt = vt->next;
|
||||
|
||||
@@ -82,6 +82,7 @@ typedef struct {
|
||||
int line_attr; ///< attribute for the whole line
|
||||
int line_attr_lowprio; ///< low-priority attribute for the line
|
||||
int sign_num_attr; ///< line number attribute (sign numhl)
|
||||
int prev_num_attr; ///< previous line's number attribute (sign numhl)
|
||||
int sign_cul_attr; ///< cursorline sign attribute (sign culhl)
|
||||
|
||||
int fromcol; ///< start of inverting
|
||||
@@ -107,6 +108,7 @@ typedef struct {
|
||||
hlf_T diff_hlf; ///< type of diff highlighting
|
||||
|
||||
int n_virt_lines; ///< nr of virtual lines
|
||||
int n_virt_below; ///< nr of virtual lines belonging to previous line
|
||||
int filler_lines; ///< nr of filler lines to be drawn
|
||||
int filler_todo; ///< nr of filler lines still to do + 1
|
||||
SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column
|
||||
@@ -564,26 +566,41 @@ static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv)
|
||||
&& (wp->w_p_culopt_flags & kOptCuloptFlagLine)));
|
||||
}
|
||||
|
||||
/// Return line number attribute, combining the appropriate LineNr* highlight
|
||||
/// with the highest priority sign numhl highlight, if any.
|
||||
static int get_line_number_attr(win_T *wp, winlinevars_T *wlv)
|
||||
{
|
||||
int numhl_attr = wlv->sign_num_attr;
|
||||
|
||||
// Get previous sign numhl for virt_lines belonging to the previous line.
|
||||
if ((wlv->n_virt_lines - wlv->filler_todo) < wlv->n_virt_below) {
|
||||
if (wlv->prev_num_attr == -1) {
|
||||
decor_redraw_signs(wp, wp->w_buffer, wlv->lnum - 2, NULL, NULL, NULL, &wlv->prev_num_attr);
|
||||
if (wlv->prev_num_attr > 0) {
|
||||
wlv->prev_num_attr = syn_id2attr(wlv->prev_num_attr);
|
||||
}
|
||||
}
|
||||
numhl_attr = wlv->prev_num_attr;
|
||||
}
|
||||
|
||||
if (use_cursor_line_nr(wp, wlv)) {
|
||||
// TODO(vim): Can we use CursorLine instead of CursorLineNr
|
||||
// when CursorLineNr isn't set?
|
||||
return win_hl_attr(wp, HLF_CLN);
|
||||
return hl_combine_attr(win_hl_attr(wp, HLF_CLN), numhl_attr);
|
||||
}
|
||||
|
||||
if (wp->w_p_rnu) {
|
||||
if (wlv->lnum < wp->w_cursor.lnum) {
|
||||
// Use LineNrAbove
|
||||
return win_hl_attr(wp, HLF_LNA);
|
||||
return hl_combine_attr(win_hl_attr(wp, HLF_LNA), numhl_attr);
|
||||
}
|
||||
if (wlv->lnum > wp->w_cursor.lnum) {
|
||||
// Use LineNrBelow
|
||||
return win_hl_attr(wp, HLF_LNB);
|
||||
return hl_combine_attr(win_hl_attr(wp, HLF_LNB), numhl_attr);
|
||||
}
|
||||
}
|
||||
|
||||
return win_hl_attr(wp, HLF_N);
|
||||
return hl_combine_attr(win_hl_attr(wp, HLF_N), numhl_attr);
|
||||
}
|
||||
|
||||
/// Display the absolute or relative line number. After the first row fill with
|
||||
@@ -605,8 +622,7 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv)
|
||||
} else {
|
||||
// Draw the line number (empty space after wrapping).
|
||||
int width = number_width(wp) + 1;
|
||||
int attr = hl_combine_attr(get_line_number_attr(wp, wlv),
|
||||
wlv->filler_todo <= 0 ? wlv->sign_num_attr : 0);
|
||||
int attr = get_line_number_attr(wp, wlv);
|
||||
if (wlv->row == wlv->startrow + wlv->filler_lines
|
||||
&& (wp->w_skipcol == 0 || wlv->row > 0 || (wp->w_p_nu && wp->w_p_rnu))) {
|
||||
char buf[32];
|
||||
@@ -678,8 +694,7 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir
|
||||
colnr_T *fold_vcol = NULL;
|
||||
size_t len = strlen(buf);
|
||||
int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
|
||||
int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv),
|
||||
wlv->filler_todo <= 0 ? wlv->sign_num_attr : 0);
|
||||
int num_attr = get_line_number_attr(wp, wlv);
|
||||
int cur_attr = num_attr;
|
||||
|
||||
// Draw each segment with the specified highlighting.
|
||||
@@ -1073,6 +1088,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
|
||||
.tocol = MAXCOL,
|
||||
.vcol_sbr = -1,
|
||||
.old_boguscols = 0,
|
||||
.prev_num_attr = -1,
|
||||
};
|
||||
|
||||
buf_T *buf = wp->w_buffer;
|
||||
@@ -1228,7 +1244,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
|
||||
area_highlighting = true;
|
||||
}
|
||||
VirtLines virt_lines = KV_INITIAL_VALUE;
|
||||
wlv.n_virt_lines = decor_virt_lines(wp, lnum - 1, lnum, &virt_lines, true);
|
||||
wlv.n_virt_lines = decor_virt_lines(wp, lnum - 1, lnum, &wlv.n_virt_below, &virt_lines, true);
|
||||
wlv.filler_lines += wlv.n_virt_lines;
|
||||
if (lnum == wp->w_topline) {
|
||||
wlv.filler_lines = wp->w_topfill;
|
||||
|
||||
@@ -720,7 +720,7 @@ bool win_may_fill(win_T *wp)
|
||||
/// @return Number of filler lines above lnum
|
||||
int win_get_fill(win_T *wp, linenr_T lnum)
|
||||
{
|
||||
int virt_lines = decor_virt_lines(wp, lnum - 1, lnum, NULL, true);
|
||||
int virt_lines = decor_virt_lines(wp, lnum - 1, lnum, NULL, NULL, true);
|
||||
|
||||
// be quick when there are no filler lines
|
||||
if (diffopt_filler()) {
|
||||
@@ -920,7 +920,7 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last, int max)
|
||||
/// Mainly used for calculating scrolling offsets.
|
||||
int plines_m_win_fill(win_T *wp, linenr_T first, linenr_T last)
|
||||
{
|
||||
int count = last - first + 1 + decor_virt_lines(wp, first - 1, last, NULL, false);
|
||||
int count = last - first + 1 + decor_virt_lines(wp, first - 1, last, NULL, NULL, false);
|
||||
|
||||
if (diffopt_filler()) {
|
||||
for (int lnum = first; lnum <= last; lnum++) {
|
||||
|
||||
Reference in New Issue
Block a user