Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(folds): cursorline highlight is not always applied on closed folds #22242

Merged
merged 1 commit into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
fix(folds): cursorline highlight is not always applied on closed folds
Problem:    The cursorline highlight logic checks for `w_cursor.lnum`
            which may be different from the line number passed to
            `win_line()` even when the cursor is actually on that line.
Solution:   Update cursor line highlight logic to check for the line
            number of the start of a closed fold if necessary.
  • Loading branch information
luukvbaal committed Feb 14, 2023
commit ea704d9a7b84dcf10b01d4916859b9daeba4230c
9 changes: 6 additions & 3 deletions src/nvim/buffer_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1112,20 +1112,23 @@ struct window_S {
win_T *w_prev; ///< link to previous window
win_T *w_next; ///< link to next window
bool w_closing; ///< window is being closed, don't let
/// autocommands close it too.
///< autocommands close it too.

frame_T *w_frame; ///< frame containing this window

pos_T w_cursor; ///< cursor position in buffer

colnr_T w_curswant; ///< Column we want to be at. This is
/// used to try to stay in the same column
/// for up/down cursor motions.
///< used to try to stay in the same column
///< for up/down cursor motions.

int w_set_curswant; // If set, then update w_curswant the next
// time through cursupdate() to the
// current virtual column

linenr_T w_cursorline; ///< Where 'cursorline' should be drawn,
///< can be different from w_cursor.lnum
///< for closed folds.
linenr_T w_last_cursorline; ///< where last 'cursorline' was drawn
pos_T w_last_cursormoved; ///< for CursorMoved event

Expand Down
39 changes: 18 additions & 21 deletions src/nvim/drawline.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
{
return wp->w_p_cul
&& lnum == wp->w_cursor.lnum
&& lnum == wp->w_cursorline
&& (wp->w_p_culopt_flags & CULOPT_NBR);
}

Expand Down Expand Up @@ -517,7 +517,7 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st
static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines)
{
return wp->w_p_cul
&& lnum == wp->w_cursor.lnum
&& lnum == wp->w_cursorline
&& (wp->w_p_culopt_flags & CULOPT_NBR)
&& (row == startrow + filler_lines
|| (row > startrow + filler_lines
Expand Down Expand Up @@ -547,6 +547,12 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size

static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines)
{
if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) {
// TODO(vim): Can we use CursorLine instead of CursorLineNr
// when CursorLineNr isn't set?
return win_hl_attr(wp, HLF_CLN);
}

if (wp->w_p_rnu) {
if (lnum < wp->w_cursor.lnum) {
// Use LineNrAbove
Expand All @@ -558,12 +564,6 @@ static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow,
}
}

if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) {
// TODO(vim): Can we use CursorLine instead of CursorLineNr
// when CursorLineNr isn't set?
return win_hl_attr(wp, HLF_CLN);
}

return win_hl_attr(wp, HLF_N);
}

Expand Down Expand Up @@ -960,20 +960,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
filler_todo = filler_lines;

// Cursor line highlighting for 'cursorline' in the current window.
if (lnum == wp->w_cursor.lnum) {
// Do not show the cursor line in the text when Visual mode is active,
// because it's not clear what is selected then.
if (wp->w_p_cul && !(wp == curwin && VIsual_active)
&& wp->w_p_culopt_flags != CULOPT_NBR) {
cul_screenline = (wp->w_p_wrap
&& (wp->w_p_culopt_flags & CULOPT_SCRLINE));
if (!cul_screenline) {
apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio);
} else {
margin_columns_win(wp, &left_curline_col, &right_curline_col);
}
area_highlighting = true;
if (wp->w_p_cul && wp->w_p_culopt_flags != CULOPT_NBR && lnum == wp->w_cursorline
// Do not show the cursor line in the text when Visual mode is active,
// because it's not clear what is selected then.
&& !(wp == curwin && VIsual_active)) {
cul_screenline = (wp->w_p_wrap && (wp->w_p_culopt_flags & CULOPT_SCRLINE));
if (!cul_screenline) {
apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio);
} else {
margin_columns_win(wp, &left_curline_col, &right_curline_col);
}
area_highlighting = true;
}

SignTextAttrs sattrs[SIGN_SHOW_MAX]; // sign attributes for the sign column
Expand Down
20 changes: 15 additions & 5 deletions src/nvim/drawscreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_old_visual_col = 0;
}

bool cursorline_standout = win_cursorline_standout(wp);
foldinfo_T cursorline_fi;
wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
if (wp->w_p_cul) {
// Make sure that the cursorline on a closed fold is redrawn
cursorline_fi = fold_info(wp, wp->w_cursor.lnum);
if (cursorline_fi.fi_level > 0 && cursorline_fi.fi_lines > 0) {
wp->w_cursorline = cursorline_fi.fi_lnum;
}
}

win_check_ns_hl(wp);

Expand Down Expand Up @@ -1604,7 +1612,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// if lines were inserted or deleted
|| (wp->w_match_head != NULL
&& buf->b_mod_xlines != 0)))))
|| (cursorline_standout && lnum == wp->w_cursor.lnum)
|| lnum == wp->w_cursorline
|| lnum == wp->w_last_cursorline) {
if (lnum == mod_top) {
top_to_mod = false;
Expand Down Expand Up @@ -1755,7 +1763,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
// When lines are folded, display one line for all of them.
// Otherwise, display normally (can be several display lines when
// 'wrap' is on).
foldinfo_T foldinfo = fold_info(wp, lnum);
foldinfo_T foldinfo = wp->w_p_cul && lnum == wp->w_cursor.lnum ?
cursorline_fi : fold_info(wp, lnum);

if (foldinfo.fi_lines == 0
&& idx < wp->w_lines_valid
Expand Down Expand Up @@ -1814,7 +1823,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum) {
// 'relativenumber' set and cursor moved vertically: The
// text doesn't need to be drawn, but the number column does.
foldinfo_T info = fold_info(wp, lnum);
foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum ?
cursorline_fi : fold_info(wp, lnum);
(void)win_line(wp, lnum, srow, wp->w_grid.rows, true, true,
info, &line_providers, &provider_err);
}
Expand Down Expand Up @@ -1849,7 +1859,7 @@ static void win_update(win_T *wp, DecorProviders *providers)

// Now that the window has been redrawn with the old and new cursor line,
// update w_last_cursorline.
wp->w_last_cursorline = cursorline_standout ? wp->w_cursor.lnum : 0;
wp->w_last_cursorline = wp->w_cursorline;

wp->w_last_cursor_lnum_rnu = wp->w_p_rnu ? wp->w_cursor.lnum : 0;

Expand Down
132 changes: 88 additions & 44 deletions test/functional/ui/fold_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local meths = helpers.meths
local exec = helpers.exec
local exec_lua = helpers.exec_lua
local assert_alive = helpers.assert_alive
local poke_eventloop = helpers.poke_eventloop


local content1 = [[
Expand Down Expand Up @@ -90,10 +91,10 @@ describe("folded lines", function()
end)

it("highlights with CursorLineFold when 'cursorline' is set", function()
command("set cursorline foldcolumn=2 foldmethod=marker")
command("set number cursorline foldcolumn=2")
command("hi link CursorLineFold Search")
insert(content1)
feed("zf3j")
feed("ggzf3jj")
if multigrid then
screen:expect([[
## grid 1
Expand All @@ -106,26 +107,26 @@ describe("folded lines", function()
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{7: }in his cave. |
{6: }{12:^ }|
{7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
{6: }{9: 5 }{12:^in his cave. }|
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
## grid 3
|
]])
else
screen:expect([[
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{7: }in his cave. |
{6: }{12:^ }|
{1:~ }|
|
{7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
{6: }{9: 5 }{12:^in his cave. }|
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]])
end
feed("k")
Expand All @@ -141,28 +142,36 @@ describe("folded lines", function()
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{6: }{12:^in his cave. }|
{7: } |
{6:+ }{9: 1 }{12:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
## grid 3
|
]])
else
screen:expect([[
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{6: }{12:^in his cave. }|
{7: } |
{1:~ }|
|
{6:+ }{9: 1 }{12:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]])
end
-- CursorLine is applied correctly with screenrow motions #22232
feed("jgk")
poke_eventloop()
screen:expect_unchanged()
-- CursorLine is applied correctly when closing a fold when cursor is not at fold start
feed("zo4Gzc")
poke_eventloop()
screen:expect_unchanged()
command("set cursorlineopt=line")
if multigrid then
screen:expect([[
Expand All @@ -176,26 +185,61 @@ describe("folded lines", function()
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{7: }{12:^in his cave. }|
{7: } |
{7:+ }{8: 1 }{12:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
## grid 3
|
]])
else
screen:expect([[
{7: }This is a |
{7: }valid English |
{7: }sentence composed by |
{7: }an exhausted developer |
{7: }{12:^in his cave. }|
{7: } |
{1:~ }|
|
{7:+ }{8: 1 }{12:^+-- 4 lines: This is a················}|
{7: }{8: 5 }in his cave. |
{7: }{8: 6 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]])
end
command("set relativenumber cursorlineopt=number")
if multigrid then
screen:expect([[
## grid 1
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[2:---------------------------------------------]|
[3:---------------------------------------------]|
## grid 2
{6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
{7: }{8: 1 }in his cave. |
{7: }{8: 2 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
## grid 3
|
]])
else
screen:expect([[
{6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
{7: }{8: 1 }in his cave. |
{7: }{8: 2 } |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]])
end
end)
Expand Down