Mercurial > vim
changeset 11325:77f3b7316d8b v8.0.0548
patch 8.0.0548: saving the redo buffer only works one time
commit https://github.com/vim/vim/commit/d4863aa99e0527e9505c79cbeafc68a6832200bf
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Apr 7 19:50:12 2017 +0200
patch 8.0.0548: saving the redo buffer only works one time
Problem: Saving the redo buffer only works one time, resulting in the "."
command not working well for a function call inside another
function call. (Ingo Karkat)
Solution: Save the redo buffer at every user function call. (closes #1619)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 07 Apr 2017 20:00:04 +0200 |
parents | c9adf54ef624 |
children | 76747bd3226c |
files | src/fileio.c src/getchar.c src/proto/getchar.pro src/structs.h src/testdir/test_functions.vim src/userfunc.c src/version.c |
diffstat | 7 files changed, 60 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/src/fileio.c +++ b/src/fileio.c @@ -9316,6 +9316,7 @@ apply_autocmds_group( proftime_T wait_time; #endif int did_save_redobuff = FALSE; + save_redo_T save_redo; /* * Quickly return if there are no autocommands for this event or @@ -9521,7 +9522,7 @@ apply_autocmds_group( if (!ins_compl_active()) #endif { - saveRedobuff(); + saveRedobuff(&save_redo); did_save_redobuff = TRUE; } did_filetype = keep_filetype; @@ -9624,7 +9625,7 @@ apply_autocmds_group( { restore_search_patterns(); if (did_save_redobuff) - restoreRedobuff(); + restoreRedobuff(&save_redo); did_filetype = FALSE; while (au_pending_free_buf != NULL) {
--- a/src/getchar.c +++ b/src/getchar.c @@ -42,10 +42,6 @@ static buffheader_T redobuff = {{NULL, {NUL}}, NULL, 0, 0}; static buffheader_T old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; -#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) -static buffheader_T save_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; -static buffheader_T save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0}; -#endif static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0}; static int typeahead_char = 0; /* typeahead char that's not flushed */ @@ -521,27 +517,22 @@ CancelRedo(void) * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff. * Used before executing autocommands and user functions. */ -static int save_level = 0; - void -saveRedobuff(void) +saveRedobuff(save_redo_T *save_redo) { char_u *s; - if (save_level++ == 0) + save_redo->sr_redobuff = redobuff; + redobuff.bh_first.b_next = NULL; + save_redo->sr_old_redobuff = old_redobuff; + old_redobuff.bh_first.b_next = NULL; + + /* Make a copy, so that ":normal ." in a function works. */ + s = get_buffcont(&save_redo->sr_redobuff, FALSE); + if (s != NULL) { - save_redobuff = redobuff; - redobuff.bh_first.b_next = NULL; - save_old_redobuff = old_redobuff; - old_redobuff.bh_first.b_next = NULL; - - /* Make a copy, so that ":normal ." in a function works. */ - s = get_buffcont(&save_redobuff, FALSE); - if (s != NULL) - { - add_buff(&redobuff, s, -1L); - vim_free(s); - } + add_buff(&redobuff, s, -1L); + vim_free(s); } } @@ -550,15 +541,12 @@ saveRedobuff(void) * Used after executing autocommands and user functions. */ void -restoreRedobuff(void) +restoreRedobuff(save_redo_T *save_redo) { - if (--save_level == 0) - { - free_buff(&redobuff); - redobuff = save_redobuff; - free_buff(&old_redobuff); - old_redobuff = save_old_redobuff; - } + free_buff(&redobuff); + redobuff = save_redo->sr_redobuff; + free_buff(&old_redobuff); + old_redobuff = save_redo->sr_old_redobuff; } #endif
--- a/src/proto/getchar.pro +++ b/src/proto/getchar.pro @@ -8,8 +8,8 @@ void typeahead_noflush(int c); void flush_buffers(int flush_typeahead); void ResetRedobuff(void); void CancelRedo(void); -void saveRedobuff(void); -void restoreRedobuff(void); +void saveRedobuff(save_redo_T *save_redo); +void restoreRedobuff(save_redo_T *save_redo); void AppendToRedobuff(char_u *s); void AppendToRedobuffLit(char_u *str, int len); void AppendCharToRedobuff(int c);
--- a/src/structs.h +++ b/src/structs.h @@ -515,6 +515,12 @@ struct buffheader int bh_space; /* space in bh_curr for appending */ }; +typedef struct +{ + buffheader_T sr_redobuff; + buffheader_T sr_old_redobuff; +} save_redo_T; + /* * used for completion on the command line */
--- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -756,3 +756,31 @@ func Test_setbufvar_options() call win_gotoid(dum1_id) bwipe! endfunc + +func Test_redo_in_nested_functions() + nnoremap g. :set opfunc=Operator<CR>g@ + function Operator( type, ... ) + let @x = 'XXX' + execute 'normal! g`[' . (a:type ==# 'line' ? 'V' : 'v') . 'g`]' . '"xp' + endfunction + + function! Apply() + 5,6normal! . + endfunction + + new + call setline(1, repeat(['some "quoted" text', 'more "quoted" text'], 3)) + 1normal g.i" + call assert_equal('some "XXX" text', getline(1)) + 3,4normal . + call assert_equal('some "XXX" text', getline(3)) + call assert_equal('more "XXX" text', getline(4)) + call Apply() + call assert_equal('some "XXX" text', getline(5)) + call assert_equal('more "XXX" text', getline(6)) + bwipe! + + nunmap g. + delfunc Operator + delfunc Apply +endfunc
--- a/src/userfunc.c +++ b/src/userfunc.c @@ -1408,6 +1408,7 @@ call_func( else { int did_save_redo = FALSE; + save_redo_T save_redo; /* * Call the user function. @@ -1419,7 +1420,7 @@ call_func( if (!ins_compl_active()) #endif { - saveRedobuff(); + saveRedobuff(&save_redo); did_save_redo = TRUE; } ++fp->uf_calls; @@ -1431,7 +1432,7 @@ call_func( * now. */ func_clear_free(fp, FALSE); if (did_save_redo) - restoreRedobuff(); + restoreRedobuff(&save_redo); restore_search_patterns(); error = ERROR_NONE; }