changeset 31463:db72745d328c v9.0.1064

patch 9.0.1064: code for making 'shortmess' temporarily empty is repeated Commit: https://github.com/vim/vim/commit/9aee8ec400fe617f6d82441c46a22d0cef6fa3e6 Author: Christian Brabandt <cb@256bit.org> Date: Fri Dec 16 16:41:23 2022 +0000 patch 9.0.1064: code for making 'shortmess' temporarily empty is repeated Problem: Code for making 'shortmess' temporarily empty is repeated. Solution: Add functions for making 'shortmess' empty and restoring it. (Christian Brabandt, closes #11709)
author Bram Moolenaar <Bram@vim.org>
date Fri, 16 Dec 2022 17:45:04 +0100
parents d6db0f4e24f3
children 6053f2ce4f2e
files src/errors.h src/ex_cmds2.c src/option.h src/optionstr.c src/proto/optionstr.pro src/testdir/test_autocmd.vim src/version.c
diffstat 7 files changed, 111 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/errors.h
+++ b/src/errors.h
@@ -3389,3 +3389,5 @@ EXTERN char e_object_member_not_found_st
 EXTERN char e_object_member_is_not_writable_str[]
 	INIT(= N_("E1335: Object member is not writable: %s"));
 #endif
+EXTERN char e_internal_error_shortmess_too_long[]
+	INIT(= N_("E1336: Internal error: shortmess too long"));
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -460,7 +460,6 @@ ex_listdo(exarg_T *eap)
 #if defined(FEAT_SYN_HL)
     char_u	*save_ei = NULL;
 #endif
-    char_u	*p_shm_save;
 #ifdef FEAT_QUICKFIX
     int		qf_size = 0;
     int		qf_idx;
@@ -541,7 +540,9 @@ ex_listdo(exarg_T *eap)
 		buf = NULL;
 	    else
 	    {
+		save_clear_shm_value();
 		ex_cc(eap);
+		restore_shm_value();
 
 		buf = curbuf;
 		i = eap->line1 - 1;
@@ -568,13 +569,9 @@ ex_listdo(exarg_T *eap)
 		{
 		    // Clear 'shm' to avoid that the file message overwrites
 		    // any output from the command.
-		    p_shm_save = vim_strsave(p_shm);
-		    set_option_value_give_err((char_u *)"shm",
-							  0L, (char_u *)"", 0);
+		    save_clear_shm_value();
 		    do_argfile(eap, i);
-		    set_option_value_give_err((char_u *)"shm",
-							    0L, p_shm_save, 0);
-		    vim_free(p_shm_save);
+		    restore_shm_value();
 		}
 		if (curwin->w_arg_idx != i)
 		    break;
@@ -630,11 +627,9 @@ ex_listdo(exarg_T *eap)
 
 		// Go to the next buffer.  Clear 'shm' to avoid that the file
 		// message overwrites any output from the command.
-		p_shm_save = vim_strsave(p_shm);
-		set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
+		save_clear_shm_value();
 		goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
-		set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
-		vim_free(p_shm_save);
+		restore_shm_value();
 
 		// If autocommands took us elsewhere, quit here.
 		if (curbuf->b_fnum != next_fnum)
@@ -650,13 +645,9 @@ ex_listdo(exarg_T *eap)
 
 		qf_idx = qf_get_cur_idx(eap);
 
-		// Clear 'shm' to avoid that the file message overwrites
-		// any output from the command.
-		p_shm_save = vim_strsave(p_shm);
-		set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
+		save_clear_shm_value();
 		ex_cnext(eap);
-		set_option_value_give_err((char_u *)"shm", 0L, p_shm_save, 0);
-		vim_free(p_shm_save);
+		restore_shm_value();
 
 		// If jumping to the next quickfix entry fails, quit here
 		if (qf_get_cur_idx(eap) == qf_idx)
--- a/src/option.h
+++ b/src/option.h
@@ -271,6 +271,8 @@ typedef enum {
 #define SHM_SEARCHCOUNT  'S'		// search stats: '[1/10]'
 #define SHM_POSIX       "AS"		// POSIX value
 #define SHM_ALL		"rmfixlnwaWtToOsAIcCqFS" // all possible flags for 'shm'
+#define SHM_LEN		30		// max length of all flags together
+					// plus a NUL character
 
 // characters for p_go:
 #define GO_TERMINAL	'!'		// use terminal for system commands
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -13,6 +13,9 @@
 
 #include "vim.h"
 
+static char_u shm_buf[SHM_LEN];
+static int set_shm_recursive = 0;
+
 static char *(p_ambw_values[]) = {"single", "double", NULL};
 static char *(p_bg_values[]) = {"light", "dark", NULL};
 static char *(p_bkc_values[]) = {"yes", "auto", "no", "breaksymlink", "breakhardlink", NULL};
@@ -2697,3 +2700,40 @@ check_ff_value(char_u *p)
 {
     return check_opt_strings(p, p_ff_values, FALSE);
 }
+
+/*
+ * Save the acutal shortmess Flags and clear them
+ * temporarily to avoid that file messages
+ * overwrites any output from the following commands.
+ *
+ * Caller must make sure to first call save_clear_shm_value() and then
+ * restore_shm_value() exactly the same number of times.
+ */
+    void
+save_clear_shm_value()
+{
+    if (STRLEN(p_shm) >= SHM_LEN)
+    {
+	iemsg(e_internal_error_shortmess_too_long);
+	return;
+    }
+
+    if (++set_shm_recursive == 1)
+    {
+	STRCPY(shm_buf, p_shm);
+	set_option_value_give_err((char_u *)"shm", 0L, (char_u *)"", 0);
+    }
+}
+
+/*
+ * Restore the shortmess Flags set from the save_clear_shm_value() function.
+ */
+    void
+restore_shm_value()
+{
+    if (--set_shm_recursive == 0)
+    {
+	set_option_value_give_err((char_u *)"shm", 0L, shm_buf, 0);
+	vim_memset(shm_buf, 0, SHM_LEN);
+    }
+}
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -11,4 +11,6 @@ void set_string_option_direct_in_buf(buf
 char *set_string_option(int opt_idx, char_u *value, int opt_flags);
 char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *errbuf, int opt_flags, int *value_checked);
 int check_ff_value(char_u *p);
+void save_clear_shm_value(void);
+void restore_shm_value(void);
 /* vim: set ft=c : */
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -4161,5 +4161,60 @@ func Test_autocmd_nested_setbufvar()
   %bwipe!
 endfunc
 
+func SetupVimTest_shm()
+  let g:bwe = []
+  let g:brp = []
+  set shortmess+=F
+
+  let dirname='XVimTestSHM'
+  call mkdir(dirname, 'R')
+  call writefile(['test'], dirname .. '/1')
+  call writefile(['test'], dirname .. '/2')
+  call writefile(['test'], dirname .. '/3')
+
+  augroup test
+      autocmd!
+      autocmd BufWinEnter * call add(g:bwe, $'BufWinEnter: {expand('<amatch>')}')
+      autocmd BufReadPost * call add(g:brp,  $'BufReadPost: {expand('<amatch>')}')
+  augroup END
+
+  call setqflist([
+        \  {'filename': dirname .. '/1', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0},
+        \  {'filename': dirname .. '/2', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0},
+        \  {'filename': dirname .. '/3', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0}
+        \  ])
+  cdo! substitute/test/TEST
+
+  " clean up
+  noa enew!
+  set shortmess&vim
+  augroup test
+      autocmd!
+  augroup END
+  augroup! test
+endfunc
+
+func Test_autocmd_shortmess()
+  CheckNotMSWindows
+
+  call SetupVimTest_shm()
+  let output = execute(':mess')->split('\n')
+
+  let info = copy(output)->filter({idx, val -> val =~# '\d of 3'} )
+  let bytes = copy(output)->filter({idx, val -> val =~# 'bytes'} )
+
+  " We test the following here:
+  " BufReadPost should have been triggered 3 times, once per file
+  " BufWinEnter should have been triggered 3 times, once per file
+  " FileInfoMessage should have been shown 3 times, regardless of shm option
+  " "(x of 3)" message from :cnext has been shown 3 times
+
+  call assert_equal(3, g:brp->len())
+  call assert_equal(3, g:bwe->len())
+  call assert_equal(3, info->len())
+  call assert_equal(3, bytes->len())
+
+  delfunc SetupVimTest_shm
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1064,
+/**/
     1063,
 /**/
     1062,