aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2023-03-29 19:54:12 +0100
committerGitHub <noreply@github.com>2023-03-29 19:54:12 +0100
commit8b7fb668e440f7793564b764bc9a691e3f45382a (patch)
tree36f9cbea1440cc8b42b436e36aeb471220793bc9 /src
parent92005db76039094d4a7180c1398b43c06940a1a1 (diff)
downloadrneovim-8b7fb668e440f7793564b764bc9a691e3f45382a.tar.gz
rneovim-8b7fb668e440f7793564b764bc9a691e3f45382a.tar.bz2
rneovim-8b7fb668e440f7793564b764bc9a691e3f45382a.zip
fix(filetype): avoid recursive FileType autocmds (#22813)
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/options.c14
-rw-r--r--src/nvim/autocmd.c29
-rw-r--r--src/nvim/optionstr.c35
3 files changed, 42 insertions, 36 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 31a2fb3b80..baeb3e88fb 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -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;
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index c66ee4286e..b488dd9f8f 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -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;
+}
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 170800b4e6..bf4ebbb3e2 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -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);
}