# HG changeset patch # User Bram Moolenaar # Date 1573416904 -3600 # Node ID 41484f342f801a4c0366950c8b301e8e8fbfcc7d # Parent 63683d3ce6ac8ebed44c50f85c77f8e56c64961b patch 8.1.2289: after :diffsplit closing the window does not disable diff Commit: https://github.com/vim/vim/commit/c8234779790dd873acb88331c50988adf94cc383 Author: Bram Moolenaar Date: Sun Nov 10 21:00:27 2019 +0100 patch 8.1.2289: after :diffsplit closing the window does not disable diff Problem: After :diffsplit closing the window does not disable diff. Solution: Add "closeoff" to 'diffopt' and add it to the default. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2591,7 +2591,7 @@ A jump table for the options with a shor security reasons. *'dip'* *'diffopt'* -'diffopt' 'dip' string (default "internal,filler") +'diffopt' 'dip' string (default "internal,filler,closeoff") global {not available when compiled without the |+diff| feature} @@ -2650,6 +2650,12 @@ A jump table for the options with a shor vertical Start diff mode with vertical splits (unless explicitly specified otherwise). + closeoff When a window is closed where 'diff' is set + and there is only one window remaining in the + same tab page with 'diff' set, execute + `:diffoff` in that window. This undoes a + `:diffsplit` command. + hiddenoff Do not use diff mode for a buffer when it becomes hidden. @@ -2933,6 +2939,9 @@ A jump table for the options with a shor won't work by default. NOTE: This option is set to the Vi default value when 'compatible' is set and to the Vim default value when 'compatible' is reset. + NOTE: when this option is off then the |modifyOtherKeys| functionality + is disabled while in Insert mode to avoid ending Insert mode with any + key that has a modifier. *'eventignore'* *'ei'* 'eventignore' 'ei' string (default "") diff --git a/src/diff.c b/src/diff.c --- a/src/diff.c +++ b/src/diff.c @@ -35,8 +35,9 @@ static int diff_need_update = FALSE; // #define DIFF_VERTICAL 0x080 // vertical splits #define DIFF_HIDDEN_OFF 0x100 // diffoff when hidden #define DIFF_INTERNAL 0x200 // use internal xdiff algorithm +#define DIFF_CLOSE_OFF 0x400 // diffoff when closing window #define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL) -static int diff_flags = DIFF_INTERNAL | DIFF_FILLER; +static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF; static long diff_algorithm = 0; @@ -1545,6 +1546,14 @@ ex_diffoff(exarg_T *eap) if (eap->forceit) diff_buf_clear(); + if (!diffwin) + { + diff_need_update = FALSE; + curtab->tp_diff_invalid = FALSE; + curtab->tp_diff_update = FALSE; + diff_clear(curtab); + } + /* Remove "hor" from from 'scrollopt' if there are no diff windows left. */ if (!diffwin && vim_strchr(p_sbo, 'h') != NULL) do_cmdline_cmd((char_u *)"set sbo-=hor"); @@ -2222,6 +2231,11 @@ diffopt_changed(void) p += 9; diff_flags_new |= DIFF_HIDDEN_OFF; } + else if (STRNCMP(p, "closeoff", 8) == 0) + { + p += 8; + diff_flags_new |= DIFF_CLOSE_OFF; + } else if (STRNCMP(p, "indent-heuristic", 16) == 0) { p += 16; @@ -2310,6 +2324,15 @@ diffopt_hiddenoff(void) } /* + * Return TRUE if 'diffopt' contains "closeoff". + */ + int +diffopt_closeoff(void) +{ + return (diff_flags & DIFF_CLOSE_OFF) != 0; +} + +/* * Find the difference within a changed line. * Returns TRUE if the line was added, no other buffer has it. */ diff --git a/src/optiondefs.h b/src/optiondefs.h --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -846,7 +846,8 @@ static struct vimoption options[] = |P_NODUP, #ifdef FEAT_DIFF (char_u *)&p_dip, PV_NONE, - {(char_u *)"internal,filler", (char_u *)NULL} + {(char_u *)"internal,filler,closeoff", + (char_u *)NULL} #else (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)NULL} diff --git a/src/proto/diff.pro b/src/proto/diff.pro --- a/src/proto/diff.pro +++ b/src/proto/diff.pro @@ -19,6 +19,7 @@ void diff_set_topline(win_T *fromwin, wi int diffopt_changed(void); int diffopt_horizontal(void); int diffopt_hiddenoff(void); +int diffopt_closeoff(void); int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp); int diff_infold(win_T *wp, linenr_T lnum); void nv_diffgetput(int put, long count); diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -964,3 +964,28 @@ func Test_diff_of_diff() call StopVimInTerminal(buf) call delete('Xtest_diff_diff') endfunc + +func CloseoffSetup() + enew + call setline(1, ['one', 'two', 'three']) + diffthis + new + call setline(1, ['one', 'tow', 'three']) + diffthis + call assert_equal(1, &diff) + only! +endfunc + +func Test_diff_closeoff() + " "closeoff" included by default: last diff win gets 'diff' reset' + call CloseoffSetup() + call assert_equal(0, &diff) + enew! + + " "closeoff" excluded: last diff win keeps 'diff' set' + set diffopt-=closeoff + call CloseoffSetup() + call assert_equal(1, &diff) + diffoff! + enew! +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2289, +/**/ 2288, /**/ 2287, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -2438,6 +2438,9 @@ win_close(win_T *win, int free_buf) int help_window = FALSE; tabpage_T *prev_curtab = curtab; frame_T *win_frame = win->w_frame->fr_parent; +#ifdef FEAT_DIFF + int had_diffmode = win->w_p_diff; +#endif if (ERROR_IF_POPUP_WINDOW) return FAIL; @@ -2625,6 +2628,23 @@ win_close(win_T *win, int free_buf) if (help_window) restore_snapshot(SNAP_HELP_IDX, close_curwin); +#ifdef FEAT_DIFF + // If the window had 'diff' set and now there is only one window left in + // the tab page with 'diff' set, and "closeoff" is in 'diffopt', then + // execute ":diffoff!". + if (diffopt_closeoff() && had_diffmode && curtab == prev_curtab) + { + int diffcount = 0; + win_T *dwin; + + FOR_ALL_WINDOWS(dwin) + if (dwin->w_p_diff) + ++diffcount; + if (diffcount == 1) + do_cmdline_cmd((char_u *)"diffoff!"); + } +#endif + #if defined(FEAT_GUI) /* When 'guioptions' includes 'L' or 'R' may have to remove scrollbars. */ if (gui.in_use && !win_hasvertsplit())