aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-04-01 06:12:11 +0800
committerGitHub <noreply@github.com>2024-04-01 06:12:11 +0800
commitb08667d4f00e434eac9874e4005ab8e1fd9d3e95 (patch)
treebf4b40e983294fbf96bdd6b9699cdb6526dd0fe6
parente005b8d2eb0d5967d46cae604e3fac0ccae37555 (diff)
downloadrneovim-b08667d4f00e434eac9874e4005ab8e1fd9d3e95.tar.gz
rneovim-b08667d4f00e434eac9874e4005ab8e1fd9d3e95.tar.bz2
rneovim-b08667d4f00e434eac9874e4005ab8e1fd9d3e95.zip
vim-patch:9.1.0231: Filetype may be undetected when SwapExists sets ft in other buf (#28136)
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: vim/vim#14344 https://github.com/vim/vim/commit/5bf6c2117fcef85fcf046c098dd3eb72a0147859
-rw-r--r--src/nvim/autocmd.c10
-rw-r--r--src/nvim/autocmd.h11
-rw-r--r--src/nvim/buffer.c6
-rw-r--r--src/nvim/buffer_defs.h13
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/fileio.c8
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--test/old/testdir/test_autocmd.vim77
12 files changed, 109 insertions, 32 deletions
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 00cfef23c7..c2cc8bd9b8 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1750,7 +1750,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
saveRedobuff(&save_redo);
did_save_redobuff = true;
}
- did_filetype = keep_filetype;
+ curbuf->b_did_filetype = curbuf->b_keep_filetype;
}
// Note that we are applying autocmds. Some commands need to know.
@@ -1760,7 +1760,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
// Remember that FileType was triggered. Used for did_filetype().
if (event == EVENT_FILETYPE) {
- did_filetype = true;
+ curbuf->b_did_filetype = true;
}
char *tail = path_tail(fname);
@@ -1864,7 +1864,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
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;
@@ -1901,7 +1901,7 @@ BYPASS_AU:
}
if (retval == OK && event == EVENT_FILETYPE) {
- au_did_filetype = true;
+ curbuf->b_au_did_filetype = true;
}
return retval;
@@ -2645,7 +2645,7 @@ void do_filetype_autocmd(buf_T *buf, bool force)
secure = 0;
ft_recursive++;
- did_filetype = true;
+ buf->b_did_filetype = true;
// Only pass true for "force" when it is true or
// used recursively, to avoid endless recurrence.
apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, force || ft_recursive == 1, buf);
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index 8019cb7145..b298fbb6a1 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -15,14 +15,6 @@
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
-// 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 bool au_did_filetype INIT( = false);
-
/// For CursorMoved event
EXTERN win_T *last_cursormoved_win INIT( = NULL);
/// For CursorMoved event, only used when last_cursormoved_win == curwin
@@ -31,9 +23,6 @@ EXTERN pos_T last_cursormoved INIT( = { 0, 0, 0 });
EXTERN bool autocmd_busy INIT( = false); ///< Is apply_autocmds() busy?
EXTERN int autocmd_no_enter INIT( = false); ///< Buf/WinEnter autocmds disabled
EXTERN int autocmd_no_leave INIT( = false); ///< Buf/WinLeave autocmds disabled
-EXTERN bool did_filetype INIT( = false); ///< FileType event found
-/// value for did_filetype when starting to execute autocommands
-EXTERN bool keep_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.
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 3c2d52e6ad..39d0d24d47 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -267,7 +267,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
// 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;
@@ -350,7 +350,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
// the changed flag. Unless in readonly mode: "ls | nvim -R -".
// 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"
|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) {
changed(curbuf);
} else if (retval != FAIL && !read_stdin && !read_fifo) {
@@ -1725,7 +1725,7 @@ void 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/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 7f7300706c..083508fe86 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -461,6 +461,19 @@ struct file_buffer {
bool b_marks_read; // Have we read ShaDa marks yet?
+ bool b_modified_was_set; ///< did ":set modified"
+ bool b_did_filetype; ///< FileType event found
+ bool 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().
+ bool b_au_did_filetype;
+
// The following only used in undo.c.
u_header_T *b_u_oldhead; // pointer to oldest header
u_header_T *b_u_newhead; // pointer to newest header; may not be valid
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 99da15ddd7..d3fe2c7e33 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -1361,7 +1361,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fp
/// "did_filetype()" function
static void f_did_filetype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = did_filetype;
+ rettv->vval.v_number = curbuf->b_did_filetype;
}
/// "diff_filler()" function
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index dd30cdbba4..6c997b9500 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -2466,7 +2466,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// 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
// false false re-edit same file, buffer is re-used
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index ee738d9e92..318d2e4ff2 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -7382,7 +7382,7 @@ void filetype_maybe_enable(void)
/// ":setfiletype [FALLBACK] {name}"
static void ex_setfiletype(exarg_T *eap)
{
- if (did_filetype) {
+ if (curbuf->b_did_filetype) {
return;
}
@@ -7393,7 +7393,7 @@ static void ex_setfiletype(exarg_T *eap)
set_option_value_give_err(kOptFiletype, CSTR_AS_OPTVAL(arg), OPT_LOCAL);
if (arg != eap->arg) {
- did_filetype = false;
+ curbuf->b_did_filetype = false;
}
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 6b50b031a3..df9c4928c9 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -234,7 +234,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
int using_b_fname;
static char *msg_is_a_directory = N_("is a directory");
- 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
@@ -1854,7 +1854,7 @@ failed:
} else if (newfile || (read_buffer && sfname != NULL)) {
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.
apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, true, curbuf);
@@ -3151,7 +3151,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
if (saved == OK) {
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 (readfile(buf->b_ffname, buf->b_fname, 0, 0,
(linenr_T)MAXLNUM, &ea, flags, shortmess(SHM_FILEINFO)) != OK) {
if (!aborting()) {
@@ -3199,7 +3199,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
curwin->w_cursor = old_cursor;
check_cursor(curwin);
update_topline(curwin);
- keep_filetype = false;
+ curbuf->b_keep_filetype = false;
// Update folds unless they are defined manually.
FOR_ALL_TAB_WINDOWS(tp, wp) {
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index bb9aca38b7..83fef1fe75 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -341,8 +341,6 @@ EXTERN bool did_check_timestamps INIT( = false); // did check timestamps
// recently
EXTERN int no_check_timestamps INIT( = 0); // Don't check timestamps
-EXTERN int modified_was_set; // did ":set modified"
-
// Mouse coordinates, set by handle_mouse_event()
EXTERN int mouse_grid;
EXTERN int mouse_row;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2c7922908c..799513e018 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2244,7 +2244,7 @@ static const char *did_set_modified(optset_T *args)
save_file_ff(buf); // Buffer is unchanged
}
redraw_titles();
- modified_was_set = (int)args->os_newval.boolean;
+ buf->b_modified_was_set = (int)args->os_newval.boolean;
return NULL;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 9f431556e8..94e176bd94 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -4274,10 +4274,10 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("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, "quickfix", NULL, false, curbuf);
apply_autocmds(EVENT_BUFWINENTER, "quickfix", NULL, false, curbuf);
- keep_filetype = false;
+ curbuf->b_keep_filetype = false;
curbuf->b_ro_locked--;
// make sure it will be redrawn
diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim
index 9dbd4ac521..61de6775fb 100644
--- a/test/old/testdir/test_autocmd.vim
+++ b/test/old/testdir/test_autocmd.vim
@@ -3977,4 +3977,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