Mercurial > vim
changeset 34705:159d598e6781 v9.1.0231
patch 9.1.0231: Filetype may be undetected when SwapExists sets ft in other buf
Commit: https://github.com/vim/vim/commit/5bf6c2117fcef85fcf046c098dd3eb72a0147859
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sun Mar 31 18:41:27 2024 +0200
patch 9.1.0231: Filetype may be undetected when SwapExists sets ft in other buf
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 31 Mar 2024 18:45:05 +0200 |
parents | 60194371609e |
children | 0577e77ea9a4 |
files | src/autocmd.c src/buffer.c src/evalfunc.c src/ex_cmds.c src/ex_docmd.c src/fileio.c src/globals.h src/option.c src/optionstr.c src/quickfix.c src/structs.h src/testdir/test_autocmd.vim src/version.c |
diffstat | 13 files changed, 111 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- 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; }
--- 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); }
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3920,7 +3920,7 @@ f_deepcopy(typval_T *argvars, typval_T * 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; } /*
--- 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
--- 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
--- 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, in 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, in curwin->w_cursor = old_cursor; check_cursor(); update_topline(); - keep_filetype = FALSE; + curbuf->b_keep_filetype = FALSE; #ifdef FEAT_FOLDING { win_T *wp;
--- a/src/globals.h +++ b/src/globals.h @@ -796,20 +796,6 @@ EXTERN int autocmd_no_enter INIT(= FALSE 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);
--- 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; }
--- a/src/optionstr.c +++ b/src/optionstr.c @@ -4332,7 +4332,7 @@ do_filetype_autocmd(char_u **varp, int o 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,
--- a/src/quickfix.c +++ b/src/quickfix.c @@ -4964,12 +4964,12 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *bu 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
--- 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. */
--- 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