mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 15:08:35 +00:00
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:
@@ -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)
|
||||||
|
126
src/nvim/fold.c
126
src/nvim/fold.c
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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' */
|
||||||
|
Reference in New Issue
Block a user