mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
fix(filetype): avoid recursive FileType autocmds (#22813)
This commit is contained in:
@@ -111,15 +111,15 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err)
|
||||
|
||||
// Set curwin/curbuf to buf and save a few things.
|
||||
aucmd_prepbuf(aco, ftbuf);
|
||||
set_option_value("bufhidden", 0L, "hide", OPT_LOCAL);
|
||||
set_option_value("buftype", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("swapfile", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("modeline", 0L, NULL, OPT_LOCAL); // 'nomodeline'
|
||||
|
||||
ftbuf->b_p_ft = xstrdup(filetype);
|
||||
|
||||
TRY_WRAP(err, {
|
||||
apply_autocmds(EVENT_FILETYPE, ftbuf->b_p_ft, ftbuf->b_fname, true, ftbuf);
|
||||
set_option_value("bufhidden", 0L, "hide", OPT_LOCAL);
|
||||
set_option_value("buftype", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("swapfile", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("modeline", 0L, NULL, OPT_LOCAL); // 'nomodeline'
|
||||
|
||||
ftbuf->b_p_ft = xstrdup(filetype);
|
||||
do_filetype_autocmd(ftbuf, false);
|
||||
});
|
||||
|
||||
return ftbuf;
|
||||
|
@@ -2758,3 +2758,32 @@ void do_autocmd_focusgained(bool gained)
|
||||
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
void do_filetype_autocmd(buf_T *buf, bool force)
|
||||
{
|
||||
static bool recursive = false;
|
||||
|
||||
if (recursive && !force) {
|
||||
return; // disallow recursion
|
||||
}
|
||||
|
||||
char **varp = &buf->b_p_ft;
|
||||
int secure_save = secure;
|
||||
|
||||
// Reset the secure flag, since the value of 'filetype' has
|
||||
// been checked to be safe.
|
||||
secure = 0;
|
||||
|
||||
recursive = true;
|
||||
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, buf);
|
||||
recursive = false;
|
||||
|
||||
// Just in case the old "buf" is now invalid
|
||||
if (varp != &(buf->b_p_ft)) {
|
||||
varp = NULL;
|
||||
}
|
||||
secure = secure_save;
|
||||
}
|
||||
|
@@ -1529,34 +1529,6 @@ static void do_syntax_autocmd(buf_T *buf, bool value_changed)
|
||||
syn_recursive--;
|
||||
}
|
||||
|
||||
static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool value_changed)
|
||||
{
|
||||
// 'filetype' is set, trigger the FileType autocommand
|
||||
// Skip this when called from a modeline and the filetype was
|
||||
// already set to this value.
|
||||
if (!(opt_flags & OPT_MODELINE) || value_changed) {
|
||||
static int ft_recursive = 0;
|
||||
int secure_save = secure;
|
||||
|
||||
// Reset the secure flag, since the value of 'filetype' has
|
||||
// been checked to be safe.
|
||||
secure = 0;
|
||||
|
||||
ft_recursive++;
|
||||
did_filetype = true;
|
||||
// Only pass true for "force" when the value changed or not
|
||||
// used recursively, to avoid endless recurrence.
|
||||
apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname,
|
||||
value_changed || ft_recursive == 1, buf);
|
||||
ft_recursive--;
|
||||
// Just in case the old "buf" is now invalid
|
||||
if (varp != &(buf->b_p_ft)) {
|
||||
varp = NULL;
|
||||
}
|
||||
secure = secure_save;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_spelllang_source(win_T *win)
|
||||
{
|
||||
char fname[200];
|
||||
@@ -1884,7 +1856,12 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char
|
||||
if (varp == &buf->b_p_syn) {
|
||||
do_syntax_autocmd(buf, value_changed);
|
||||
} else if (varp == &buf->b_p_ft) {
|
||||
do_filetype_autocmd(buf, varp, opt_flags, value_changed);
|
||||
// 'filetype' is set, trigger the FileType autocommand
|
||||
// Skip this when called from a modeline
|
||||
// Force autocmd when the filetype was changed
|
||||
if (!(opt_flags & OPT_MODELINE) || value_changed) {
|
||||
do_filetype_autocmd(buf, value_changed);
|
||||
}
|
||||
} else if (varp == &win->w_s->b_p_spl) {
|
||||
do_spelllang_source(win);
|
||||
}
|
||||
|
Reference in New Issue
Block a user