From 328640aed0ff43680e0d58a045ec3eca83f04571 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 14 Jan 2026 09:37:53 +0800 Subject: [PATCH] vim-patch:9.1.1323: b:undo_ftplugin not executed when re-using buffer Problem: b:undo_ftplugin not executed when re-using buffer (archy3) Solution: explicitly execute b:undo_ftplugin in buflist_new() when re-using the current buffer fixes: vim/vim#17113 closes: vim/vim#17133 https://github.com/vim/vim/commit/baa8c90cc0d214e036a3a7980d5cf95cae88a68d Cherry-pick test_filetype.vim changes from patch 9.1.1325. Co-authored-by: Christian Brabandt --- src/nvim/buffer.c | 13 +++++++++++++ src/nvim/window.c | 4 ++-- test/old/testdir/test_filetype.vim | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 96ebfe6293..85cb824389 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -129,6 +129,18 @@ typedef enum { kBffInitChangedtick = 2, } BufFreeFlags; +static void trigger_undo_ftplugin(buf_T *buf, win_T *win) +{ + window_layout_lock(); + buf->b_locked++; + win->w_locked = true; + // b:undo_ftplugin may be set, undo it + do_cmdline_cmd("if exists('b:undo_ftplugin') | exe b:undo_ftplugin | endif"); + buf->b_locked--; + win->w_locked = false; + window_layout_unlock(); +} + /// Calculate the percentage that `part` is of the `whole`. int calc_percentage(int64_t part, int64_t whole) { @@ -1945,6 +1957,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) assert(curbuf != NULL); buf = curbuf; set_bufref(&bufref, buf); + trigger_undo_ftplugin(buf, curwin); // It's like this buffer is deleted. Watch out for autocommands that // change curbuf! If that happens, allocate a new buffer anyway. buf_freeall(buf, BFA_WIPE | BFA_DEL); diff --git a/src/nvim/window.c b/src/nvim/window.c index 1514c26558..4fcf1ad85a 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -117,13 +117,13 @@ static int close_disallowed = 0; /// Used for autocommands that temporarily use another window and need to /// make sure the previously selected window is still there. /// Must be matched with exactly one call to window_layout_unlock()! -static void window_layout_lock(void) +void window_layout_lock(void) { split_disallowed++; close_disallowed++; } -static void window_layout_unlock(void) +void window_layout_unlock(void) { split_disallowed--; close_disallowed--; diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index 4cd6b764ca..022091b06a 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -1196,6 +1196,34 @@ func Test_filetype_indent_off() close endfunc +func Test_undo_ftplugin_on_buffer_reuse() + filetype on + + new + let b:undo_ftplugin = ":let g:var='exists'" + let g:bufnr = bufnr('%') + " no changes done to the buffer, so the buffer will be re-used + e $VIMRUNTIME/defaults.vim + call assert_equal(g:bufnr, bufnr('%')) + call assert_equal('exists', get(g:, 'var', 'fail')) + unlet! g:bufnr g:var + + " try to wipe the buffer + enew + bw defaults.vim + let b:undo_ftplugin = ':bw' + call assert_fails(':e $VIMRUNTIME/defaults.vim', 'E937:') + + " try to split the window + enew + bw defaults.vim + let b:undo_ftplugin = ':sp $VIMRUNTIME/defaults.vim' + call assert_fails(':e $VIMRUNTIME/defaults.vim', 'E242:') + + bwipe! + filetype off +endfunc + """"""""""""""""""""""""""""""""""""""""""""""""" " Tests for specific extensions and filetypes. " Keep sorted.