aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2024-01-22 10:13:35 +0000
committerGitHub <noreply@github.com>2024-01-22 10:13:35 +0000
commit1233ac467de7504b277425988ef9be7f8d3a9626 (patch)
tree0f90618b9a542e3bc859cf03079d8149d10e77e1 /src
parent21b36c7d7fa351544253316c606651e9ce925b29 (diff)
downloadrneovim-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.c50
-rw-r--r--src/nvim/drawscreen.c12
-rw-r--r--src/nvim/options.lua3
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,