Merge pull request #11716 from teto/folds_auto_backup

[RFC] foldcolumn autowidth
This commit is contained in:
Matthieu Coudron
2020-03-02 13:56:27 +01:00
committed by GitHub
18 changed files with 149 additions and 50 deletions

View File

@@ -527,8 +527,7 @@ FOLDCOLUMN *fold-foldcolumn*
'foldcolumn' is a number, which sets the width for a column on the side of the 'foldcolumn' is a number, which sets the width for a column on the side of the
window to indicate folds. When it is zero, there is no foldcolumn. A normal window to indicate folds. When it is zero, there is no foldcolumn. A normal
value is 4 or 5. The minimal useful value is 2, although 1 still provides value is auto:9. The maximum is 9.
some information. The maximum is 12.
An open fold is indicated with a column that has a '-' at the top and '|' An open fold is indicated with a column that has a '-' at the top and '|'
characters below it. This column stops where the open fold stops. When folds characters below it. This column stops where the open fold stops. When folds

View File

@@ -2421,11 +2421,14 @@ A jump table for the options with a short description can be found at |Q_op|.
automatically close when moving out of them. automatically close when moving out of them.
*'foldcolumn'* *'fdc'* *'foldcolumn'* *'fdc'*
'foldcolumn' 'fdc' number (default 0) 'foldcolumn' 'fdc' string (default "0")
local to window local to window
When non-zero, a column with the specified width is shown at the side When and how to draw the foldcolumn. Valid values are:
of the window which indicates open and closed folds. The maximum "auto": resize to the maximum amount of folds to display.
value is 12. "auto:[1-9]": resize to accommodate multiple folds up to the
selected level
0: to disable foldcolumn
"[1-9]": to display a fixed number of columns
See |folding|. See |folding|.
*'foldenable'* *'fen'* *'nofoldenable'* *'nofen'* *'foldenable'* *'fen'* *'nofoldenable'* *'nofen'*

View File

@@ -201,6 +201,7 @@ Options:
'guicursor' works in the terminal 'guicursor' works in the terminal
'fillchars' flags: "msgsep" (see 'display'), "eob" for |hl-EndOfBuffer| 'fillchars' flags: "msgsep" (see 'display'), "eob" for |hl-EndOfBuffer|
marker, "foldopen", "foldsep", "foldclose" marker, "foldopen", "foldsep", "foldclose"
'foldcolumn' supports up to 9 dynamic/fixed columns
'inccommand' shows interactive results for |:substitute|-like commands 'inccommand' shows interactive results for |:substitute|-like commands
'listchars' local to window 'listchars' local to window
'pumblend' pseudo-transparent popupmenu 'pumblend' pseudo-transparent popupmenu

View File

@@ -166,11 +166,11 @@ typedef struct {
char_u *wo_briopt; char_u *wo_briopt;
# define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */ # define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */
int wo_diff; int wo_diff;
# define w_p_diff w_onebuf_opt.wo_diff /* 'diff' */ # define w_p_diff w_onebuf_opt.wo_diff // 'diff'
long wo_fdc; char_u *wo_fdc;
# define w_p_fdc w_onebuf_opt.wo_fdc /* 'foldcolumn' */ # define w_p_fdc w_onebuf_opt.wo_fdc // 'foldcolumn'
int wo_fdc_save; char_u *wo_fdc_save;
# define w_p_fdc_save w_onebuf_opt.wo_fdc_save /* 'foldenable' saved for diff mode */ # define w_p_fdc_save w_onebuf_opt.wo_fdc_save // 'fdc' saved for diff mode
int wo_fen; int wo_fen;
# define w_p_fen w_onebuf_opt.wo_fen /* 'foldenable' */ # define w_p_fen w_onebuf_opt.wo_fen /* 'foldenable' */
int wo_fen_save; int wo_fen_save;

View File

@@ -1385,11 +1385,17 @@ void diff_win_options(win_T *wp, int addbuf)
curbuf = curwin->w_buffer; curbuf = curwin->w_buffer;
if (!wp->w_p_diff) { if (!wp->w_p_diff) {
wp->w_p_fdc_save = wp->w_p_fdc;
wp->w_p_fen_save = wp->w_p_fen; wp->w_p_fen_save = wp->w_p_fen;
wp->w_p_fdl_save = wp->w_p_fdl; wp->w_p_fdl_save = wp->w_p_fdl;
if (wp->w_p_diff_saved) {
free_string_option(wp->w_p_fdc_save);
}
wp->w_p_fdc_save = vim_strsave(wp->w_p_fdc);
} }
wp->w_p_fdc = diff_foldcolumn; xfree(wp->w_p_fdc);
wp->w_p_fdc = (char_u *)xstrdup("2");
snprintf((char *)wp->w_p_fdc, sizeof(wp->w_p_fdc), "%d", diff_foldcolumn);
wp->w_p_fen = true; wp->w_p_fen = true;
wp->w_p_fdl = 0; wp->w_p_fdl = 0;
foldUpdateAll(wp); foldUpdateAll(wp);
@@ -1443,9 +1449,9 @@ void ex_diffoff(exarg_T *eap)
wp->w_p_fdm = vim_strsave(*wp->w_p_fdm_save wp->w_p_fdm = vim_strsave(*wp->w_p_fdm_save
? wp->w_p_fdm_save ? wp->w_p_fdm_save
: (char_u *)"manual"); : (char_u *)"manual");
if (wp->w_p_fdc == diff_foldcolumn) { free_string_option(wp->w_p_fdc);
wp->w_p_fdc = wp->w_p_fdc_save; wp->w_p_fdc = vim_strsave(wp->w_p_fdc_save);
}
if (wp->w_p_fdl == 0) { if (wp->w_p_fdl == 0) {
wp->w_p_fdl = wp->w_p_fdl_save; wp->w_p_fdl = wp->w_p_fdl_save;
} }

View File

@@ -6215,7 +6215,7 @@ comp_textwidth (
if (cmdwin_type != 0) { if (cmdwin_type != 0) {
textwidth -= 1; textwidth -= 1;
} }
textwidth -= curwin->w_p_fdc; textwidth -= win_fdccol_count(curwin);
textwidth -= win_signcol_count(curwin); textwidth -= win_signcol_count(curwin);
if (curwin->w_p_nu || curwin->w_p_rnu) if (curwin->w_p_nu || curwin->w_p_rnu)

View File

@@ -4482,8 +4482,9 @@ prepare_tagpreview (
curwin->w_p_wfh = TRUE; curwin->w_p_wfh = TRUE;
RESET_BINDING(curwin); /* don't take over 'scrollbind' RESET_BINDING(curwin); /* don't take over 'scrollbind'
and 'cursorbind' */ and 'cursorbind' */
curwin->w_p_diff = FALSE; /* no 'diff' */ curwin->w_p_diff = false; // no 'diff'
curwin->w_p_fdc = 0; /* no 'foldcolumn' */ set_string_option_direct((char_u *)"fdc", -1, // no 'foldcolumn'
(char_u *)"0", OPT_FREE, SID_NONE);
return true; return true;
} }
} }

View File

@@ -1465,10 +1465,10 @@ static void foldMarkAdjustRecurse(garray_T *gap, linenr_T line1, linenr_T line2,
* Get the lowest 'foldlevel' value that makes the deepest nested fold in the * Get the lowest 'foldlevel' value that makes the deepest nested fold in the
* current window open. * current window open.
*/ */
int getDeepestNesting(void) int getDeepestNesting(win_T *wp)
{ {
checkupdate(curwin); checkupdate(wp);
return getDeepestNestingRecurse(&curwin->w_folds); return getDeepestNestingRecurse(&wp->w_folds);
} }
static int getDeepestNestingRecurse(garray_T *gap) static int getDeepestNestingRecurse(garray_T *gap)

View File

@@ -73,6 +73,7 @@ int jump_to_mouse(int flags,
int col = mouse_col; int col = mouse_col;
int grid = mouse_grid; int grid = mouse_grid;
int mouse_char; int mouse_char;
int fdc = 0;
mouse_past_bottom = false; mouse_past_bottom = false;
mouse_past_eol = false; mouse_past_eol = false;
@@ -131,6 +132,7 @@ retnomove:
if (wp == NULL) { if (wp == NULL) {
return IN_UNKNOWN; return IN_UNKNOWN;
} }
fdc = win_fdccol_count(wp);
dragwin = NULL; dragwin = NULL;
// winpos and height may change in win_enter()! // winpos and height may change in win_enter()!
if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) { if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) {
@@ -165,9 +167,8 @@ retnomove:
|| (!on_status_line || (!on_status_line
&& !on_sep_line && !on_sep_line
&& (wp->w_p_rl && (wp->w_p_rl
? col < wp->w_width_inner - wp->w_p_fdc ? col < wp->w_width_inner - fdc
: col >= wp->w_p_fdc + (cmdwin_type == 0 && wp == curwin : col >= fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1))
? 0 : 1))
&& (flags & MOUSE_MAY_STOP_VIS)))) { && (flags & MOUSE_MAY_STOP_VIS)))) {
end_visual_mode(); end_visual_mode();
redraw_curbuf_later(INVERTED); // delete the inversion redraw_curbuf_later(INVERTED); // delete the inversion
@@ -305,8 +306,8 @@ retnomove:
} }
// Check for position outside of the fold column. // Check for position outside of the fold column.
if (curwin->w_p_rl ? col < curwin->w_width_inner - curwin->w_p_fdc : if (curwin->w_p_rl ? col < curwin->w_width_inner - fdc :
col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)) { col >= fdc + (cmdwin_type == 0 ? 0 : 1)) {
mouse_char = ' '; mouse_char = ' ';
} }

View File

@@ -674,7 +674,7 @@ int win_col_off(win_T *wp)
{ {
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0) return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1) + (cmdwin_type == 0 || wp != curwin ? 0 : 1)
+ (int)wp->w_p_fdc + win_fdccol_count(wp)
+ (win_signcol_count(wp) * win_signcol_width(wp)); + (win_signcol_count(wp) * win_signcol_width(wp));
} }

View File

@@ -4458,16 +4458,16 @@ dozet:
case 'r': case 'r':
curwin->w_p_fdl += cap->count1; curwin->w_p_fdl += cap->count1;
{ {
int d = getDeepestNesting(); int d = getDeepestNesting(curwin);
if (curwin->w_p_fdl >= d) { if (curwin->w_p_fdl >= d) {
curwin->w_p_fdl = d; curwin->w_p_fdl = d;
} }
} }
break; break;
/* "zR": open all folds */ case 'R': // "zR": open all folds
case 'R': curwin->w_p_fdl = getDeepestNesting(); curwin->w_p_fdl = getDeepestNesting(curwin);
old_fdl = -1; /* force an update */ old_fdl = -1; // force an update
break; break;
case 'j': /* "zj" move to next fold downwards */ case 'j': /* "zj" move to next fold downwards */

View File

@@ -315,6 +315,9 @@ static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2",
"auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9",
"yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8", "yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8",
"yes:9", NULL }; "yes:9", NULL };
static char *(p_fdc_values[]) = { "auto:1", "auto:2",
"auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
/// All possible flags for 'shm'. /// All possible flags for 'shm'.
static char_u SHM_ALL[] = { static char_u SHM_ALL[] = {
@@ -3199,6 +3202,11 @@ ambw_end:
if (check_opt_strings(*varp, p_scl_values, false) != OK) { if (check_opt_strings(*varp, p_scl_values, false) != OK) {
errmsg = e_invarg; errmsg = e_invarg;
} }
} else if (varp == &curwin->w_p_fdc || varp == &curwin->w_allbuf_opt.wo_fdc) {
// 'foldcolumn'
if (check_opt_strings(*varp, p_fdc_values, false) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_pt) { } else if (varp == &p_pt) {
// 'pastetoggle': translate key codes like in a mapping // 'pastetoggle': translate key codes like in a mapping
if (*p_pt) { if (*p_pt) {
@@ -4363,12 +4371,6 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
if (value < 0) { if (value < 0) {
errmsg = e_positive; errmsg = e_positive;
} }
} else if (pp == &curwin->w_p_fdc || pp == &curwin->w_allbuf_opt.wo_fdc) {
if (value < 0) {
errmsg = e_positive;
} else if (value > 12) {
errmsg = e_invarg;
}
} else if (pp == &curwin->w_p_cole || pp == &curwin->w_allbuf_opt.wo_cole) { } else if (pp == &curwin->w_p_cole || pp == &curwin->w_allbuf_opt.wo_cole) {
if (value < 0) { if (value < 0) {
errmsg = e_positive; errmsg = e_positive;
@@ -5936,8 +5938,9 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_diff_saved = from->wo_diff_saved; to->wo_diff_saved = from->wo_diff_saved;
to->wo_cocu = vim_strsave(from->wo_cocu); to->wo_cocu = vim_strsave(from->wo_cocu);
to->wo_cole = from->wo_cole; to->wo_cole = from->wo_cole;
to->wo_fdc = from->wo_fdc; to->wo_fdc = vim_strsave(from->wo_fdc);
to->wo_fdc_save = from->wo_fdc_save; to->wo_fdc_save = from->wo_diff_saved
? vim_strsave(from->wo_fdc_save) : empty_option;
to->wo_fen = from->wo_fen; to->wo_fen = from->wo_fen;
to->wo_fen_save = from->wo_fen_save; to->wo_fen_save = from->wo_fen_save;
to->wo_fdi = vim_strsave(from->wo_fdi); to->wo_fdi = vim_strsave(from->wo_fdi);
@@ -5973,6 +5976,8 @@ void check_win_options(win_T *win)
*/ */
static void check_winopt(winopt_T *wop) static void check_winopt(winopt_T *wop)
{ {
check_string_option(&wop->wo_fdc);
check_string_option(&wop->wo_fdc_save);
check_string_option(&wop->wo_fdi); check_string_option(&wop->wo_fdi);
check_string_option(&wop->wo_fdm); check_string_option(&wop->wo_fdm);
check_string_option(&wop->wo_fdm_save); check_string_option(&wop->wo_fdm_save);
@@ -5995,6 +6000,8 @@ static void check_winopt(winopt_T *wop)
*/ */
void clear_winopt(winopt_T *wop) void clear_winopt(winopt_T *wop)
{ {
clear_string_option(&wop->wo_fdc);
clear_string_option(&wop->wo_fdc_save);
clear_string_option(&wop->wo_fdi); clear_string_option(&wop->wo_fdi);
clear_string_option(&wop->wo_fdm); clear_string_option(&wop->wo_fdm);
clear_string_option(&wop->wo_fdm_save); clear_string_option(&wop->wo_fdm_save);

View File

@@ -831,10 +831,11 @@ return {
}, },
{ {
full_name='foldcolumn', abbreviation='fdc', full_name='foldcolumn', abbreviation='fdc',
type='number', scope={'window'}, type='string', scope={'window'},
vi_def=true, vi_def=true,
alloced=true,
redraw={'current_window'}, redraw={'current_window'},
defaults={if_true={vi=false}} defaults={if_true={vi="0"}}
}, },
{ {
full_name='foldenable', abbreviation='fen', full_name='foldenable', abbreviation='fen',

View File

@@ -1744,7 +1744,7 @@ static int advance_color_col(int vcol, int **color_cols)
// space is available for window "wp", minus "col". // space is available for window "wp", minus "col".
static int compute_foldcolumn(win_T *wp, int col) static int compute_foldcolumn(win_T *wp, int col)
{ {
int fdc = wp->w_p_fdc; int fdc = win_fdccol_count(wp);
int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw; int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw;
int wwidth = wp->w_grid.Columns; int wwidth = wp->w_grid.Columns;

View File

@@ -67,7 +67,7 @@ func Common_vert_split()
set foldmethod=marker foldcolumn=4 set foldmethod=marker foldcolumn=4
call assert_equal(0, &diff) call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod) call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn) call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind) call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind) call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap) call assert_equal(1, &wrap)
@@ -76,7 +76,7 @@ func Common_vert_split()
vert diffsplit Xtest2 vert diffsplit Xtest2
call assert_equal(1, &diff) call assert_equal(1, &diff)
call assert_equal('diff', &foldmethod) call assert_equal('diff', &foldmethod)
call assert_equal(2, &foldcolumn) call assert_equal('2', &foldcolumn)
call assert_equal(1, &scrollbind) call assert_equal(1, &scrollbind)
call assert_equal(1, &cursorbind) call assert_equal(1, &cursorbind)
call assert_equal(0, &wrap) call assert_equal(0, &wrap)
@@ -142,7 +142,7 @@ func Common_vert_split()
1wincmd w 1wincmd w
call assert_equal(0, &diff) call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod) call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn) call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind) call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind) call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap) call assert_equal(1, &wrap)
@@ -150,7 +150,7 @@ func Common_vert_split()
wincmd w wincmd w
call assert_equal(0, &diff) call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod) call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn) call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind) call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind) call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap) call assert_equal(1, &wrap)
@@ -158,7 +158,7 @@ func Common_vert_split()
wincmd w wincmd w
call assert_equal(0, &diff) call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod) call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn) call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind) call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind) call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap) call assert_equal(1, &wrap)

View File

@@ -618,7 +618,6 @@ void win_set_minimal_style(win_T *wp)
wp->w_p_cuc = false; wp->w_p_cuc = false;
wp->w_p_spell = false; wp->w_p_spell = false;
wp->w_p_list = false; wp->w_p_list = false;
wp->w_p_fdc = 0;
// Hide EOB region: use " " fillchar and cleared highlighting // Hide EOB region: use " " fillchar and cleared highlighting
if (wp->w_p_fcs_chars.eob != ' ') { if (wp->w_p_fcs_chars.eob != ' ') {
@@ -642,6 +641,12 @@ void win_set_minimal_style(win_T *wp)
wp->w_p_scl = (char_u *)xstrdup("auto"); wp->w_p_scl = (char_u *)xstrdup("auto");
} }
// foldcolumn: use 'auto'
if (wp->w_p_fdc[0] != '0') {
xfree(wp->w_p_fdc);
wp->w_p_fdc = (char_u *)xstrdup("0");
}
// colorcolumn: cleared // colorcolumn: cleared
if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) { if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) {
xfree(wp->w_p_cc); xfree(wp->w_p_cc);
@@ -689,6 +694,21 @@ void win_check_anchored_floats(win_T *win)
} }
} }
/// Return the number of fold columns to display
int win_fdccol_count(win_T *wp)
{
const char *fdc = (const char *)wp->w_p_fdc;
// auto:<NUM>
if (strncmp(fdc, "auto:", 5) == 0) {
int needed_fdccols = getDeepestNesting(wp);
return MIN(fdc[5] - '0', needed_fdccols);
} else {
return fdc[0] - '0';
}
}
static void ui_ext_win_position(win_T *wp) static void ui_ext_win_position(win_T *wp)
{ {
if (!wp->w_floating) { if (!wp->w_floating) {

View File

@@ -72,7 +72,7 @@ describe(':set validation', function()
should_fail('updatetime', -1, 'E487') should_fail('updatetime', -1, 'E487')
should_fail('foldlevel', -5, 'E487') should_fail('foldlevel', -5, 'E487')
should_fail('foldcolumn', 13, 'E474') should_fail('foldcolumn', '13', 'E474')
should_fail('conceallevel', 4, 'E474') should_fail('conceallevel', 4, 'E474')
should_fail('numberwidth', 21, 'E474') should_fail('numberwidth', 21, 'E474')
should_fail('numberwidth', 0, 'E487') should_fail('numberwidth', 0, 'E487')

View File

@@ -295,4 +295,64 @@ describe("folded lines", function()
]]) ]])
end) end)
it("work with autoresize", function()
funcs.setline(1, 'line 1')
funcs.setline(2, 'line 2')
funcs.setline(3, 'line 3')
funcs.setline(4, 'line 4')
feed("zfj")
command("set foldcolumn=0")
screen:expect{grid=[[
{5:^+-- 2 lines: line 1·························}|
line 3 |
line 4 |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
-- should adapt to the current nesting of folds (e.g., 1)
command("set foldcolumn=auto:1")
screen:expect{grid=[[
{7:+}{5:^+-- 2 lines: line 1························}|
{7: }line 3 |
{7: }line 4 |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
-- fdc should not change with a new fold as the maximum is 1
feed("zf3j")
screen:expect{grid=[[
{7:+}{5:^+-- 4 lines: line 1························}|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
-- relax the maximum fdc thus fdc should expand to
-- accomodate the current number of folds
command("set foldcolumn=auto:4")
screen:expect{grid=[[
{7:+ }{5:^+-- 4 lines: line 1·······················}|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
end)
end) end)