forked from aniani/vim
patch 9.0.0387: repeat <ScriptCmd> mapping doesn't use right script context
Problem: repeating a <ScriptCmd> mapping does not use the right script context. Solution: When using a mapping put <SID>{sid}; in the redo buffer. (closes #11049)
This commit is contained in:
parent
b1f471ee20
commit
ddf7dba96e
@ -85,6 +85,7 @@ static int last_recorded_len = 0; // number of last recorded chars
|
|||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
mapblock_T *last_used_map = NULL;
|
mapblock_T *last_used_map = NULL;
|
||||||
|
int last_used_sid = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int read_readbuf(buffheader_T *buf, int advance);
|
static int read_readbuf(buffheader_T *buf, int advance);
|
||||||
@ -837,6 +838,22 @@ start_redo(long count, int old_redo)
|
|||||||
|
|
||||||
c = read_redo(FALSE, old_redo);
|
c = read_redo(FALSE, old_redo);
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (c == K_SID)
|
||||||
|
{
|
||||||
|
// Copy the <SID>{sid}; sequence
|
||||||
|
add_char_buff(&readbuf2, c);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
c = read_redo(FALSE, old_redo);
|
||||||
|
add_char_buff(&readbuf2, c);
|
||||||
|
if (!isdigit(c))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = read_redo(FALSE, old_redo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// copy the buffer name, if present
|
// copy the buffer name, if present
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
{
|
{
|
||||||
@ -876,7 +893,7 @@ start_redo(long count, int old_redo)
|
|||||||
add_num_buff(&readbuf2, count);
|
add_num_buff(&readbuf2, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy from the redo buffer into the stuff buffer
|
// copy the rest from the redo buffer into the stuff buffer
|
||||||
add_char_buff(&readbuf2, c);
|
add_char_buff(&readbuf2, c);
|
||||||
copy_redo(old_redo);
|
copy_redo(old_redo);
|
||||||
return OK;
|
return OK;
|
||||||
@ -1795,8 +1812,22 @@ vgetc(void)
|
|||||||
// avoid it being recognized as the start of a special key.
|
// avoid it being recognized as the start of a special key.
|
||||||
if (c == K_CSI)
|
if (c == K_CSI)
|
||||||
c = CSI;
|
c = CSI;
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (c == K_SID)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
// Handle <SID>{sid}; Do up to 20 digits for safety.
|
||||||
|
last_used_sid = 0;
|
||||||
|
for (j = 0; j < 20 && isdigit(c = vgetorpeek(TRUE)); ++j)
|
||||||
|
last_used_sid = last_used_sid * 10 + (c - '0');
|
||||||
|
last_used_map = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// a keypad or special function key was not mapped, use it like
|
// a keypad or special function key was not mapped, use it like
|
||||||
// its ASCII equivalent
|
// its ASCII equivalent
|
||||||
switch (c)
|
switch (c)
|
||||||
@ -2922,6 +2953,10 @@ handle_mapping(
|
|||||||
{
|
{
|
||||||
int noremap;
|
int noremap;
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
last_used_map = mp;
|
||||||
|
last_used_sid = -1;
|
||||||
|
#endif
|
||||||
if (save_m_noremap != REMAP_YES)
|
if (save_m_noremap != REMAP_YES)
|
||||||
noremap = save_m_noremap;
|
noremap = save_m_noremap;
|
||||||
else if (
|
else if (
|
||||||
@ -2940,7 +2975,6 @@ handle_mapping(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
if (save_m_expr)
|
if (save_m_expr)
|
||||||
vim_free(map_str);
|
vim_free(map_str);
|
||||||
last_used_map = mp;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
@ -3896,6 +3930,29 @@ getcmdkeycmd(
|
|||||||
return (char_u *)line_ga.ga_data;
|
return (char_u *)line_ga.ga_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* If there was a mapping put info about it in the redo buffer, so that "."
|
||||||
|
* will use the same script context. We only need the SID.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
may_add_last_used_map_to_redobuff(void)
|
||||||
|
{
|
||||||
|
char_u buf[3 + 20];
|
||||||
|
|
||||||
|
if (last_used_map == NULL || last_used_map->m_script_ctx.sc_sid < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// <K_SID>{nr};
|
||||||
|
buf[0] = K_SPECIAL;
|
||||||
|
buf[1] = KS_EXTRA;
|
||||||
|
buf[2] = KE_SID;
|
||||||
|
vim_snprintf((char *)buf + 3, 20, "%d;",
|
||||||
|
last_used_map->m_script_ctx.sc_sid);
|
||||||
|
add_buff(&redobuff, buf, -1L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
do_cmdkey_command(int key UNUSED, int flags)
|
do_cmdkey_command(int key UNUSED, int flags)
|
||||||
{
|
{
|
||||||
@ -3903,10 +3960,18 @@ do_cmdkey_command(int key UNUSED, int flags)
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
sctx_T save_current_sctx = {-1, 0, 0, 0};
|
sctx_T save_current_sctx = {-1, 0, 0, 0};
|
||||||
|
|
||||||
if (key == K_SCRIPT_COMMAND && last_used_map != NULL)
|
if (key == K_SCRIPT_COMMAND
|
||||||
|
&& (last_used_map != NULL || SCRIPT_ID_VALID(last_used_sid)))
|
||||||
{
|
{
|
||||||
save_current_sctx = current_sctx;
|
save_current_sctx = current_sctx;
|
||||||
current_sctx = last_used_map->m_script_ctx;
|
if (last_used_map != NULL)
|
||||||
|
current_sctx = last_used_map->m_script_ctx;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_sctx.sc_sid = last_used_sid;
|
||||||
|
current_sctx.sc_lnum = 0;
|
||||||
|
current_sctx.sc_version = SCRIPT_ITEM(last_used_sid)->sn_version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3925,6 +3990,9 @@ do_cmdkey_command(int key UNUSED, int flags)
|
|||||||
reset_last_used_map(mapblock_T *mp)
|
reset_last_used_map(mapblock_T *mp)
|
||||||
{
|
{
|
||||||
if (last_used_map == mp)
|
if (last_used_map == mp)
|
||||||
|
{
|
||||||
last_used_map = NULL;
|
last_used_map = NULL;
|
||||||
|
last_used_sid = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -277,6 +277,7 @@ enum key_extra
|
|||||||
, KE_COMMAND = 103 // <Cmd> special key
|
, KE_COMMAND = 103 // <Cmd> special key
|
||||||
, KE_SCRIPT_COMMAND = 104 // <ScriptCmd> special key
|
, KE_SCRIPT_COMMAND = 104 // <ScriptCmd> special key
|
||||||
, KE_S_BS = 105 // shift + <BS>
|
, KE_S_BS = 105 // shift + <BS>
|
||||||
|
, KE_SID = 106 // <SID> special key, followed by {nr};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -483,6 +484,7 @@ enum key_extra
|
|||||||
|
|
||||||
#define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND)
|
#define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND)
|
||||||
#define K_SCRIPT_COMMAND TERMCAP2KEY(KS_EXTRA, KE_SCRIPT_COMMAND)
|
#define K_SCRIPT_COMMAND TERMCAP2KEY(KS_EXTRA, KE_SCRIPT_COMMAND)
|
||||||
|
#define K_SID TERMCAP2KEY(KS_EXTRA, KE_SID)
|
||||||
|
|
||||||
// Bits for modifier mask
|
// Bits for modifier mask
|
||||||
// 0x01 cannot be used, because the modifier must be 0x02 or higher
|
// 0x01 cannot be used, because the modifier must be 0x02 or higher
|
||||||
|
@ -1466,6 +1466,13 @@ prep_redo_num2(
|
|||||||
int cmd5)
|
int cmd5)
|
||||||
{
|
{
|
||||||
ResetRedobuff();
|
ResetRedobuff();
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
// Put info about a mapping in the redo buffer, so that "." will use the
|
||||||
|
// same script context.
|
||||||
|
may_add_last_used_map_to_redobuff();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (regname != 0) // yank from specified buffer
|
if (regname != 0) // yank from specified buffer
|
||||||
{
|
{
|
||||||
AppendCharToRedobuff('"');
|
AppendCharToRedobuff('"');
|
||||||
|
@ -52,6 +52,7 @@ void parse_queued_messages(void);
|
|||||||
void vungetc(int c);
|
void vungetc(int c);
|
||||||
int fix_input_buffer(char_u *buf, int len);
|
int fix_input_buffer(char_u *buf, int len);
|
||||||
int input_available(void);
|
int input_available(void);
|
||||||
|
void may_add_last_used_map_to_redobuff(void);
|
||||||
int do_cmdkey_command(int key, int flags);
|
int do_cmdkey_command(int key, int flags);
|
||||||
void reset_last_used_map(mapblock_T *mp);
|
void reset_last_used_map(mapblock_T *mp);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -1529,6 +1529,35 @@ func Test_map_script_cmd_survives_unmap()
|
|||||||
autocmd! CmdlineEnter
|
autocmd! CmdlineEnter
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_map_script_cmd_redo()
|
||||||
|
call mkdir('Xmapcmd')
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
import autoload './script.vim'
|
||||||
|
onoremap <F3> <ScriptCmd>script.Func()<CR>
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xmapcmd/plugin.vim')
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
export def Func()
|
||||||
|
normal! dd
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xmapcmd/script.vim')
|
||||||
|
new
|
||||||
|
call setline(1, ['one', 'two', 'three', 'four'])
|
||||||
|
nnoremap j j
|
||||||
|
source Xmapcmd/plugin.vim
|
||||||
|
call feedkeys("d\<F3>j.", 'xt')
|
||||||
|
call assert_equal(['two', 'four'], getline(1, '$'))
|
||||||
|
|
||||||
|
ounmap <F3>
|
||||||
|
nunmap j
|
||||||
|
call delete('Xmapcmd', 'rf')
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test for using <script> with a map to remap characters in rhs
|
" Test for using <script> with a map to remap characters in rhs
|
||||||
func Test_script_local_remap()
|
func Test_script_local_remap()
|
||||||
new
|
new
|
||||||
|
@ -703,6 +703,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
387,
|
||||||
/**/
|
/**/
|
||||||
386,
|
386,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user