From 1233ac467de7504b277425988ef9be7f8d3a9626 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 22 Jan 2024 10:13:35 +0000 Subject: [PATCH] feat(fold): transparent foldtext 'foldtext' can be set to an empty string to disable and render the line with: - extmark highlight - syntax highlighting - search highlighting - no line wrapping - spelling - conceal - inline virtual text - respects `fillchars:fold` Currently normal virtual text is not displayed Co-authored-by: zeertzjq --- runtime/doc/news.txt | 3 + runtime/doc/options.txt | 3 + runtime/lua/vim/_meta/options.lua | 3 + src/nvim/drawline.c | 50 ++-- src/nvim/drawscreen.c | 12 +- src/nvim/options.lua | 3 + test/functional/ui/fold_spec.lua | 416 +++++++++++++++++++++++------- 7 files changed, 374 insertions(+), 116 deletions(-) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 9ef9132c65..d63d1e6928 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -154,6 +154,9 @@ The following new APIs and features were added. • 'foldtext' now supports virtual text format. |fold-foldtext| +• |'foldtext'| can be set to an empty string to disable and render the line: + as normal with regular highlighting and no line wrapping. + • The terminal buffer now supports reflow (wrapped lines adapt when the buffer is resized horizontally). Note: Lines that are not visible and kept in |'scrollback'| are not reflown. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 59ac3b7f34..ac35ad2592 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2714,6 +2714,9 @@ A jump table for the options with a short description can be found at |Q_op|. It is not allowed to change text or jump to another window while evaluating 'foldtext' |textlock|. + When set to an empty string, foldtext is disabled, and the line + is displayed normally with highlighting and no line wrapping. + *'formatexpr'* *'fex'* 'formatexpr' 'fex' string (default "") local to buffer diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index c9e2e302dc..60339f57d8 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -2473,6 +2473,9 @@ vim.go.fdo = vim.go.foldopen --- It is not allowed to change text or jump to another window while --- evaluating 'foldtext' `textlock`. --- +--- When set to an empty string, foldtext is disabled, and the line +--- is displayed normally with highlighting and no line wrapping. +--- --- @type string vim.o.foldtext = "foldtext()" vim.o.fdt = vim.o.foldtext diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 7afa2493b9..ae538ed7a6 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -944,6 +944,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol // at end-of-line const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; + const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL; + + const bool is_wrapped = wp->w_p_wrap + && !has_fold; // Never wrap folded lines int saved_attr2 = 0; // char_attr saved for n_attr int n_attr3 = 0; // chars with overruling special attr @@ -1036,7 +1040,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // trailing white space and/or syntax processing to be done. extra_check = wp->w_p_lbr; if (syntax_present(wp) && !wp->w_s->b_syn_error && !wp->w_s->b_syn_slow - && !has_fold && !end_fill) { + && !has_foldtext && !end_fill) { // Prepare for syntax highlighting in this line. When there is an // error, stop syntax highlighting. int save_did_emsg = did_emsg; @@ -1132,7 +1136,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // handle 'incsearch' and ":s///c" highlighting } else if (highlight_match && wp == curwin - && !has_fold + && !has_foldtext && lnum >= curwin->w_cursor.lnum && lnum <= curwin->w_cursor.lnum + search_match_lines) { if (lnum == curwin->w_cursor.lnum) { @@ -1192,7 +1196,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // 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)); + cul_screenline = (is_wrapped && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); if (!cul_screenline) { apply_cursorline_highlight(wp, &wlv); } else { @@ -1315,7 +1319,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s const schar_T lcs_eol = wp->w_p_lcs_chars.eol; // 'eol' value schar_T lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used, then NUL - if (wp->w_p_list && !has_fold && !end_fill) { + if (wp->w_p_list && !has_foldtext && !end_fill) { if (wp->w_p_lcs_chars.space || wp->w_p_lcs_chars.multispace != NULL || wp->w_p_lcs_chars.leadmultispace != NULL @@ -1467,7 +1471,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } } - if (col_rows == 0 && !has_fold && !end_fill) { + if (col_rows == 0 && !has_foldtext && !end_fill) { const int v = (int)(ptr - line); area_highlighting |= prepare_search_hl_line(wp, lnum, v, &line, &screen_search_hl, &search_attr, @@ -1605,6 +1609,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s const bool draw_folded = has_fold && wlv.row == startrow + wlv.filler_lines; if (draw_folded && wlv.n_extra == 0) { wlv.char_attr = folded_attr = win_hl_attr(wp, HLF_FL); + decor_attr = 0; } int extmark_attr = 0; @@ -1640,7 +1645,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s &decor_state); } - if (!has_fold && wp->w_buffer->b_virt_text_inline > 0) { + if (!has_foldtext && wp->w_buffer->b_virt_text_inline > 0) { handle_inline_virtual_text(wp, &wlv, ptr - line); if (wlv.n_extra > 0 && wlv.virt_inline_hl_mode <= kHlModeReplace) { // restore search_attr and area_attr when n_extra is down to zero @@ -1679,7 +1684,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s area_active = false; } - if (!has_fold && wlv.n_extra == 0) { + if (!has_foldtext && wlv.n_extra == 0) { // Check for start/end of 'hlsearch' and other matches. // After end, check for start/end of next match. // When another match, have to check for start again. @@ -1746,7 +1751,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } } - if (draw_folded && wlv.n_extra == 0 && wlv.col == win_col_offset) { + if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) { const int v = (int)(ptr - line); linenr_T lnume = lnum + foldinfo.fi_lines - 1; memset(buf_fold, ' ', FOLD_TEXT_LEN); @@ -1765,7 +1770,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s ptr = line + v; } - if (draw_folded && wlv.n_extra == 0 && wlv.col < grid->cols) { + if (draw_folded && wlv.n_extra == 0 && wlv.col < grid->cols && (has_foldtext || *ptr == NUL)) { // Fill rest of line with 'fold'. wlv.sc_extra = wp->w_p_fcs_chars.fold; wlv.sc_final = NUL; @@ -1848,7 +1853,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // initialize these. mb_c = ' '; mb_schar = schar_from_ascii(' '); - } else if (has_fold) { + } else if (has_foldtext || (has_fold && wlv.col >= grid->cols)) { // skip writing the buffer line itself mb_schar = NUL; } else { @@ -1974,6 +1979,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s can_spell = TRISTATE_TO_BOOL(decor_state.spell, can_spell); } + if (folded_attr) { + decor_attr = hl_combine_attr(folded_attr, decor_attr); + } + if (decor_attr) { if (!attr_pri) { if (wlv.cul_attr) { @@ -2388,7 +2397,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s wlv.vcol_off += wlv.n_extra; } wlv.vcol += wlv.n_extra; - if (wp->w_p_wrap && wlv.n_extra > 0) { + if (is_wrapped && wlv.n_extra > 0) { wlv.boguscols += wlv.n_extra; wlv.col += wlv.n_extra; } @@ -2489,7 +2498,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // Add a blank character to highlight. linebuf_char[wlv.off] = schar_from_ascii(' '); } - if (area_attr == 0 && !has_fold) { + if (area_attr == 0 && !has_foldtext) { // Use attributes from match with highest priority among // 'search_hl' and the match list. get_search_match_hl(wp, @@ -2616,7 +2625,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } // When the window is too narrow draw all "@" lines. - if (leftcols_width >= wp->w_grid.cols && wp->w_p_wrap) { + if (leftcols_width >= wp->w_grid.cols && is_wrapped) { win_draw_end(wp, schar_from_ascii('@'), true, wlv.row, wp->w_grid.rows, HLF_AT); set_empty_rows(wp, wlv.row); wlv.row = endrow; @@ -2627,12 +2636,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // Show "extends" character from 'listchars' if beyond the line end and // 'list' is set. + // Don't show this with 'wrap' as the line can't be scrolled horizontally. if (wp->w_p_lcs_chars.ext != NUL && wp->w_p_list && !wp->w_p_wrap && wlv.filler_todo <= 0 && wlv.col == grid->cols - 1 - && !has_fold) { + && !has_foldtext) { if (has_decor && *ptr == NUL && lcs_eol == 0 && lcs_eol_todo) { // Tricky: there might be a virtual text just _after_ the last char decor_redraw_col(wp, (colnr_T)(ptr - line), wlv.off, false, &decor_state); @@ -2714,7 +2724,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s if (wlv.n_extra > 0) { wlv.vcol_off += wlv.n_extra; } - if (wp->w_p_wrap) { + if (is_wrapped) { // Special voodoo required if 'wrap' is on. // // Advance the column indicator to force the line @@ -2782,11 +2792,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s if (has_decor && wlv.filler_todo <= 0 && wlv.col >= grid->cols) { // At the end of screen line: might need to peek for decorations just after // this position. - if (!has_fold && wp->w_p_wrap && wlv.n_extra == 0) { + if (is_wrapped && wlv.n_extra == 0) { decor_redraw_col(wp, (colnr_T)(ptr - line), -3, false, &decor_state); // Check position/hiding of virtual text again on next screen line. decor_need_recheck = true; - } else if (has_fold || !wp->w_p_wrap) { + } else if (!is_wrapped) { // Without wrapping, we might need to display right_align and win_col // virt_text for the entire text line. decor_redraw_col(wp, MAXCOL, -1, true, &decor_state); @@ -2795,14 +2805,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. - if (wlv.col >= grid->cols && (!has_fold || virt_line_offset >= 0) + if (wlv.col >= grid->cols && (!has_foldtext || virt_line_offset >= 0) && (*ptr != NUL || wlv.filler_todo > 0 || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && wlv.p_extra != at_end_str) || (wlv.n_extra != 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL)) || has_more_inline_virt(&wlv, ptr - line))) { - const bool wrap = wp->w_p_wrap // Wrapping enabled. + const bool wrap = is_wrapped // Wrapping enabled (not a folded line). && wlv.filler_todo <= 0 // Not drawing diff filler lines. && lcs_eol_todo // Haven't printed the lcs_eol character. && wlv.row != endrow - 1 // Not the last line being displayed. @@ -2835,7 +2845,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // When not wrapping and finished diff lines, or when displayed // '$' and highlighting until last column, break here. - if ((!wp->w_p_wrap && wlv.filler_todo <= 0) || !lcs_eol_todo) { + if ((!is_wrapped && wlv.filler_todo <= 0) || !lcs_eol_todo) { break; } diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 9a3fffde07..1cc04d2588 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -2283,22 +2283,28 @@ static void win_update(win_T *wp) syntax_end_parsing(wp, syntax_last_parsed + 1); } + bool display_buf_line = (foldinfo.fi_lines == 0 || *wp->w_p_fdt == NUL); + // Display one line spellvars_T zero_spv = { 0 }; row = win_line(wp, lnum, srow, wp->w_grid.rows, 0, - foldinfo.fi_lines > 0 ? &zero_spv : &spv, foldinfo); + display_buf_line ? &spv : &zero_spv, foldinfo); + + if (display_buf_line) { + syntax_last_parsed = lnum; + } else { + spv.spv_capcol_lnum = 0; + } if (foldinfo.fi_lines == 0) { wp->w_lines[idx].wl_folded = false; wp->w_lines[idx].wl_lastlnum = lnum; did_update = DID_LINE; - syntax_last_parsed = lnum; } else { foldinfo.fi_lines--; wp->w_lines[idx].wl_folded = true; wp->w_lines[idx].wl_lastlnum = lnum + foldinfo.fi_lines; did_update = DID_FOLD; - spv.spv_capcol_lnum = 0; } } diff --git a/src/nvim/options.lua b/src/nvim/options.lua index db33c94be3..8ef22d649a 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -3181,6 +3181,9 @@ return { It is not allowed to change text or jump to another window while evaluating 'foldtext' |textlock|. + + When set to an empty string, foldtext is disabled, and the line + is displayed normally with highlighting and no line wrapping. ]=], full_name = 'foldtext', modelineexpr = true, diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index a440645fe2..95d209496f 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -80,56 +80,113 @@ describe('folded lines', function() end end) - local function test_folded_cursorline() + local function test_folded_cursorline(foldtext) + if not foldtext then + command('set foldtext=') + end command('set number cursorline foldcolumn=2') command('hi link CursorLineFold Search') insert(content1) feed('ggzf3jj') + if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]|*7 - [3:---------------------------------------------]| - ## grid 2 - {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}| - {6: }{9: 5 }{12:^in his cave. }| - {7: }{8: 6 } | - {1:~ }|*4 - ## grid 3 - | - ]]) + if foldtext then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}| + {6: }{9: 5 }{12:^in his cave. }| + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + else + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {7:+ }{8: 1 }{5:This is a······························}| + {6: }{9: 5 }{12:^in his cave. }| + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + end else - screen:expect([[ - {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}| - {6: }{9: 5 }{12:^in his cave. }| - {7: }{8: 6 } | - {1:~ }|*4 - | - ]]) + if foldtext then + screen:expect([[ + {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}| + {6: }{9: 5 }{12:^in his cave. }| + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + else + screen:expect([[ + {7:+ }{8: 1 }{5:This is a······························}| + {6: }{9: 5 }{12:^in his cave. }| + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + end end + feed('k') + if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]|*7 - [3:---------------------------------------------]| - ## grid 2 - {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}| - {7: }{8: 5 }in his cave. | - {7: }{8: 6 } | - {1:~ }|*4 - ## grid 3 - | - ]]) + if foldtext then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + else + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {6:+ }{9: 1 }{13:^This is a······························}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + end else - screen:expect([[ - {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}| - {7: }{8: 5 }in his cave. | - {7: }{8: 6 } | - {1:~ }|*4 - | - ]]) + if foldtext then + screen:expect([[ + {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + else + screen:expect([[ + {6:+ }{9: 1 }{13:^This is a······························}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + end end + -- CursorLine is applied correctly with screenrow motions #22232 feed('jgk') screen:expect_unchanged() @@ -137,71 +194,130 @@ describe('folded lines', function() feed('zo4Gzc') screen:expect_unchanged() command('set cursorlineopt=line') + if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]|*7 - [3:---------------------------------------------]| - ## grid 2 - {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}| - {7: }{8: 5 }in his cave. | - {7: }{8: 6 } | - {1:~ }|*4 - ## grid 3 - | - ]]) + if foldtext then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + else + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {7:+ }{8: 1 }{13:^This is a······························}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + end else - screen:expect([[ - {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}| - {7: }{8: 5 }in his cave. | - {7: }{8: 6 } | - {1:~ }|*4 - | - ]]) + if foldtext then + screen:expect([[ + {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + else + screen:expect([[ + {7:+ }{8: 1 }{13:^This is a······························}| + {7: }{8: 5 }in his cave. | + {7: }{8: 6 } | + {1:~ }|*4 + | + ]]) + end end + command('set relativenumber cursorlineopt=number') + if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]|*7 - [3:---------------------------------------------]| - ## grid 2 - {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}| - {7: }{8: 1 }in his cave. | - {7: }{8: 2 } | - {1:~ }|*4 - ## grid 3 - | - ]]) + if foldtext then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}| + {7: }{8: 1 }in his cave. | + {7: }{8: 2 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + else + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]|*7 + [3:---------------------------------------------]| + ## grid 2 + {6:+ }{9:1 }{5:^This is a······························}| + {7: }{8: 1 }in his cave. | + {7: }{8: 2 } | + {1:~ }|*4 + ## grid 3 + | + ]]) + end else - screen:expect([[ - {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}| - {7: }{8: 1 }in his cave. | - {7: }{8: 2 } | - {1:~ }|*4 - | - ]]) + if foldtext then + screen:expect([[ + {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}| + {7: }{8: 1 }in his cave. | + {7: }{8: 2 } | + {1:~ }|*4 + | + ]]) + else + screen:expect([[ + {6:+ }{9:1 }{5:^This is a······························}| + {7: }{8: 1 }in his cave. | + {7: }{8: 2 } | + {1:~ }|*4 + | + ]]) + end end end describe("when 'cursorline' is set", function() - it('with high-priority CursorLine', function() - command('hi! CursorLine guibg=NONE guifg=Red gui=NONE') - test_folded_cursorline() - end) + local function cursorline_tests(foldtext) + local sfx = not foldtext and ' (disabled foldtext)' or '' + it('with high-priority CursorLine' .. sfx, function() + command('hi! CursorLine guibg=NONE guifg=Red gui=NONE') + test_folded_cursorline(foldtext) + end) - it('with low-priority CursorLine', function() - command('hi! CursorLine guibg=NONE guifg=NONE gui=underline') - local attrs = screen:get_default_attr_ids() - attrs[12] = { underline = true } - attrs[13] = { - foreground = Screen.colors.DarkBlue, - background = Screen.colors.LightGrey, - underline = true, - } - screen:set_default_attr_ids(attrs) - test_folded_cursorline() - end) + it('with low-priority CursorLine' .. sfx, function() + command('hi! CursorLine guibg=NONE guifg=NONE gui=underline') + local attrs = screen:get_default_attr_ids() + attrs[12] = { underline = true } + attrs[13] = { + foreground = Screen.colors.DarkBlue, + background = Screen.colors.LightGrey, + underline = true, + } + screen:set_default_attr_ids(attrs) + test_folded_cursorline(foldtext) + end) + end + + cursorline_tests(true) + cursorline_tests(false) end) it('work with spell', function() @@ -2549,6 +2665,120 @@ describe('folded lines', function() ]]) end end) + + it('supports disabled foldtext', function() + screen:try_resize(30, 7) + insert(content1) + command('hi! CursorLine guibg=NONE guifg=Red gui=NONE') + command('hi F0 guibg=Red guifg=Black') + command('hi F1 guifg=White') + api.nvim_set_option_value('cursorline', true, {}) + api.nvim_set_option_value('foldcolumn', '4', {}) + api.nvim_set_option_value('foldtext', '', {}) + + command('3,4fold') + command('5,6fold') + command('2,6fold') + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + {7: }This is a | + {7:+ }{13:^valid English·············}| + {1:~ }|*4 + ## grid 3 + | + ]]) + else + screen:expect([[ + {7: }This is a | + {7:+ }{13:^valid English·············}| + {1:~ }|*4 + | + ]]) + end + + feed('zo') + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + {7: }This is a | + {7:- }valid English | + {7:│+ }{5:sentence composed by······}| + {7:│+ }{13:^in his cave.··············}| + {1:~ }|*2 + ## grid 3 + | + ]]) + else + screen:expect([[ + {7: }This is a | + {7:- }valid English | + {7:│+ }{5:sentence composed by······}| + {7:│+ }{13:^in his cave.··············}| + {1:~ }|*2 + | + ]]) + end + + command('hi! Visual guibg=Red') + feed('V2k') + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + {7: }This is a | + {7:- }^v{14:alid English} | + {7:│+ }{15:sentence composed by······}| + {7:│+ }{15:in his cave.··············}| + {1:~ }|*2 + ## grid 3 + {11:-- VISUAL LINE --} | + ]]) + else + screen:expect([[ + {7: }This is a | + {7:- }^v{14:alid English} | + {7:│+ }{15:sentence composed by······}| + {7:│+ }{15:in his cave.··············}| + {1:~ }|*2 + {11:-- VISUAL LINE --} | + ]]) + end + + api.nvim_set_option_value('rightleft', true, {}) + if multigrid then + screen:expect([[ + ## grid 1 + [2:------------------------------]|*6 + [3:------------------------------]| + ## grid 2 + a si sihT{7: }| + {14:hsilgnE dila}^v{7: -}| + {15:······yb desopmoc ecnetnes}{7: +│}| + {15:··············.evac sih ni}{7: +│}| + {1: ~}|*2 + ## grid 3 + {11:-- VISUAL LINE --} | + ]]) + else + screen:expect([[ + a si sihT{7: }| + {14:hsilgnE dila}^v{7: -}| + {15:······yb desopmoc ecnetnes}{7: +│}| + {15:··············.evac sih ni}{7: +│}| + {1: ~}|*2 + {11:-- VISUAL LINE --} | + ]]) + end + end) end describe('with ext_multigrid', function()