mirror of
https://github.com/neovim/neovim.git
synced 2025-09-14 07:18:17 +00:00
vim-patch:8.0.0548: saving the redo buffer only works one time (#8629)
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 vim/vim#1619)
d4863aa99e
This commit is contained in:

committed by
Justin M. Keyes

parent
83be7cec98
commit
38fb835854
@@ -143,6 +143,12 @@ struct buffheader {
|
|||||||
size_t bh_space; // space in bh_curr for appending
|
size_t bh_space; // space in bh_curr for appending
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
buffheader_T sr_redobuff;
|
||||||
|
buffheader_T sr_old_redobuff;
|
||||||
|
} save_redo_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure that contains all options that are local to a window.
|
* Structure that contains all options that are local to a window.
|
||||||
* Used twice in a window: for the current buffer and for all buffers.
|
* Used twice in a window: for the current buffer and for all buffers.
|
||||||
|
@@ -21174,6 +21174,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
|
|||||||
proftime_T wait_start;
|
proftime_T wait_start;
|
||||||
proftime_T call_start;
|
proftime_T call_start;
|
||||||
bool did_save_redo = false;
|
bool did_save_redo = false;
|
||||||
|
save_redo_T save_redo;
|
||||||
|
|
||||||
/* If depth of calling is getting too high, don't execute the function */
|
/* If depth of calling is getting too high, don't execute the function */
|
||||||
if (depth >= p_mfd) {
|
if (depth >= p_mfd) {
|
||||||
@@ -21186,7 +21187,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
|
|||||||
// Save search patterns and redo buffer.
|
// Save search patterns and redo buffer.
|
||||||
save_search_patterns();
|
save_search_patterns();
|
||||||
if (!ins_compl_active()) {
|
if (!ins_compl_active()) {
|
||||||
saveRedobuff();
|
saveRedobuff(&save_redo);
|
||||||
did_save_redo = true;
|
did_save_redo = true;
|
||||||
}
|
}
|
||||||
++fp->uf_calls;
|
++fp->uf_calls;
|
||||||
@@ -21501,7 +21502,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars,
|
|||||||
}
|
}
|
||||||
// restore search patterns and redo buffer
|
// restore search patterns and redo buffer
|
||||||
if (did_save_redo) {
|
if (did_save_redo) {
|
||||||
restoreRedobuff();
|
restoreRedobuff(&save_redo);
|
||||||
}
|
}
|
||||||
restore_search_patterns();
|
restore_search_patterns();
|
||||||
}
|
}
|
||||||
|
@@ -6696,6 +6696,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|
|||||||
static int filechangeshell_busy = FALSE;
|
static int filechangeshell_busy = FALSE;
|
||||||
proftime_T wait_time;
|
proftime_T wait_time;
|
||||||
bool did_save_redobuff = false;
|
bool did_save_redobuff = false;
|
||||||
|
save_redo_T save_redo;
|
||||||
|
|
||||||
// Quickly return if there are no autocommands for this event or
|
// Quickly return if there are no autocommands for this event or
|
||||||
// autocommands are blocked.
|
// autocommands are blocked.
|
||||||
@@ -6876,7 +6877,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|
|||||||
if (!autocmd_busy) {
|
if (!autocmd_busy) {
|
||||||
save_search_patterns();
|
save_search_patterns();
|
||||||
if (!ins_compl_active()) {
|
if (!ins_compl_active()) {
|
||||||
saveRedobuff();
|
saveRedobuff(&save_redo);
|
||||||
did_save_redobuff = true;
|
did_save_redobuff = true;
|
||||||
}
|
}
|
||||||
did_filetype = keep_filetype;
|
did_filetype = keep_filetype;
|
||||||
@@ -6965,7 +6966,7 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|
|||||||
if (!autocmd_busy) {
|
if (!autocmd_busy) {
|
||||||
restore_search_patterns();
|
restore_search_patterns();
|
||||||
if (did_save_redobuff) {
|
if (did_save_redobuff) {
|
||||||
restoreRedobuff();
|
restoreRedobuff(&save_redo);
|
||||||
}
|
}
|
||||||
did_filetype = FALSE;
|
did_filetype = FALSE;
|
||||||
while (au_pending_free_buf != NULL) {
|
while (au_pending_free_buf != NULL) {
|
||||||
|
@@ -78,11 +78,9 @@ FileDescriptor *scriptin[NSCRIPT] = { NULL };
|
|||||||
|
|
||||||
#define MINIMAL_SIZE 20 /* minimal size for b_str */
|
#define MINIMAL_SIZE 20 /* minimal size for b_str */
|
||||||
|
|
||||||
static buffheader_T redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
static buffheader_T redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
||||||
static buffheader_T old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
static buffheader_T old_redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
||||||
static buffheader_T save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
static buffheader_T recordbuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
||||||
static buffheader_T save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
|
|
||||||
static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
|
|
||||||
|
|
||||||
// First read ahead buffer. Used for translated commands.
|
// First read ahead buffer. Used for translated commands.
|
||||||
static buffheader_T readbuf1 = {{NULL, {NUL}}, NULL, 0, 0};
|
static buffheader_T readbuf1 = {{NULL, {NUL}}, NULL, 0, 0};
|
||||||
@@ -480,41 +478,31 @@ void CancelRedo(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Save redobuff and old_redobuff to save_redobuff and save_old_redobuff.
|
||||||
* Save redobuff and old_redobuff to save_redobuff and save_old_redobuff.
|
/// Used before executing autocommands and user functions.
|
||||||
* Used before executing autocommands and user functions.
|
void saveRedobuff(save_redo_T *save_redo)
|
||||||
*/
|
|
||||||
static int save_level = 0;
|
|
||||||
|
|
||||||
void saveRedobuff(void)
|
|
||||||
{
|
{
|
||||||
if (save_level++ == 0) {
|
save_redo->sr_redobuff = redobuff;
|
||||||
save_redobuff = redobuff;
|
|
||||||
redobuff.bh_first.b_next = NULL;
|
redobuff.bh_first.b_next = NULL;
|
||||||
save_old_redobuff = old_redobuff;
|
save_redo->sr_old_redobuff = old_redobuff;
|
||||||
old_redobuff.bh_first.b_next = NULL;
|
old_redobuff.bh_first.b_next = NULL;
|
||||||
|
|
||||||
// Make a copy, so that ":normal ." in a function works.
|
// Make a copy, so that ":normal ." in a function works.
|
||||||
char *const s = (char *)get_buffcont(&save_redobuff, false);
|
char *const s = (char *)get_buffcont(&save_redo->sr_redobuff, false);
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
add_buff(&redobuff, s, -1L);
|
add_buff(&redobuff, s, -1L);
|
||||||
xfree(s);
|
xfree(s);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Restore redobuff and old_redobuff from save_redobuff and save_old_redobuff.
|
||||||
* Restore redobuff and old_redobuff from save_redobuff and save_old_redobuff.
|
/// Used after executing autocommands and user functions.
|
||||||
* Used after executing autocommands and user functions.
|
void restoreRedobuff(save_redo_T *save_redo)
|
||||||
*/
|
|
||||||
void restoreRedobuff(void)
|
|
||||||
{
|
{
|
||||||
if (--save_level == 0) {
|
|
||||||
free_buff(&redobuff);
|
free_buff(&redobuff);
|
||||||
redobuff = save_redobuff;
|
redobuff = save_redo->sr_redobuff;
|
||||||
free_buff(&old_redobuff);
|
free_buff(&old_redobuff);
|
||||||
old_redobuff = save_old_redobuff;
|
old_redobuff = save_redo->sr_old_redobuff;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -795,3 +795,31 @@ func Test_shellescape()
|
|||||||
|
|
||||||
let &shell = save_shell
|
let &shell = save_shell
|
||||||
endfunc
|
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
|
||||||
|
Reference in New Issue
Block a user