aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/fold.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/fold.c
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/fold.c')
-rw-r--r--src/nvim/fold.c169
1 files changed, 103 insertions, 66 deletions
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 7306131574..c905b2d3ed 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -1,6 +1,3 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
// vim: set fdm=marker fdl=1 fdc=3
// fold.c: code for folding
@@ -12,21 +9,27 @@
#include <stdlib.h>
#include <string.h>
-#include "nvim/ascii.h"
+#include "klib/kvec.h"
+#include "nvim/api/extmark.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
+#include "nvim/decoration.h"
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
-#include "nvim/eval/typval_defs.h"
#include "nvim/ex_session.h"
#include "nvim/extmark.h"
#include "nvim/fold.h"
+#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
@@ -37,15 +40,17 @@
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/ops.h"
-#include "nvim/option.h"
+#include "nvim/option_vars.h"
#include "nvim/os/input.h"
#include "nvim/plines.h"
+#include "nvim/pos_defs.h"
#include "nvim/search.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
-#include "nvim/types.h"
+#include "nvim/types_defs.h"
#include "nvim/undo.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
// local declarations. {{{1
// typedef fold_T {{{2
@@ -101,12 +106,12 @@ typedef void (*LevelGetter)(fline_T *);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "fold.c.generated.h"
#endif
-static char *e_nofold = N_("E490: No fold found");
+static const char *e_nofold = N_("E490: No fold found");
// While updating the folds lines between invalid_top and invalid_bot have an
// undefined fold level. Only used for the window currently being updated.
-static linenr_T invalid_top = (linenr_T)0;
-static linenr_T invalid_bot = (linenr_T)0;
+static linenr_T invalid_top = 0;
+static linenr_T invalid_bot = 0;
// When using 'foldexpr' we sometimes get the level of the next line, which
// calls foldlevel() to get the level of the current line, which hasn't been
@@ -201,7 +206,7 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp
if (first == 0) {
// Recursively search for a fold that contains "lnum".
garray_T *gap = &win->w_folds;
- for (;;) {
+ while (true) {
if (!foldFind(gap, lnum_rel, &fp)) {
break;
}
@@ -263,7 +268,7 @@ static int foldLevel(linenr_T lnum)
{
// While updating the folds lines between invalid_top and invalid_bot have
// an undefined fold level. Otherwise update the folds first.
- if (invalid_top == (linenr_T)0) {
+ if (invalid_top == 0) {
checkupdate(curwin);
} else if (lnum == prev_lnum && prev_lnum_lvl >= 0) {
return prev_lnum_lvl;
@@ -358,7 +363,7 @@ int foldmethodIsDiff(win_T *wp)
// closeFold() {{{2
/// Close fold for current window at position "pos".
/// Repeat "count" times.
-void closeFold(pos_T pos, long count)
+void closeFold(pos_T pos, int count)
{
setFoldRepeat(pos, count, false);
}
@@ -412,7 +417,7 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha
// openFold() {{{2
/// Open fold for current window at position "pos".
/// Repeat "count" times.
-void openFold(pos_T pos, long count)
+void openFold(pos_T pos, int count)
{
setFoldRepeat(pos, count, true);
}
@@ -430,7 +435,7 @@ void foldOpenCursor(void)
{
checkupdate(curwin);
if (hasAnyFolding(curwin)) {
- for (;;) {
+ while (true) {
int done = DONE_NOTHING;
(void)setManualFold(curwin->w_cursor, true, false, &done);
if (!(done & DONE_ACTION)) {
@@ -562,7 +567,7 @@ void foldCreate(win_T *wp, pos_T start, pos_T end)
i = 0;
} else {
fold_T *fp;
- for (;;) {
+ while (true) {
if (!foldFind(gap, start_rel.lnum, &fp)) {
break;
}
@@ -645,7 +650,7 @@ void foldCreate(win_T *wp, pos_T start, pos_T end)
// We want the new fold to be closed. If it would remain open because
// of using 'foldlevel', need to adjust fd_flags of containing folds.
if (use_level && !closed && level < wp->w_p_fdl) {
- closeFold(start, 1L);
+ closeFold(start, 1);
}
if (!use_level) {
wp->w_fold_manual = true;
@@ -683,7 +688,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const
garray_T *found_ga = NULL;
linenr_T lnum_off = 0;
bool use_level = false;
- for (;;) {
+ while (true) {
fold_T *fp;
if (!foldFind(gap, lnum - lnum_off, &fp)) {
break;
@@ -743,8 +748,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const
}
if (last_lnum > 0) {
- // TODO(teto): pass the buffer
- changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L, false);
+ changed_lines(wp->w_buffer, first_lnum, 0, last_lnum, 0, false);
// send one nvim_buf_lines_event at the end
// last_lnum is the line *after* the last line of the outermost fold
@@ -771,7 +775,7 @@ void clearFolding(win_T *win)
/// The changes in lines from top to bot (inclusive).
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{
- if (disable_fold_update || State & MODE_INSERT) {
+ if (disable_fold_update || (State & MODE_INSERT && !foldmethodIsIndent(wp))) {
return;
}
@@ -843,7 +847,7 @@ void foldUpdateAll(win_T *win)
/// @return FAIL if not moved.
///
/// @param dir FORWARD or BACKWARD
-int foldMoveTo(const bool updown, const int dir, const long count)
+int foldMoveTo(const bool updown, const int dir, const int count)
{
int retval = FAIL;
linenr_T lnum;
@@ -852,7 +856,7 @@ int foldMoveTo(const bool updown, const int dir, const long count)
checkupdate(curwin);
// Repeat "count" times.
- for (long n = 0; n < count; n++) {
+ for (int n = 0; n < count; n++) {
// Find nested folds. Stop when a fold is closed. The deepest fold
// that moves the cursor is used.
linenr_T lnum_off = 0;
@@ -865,7 +869,7 @@ int foldMoveTo(const bool updown, const int dir, const long count)
linenr_T lnum_found = curwin->w_cursor.lnum;
int level = 0;
bool last = false;
- for (;;) {
+ while (true) {
if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) {
if (!updown || gap->ga_len == 0) {
break;
@@ -1104,7 +1108,7 @@ static int foldLevelWin(win_T *wp, linenr_T lnum)
// Recursively search for a fold that contains "lnum".
garray_T *gap = &wp->w_folds;
- for (;;) {
+ while (true) {
if (!foldFind(gap, lnum_rel, &fp)) {
break;
}
@@ -1125,14 +1129,14 @@ static void checkupdate(win_T *wp)
return;
}
- foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); // will update all
+ foldUpdate(wp, 1, (linenr_T)MAXLNUM); // will update all
wp->w_foldinvalid = false;
}
// setFoldRepeat() {{{2
/// Open or close fold for current window at position `pos`.
/// Repeat "count" times.
-static void setFoldRepeat(pos_T pos, long count, int do_open)
+static void setFoldRepeat(pos_T pos, int count, int do_open)
{
for (int n = 0; n < count; n++) {
int done = DONE_NOTHING;
@@ -1201,7 +1205,7 @@ static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recu
// Find the fold, open or close it.
garray_T *gap = &wp->w_folds;
- for (;;) {
+ while (true) {
if (!foldFind(gap, lnum, &fp)) {
// If there is a following fold, continue there next time.
if (fp != NULL && fp < (fold_T *)gap->ga_data + gap->ga_len) {
@@ -1360,7 +1364,7 @@ void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount,
}
// If appending a line in Insert mode, it should be included in the fold
// just above the line.
- if ((State & MODE_INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) {
+ if ((State & MODE_INSERT) && amount == 1 && line2 == MAXLNUM) {
line1--;
}
foldMarkAdjustRecurse(wp, &wp->w_folds, line1, line2, amount, amount_after);
@@ -1378,7 +1382,7 @@ static void foldMarkAdjustRecurse(win_T *wp, garray_T *gap, linenr_T line1, line
// In Insert mode an inserted line at the top of a fold is considered part
// of the fold, otherwise it isn't.
- if ((State & MODE_INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) {
+ if ((State & MODE_INSERT) && amount == 1 && line2 == MAXLNUM) {
top = line1 + 1;
} else {
top = line1;
@@ -1580,8 +1584,7 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
// Update both changes here, to avoid all folds after the start are
// changed when the start marker is inserted and the end isn't.
- // TODO(teto): pass the buffer
- changed_lines(start.lnum, (colnr_T)0, end.lnum, 0L, false);
+ changed_lines(buf, start.lnum, 0, end.lnum, 0, false);
// Note: foldAddMarker() may not actually change start and/or end if
// u_save() is unable to save the buffer line, but we send the
@@ -1601,7 +1604,7 @@ static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t mark
linenr_T lnum = pos.lnum;
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
- char *line = ml_get_buf(buf, lnum, false);
+ char *line = ml_get_buf(buf, lnum);
size_t line_len = strlen(line);
size_t added = 0;
@@ -1661,7 +1664,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t marker
}
char *cms = buf->b_p_cms;
- char *line = ml_get_buf(buf, lnum, false);
+ char *line = ml_get_buf(buf, lnum);
for (char *p = line; *p != NUL; p++) {
if (strncmp(p, marker, markerlen) != 0) {
continue;
@@ -1704,8 +1707,9 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t marker
/// @return the text for a closed fold
///
/// Otherwise the result is in allocated memory.
-char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo, char *buf)
- FUNC_ATTR_NONNULL_ARG(1)
+char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo, char *buf,
+ VirtText *vt)
+ FUNC_ATTR_NONNULL_ALL
{
char *text = NULL;
// an error occurred when evaluating 'fdt' setting
@@ -1742,15 +1746,33 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo
set_vim_var_string(VV_FOLDDASHES, dashes, -1);
set_vim_var_nr(VV_FOLDLEVEL, (varnumber_T)level);
- // skip evaluating foldtext on errors
+ // skip evaluating 'foldtext' on errors
if (!got_fdt_error) {
- win_T *save_curwin = curwin;
+ win_T *const save_curwin = curwin;
+ const sctx_T saved_sctx = current_sctx;
+
curwin = wp;
curbuf = wp->w_buffer;
+ current_sctx = wp->w_p_script_ctx[WV_FDT].script_ctx;
+
+ emsg_off++; // handle exceptions, but don't display errors
+
+ Object obj = eval_foldtext(wp);
+ if (obj.type == kObjectTypeArray) {
+ Error err = ERROR_INIT;
+ *vt = parse_virt_text(obj.data.array, &err, NULL);
+ if (!ERROR_SET(&err)) {
+ *buf = NUL;
+ text = buf;
+ }
+ api_clear_error(&err);
+ } else if (obj.type == kObjectTypeString) {
+ text = obj.data.string.data;
+ obj = NIL;
+ }
+ api_free_object(obj);
- emsg_silent++; // handle exceptions, but don't display errors
- text = eval_to_string_safe(wp->w_p_fdt, NULL, was_set_insecurely(wp, "foldtext", OPT_LOCAL));
- emsg_silent--;
+ emsg_off--;
if (text == NULL || did_emsg) {
got_fdt_error = true;
@@ -1758,9 +1780,10 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo
curwin = save_curwin;
curbuf = curwin->w_buffer;
+ current_sctx = saved_sctx;
}
last_lnum = lnum;
- last_wp = wp;
+ last_wp = wp;
set_vim_var_string(VV_FOLDDASHES, NULL, -1);
if (!did_emsg && save_did_emsg) {
@@ -1786,18 +1809,18 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo
}
}
if (*p != NUL) {
- p = transstr((const char *)text, true);
+ p = transstr(text, true);
xfree(text);
text = p;
}
}
}
if (text == NULL) {
- long count = lnume - lnum + 1;
+ int count = lnume - lnum + 1;
vim_snprintf(buf, FOLD_TEXT_LEN,
- NGETTEXT("+--%3ld line folded",
- "+--%3ld lines folded ", count),
+ NGETTEXT("+--%3d line folded",
+ "+--%3d lines folded ", count),
count);
text = buf;
}
@@ -1888,7 +1911,7 @@ static void foldtext_cleanup(char *str)
static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
{
// Avoid problems when being called recursively.
- if (invalid_top != (linenr_T)0) {
+ if (invalid_top != 0) {
return;
}
@@ -2109,7 +2132,7 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
}
}
- invalid_top = (linenr_T)0;
+ invalid_top = 0;
}
// foldUpdateIEMSRecurse() {{{2
@@ -2271,12 +2294,12 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
// We will move the start of this fold up, hence we move all
// nested folds (with relative line numbers) down.
foldMarkAdjustRecurse(flp->wp, &fp->fd_nested,
- (linenr_T)0, (linenr_T)MAXLNUM,
- (fp->fd_top - firstlnum), 0L);
+ 0, (linenr_T)MAXLNUM,
+ (fp->fd_top - firstlnum), 0);
} else {
// Will move fold down, move nested folds relatively up.
foldMarkAdjustRecurse(flp->wp, &fp->fd_nested,
- (linenr_T)0,
+ 0,
(firstlnum - fp->fd_top - 1),
(linenr_T)MAXLNUM,
(fp->fd_top - firstlnum));
@@ -2344,7 +2367,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
fp->fd_len = startlnum - fp->fd_top;
foldMarkAdjustRecurse(flp->wp, &fp->fd_nested,
fp->fd_len, (linenr_T)MAXLNUM,
- (linenr_T)MAXLNUM, 0L);
+ (linenr_T)MAXLNUM, 0);
fold_changed = true;
}
} else {
@@ -2504,7 +2527,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
// delete following folds that end before the current line
- for (;;) {
+ while (true) {
fp2 = fp + 1;
if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len
|| fp2->fd_top > flp->lnum) {
@@ -2514,7 +2537,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
if (fp2->fd_top < flp->lnum) {
// Make fold that includes lnum start at lnum.
foldMarkAdjustRecurse(flp->wp, &fp2->fd_nested,
- (linenr_T)0, (flp->lnum - fp2->fd_top - 1),
+ 0, (flp->lnum - fp2->fd_top - 1),
(linenr_T)MAXLNUM, (fp2->fd_top - flp->lnum));
fp2->fd_len -= flp->lnum - fp2->fd_top;
fp2->fd_top = flp->lnum;
@@ -2652,7 +2675,7 @@ static void foldRemove(win_T *const wp, garray_T *gap, linenr_T top, linenr_T bo
if (fp->fd_top + fp->fd_len - 1 > bot) {
// 5: Make fold that includes bot start below bot.
foldMarkAdjustRecurse(wp, &fp->fd_nested,
- (linenr_T)0, (bot - fp->fd_top),
+ 0, (bot - fp->fd_top),
(linenr_T)MAXLNUM, (fp->fd_top - bot - 1));
fp->fd_len -= bot - fp->fd_top + 1;
fp->fd_top = bot + 1;
@@ -2718,7 +2741,6 @@ static void truncate_fold(win_T *const wp, fold_T *fp, linenr_T end)
}
#define FOLD_END(fp) ((fp)->fd_top + (fp)->fd_len - 1)
-// -V:VALID_FOLD:V560
#define VALID_FOLD(fp, gap) \
((gap)->ga_len > 0 && (fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len))
#define FOLD_INDEX(fp, gap) ((size_t)((fp) - ((fold_T *)(gap)->ga_data)))
@@ -2838,7 +2860,7 @@ static void foldMerge(win_T *const wp, fold_T *fp1, garray_T *gap, fold_T *fp2)
// If the last nested fold in fp1 touches the first nested fold in fp2,
// merge them recursively.
- if (foldFind(gap1, fp1->fd_len - 1, &fp3) && foldFind(gap2, 0L, &fp4)) {
+ if (foldFind(gap1, fp1->fd_len - 1, &fp3) && foldFind(gap2, 0, &fp4)) {
foldMerge(wp, fp3, gap2, fp4);
}
@@ -2869,7 +2891,7 @@ static void foldlevelIndent(fline_T *flp)
linenr_T lnum = flp->lnum + flp->off;
buf_T *buf = flp->wp->w_buffer;
- char *s = skipwhite(ml_get_buf(buf, lnum, false));
+ char *s = skipwhite(ml_get_buf(buf, lnum));
// empty line or lines starting with a character in 'foldignore': level
// depends on surrounding lines
@@ -2926,7 +2948,7 @@ static void foldlevelExpr(fline_T *flp)
const bool save_keytyped = KeyTyped;
int c;
- const int n = eval_foldexpr(flp->wp->w_p_fde, &c);
+ const int n = eval_foldexpr(flp->wp, &c);
KeyTyped = save_keytyped;
switch (c) {
@@ -3031,7 +3053,7 @@ static void foldlevelMarker(fline_T *flp)
flp->start = 0;
flp->lvl_next = flp->lvl;
- char *s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, false);
+ char *s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off);
while (*s) {
if (*s == cstart
&& strncmp(s + 1, startmarker, foldstartmarkerlen - 1) == 0) {
@@ -3109,7 +3131,7 @@ int put_folds(FILE *fd, win_T *wp)
{
if (foldmethodIsManual(wp)) {
if (put_line(fd, "silent! normal! zE") == FAIL
- || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL
+ || put_folds_recurse(fd, &wp->w_folds, 0) == FAIL
|| put_line(fd, "let &fdl = &fdl") == FAIL) {
return FAIL;
}
@@ -3117,7 +3139,7 @@ int put_folds(FILE *fd, win_T *wp)
// If some folds are manually opened/closed, need to restore that.
if (wp->w_fold_manual) {
- return put_foldopen_recurse(fd, wp, &wp->w_folds, (linenr_T)0);
+ return put_foldopen_recurse(fd, wp, &wp->w_folds, 0);
}
return OK;
@@ -3281,8 +3303,8 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
}
- long count = foldend - foldstart + 1;
- char *txt = NGETTEXT("+-%s%3ld line: ", "+-%s%3ld lines: ", count);
+ int count = foldend - foldstart + 1;
+ char *txt = NGETTEXT("+-%s%3d line: ", "+-%s%3d lines: ", count);
size_t len = strlen(txt)
+ strlen(dashes) // for %s
+ 20 // for %3ld
@@ -3317,10 +3339,25 @@ void f_foldtextresult(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
foldinfo_T info = fold_info(curwin, lnum);
if (info.fi_lines > 0) {
- char *text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf);
+ VirtText vt = VIRTTEXT_EMPTY;
+ char *text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf, &vt);
if (text == buf) {
text = xstrdup(text);
}
+ if (kv_size(vt) > 0) {
+ assert(*text == NUL);
+ for (size_t i = 0; i < kv_size(vt);) {
+ int attr = 0;
+ char *new_text = next_virt_text_chunk(vt, &i, &attr);
+ if (new_text == NULL) {
+ break;
+ }
+ new_text = concat_str(text, new_text);
+ xfree(text);
+ text = new_text;
+ }
+ }
+ clear_virttext(&vt);
rettv->vval.v_string = text;
}