folds: decrease reliance on global "curwin" (#12132)

Pass the window in which to create/delete folds instead of using the
global "curwin" (current window).
Preliminary work for a fold API.

TODO: I kept changed_lines prototype unchanged. This should be updated
when a fold API sees the light.
This commit is contained in:
Matthieu Coudron 2020-04-16 21:29:04 +02:00 committed by GitHub
parent a5818204b1
commit fb4c7a53cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 72 deletions

View File

@ -9291,8 +9291,9 @@ static void ex_match(exarg_T *eap)
static void ex_fold(exarg_T *eap)
{
if (foldManualAllowed(TRUE))
foldCreate(eap->line1, eap->line2);
if (foldManualAllowed(true)) {
foldCreate(curwin, eap->line1, eap->line2);
}
}
static void ex_foldopen(exarg_T *eap)

View File

@ -539,12 +539,10 @@ int foldManualAllowed(int create)
return FALSE;
}
/* foldCreate() {{{2 */
/*
* Create a fold from line "start" to line "end" (inclusive) in the current
* window.
*/
void foldCreate(linenr_T start, linenr_T end)
// foldCreate() {{{2
/// Create a fold from line "start" to line "end" (inclusive) in the current
/// window.
void foldCreate(win_T *wp, linenr_T start, linenr_T end)
{
fold_T *fp;
garray_T *gap;
@ -565,16 +563,16 @@ void foldCreate(linenr_T start, linenr_T end)
end_rel = end;
}
/* When 'foldmethod' is "marker" add markers, which creates the folds. */
if (foldmethodIsMarker(curwin)) {
foldCreateMarkers(start, end);
// When 'foldmethod' is "marker" add markers, which creates the folds.
if (foldmethodIsMarker(wp)) {
foldCreateMarkers(wp, start, end);
return;
}
checkupdate(curwin);
checkupdate(wp);
/* Find the place to insert the new fold. */
gap = &curwin->w_folds;
// Find the place to insert the new fold
gap = &wp->w_folds;
for (;; ) {
if (!foldFind(gap, start_rel, &fp))
break;
@ -584,12 +582,14 @@ void foldCreate(linenr_T start, linenr_T end)
start_rel -= fp->fd_top;
end_rel -= fp->fd_top;
if (use_level || fp->fd_flags == FD_LEVEL) {
use_level = TRUE;
if (level >= curwin->w_p_fdl)
closed = TRUE;
} else if (fp->fd_flags == FD_CLOSED)
closed = TRUE;
++level;
use_level = true;
if (level >= wp->w_p_fdl) {
closed = true;
}
} else if (fp->fd_flags == FD_CLOSED) {
closed = true;
}
level++;
} else {
/* This fold and new fold overlap: Insert here and move some folds
* inside the new fold. */
@ -655,13 +655,13 @@ void foldCreate(linenr_T start, linenr_T end)
}
/* deleteFold() {{{2 */
/*
* Delete a fold at line "start" in the current window.
* When "end" is not 0, delete all folds from "start" to "end".
* When "recursive" is TRUE delete recursively.
*/
// deleteFold() {{{2
/// @param start delete all folds from start to end when not 0
/// @param end delete all folds from start to end when not 0
/// @param recursive delete recursively if true
/// @param had_visual true when Visual selection used
void deleteFold(
win_T *const wp,
const linenr_T start,
const linenr_T end,
const int recursive,
@ -678,11 +678,11 @@ void deleteFold(
linenr_T first_lnum = MAXLNUM;
linenr_T last_lnum = 0;
checkupdate(curwin);
checkupdate(wp);
while (lnum <= end) {
// Find the deepest fold for "start".
garray_T *gap = &curwin->w_folds;
garray_T *gap = &wp->w_folds;
garray_T *found_ga = NULL;
linenr_T lnum_off = 0;
bool use_level = false;
@ -694,10 +694,11 @@ void deleteFold(
found_fp = fp;
found_off = lnum_off;
/* if "lnum" is folded, don't check nesting */
if (check_closed(curwin, fp, &use_level, level,
&maybe_small, lnum_off))
// if "lnum" is folded, don't check nesting
if (check_closed(wp, fp, &use_level, level,
&maybe_small, lnum_off)) {
break;
}
/* check nested folds */
gap = &fp->fd_nested;
@ -709,16 +710,20 @@ void deleteFold(
} else {
lnum = found_fp->fd_top + found_fp->fd_len + found_off;
if (foldmethodIsManual(curwin))
if (foldmethodIsManual(wp)) {
deleteFoldEntry(found_ga,
(int)(found_fp - (fold_T *)found_ga->ga_data), recursive);
else {
if (first_lnum > found_fp->fd_top + found_off)
(int)(found_fp - (fold_T *)found_ga->ga_data),
recursive);
} else {
if (first_lnum > found_fp->fd_top + found_off) {
first_lnum = found_fp->fd_top + found_off;
if (last_lnum < lnum)
}
if (last_lnum < lnum) {
last_lnum = lnum;
if (!did_one)
parseMarker(curwin);
}
if (!did_one) {
parseMarker(wp);
}
deleteFoldMarkers(found_fp, recursive, found_off);
}
did_one = true;
@ -737,6 +742,7 @@ void deleteFold(
check_cursor_col();
if (last_lnum > 0) {
// TODO(teto): pass the buffer
changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L, false);
// send one nvim_buf_lines_event at the end
@ -1048,7 +1054,7 @@ void cloneFoldGrowArray(garray_T *from, garray_T *to)
* the first fold below it (careful: it can be beyond the end of the array!).
* Returns FALSE when there is no fold that contains "lnum".
*/
static int foldFind(garray_T *gap, linenr_T lnum, fold_T **fpp)
static int foldFind(const garray_T *gap, linenr_T lnum, fold_T **fpp)
{
linenr_T low, high;
fold_T *fp;
@ -1487,12 +1493,15 @@ static int getDeepestNestingRecurse(garray_T *gap)
return maxlevel;
}
/* check_closed() {{{2 */
/*
* Check if a fold is closed and update the info needed to check nested folds.
*/
// check_closed() {{{2
/// Check if a fold is closed and update the info needed to check nested folds.
///
/// @param[in,out] use_levelp true: outer fold had FD_LEVEL
/// @param level folding depth
/// @param[out] maybe_smallp TRUE: outer this had fd_small == kNone
/// @param lnum_off line number offset for fp->fd_top
static bool check_closed(
win_T *const win,
win_T *const wp,
fold_T *const fp,
bool *const use_levelp, // true: outer fold had FD_LEVEL
const int level, // folding depth
@ -1506,7 +1515,7 @@ static bool check_closed(
* fold and all folds it contains depend on 'foldlevel'. */
if (*use_levelp || fp->fd_flags == FD_LEVEL) {
*use_levelp = true;
if (level >= win->w_p_fdl) {
if (level >= wp->w_p_fdl) {
closed = true;
}
} else if (fp->fd_flags == FD_CLOSED) {
@ -1521,7 +1530,7 @@ static bool check_closed(
if (*maybe_smallp) {
fp->fd_small = kNone;
}
checkSmall(win, fp, lnum_off);
checkSmall(wp, fp, lnum_off);
if (fp->fd_small == kTrue) {
closed = false;
}
@ -1529,10 +1538,9 @@ static bool check_closed(
return closed;
}
/* checkSmall() {{{2 */
/*
* Update fd_small field of fold "fp".
*/
// checkSmall() {{{2
/// Update fd_small field of fold "fp".
/// @param lnum_off offset for fp->fd_top
static void
checkSmall(
win_T *const wp,
@ -1575,19 +1583,21 @@ static void setSmallMaybe(garray_T *gap)
* Create a fold from line "start" to line "end" (inclusive) in the current
* window by adding markers.
*/
static void foldCreateMarkers(linenr_T start, linenr_T end)
static void foldCreateMarkers(win_T *wp, linenr_T start, linenr_T end)
{
if (!MODIFIABLE(curbuf)) {
buf_T *buf = wp->w_buffer;
if (!MODIFIABLE(buf)) {
EMSG(_(e_modifiable));
return;
}
parseMarker(curwin);
parseMarker(wp);
foldAddMarker(start, curwin->w_p_fmr, foldstartmarkerlen);
foldAddMarker(end, foldendmarker, foldendmarkerlen);
foldAddMarker(buf, start, wp->w_p_fmr, foldstartmarkerlen);
foldAddMarker(buf, end, foldendmarker, foldendmarkerlen);
/* 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, (colnr_T)0, end, 0L, false);
// Note: foldAddMarker() may not actually change start and/or end if
@ -1601,12 +1611,13 @@ static void foldCreateMarkers(linenr_T start, linenr_T end)
/*
* Add "marker[markerlen]" in 'commentstring' to line "lnum".
*/
static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen)
static void foldAddMarker(
buf_T *buf, linenr_T lnum, const char_u *marker, size_t markerlen)
{
char_u *cms = curbuf->b_p_cms;
char_u *cms = buf->b_p_cms;
char_u *line;
char_u *newline;
char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s");
char_u *p = (char_u *)strstr((char *)buf->b_p_cms, "%s");
bool line_is_comment = false;
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
@ -1631,7 +1642,7 @@ static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen)
}
ml_replace(lnum, newline, false);
if (added) {
extmark_splice(curbuf, (int)lnum-1, (int)line_len,
extmark_splice(buf, (int)lnum-1, (int)line_len,
0, 0,
0, (int)added, kExtmarkUndo);
}
@ -1893,6 +1904,7 @@ void foldtext_cleanup(char_u *str)
/*
* Update the folding for window "wp", at least from lines "top" to "bot".
* Return TRUE if any folds did change.
* IEMS = "Indent Expr Marker Syntax"
*/
static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
{

View File

@ -1967,8 +1967,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
break;
case OP_FOLD:
VIsual_reselect = false; /* don't reselect now */
foldCreate(oap->start.lnum, oap->end.lnum);
VIsual_reselect = false; // don't reselect now
foldCreate(curwin, oap->start.lnum, oap->end.lnum);
break;
case OP_FOLDOPEN:
@ -1986,9 +1986,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
case OP_FOLDDEL:
case OP_FOLDDELREC:
VIsual_reselect = false; /* don't reselect now */
deleteFold(oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
VIsual_reselect = false; // don't reselect now
deleteFold(curwin, oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break;
case OP_NR_ADD:
@ -4345,11 +4345,12 @@ dozet:
/* "zD": delete fold at cursor recursively */
case 'd':
case 'D': if (foldManualAllowed(false)) {
if (VIsual_active)
if (VIsual_active) {
nv_operator(cap);
else
deleteFold(curwin->w_cursor.lnum,
curwin->w_cursor.lnum, nchar == 'D', false);
} else {
deleteFold(curwin, curwin->w_cursor.lnum,
curwin->w_cursor.lnum, nchar == 'D', false);
}
}
break;
@ -4357,11 +4358,11 @@ dozet:
case 'E': if (foldmethodIsManual(curwin)) {
clearFolding(curwin);
changed_window_setting();
} else if (foldmethodIsMarker(curwin))
deleteFold((linenr_T)1, curbuf->b_ml.ml_line_count,
true, false);
else
} else if (foldmethodIsMarker(curwin)) {
deleteFold(curwin, (linenr_T)1, curbuf->b_ml.ml_line_count, true, false);
} else {
EMSG(_("E352: Cannot erase folds with current 'foldmethod'"));
}
break;
/* "zn": fold none: reset 'foldenable' */