summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-03-31 18:41:27 +0200
committerChristian Brabandt <cb@256bit.org>2024-03-31 18:41:27 +0200
commit5bf6c2117fcef85fcf046c098dd3eb72a0147859 (patch)
tree32804af25b55ac2859188f9bc0771a38d078862c
parent86032702932995db74fed265ba99ae0c823cb75d (diff)
patch 9.1.0231: Filetype may be undetected when SwapExists sets ft in other bufv9.1.0231
Problem: Filetype may be undetected when a SwapExists autocommand sets filetype in another buffer. Solution: Make filetype detection state buffer-specific. Also fix a similar problem for 'modified' (zeertzjq). closes: #14344 Signed-off-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/autocmd.c8
-rw-r--r--src/buffer.c6
-rw-r--r--src/evalfunc.c2
-rw-r--r--src/ex_cmds.c2
-rw-r--r--src/ex_docmd.c4
-rw-r--r--src/fileio.c8
-rw-r--r--src/globals.h14
-rw-r--r--src/option.c2
-rw-r--r--src/optionstr.c2
-rw-r--r--src/quickfix.c4
-rw-r--r--src/structs.h13
-rw-r--r--src/testdir/test_autocmd.vim77
-rw-r--r--src/version.c2
13 files changed, 111 insertions, 33 deletions
diff --git a/src/autocmd.c b/src/autocmd.c
index 8a7e6072a9..9632c74d49 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -2258,7 +2258,7 @@ apply_autocmds_group(
saveRedobuff(&save_redo);
did_save_redobuff = TRUE;
}
- did_filetype = keep_filetype;
+ curbuf->b_did_filetype = curbuf->b_keep_filetype;
}
/*
@@ -2270,7 +2270,7 @@ apply_autocmds_group(
// Remember that FileType was triggered. Used for did_filetype().
if (event == EVENT_FILETYPE)
- did_filetype = TRUE;
+ curbuf->b_did_filetype = TRUE;
tail = gettail(fname);
@@ -2379,7 +2379,7 @@ apply_autocmds_group(
restore_search_patterns();
if (did_save_redobuff)
restoreRedobuff(&save_redo);
- did_filetype = FALSE;
+ curbuf->b_did_filetype = FALSE;
while (au_pending_free_buf != NULL)
{
buf_T *b = au_pending_free_buf->b_next;
@@ -2421,7 +2421,7 @@ BYPASS_AU:
aubuflocal_remove(buf);
if (retval == OK && event == EVENT_FILETYPE)
- au_did_filetype = TRUE;
+ curbuf->b_au_did_filetype = TRUE;
return retval;
}
diff --git a/src/buffer.c b/src/buffer.c
index 243593a523..58e9718e3d 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -225,7 +225,7 @@ open_buffer(
// The autocommands in readfile() may change the buffer, but only AFTER
// reading the file.
set_bufref(&old_curbuf, curbuf);
- modified_was_set = FALSE;
+ curbuf->b_modified_was_set = FALSE;
// mark cursor position as being invalid
curwin->w_valid = 0;
@@ -322,7 +322,7 @@ open_buffer(
// the changed flag. Unless in readonly mode: "ls | gview -".
// When interrupted and 'cpoptions' contains 'i' set changed flag.
if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
- || modified_was_set // ":set modified" used in autocmd
+ || curbuf->b_modified_was_set // autocmd did ":set modified"
#ifdef FEAT_EVAL
|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
#endif
@@ -1944,7 +1944,7 @@ enter_buffer(buf_T *buf)
// ":ball" used in an autocommand. If there already is a filetype we
// might prefer to keep it.
if (*curbuf->b_p_ft == NUL)
- did_filetype = FALSE;
+ curbuf->b_did_filetype = FALSE;
open_buffer(FALSE, NULL, 0);
}
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 8c27986b42..0e071d87bc 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3920,7 +3920,7 @@ f_deepcopy(typval_T *argvars, typval_T *rettv)
static void
f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
{
- rettv->vval.v_number = did_filetype;
+ rettv->vval.v_number = curbuf->b_did_filetype;
}
/*
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 864f89d43c..2a5d842fc9 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -2961,7 +2961,7 @@ do_ecmd(
// Since we are starting to edit a file, consider the filetype to be
// unset. Helps for when an autocommand changes files and expects syntax
// highlighting to work in the other file.
- did_filetype = FALSE;
+ curbuf->b_did_filetype = FALSE;
/*
* other_file oldbuf
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 981d270dc7..cc42e52a5a 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -9898,7 +9898,7 @@ ex_filetype(exarg_T *eap)
static void
ex_setfiletype(exarg_T *eap)
{
- if (did_filetype)
+ if (curbuf->b_did_filetype)
return;
char_u *arg = eap->arg;
@@ -9907,7 +9907,7 @@ ex_setfiletype(exarg_T *eap)
set_option_value_give_err((char_u *)"filetype", 0L, arg, OPT_LOCAL);
if (arg != eap->arg)
- did_filetype = FALSE;
+ curbuf->b_did_filetype = FALSE;
}
static void
diff --git a/src/fileio.c b/src/fileio.c
index 53bfbeadfa..07e05fc802 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -225,7 +225,7 @@ readfile(
int may_need_lseek = FALSE;
#endif
- au_did_filetype = FALSE; // reset before triggering any autocommands
+ curbuf->b_au_did_filetype = FALSE; // reset before triggering any autocommands
curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read
@@ -2696,7 +2696,7 @@ failed:
{
apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
FALSE, curbuf, eap);
- if (!au_did_filetype && *curbuf->b_p_ft != NUL)
+ if (!curbuf->b_au_did_filetype && *curbuf->b_p_ft != NUL)
/*
* EVENT_FILETYPE was not triggered but the buffer already has a
* filetype. Trigger EVENT_FILETYPE using the existing filetype.
@@ -4492,7 +4492,7 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
int old_msg_silent = msg_silent;
curbuf->b_flags |= BF_CHECK_RO; // check for RO again
- keep_filetype = TRUE; // don't detect 'filetype'
+ curbuf->b_keep_filetype = TRUE; // don't detect 'filetype'
if (shortmess(SHM_FILEINFO))
msg_silent = 1;
@@ -4549,7 +4549,7 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
curwin->w_cursor = old_cursor;
check_cursor();
update_topline();
- keep_filetype = FALSE;
+ curbuf->b_keep_filetype = FALSE;
#ifdef FEAT_FOLDING
{
win_T *wp;
diff --git a/src/globals.h b/src/globals.h
index f04f19dd2a..29ad7edd47 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -796,20 +796,6 @@ EXTERN int autocmd_no_enter INIT(= FALSE); // Buf/WinEnter autocmds disabled
EXTERN int autocmd_no_leave INIT(= FALSE); // Buf/WinLeave autocmds disabled
EXTERN int tabpage_move_disallowed INIT(= FALSE); // moving tabpages around disallowed
-EXTERN int modified_was_set; // did ":set modified"
-EXTERN int did_filetype INIT(= FALSE); // FileType event found
-EXTERN int keep_filetype INIT(= FALSE); // value for did_filetype when
- // starting to execute
- // autocommands
-
-// Set by the apply_autocmds_group function if the given event is equal to
-// EVENT_FILETYPE. Used by the readfile function in order to determine if
-// EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
-//
-// Relying on this value requires one to reset it prior calling
-// apply_autocmds_group.
-EXTERN int au_did_filetype INIT(= FALSE);
-
// When deleting the current buffer, another one must be loaded. If we know
// which one is preferred, au_new_curbuf is set to it
EXTERN bufref_T au_new_curbuf INIT3(NULL, 0, 0);
diff --git a/src/option.c b/src/option.c
index 8123a2a2c6..c594301a9b 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3678,7 +3678,7 @@ did_set_modified(optset_T *args)
if (!args->os_newval.boolean)
save_file_ff(curbuf); // Buffer is unchanged
redraw_titles();
- modified_was_set = args->os_newval.boolean;
+ curbuf->b_modified_was_set = args->os_newval.boolean;
return NULL;
}
diff --git a/src/optionstr.c b/src/optionstr.c
index e5f4946b44..45f126ff6b 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -4332,7 +4332,7 @@ do_filetype_autocmd(char_u **varp, int opt_flags, int value_changed)
secure = 0;
++ft_recursive;
- did_filetype = TRUE;
+ curbuf->b_did_filetype = TRUE;
// Only pass TRUE for "force" when the value changed or not
// used recursively, to avoid endless recurrence.
apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
diff --git a/src/quickfix.c b/src/quickfix.c
index 0bf4cfe6b4..2e5b693733 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -4964,12 +4964,12 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
0L, (char_u *)"qf", OPT_LOCAL);
curbuf->b_p_ma = FALSE;
- keep_filetype = TRUE; // don't detect 'filetype'
+ curbuf->b_keep_filetype = TRUE; // don't detect 'filetype'
apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL,
FALSE, curbuf);
apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
FALSE, curbuf);
- keep_filetype = FALSE;
+ curbuf->b_keep_filetype = FALSE;
--curbuf_lock;
// make sure it will be redrawn
diff --git a/src/structs.h b/src/structs.h
index 0d3f60acb4..2218de7037 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3133,6 +3133,19 @@ struct file_buffer
int b_marks_read; // Have we read viminfo marks yet?
#endif
+ int b_modified_was_set; // did ":set modified"
+ int b_did_filetype; // FileType event found
+ int b_keep_filetype; // value for did_filetype when starting
+ // to execute autocommands
+
+ // Set by the apply_autocmds_group function if the given event is equal to
+ // EVENT_FILETYPE. Used by the readfile function in order to determine if
+ // EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
+ //
+ // Relying on this value requires one to reset it prior calling
+ // apply_autocmds_group().
+ int b_au_did_filetype;
+
/*
* The following only used in undo.c.
*/
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index bf9087111c..e69a3f60e7 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -4550,4 +4550,81 @@ func Test_Changed_ChangedI_2()
call delete('XTextChangedI3')
endfunc
+" Test that filetype detection still works when SwapExists autocommand sets
+" filetype in another buffer.
+func Test_SwapExists_set_other_buf_filetype()
+ let lines =<< trim END
+ set nocompatible directory=.
+ filetype on
+
+ let g:buf = bufnr()
+ new
+
+ func SwapExists()
+ let v:swapchoice = 'o'
+ call setbufvar(g:buf, '&filetype', 'text')
+ endfunc
+
+ func SafeState()
+ edit <script>
+ redir! > XftSwapExists.out
+ set readonly? filetype?
+ redir END
+ qall!
+ endfunc
+
+ autocmd SwapExists * ++nested call SwapExists()
+ autocmd SafeState * ++nested ++once call SafeState()
+ END
+ call writefile(lines, 'XftSwapExists.vim', 'D')
+
+ new XftSwapExists.vim
+ if RunVim('', '', ' -S XftSwapExists.vim')
+ call assert_equal(
+ \ ['', ' readonly', ' filetype=vim'],
+ \ readfile('XftSwapExists.out'))
+ call delete('XftSwapExists.out')
+ endif
+
+ bwipe!
+endfunc
+
+" Test that file is not marked as modified when SwapExists autocommand sets
+" 'modified' in another buffer.
+func Test_SwapExists_set_other_buf_modified()
+ let lines =<< trim END
+ set nocompatible directory=.
+
+ let g:buf = bufnr()
+ new
+
+ func SwapExists()
+ let v:swapchoice = 'o'
+ call setbufvar(g:buf, '&modified', 1)
+ endfunc
+
+ func SafeState()
+ edit <script>
+ redir! > XmodSwapExists.out
+ set readonly? modified?
+ redir END
+ qall!
+ endfunc
+
+ autocmd SwapExists * ++nested call SwapExists()
+ autocmd SafeState * ++nested ++once call SafeState()
+ END
+ call writefile(lines, 'XmodSwapExists.vim', 'D')
+
+ new XmodSwapExists.vim
+ if RunVim('', '', ' -S XmodSwapExists.vim')
+ call assert_equal(
+ \ ['', ' readonly', 'nomodified'],
+ \ readfile('XmodSwapExists.out'))
+ call delete('XmodSwapExists.out')
+ endif
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index db942bc3a3..e7187447c7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 231,
+/**/
230,
/**/
229,