diff options
author | Lewis Russell <lewis6991@gmail.com> | 2024-01-22 10:13:35 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-22 10:13:35 +0000 |
commit | 1233ac467de7504b277425988ef9be7f8d3a9626 (patch) | |
tree | 0f90618b9a542e3bc859cf03079d8149d10e77e1 /src | |
parent | 21b36c7d7fa351544253316c606651e9ce925b29 (diff) | |
download | rneovim-1233ac467de7504b277425988ef9be7f8d3a9626.tar.gz rneovim-1233ac467de7504b277425988ef9be7f8d3a9626.tar.bz2 rneovim-1233ac467de7504b277425988ef9be7f8d3a9626.zip |
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 <zeertzjq@outlook.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/drawline.c | 50 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 12 | ||||
-rw-r--r-- | src/nvim/options.lua | 3 |
3 files changed, 42 insertions, 23 deletions
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, |