diff options
author | Lewis Russell <lewis6991@gmail.com> | 2023-03-29 19:54:12 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-29 19:54:12 +0100 |
commit | 8b7fb668e440f7793564b764bc9a691e3f45382a (patch) | |
tree | 36f9cbea1440cc8b42b436e36aeb471220793bc9 /src | |
parent | 92005db76039094d4a7180c1398b43c06940a1a1 (diff) | |
download | rneovim-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.c | 14 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 29 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 35 |
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); } |