# HG changeset patch # User Bram Moolenaar # Date 1671209104 -3600 # Node ID db72745d328c89a34a35e9d419ca03bb126c8ee0 # Parent d6db0f4e24f34f0850e6334fdbbce3e93ce9a303 patch 9.0.1064: code for making 'shortmess' temporarily empty is repeated Commit: https://github.com/vim/vim/commit/9aee8ec400fe617f6d82441c46a22d0cef6fa3e6 Author: Christian Brabandt 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) diff --git a/src/errors.h b/src/errors.h --- 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")); diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c --- 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) diff --git a/src/option.h b/src/option.h --- 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 diff --git a/src/optionstr.c b/src/optionstr.c --- 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); + } +} diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro --- 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 : */ diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim --- 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('')}') + autocmd BufReadPost * call add(g:brp, $'BufReadPost: {expand('')}') + 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 diff --git a/src/version.c b/src/version.c --- 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,