foldcolumn: allow auto:X

Similar to signcolumn, allow foldcolumn to adapt itself to the number of
folds.

Regression:
vim supports a maximum fdc of 12, this limits it to 9.
This commit is contained in:
Matthieu Coudron 2020-01-14 19:50:30 +01:00
parent 49cd750d6a
commit 1a2be57da3
15 changed files with 144 additions and 44 deletions

View File

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

View File

@ -1385,11 +1385,17 @@ void diff_win_options(win_T *wp, int addbuf)
curbuf = curwin->w_buffer;
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_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_fdl = 0;
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_save
: (char_u *)"manual");
if (wp->w_p_fdc == diff_foldcolumn) {
wp->w_p_fdc = wp->w_p_fdc_save;
}
free_string_option(wp->w_p_fdc);
wp->w_p_fdc = vim_strsave(wp->w_p_fdc_save);
if (wp->w_p_fdl == 0) {
wp->w_p_fdl = wp->w_p_fdl_save;
}

View File

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

View File

@ -4482,8 +4482,9 @@ prepare_tagpreview (
curwin->w_p_wfh = TRUE;
RESET_BINDING(curwin); /* don't take over 'scrollbind'
and 'cursorbind' */
curwin->w_p_diff = FALSE; /* no 'diff' */
curwin->w_p_fdc = 0; /* no 'foldcolumn' */
curwin->w_p_diff = false; // no 'diff'
set_string_option_direct((char_u *)"fdc", -1,
(char_u *)"0", OPT_FREE, SID_NONE);
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
* current window open.
*/
int getDeepestNesting(void)
int getDeepestNesting(win_T *wp)
{
checkupdate(curwin);
return getDeepestNestingRecurse(&curwin->w_folds);
checkupdate(wp);
return getDeepestNestingRecurse(&wp->w_folds);
}
static int getDeepestNestingRecurse(garray_T *gap)

View File

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

View File

@ -4458,16 +4458,16 @@ dozet:
case 'r':
curwin->w_p_fdl += cap->count1;
{
int d = getDeepestNesting();
int d = getDeepestNesting(curwin);
if (curwin->w_p_fdl >= d) {
curwin->w_p_fdl = d;
}
}
break;
/* "zR": open all folds */
case 'R': curwin->w_p_fdl = getDeepestNesting();
old_fdl = -1; /* force an update */
case 'R': // "zR": open all folds
curwin->w_p_fdl = getDeepestNesting(curwin);
old_fdl = -1; // force an update
break;
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",
"yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8",
"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'.
static char_u SHM_ALL[] = {
@ -2322,6 +2325,7 @@ void check_buf_options(buf_T *buf)
* Does NOT check for P_ALLOCED flag!
*/
void free_string_option(char_u *p)
{
if (p != empty_option) {
xfree(p);
@ -3199,6 +3203,11 @@ ambw_end:
if (check_opt_strings(*varp, p_scl_values, false) != OK) {
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) {
// 'pastetoggle': translate key codes like in a mapping
if (*p_pt) {
@ -4363,12 +4372,6 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
if (value < 0) {
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) {
if (value < 0) {
errmsg = e_positive;
@ -5936,8 +5939,9 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_diff_saved = from->wo_diff_saved;
to->wo_cocu = vim_strsave(from->wo_cocu);
to->wo_cole = from->wo_cole;
to->wo_fdc = from->wo_fdc;
to->wo_fdc_save = from->wo_fdc_save;
to->wo_fdc = vim_strsave(from->wo_fdc);
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_save = from->wo_fen_save;
to->wo_fdi = vim_strsave(from->wo_fdi);
@ -5973,6 +5977,8 @@ void check_win_options(win_T *win)
*/
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_fdm);
check_string_option(&wop->wo_fdm_save);
@ -5995,6 +6001,8 @@ static void check_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_fdm);
clear_string_option(&wop->wo_fdm_save);

View File

@ -831,10 +831,11 @@ return {
},
{
full_name='foldcolumn', abbreviation='fdc',
type='number', scope={'window'},
type='string', scope={'window'},
vi_def=true,
alloced=true,
redraw={'current_window'},
defaults={if_true={vi=false}}
defaults={if_true={vi="0"}}
},
{
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".
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 wwidth = wp->w_grid.Columns;

View File

@ -67,7 +67,7 @@ func Common_vert_split()
set foldmethod=marker foldcolumn=4
call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn)
call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap)
@ -76,7 +76,7 @@ func Common_vert_split()
vert diffsplit Xtest2
call assert_equal(1, &diff)
call assert_equal('diff', &foldmethod)
call assert_equal(2, &foldcolumn)
call assert_equal('2', &foldcolumn)
call assert_equal(1, &scrollbind)
call assert_equal(1, &cursorbind)
call assert_equal(0, &wrap)
@ -142,7 +142,7 @@ func Common_vert_split()
1wincmd w
call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn)
call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap)
@ -150,7 +150,7 @@ func Common_vert_split()
wincmd w
call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn)
call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind)
call assert_equal(1, &wrap)
@ -158,7 +158,7 @@ func Common_vert_split()
wincmd w
call assert_equal(0, &diff)
call assert_equal('marker', &foldmethod)
call assert_equal(4, &foldcolumn)
call assert_equal('4', &foldcolumn)
call assert_equal(0, &scrollbind)
call assert_equal(0, &cursorbind)
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_spell = false;
wp->w_p_list = false;
wp->w_p_fdc = 0;
// Hide EOB region: use " " fillchar and cleared highlighting
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");
}
// 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
if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) {
xfree(wp->w_p_cc);
@ -689,6 +694,24 @@ void win_check_anchored_floats(win_T *win)
}
}
/// Return the number of requested fold columns, based on current
/// folds signs and on user configuration.
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;
needed_fdccols = getDeepestNesting(wp);
int maximum = fdc[5] - '0';
return MIN(maximum, needed_fdccols);
} else {
return fdc[0] - '0';
}
}
static void ui_ext_win_position(win_T *wp)
{
if (!wp->w_floating) {

View File

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

View File

@ -295,4 +295,64 @@ describe("folded lines", function()
]])
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)