diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-07-29 21:10:07 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-07-29 21:10:07 +0200 |
commit | 9d997addc7bd0fd132a809cf497ed816e61fcd25 (patch) | |
tree | 0ef7b82926d68d877b145c29396e7b063e56cf65 | |
parent | baaf6deb957e11227c6ffa5e22b48d9082ae7e77 (diff) |
patch 9.1.0642: Check that mapping rhs starts with lhs fails if not simplifiedv9.1.0642
Problem: Check that mapping rhs starts with lhs doesn't work if lhs is
not simplified.
Solution: Keep track of the mapblock containing the alternative lhs and
also compare with it (zeertzjq).
fixes: #15376
closes: #15384
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r-- | src/getchar.c | 24 | ||||
-rw-r--r-- | src/map.c | 46 | ||||
-rw-r--r-- | src/structs.h | 3 | ||||
-rw-r--r-- | src/testdir/test_mapping.vim | 43 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 99 insertions, 19 deletions
diff --git a/src/getchar.c b/src/getchar.c index 4af176978c..54222ec308 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -3156,6 +3156,7 @@ handle_mapping( int save_m_noremap; int save_m_silent; char_u *save_m_keys; + char_u *save_alt_m_keys; #else # define save_m_noremap mp->m_noremap # define save_m_silent mp->m_silent @@ -3204,6 +3205,7 @@ handle_mapping( save_m_noremap = mp->m_noremap; save_m_silent = mp->m_silent; save_m_keys = NULL; // only saved when needed + save_alt_m_keys = NULL; // only saved when needed /* * Handle ":map <expr>": evaluate the {rhs} as an expression. Also @@ -3221,6 +3223,8 @@ handle_mapping( may_garbage_collect = FALSE; save_m_keys = vim_strsave(mp->m_keys); + save_alt_m_keys = mp->m_alt != NULL + ? vim_strsave(mp->m_alt->m_keys) : NULL; map_str = eval_map_expr(mp, NUL); // The mapping may do anything, but we expect it to take care of @@ -3278,15 +3282,20 @@ handle_mapping( noremap = save_m_noremap; else if ( #ifdef FEAT_EVAL - STRNCMP(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys, - (size_t)keylen) -#else - STRNCMP(map_str, mp->m_keys, (size_t)keylen) + save_m_expr ? + (save_m_keys != NULL + && STRNCMP(map_str, save_m_keys, (size_t)keylen) == 0) + || (save_alt_m_keys != NULL + && STRNCMP(map_str, save_alt_m_keys, + STRLEN(save_alt_m_keys)) == 0) : #endif - != 0) - noremap = REMAP_YES; - else + STRNCMP(map_str, mp->m_keys, (size_t)keylen) == 0 + || (mp->m_alt != NULL + && STRNCMP(map_str, mp->m_alt->m_keys, + STRLEN(mp->m_alt->m_keys)) == 0)) noremap = REMAP_SKIP; + else + noremap = REMAP_YES; i = ins_typebuf(map_str, noremap, 0, TRUE, cmd_silent || save_m_silent); #ifdef FEAT_EVAL @@ -3296,6 +3305,7 @@ handle_mapping( } #ifdef FEAT_EVAL vim_free(save_m_keys); + vim_free(save_alt_m_keys); #endif *keylenp = keylen; if (i == FAIL) @@ -85,6 +85,8 @@ map_free(mapblock_T **mpp) mp = *mpp; vim_free(mp->m_keys); + if (mp->m_alt != NULL) + mp->m_alt->m_alt = NULL; vim_free(mp->m_str); vim_free(mp->m_orig_str); *mpp = mp->m_next; @@ -213,7 +215,7 @@ theend: --map_locked; } - static int + static mapblock_T * map_add( mapblock_T **map_table, mapblock_T **abbr_table, @@ -236,7 +238,7 @@ map_add( mapblock_T *mp = ALLOC_CLEAR_ONE(mapblock_T); if (mp == NULL) - return FAIL; + return NULL; // If CTRL-C has been mapped, don't always use it for Interrupting. if (*keys == Ctrl_C) @@ -256,7 +258,7 @@ map_add( vim_free(mp->m_str); vim_free(mp->m_orig_str); vim_free(mp); - return FAIL; + return NULL; } mp->m_keylen = (int)STRLEN(mp->m_keys); mp->m_noremap = noremap; @@ -292,7 +294,7 @@ map_add( mp->m_next = map_table[n]; map_table[n] = mp; } - return OK; + return mp; } /* @@ -444,6 +446,7 @@ do_map( { char_u *keys; mapblock_T *mp, **mpp; + mapblock_T *mp_result[2] = {NULL, NULL}; char_u *rhs; char_u *p; int n; @@ -844,6 +847,8 @@ do_map( retval = 4; // no mem goto theend; } + if (mp->m_alt != NULL) + mp->m_alt = mp->m_alt->m_alt = NULL; vim_free(mp->m_str); mp->m_str = newstr; vim_free(mp->m_orig_str); @@ -858,6 +863,7 @@ do_map( mp->m_script_ctx = current_sctx; mp->m_script_ctx.sc_lnum += SOURCING_LNUM; #endif + mp_result[keyround - 1] = mp; did_it = TRUE; } } @@ -921,18 +927,25 @@ do_map( continue; // have added the new entry already // Get here when adding a new entry to the maphash[] list or abbrlist. - if (map_add(map_table, abbr_table, keys, rhs, orig_rhs, - noremap, nowait, silent, mode, abbrev, + mp_result[keyround - 1] = map_add(map_table, abbr_table, keys, + rhs, orig_rhs, noremap, nowait, silent, mode, abbrev, #ifdef FEAT_EVAL expr, /* sid */ 0, /* scriptversion */ 0, /* lnum */ 0, #endif - keyround1_simplified) == FAIL) + keyround1_simplified); + if (mp_result[keyround - 1] == NULL) { retval = 4; // no mem goto theend; } } + if (mp_result[0] != NULL && mp_result[1] != NULL) + { + mp_result[0]->m_alt = mp_result[1]; + mp_result[1]->m_alt = mp_result[0]; + } + theend: vim_free(keys_buf); vim_free(alt_keys_buf); @@ -2710,6 +2723,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED) int nowait; char_u *arg; int dict_only; + mapblock_T *mp_result[2] = {NULL, NULL}; // If first arg is a dict, then that's the only arg permitted. dict_only = argvars[0].v_type == VAR_DICT; @@ -2806,12 +2820,20 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED) do_map(MAPTYPE_UNMAP, arg, mode, is_abbr); vim_free(arg); - (void)map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, noremap, - nowait, silent, mode, is_abbr, expr, sid, scriptversion, lnum, 0); + mp_result[0] = map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, + noremap, nowait, silent, mode, is_abbr, expr, sid, + scriptversion, lnum, 0); if (lhsrawalt != NULL) - (void)map_add(map_table, abbr_table, lhsrawalt, rhs, orig_rhs, noremap, - nowait, silent, mode, is_abbr, expr, sid, scriptversion, - lnum, 1); + mp_result[1] = map_add(map_table, abbr_table, lhsrawalt, rhs, orig_rhs, + noremap, nowait, silent, mode, is_abbr, expr, sid, + scriptversion, lnum, 1); + + if (mp_result[0] != NULL && mp_result[1] != NULL) + { + mp_result[0]->m_alt = mp_result[1]; + mp_result[1]->m_alt = mp_result[0]; + } + vim_free(arg_buf); } #endif diff --git a/src/structs.h b/src/structs.h index 32c35b7bf5..fe4704a367 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1309,6 +1309,9 @@ typedef struct mapblock mapblock_T; struct mapblock { mapblock_T *m_next; // next mapblock in list + mapblock_T *m_alt; // pointer to mapblock of the same mapping + // with an alternative form of m_keys, or NULL + // if there is no such mapblock char_u *m_keys; // mapped from, lhs char_u *m_str; // mapped to, rhs char_u *m_orig_str; // rhs as entered by the user diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 1175310465..654a6734e2 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -1767,6 +1767,49 @@ func Test_unmap_simplifiable() unmap <C-I> endfunc +" Test that the first byte of rhs is not remapped if rhs starts with lhs. +func Test_map_rhs_starts_with_lhs() + new + func MapExpr() + return "\<C-R>\<C-P>" + endfunc + + for expr in [v:false, v:true] + if expr + imap <buffer><expr> <C-R> MapExpr() + else + imap <buffer> <C-R> <C-R><C-P> + endif + + for restore in [v:false, v:true] + if restore + let saved = maparg('<C-R>', 'i', v:false, v:true) + iunmap <buffer> <C-R> + call mapset(saved) + endif + + let @a = 'foo' + call feedkeys("S\<C-R>a", 'tx') + call assert_equal('foo', getline('.')) + + let @a = 'bar' + call feedkeys("S\<*C-R>a", 'tx') + call assert_equal('bar', getline('.')) + endfor + endfor + + " When two mappings are used for <C-I> and <Tab>, remapping should work. + imap <buffer> <C-I> <Tab>bar + imap <buffer> <Tab> foo + call feedkeys("S\<Tab>", 'xt') + call assert_equal('foo', getline('.')) + call feedkeys("S\<*C-I>", 'xt') + call assert_equal('foobar', getline('.')) + + delfunc MapExpr + bwipe! +endfunc + func Test_expr_map_escape_special() nnoremap … <Cmd>let g:got_ellipsis += 1<CR> func Func() diff --git a/src/version.c b/src/version.c index 8afbd01487..153685953a 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 642, +/**/ 641, /**/ 640, |