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
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) static void ex_fold(exarg_T *eap)
{ {
if (foldManualAllowed(TRUE)) if (foldManualAllowed(true)) {
foldCreate(eap->line1, eap->line2); foldCreate(curwin, eap->line1, eap->line2);
}
} }
static void ex_foldopen(exarg_T *eap) static void ex_foldopen(exarg_T *eap)

View File

@@ -539,12 +539,10 @@ int foldManualAllowed(int create)
return FALSE; return FALSE;
} }
/* foldCreate() {{{2 */ // foldCreate() {{{2
/* /// Create a fold from line "start" to line "end" (inclusive) in the current
* Create a fold from line "start" to line "end" (inclusive) in the current /// window.
* window. void foldCreate(win_T *wp, linenr_T start, linenr_T end)
*/
void foldCreate(linenr_T start, linenr_T end)
{ {
fold_T *fp; fold_T *fp;
garray_T *gap; garray_T *gap;
@@ -565,16 +563,16 @@ void foldCreate(linenr_T start, linenr_T end)
end_rel = end; end_rel = end;
} }
/* When 'foldmethod' is "marker" add markers, which creates the folds. */ // When 'foldmethod' is "marker" add markers, which creates the folds.
if (foldmethodIsMarker(curwin)) { if (foldmethodIsMarker(wp)) {
foldCreateMarkers(start, end); foldCreateMarkers(wp, start, end);
return; return;
} }
checkupdate(curwin); checkupdate(wp);
/* Find the place to insert the new fold. */ // Find the place to insert the new fold
gap = &curwin->w_folds; gap = &wp->w_folds;
for (;; ) { for (;; ) {
if (!foldFind(gap, start_rel, &fp)) if (!foldFind(gap, start_rel, &fp))
break; break;
@@ -584,12 +582,14 @@ void foldCreate(linenr_T start, linenr_T end)
start_rel -= fp->fd_top; start_rel -= fp->fd_top;
end_rel -= fp->fd_top; end_rel -= fp->fd_top;
if (use_level || fp->fd_flags == FD_LEVEL) { if (use_level || fp->fd_flags == FD_LEVEL) {
use_level = TRUE; use_level = true;
if (level >= curwin->w_p_fdl) if (level >= wp->w_p_fdl) {
closed = TRUE; closed = true;
} else if (fp->fd_flags == FD_CLOSED) }
closed = TRUE; } else if (fp->fd_flags == FD_CLOSED) {
++level; closed = true;
}
level++;
} else { } else {
/* This fold and new fold overlap: Insert here and move some folds /* This fold and new fold overlap: Insert here and move some folds
* inside the new fold. */ * inside the new fold. */
@@ -655,13 +655,13 @@ void foldCreate(linenr_T start, linenr_T end)
} }
/* deleteFold() {{{2 */ // deleteFold() {{{2
/* /// @param start delete all folds from start to end when not 0
* Delete a fold at line "start" in the current window. /// @param end delete all folds from start to end when not 0
* When "end" is not 0, delete all folds from "start" to "end". /// @param recursive delete recursively if true
* When "recursive" is TRUE delete recursively. /// @param had_visual true when Visual selection used
*/
void deleteFold( void deleteFold(
win_T *const wp,
const linenr_T start, const linenr_T start,
const linenr_T end, const linenr_T end,
const int recursive, const int recursive,
@@ -678,11 +678,11 @@ void deleteFold(
linenr_T first_lnum = MAXLNUM; linenr_T first_lnum = MAXLNUM;
linenr_T last_lnum = 0; linenr_T last_lnum = 0;
checkupdate(curwin); checkupdate(wp);
while (lnum <= end) { while (lnum <= end) {
// Find the deepest fold for "start". // Find the deepest fold for "start".
garray_T *gap = &curwin->w_folds; garray_T *gap = &wp->w_folds;
garray_T *found_ga = NULL; garray_T *found_ga = NULL;
linenr_T lnum_off = 0; linenr_T lnum_off = 0;
bool use_level = false; bool use_level = false;
@@ -694,10 +694,11 @@ void deleteFold(
found_fp = fp; found_fp = fp;
found_off = lnum_off; found_off = lnum_off;
/* if "lnum" is folded, don't check nesting */ // if "lnum" is folded, don't check nesting
if (check_closed(curwin, fp, &use_level, level, if (check_closed(wp, fp, &use_level, level,
&maybe_small, lnum_off)) &maybe_small, lnum_off)) {
break; break;
}
/* check nested folds */ /* check nested folds */
gap = &fp->fd_nested; gap = &fp->fd_nested;
@@ -709,16 +710,20 @@ void deleteFold(
} else { } else {
lnum = found_fp->fd_top + found_fp->fd_len + found_off; lnum = found_fp->fd_top + found_fp->fd_len + found_off;
if (foldmethodIsManual(curwin)) if (foldmethodIsManual(wp)) {
deleteFoldEntry(found_ga, deleteFoldEntry(found_ga,
(int)(found_fp - (fold_T *)found_ga->ga_data), recursive); (int)(found_fp - (fold_T *)found_ga->ga_data),
else { recursive);
if (first_lnum > found_fp->fd_top + found_off) } else {
if (first_lnum > found_fp->fd_top + found_off) {
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; last_lnum = lnum;
if (!did_one) }
parseMarker(curwin); if (!did_one) {
parseMarker(wp);
}
deleteFoldMarkers(found_fp, recursive, found_off); deleteFoldMarkers(found_fp, recursive, found_off);
} }
did_one = true; did_one = true;
@@ -737,6 +742,7 @@ void deleteFold(
check_cursor_col(); check_cursor_col();
if (last_lnum > 0) { if (last_lnum > 0) {
// TODO(teto): pass the buffer
changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L, false); changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L, false);
// send one nvim_buf_lines_event at the end // 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!). * 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". * 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; linenr_T low, high;
fold_T *fp; fold_T *fp;
@@ -1487,12 +1493,15 @@ static int getDeepestNestingRecurse(garray_T *gap)
return maxlevel; return maxlevel;
} }
/* check_closed() {{{2 */ // check_closed() {{{2
/* /// Check if a fold is closed and update the info needed to check nested folds.
* 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( static bool check_closed(
win_T *const win, win_T *const wp,
fold_T *const fp, fold_T *const fp,
bool *const use_levelp, // true: outer fold had FD_LEVEL bool *const use_levelp, // true: outer fold had FD_LEVEL
const int level, // folding depth const int level, // folding depth
@@ -1506,7 +1515,7 @@ static bool check_closed(
* fold and all folds it contains depend on 'foldlevel'. */ * fold and all folds it contains depend on 'foldlevel'. */
if (*use_levelp || fp->fd_flags == FD_LEVEL) { if (*use_levelp || fp->fd_flags == FD_LEVEL) {
*use_levelp = true; *use_levelp = true;
if (level >= win->w_p_fdl) { if (level >= wp->w_p_fdl) {
closed = true; closed = true;
} }
} else if (fp->fd_flags == FD_CLOSED) { } else if (fp->fd_flags == FD_CLOSED) {
@@ -1521,7 +1530,7 @@ static bool check_closed(
if (*maybe_smallp) { if (*maybe_smallp) {
fp->fd_small = kNone; fp->fd_small = kNone;
} }
checkSmall(win, fp, lnum_off); checkSmall(wp, fp, lnum_off);
if (fp->fd_small == kTrue) { if (fp->fd_small == kTrue) {
closed = false; closed = false;
} }
@@ -1529,10 +1538,9 @@ static bool check_closed(
return closed; return closed;
} }
/* checkSmall() {{{2 */ // checkSmall() {{{2
/* /// Update fd_small field of fold "fp".
* Update fd_small field of fold "fp". /// @param lnum_off offset for fp->fd_top
*/
static void static void
checkSmall( checkSmall(
win_T *const wp, 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 * Create a fold from line "start" to line "end" (inclusive) in the current
* window by adding markers. * 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)); EMSG(_(e_modifiable));
return; return;
} }
parseMarker(curwin); parseMarker(wp);
foldAddMarker(start, curwin->w_p_fmr, foldstartmarkerlen); foldAddMarker(buf, start, wp->w_p_fmr, foldstartmarkerlen);
foldAddMarker(end, foldendmarker, foldendmarkerlen); foldAddMarker(buf, end, foldendmarker, foldendmarkerlen);
/* Update both changes here, to avoid all folds after the start are /* Update both changes here, to avoid all folds after the start are
* changed when the start marker is inserted and the end isn't. */ * 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); changed_lines(start, (colnr_T)0, end, 0L, false);
// Note: foldAddMarker() may not actually change start and/or end if // 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". * 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 *line;
char_u *newline; 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; bool line_is_comment = false;
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end // 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); ml_replace(lnum, newline, false);
if (added) { if (added) {
extmark_splice(curbuf, (int)lnum-1, (int)line_len, extmark_splice(buf, (int)lnum-1, (int)line_len,
0, 0, 0, 0,
0, (int)added, kExtmarkUndo); 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". * Update the folding for window "wp", at least from lines "top" to "bot".
* Return TRUE if any folds did change. * 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) 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; break;
case OP_FOLD: case OP_FOLD:
VIsual_reselect = false; /* don't reselect now */ VIsual_reselect = false; // don't reselect now
foldCreate(oap->start.lnum, oap->end.lnum); foldCreate(curwin, oap->start.lnum, oap->end.lnum);
break; break;
case OP_FOLDOPEN: 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_FOLDDEL:
case OP_FOLDDELREC: case OP_FOLDDELREC:
VIsual_reselect = false; /* don't reselect now */ VIsual_reselect = false; // don't reselect now
deleteFold(oap->start.lnum, oap->end.lnum, deleteFold(curwin, oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual); oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break; break;
case OP_NR_ADD: case OP_NR_ADD:
@@ -4345,11 +4345,12 @@ dozet:
/* "zD": delete fold at cursor recursively */ /* "zD": delete fold at cursor recursively */
case 'd': case 'd':
case 'D': if (foldManualAllowed(false)) { case 'D': if (foldManualAllowed(false)) {
if (VIsual_active) if (VIsual_active) {
nv_operator(cap); nv_operator(cap);
else } else {
deleteFold(curwin->w_cursor.lnum, deleteFold(curwin, curwin->w_cursor.lnum,
curwin->w_cursor.lnum, nchar == 'D', false); curwin->w_cursor.lnum, nchar == 'D', false);
}
} }
break; break;
@@ -4357,11 +4358,11 @@ dozet:
case 'E': if (foldmethodIsManual(curwin)) { case 'E': if (foldmethodIsManual(curwin)) {
clearFolding(curwin); clearFolding(curwin);
changed_window_setting(); changed_window_setting();
} else if (foldmethodIsMarker(curwin)) } else if (foldmethodIsMarker(curwin)) {
deleteFold((linenr_T)1, curbuf->b_ml.ml_line_count, deleteFold(curwin, (linenr_T)1, curbuf->b_ml.ml_line_count, true, false);
true, false); } else {
else
EMSG(_("E352: Cannot erase folds with current 'foldmethod'")); EMSG(_("E352: Cannot erase folds with current 'foldmethod'"));
}
break; break;
/* "zn": fold none: reset 'foldenable' */ /* "zn": fold none: reset 'foldenable' */