To: vim_dev@googlegroups.com Subject: Patch 8.0.0548 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.0548 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) Files: src/getchar.c, src/proto/getchar.pro, src/structs.h, src/fileio.c, src/userfunc.c, src/testdir/test_functions.vim *** ../vim-8.0.0547/src/getchar.c 2017-03-16 17:23:26.823815869 +0100 --- src/getchar.c 2017-04-07 19:39:39.270876710 +0200 *************** *** 42,51 **** 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 */ --- 42,47 ---- *************** *** 521,547 **** * 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) { char_u *s; ! if (save_level++ == 0) { ! 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); ! } } } --- 517,538 ---- * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff. * Used before executing autocommands and user functions. */ void ! saveRedobuff(save_redo_T *save_redo) { char_u *s; ! 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) { ! add_buff(&redobuff, s, -1L); ! vim_free(s); } } *************** *** 550,564 **** * Used after executing autocommands and user functions. */ void ! restoreRedobuff(void) { ! if (--save_level == 0) ! { ! free_buff(&redobuff); ! redobuff = save_redobuff; ! free_buff(&old_redobuff); ! old_redobuff = save_old_redobuff; ! } } #endif --- 541,552 ---- * Used after executing autocommands and user functions. */ void ! restoreRedobuff(save_redo_T *save_redo) { ! free_buff(&redobuff); ! redobuff = save_redo->sr_redobuff; ! free_buff(&old_redobuff); ! old_redobuff = save_redo->sr_old_redobuff; } #endif *** ../vim-8.0.0547/src/proto/getchar.pro 2016-09-12 13:04:04.000000000 +0200 --- src/proto/getchar.pro 2017-04-07 19:42:58.705664267 +0200 *************** *** 8,15 **** void flush_buffers(int flush_typeahead); void ResetRedobuff(void); void CancelRedo(void); ! void saveRedobuff(void); ! void restoreRedobuff(void); void AppendToRedobuff(char_u *s); void AppendToRedobuffLit(char_u *str, int len); void AppendCharToRedobuff(int c); --- 8,15 ---- void flush_buffers(int flush_typeahead); void ResetRedobuff(void); void CancelRedo(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); *** ../vim-8.0.0547/src/structs.h 2017-03-08 22:19:21.717870787 +0100 --- src/structs.h 2017-04-07 19:42:14.217934749 +0200 *************** *** 515,520 **** --- 515,526 ---- 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 */ *** ../vim-8.0.0547/src/fileio.c 2017-03-19 17:09:51.831080752 +0100 --- src/fileio.c 2017-04-07 19:40:58.598394480 +0200 *************** *** 9316,9321 **** --- 9316,9322 ---- 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,9527 **** if (!ins_compl_active()) #endif { ! saveRedobuff(); did_save_redobuff = TRUE; } did_filetype = keep_filetype; --- 9522,9528 ---- if (!ins_compl_active()) #endif { ! saveRedobuff(&save_redo); did_save_redobuff = TRUE; } did_filetype = keep_filetype; *************** *** 9624,9630 **** { restore_search_patterns(); if (did_save_redobuff) ! restoreRedobuff(); did_filetype = FALSE; while (au_pending_free_buf != NULL) { --- 9625,9631 ---- { restore_search_patterns(); if (did_save_redobuff) ! restoreRedobuff(&save_redo); did_filetype = FALSE; while (au_pending_free_buf != NULL) { *** ../vim-8.0.0547/src/userfunc.c 2017-04-01 21:21:26.578627608 +0200 --- src/userfunc.c 2017-04-07 19:41:18.590272942 +0200 *************** *** 1408,1413 **** --- 1408,1414 ---- else { int did_save_redo = FALSE; + save_redo_T save_redo; /* * Call the user function. *************** *** 1419,1425 **** if (!ins_compl_active()) #endif { ! saveRedobuff(); did_save_redo = TRUE; } ++fp->uf_calls; --- 1420,1426 ---- if (!ins_compl_active()) #endif { ! saveRedobuff(&save_redo); did_save_redo = TRUE; } ++fp->uf_calls; *************** *** 1431,1437 **** * now. */ func_clear_free(fp, FALSE); if (did_save_redo) ! restoreRedobuff(); restore_search_patterns(); error = ERROR_NONE; } --- 1432,1438 ---- * now. */ func_clear_free(fp, FALSE); if (did_save_redo) ! restoreRedobuff(&save_redo); restore_search_patterns(); error = ERROR_NONE; } *** ../vim-8.0.0547/src/testdir/test_functions.vim 2017-03-19 16:09:41.157653918 +0100 --- src/testdir/test_functions.vim 2017-04-07 19:31:09.941971823 +0200 *************** *** 756,758 **** --- 756,786 ---- call win_gotoid(dum1_id) bwipe! endfunc + + func Test_redo_in_nested_functions() + nnoremap g. :set opfunc=Operatorg@ + 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 *** ../vim-8.0.0547/src/version.c 2017-04-07 16:17:35.585077280 +0200 --- src/version.c 2017-04-07 19:08:46.534123562 +0200 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 548, /**/ -- The greatest lies of all time: (1) The check is in the mail. (2) We have a really challenging assignment for you. (3) I love you. (4) All bugs have been fixed. (5) This won't hurt a bit. (6) Honey, I just need to debug this program and be home in 5 minutes. (7) I have just sent you an e-mail about that. (8) Of course I'll respect you in the morning. (9) I'm from the government, and I'm here to help you. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///