]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0059: No event triggered before creating a window v9.1.0059
authorSergey Vlasov <sergey@vlasov.me>
Thu, 25 Jan 2024 22:07:00 +0000 (23:07 +0100)
committerChristian Brabandt <cb@256bit.org>
Thu, 25 Jan 2024 22:07:00 +0000 (23:07 +0100)
Problem:  No event is triggered before creating a window.
          (Sergey Vlasov)
Solution: Add the WinNewPre event (Sergey Vlasov)

fixes: #10635
closes: #12761

Signed-off-by: Sergey Vlasov <sergey@vlasov.me>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/autocmd.txt
runtime/doc/tags
runtime/doc/todo.txt
runtime/syntax/vim.vim
src/autocmd.c
src/testdir/test_autocmd.vim
src/version.c
src/vim.h
src/window.c

index 16413617912fdcf25f2126c2a2be6ba7fa6db6cb..5f9f51ecb6f8407f823c6d3ee0eae9a9228d2297 100644 (file)
@@ -1,4 +1,4 @@
-*autocmd.txt*   For Vim version 9.1.  Last change: 2024 Jan 23
+*autocmd.txt*   For Vim version 9.1.  Last change: 2024 Jan 25
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -381,6 +381,7 @@ Name                        triggered by ~
 |CursorMoved|          the cursor was moved in Normal mode
 |CursorMovedI|         the cursor was moved in Insert mode
 
+|WinNewPre|            before creating a new window
 |WinNew|               after creating a new window
 |TabNew|               after creating a new tab page
 |WinClosed|            after closing a window
@@ -1390,6 +1391,18 @@ WinLeave                 Before leaving a window.  If the window to be
                                WinLeave autocommands (but not for ":new").
                                Not used for ":qa" or ":q" when exiting Vim.
 
+                                                       *WinNewPre*
+WinNewPre                      Before creating a new window. Triggered
+                               before commands that modify window layout by
+                               creating a split or new tab page. Not done for
+                               the first window, when Vim has just started.
+                               It is not allowed to modify window layout
+                               while executing commands for the WinNewPre
+                               event.
+                               Most useful to store current window layout
+                               and compare it with the new layout after the
+                               Window has been created.
+
                                                        *WinNew*
 WinNew                         When a new window was created.  Not done for
                                the first window, when Vim has just started.
index 9a89916e082be985877982b926585aca3a753dcf..ee6c0a9dd13256a1a6a563571efe2f19def7c31a 100644 (file)
@@ -5785,6 +5785,7 @@ WinClosed autocmd.txt     /*WinClosed*
 WinEnter       autocmd.txt     /*WinEnter*
 WinLeave       autocmd.txt     /*WinLeave*
 WinNew autocmd.txt     /*WinNew*
+WinNewPre      autocmd.txt     /*WinNewPre*
 WinResized     autocmd.txt     /*WinResized*
 WinResized-event       windows.txt     /*WinResized-event*
 WinScrolled    autocmd.txt     /*WinScrolled*
index c29ac2e2c050a02f0b73bb100bf6e27d8f5361d4..bb58597a40d5ffc97b9cd174ea26828929454d02 100644 (file)
@@ -4667,7 +4667,6 @@ GUI:
 
 
 Autocommands:
-9   Add WinNewPre - before creating a new window. #10635
 9   When triggering WinNew provide the window ID somehow.  #10633
 9   Rework the code from FEAT_OSFILETYPE for autocmd-osfiletypes to use
     'filetype'.  Only for when the current buffer is known.
index 46fe5684a36fd928e6b0008e0a7015be3f83ba0f..73884cc7fd15e3b4ac5ce7be78c062381dc92563 100644 (file)
@@ -11,6 +11,7 @@
 "      2024 Jan 14 by Vim Project (TermResponseAll autocommand)
 "      2024 Jan 15 by Vim Project (:hi ctermfont attribute)
 "      2024 Jan 23 by Vim Project (add :[23]match commands)
+"      2024 Jan 25 by Vim Project (WinNewPre autocommand)
 " Version:     9.0-25
 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_VIM
 " Automatically generated keyword lists: {{{1
@@ -76,7 +77,7 @@ syn keyword vimErrSetting contained   bioskey biosk conskey consk autoprint beauti
 
 " AutoCmd Events {{{2
 syn case ignore
-syn keyword vimAutoEvent contained     BufAdd BufDelete BufFilePost BufHidden BufNew BufRead BufReadPost BufUnload BufWinLeave BufWrite BufWritePost CmdlineChanged CmdlineLeave CmdwinEnter ColorScheme CompleteChanged CompleteDonePre CursorHoldI CursorMovedI DiffUpdated DirChanged DirChangedPre EncodingChanged ExitPre FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileExplorer FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave InsertLeavePre MenuPopup ModeChanged OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost ShellCmdPost ShellFilterPost SigUSR1 SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TermResponseAll TextChanged TextChangedI TextChangedP TextChangedT TextYankPost User VimEnter VimLeave VimLeavePre VimResized VimResume VimSuspend WinClosed WinEnter WinLeave WinNew WinResized WinScrolled
+syn keyword vimAutoEvent contained     BufAdd BufDelete BufFilePost BufHidden BufNew BufRead BufReadPost BufUnload BufWinLeave BufWrite BufWritePost CmdlineChanged CmdlineLeave CmdwinEnter ColorScheme CompleteChanged CompleteDonePre CursorHoldI CursorMovedI DiffUpdated DirChanged DirChangedPre EncodingChanged ExitPre FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileExplorer FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave InsertLeavePre MenuPopup ModeChanged OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost ShellCmdPost ShellFilterPost SigUSR1 SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TermResponseAll TextChanged TextChangedI TextChangedP TextChangedT TextYankPost User VimEnter VimLeave VimLeavePre VimResized VimResume VimSuspend WinClosed WinEnter WinLeave WinNewPre WinNew WinResized WinScrolled
 syn keyword vimAutoEvent contained     BufCreate BufEnter BufFilePre BufLeave BufNewFile BufReadCmd BufReadPre BufWinEnter BufWipeout BufWriteCmd BufWritePre CmdlineEnter CmdUndefined CmdwinLeave ColorSchemePre CompleteDone CursorHold CursorMoved
 
 " Highlight commonly used Groupnames {{{2
index 80ce8ca6c8e055436c18503697fa0d7a4b9f9a33..7e4a1b211ffab0948ad5aba9112d159efb345803 100644 (file)
@@ -188,6 +188,7 @@ static struct event_name
     {"VimEnter",       EVENT_VIMENTER},
     {"VimLeave",       EVENT_VIMLEAVE},
     {"VimLeavePre",    EVENT_VIMLEAVEPRE},
+    {"WinNewPre",      EVENT_WINNEWPRE},
     {"WinNew",         EVENT_WINNEW},
     {"WinClosed",      EVENT_WINCLOSED},
     {"WinEnter",       EVENT_WINENTER},
index cecb55aaf9e7c0b40dbe512b739b8859772f6468..be73c18197ea5995ff0f2a5780458180c94d24b4 100644 (file)
@@ -270,6 +270,7 @@ func Test_win_tab_autocmd()
   let g:record = []
 
   augroup testing
+    au WinNewPre * call add(g:record, 'WinNewPre')
     au WinNew * call add(g:record, 'WinNew')
     au WinClosed * call add(g:record, 'WinClosed')
     au WinEnter * call add(g:record, 'WinEnter')
@@ -286,8 +287,8 @@ func Test_win_tab_autocmd()
   close
 
   call assert_equal([
-       \ 'WinLeave', 'WinNew', 'WinEnter',
-       \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
+       \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+       \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
        \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
        \ 'WinLeave', 'WinClosed', 'WinEnter'
        \ ], g:record)
@@ -298,17 +299,96 @@ func Test_win_tab_autocmd()
   bwipe somefile
 
   call assert_equal([
-       \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
+       \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
        \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
        \ 'WinClosed', 'TabClosed'
        \ ], g:record)
 
+  let g:record = []
+  copen
+  help
+  tabnext
+  vnew
+
+  call assert_equal([
+       \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+       \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
+       \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter'
+       \ ], g:record)
+
   augroup testing
     au!
   augroup END
   unlet g:record
 endfunc
 
+func Test_WinNewPre()
+  " Test that the old window layout can be accessed before a new window is created.
+  let g:layouts_pre = []
+  let g:layouts_post = []
+  augroup testing
+    au WinNewPre * call add(g:layouts_pre, winlayout())
+    au WinNew * call add(g:layouts_post, winlayout())
+  augroup END
+  split
+  call assert_notequal(g:layouts_pre[0], g:layouts_post[0])
+  split
+  call assert_equal(g:layouts_pre[1], g:layouts_post[0])
+  call assert_notequal(g:layouts_pre[1], g:layouts_post[1])
+  tabnew
+  call assert_notequal(g:layouts_pre[2], g:layouts_post[1])
+  call assert_notequal(g:layouts_pre[2], g:layouts_post[2])
+  augroup testing
+    au!
+  augroup END
+  unlet g:layouts_pre
+  unlet g:layouts_post
+
+  " Test modifying window layout during WinNewPre throws.
+  let g:caught = 0
+  augroup testing
+    au!
+    au WinNewPre * split
+  augroup END
+  try
+    vnew
+  catch
+    let g:caught += 1
+  endtry
+  augroup testing
+    au!
+    au WinNewPre * tabnew
+  augroup END
+  try
+    vnew
+  catch
+    let g:caught += 1
+  endtry
+  augroup testing
+    au!
+    au WinNewPre * close
+  augroup END
+  try
+    vnew
+  catch
+    let g:caught += 1
+  endtry
+  augroup testing
+    au!
+    au WinNewPre * tabclose
+  augroup END
+  try
+    vnew
+  catch
+    let g:caught += 1
+  endtry
+  call assert_equal(4, g:caught)
+  augroup testing
+    au!
+  augroup END
+  unlet g:caught
+endfunc
+
 func Test_WinResized()
   CheckRunVimInTerminal
 
index 10a70e3c01d0686e4d6a2bac2f88b10c2d285562..841d0182fc08e100c8692f7e56747a375ca7726d 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    59,
 /**/
     58,
 /**/
index 0f52ba217dcae352f6116ea2b05d234d9caa47ec..fe239581af803e40845ba41ab054bb2d4d71dadc 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -1435,7 +1435,8 @@ enum auto_event
     EVENT_VIMRESIZED,          // after Vim window was resized
     EVENT_WINENTER,            // after entering a window
     EVENT_WINLEAVE,            // before leaving a window
-    EVENT_WINNEW,              // when entering a new window
+    EVENT_WINNEWPRE,           // before creating a new window
+    EVENT_WINNEW,              // after creating a new window
     EVENT_WINCLOSED,           // after closing a window
     EVENT_VIMSUSPEND,          // before Vim is suspended
     EVENT_VIMRESUME,           // after Vim is resumed
index fda42e924c178dd32a9200158f19c4642540f9c5..5cb6c3cd9a1a403a53216b2b548ac377b679b178 100644 (file)
@@ -19,6 +19,7 @@ static void win_exchange(long);
 static void win_rotate(int, int);
 static void win_totop(int size, int flags);
 static void win_equal_rec(win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height);
+static void trigger_winnewpre(void);
 static void trigger_winclosed(win_T *win);
 static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp);
 static frame_T *win_altframe(win_T *win, tabpage_T *tp);
@@ -955,6 +956,8 @@ win_split_ins(
     // Do not redraw here, curwin->w_buffer may be invalid.
     ++RedrawingDisabled;
 
+    trigger_winnewpre();
+
     if (flags & WSP_TOP)
        oldwin = firstwin;
     else if (flags & WSP_BOT)
@@ -2886,6 +2889,14 @@ win_close(win_T *win, int free_buf)
     return OK;
 }
 
+    static void
+trigger_winnewpre(void)
+{
+    window_layout_lock();
+    apply_autocmds(EVENT_WINNEWPRE, NULL, NULL, FALSE, NULL);
+    window_layout_unlock();
+}
+
     static void
 trigger_winclosed(win_T *win)
 {
@@ -4477,6 +4488,9 @@ win_new_tabpage(int after)
 
     newtp->tp_localdir = (tp->tp_localdir == NULL)
                                    ? NULL : vim_strsave(tp->tp_localdir);
+
+    trigger_winnewpre();
+
     // Create a new empty window.
     if (win_alloc_firstwin(tp->tp_curwin) == OK)
     {