1
0
forked from aniani/vim

updated for version 7.3.032

Problem:    maparg() doesn't return the flags, such as <buffer>, <script>,
            <silent>.  These are needed to save and restore a mapping.
Solution:   Improve maparg(). (also by Christian Brabandt)
This commit is contained in:
Bram Moolenaar
2010-10-20 21:23:33 +02:00
parent 727c876b78
commit bd74325960
11 changed files with 196 additions and 74 deletions

View File

@@ -1827,7 +1827,7 @@ localtime() Number current time
log( {expr}) Float natural logarithm (base e) of {expr} log( {expr}) Float natural logarithm (base e) of {expr}
log10( {expr}) Float logarithm of Float {expr} to base 10 log10( {expr}) Float logarithm of Float {expr} to base 10
map( {expr}, {string}) List/Dict change each item in {expr} to {expr} map( {expr}, {string}) List/Dict change each item in {expr} to {expr}
maparg( {name}[, {mode} [, {abbr}]]) maparg( {name}[, {mode} [, {abbr} [, {dict}]]])
String rhs of mapping {name} in mode {mode} String rhs of mapping {name} in mode {mode}
mapcheck( {name}[, {mode} [, {abbr}]]) mapcheck( {name}[, {mode} [, {abbr}]])
String check for mappings matching {name} String check for mappings matching {name}
@@ -3972,23 +3972,51 @@ map({expr}, {string}) *map()*
further items in {expr} are processed. further items in {expr} are processed.
maparg({name}[, {mode} [, {abbr}]]) *maparg()* maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()*
Return the rhs of mapping {name} in mode {mode}. When there When {dict} is omitted or zero: Return the rhs of mapping
is no mapping for {name}, an empty String is returned. {name} in mode {mode}. The returned String has special
characters translated like in the output of the ":map" command
listing.
When there is no mapping for {name}, an empty String is
returned.
The {name} can have special key names, like in the ":map"
command.
{mode} can be one of these strings: {mode} can be one of these strings:
"n" Normal "n" Normal
"v" Visual "v" Visual (including Select)
"o" Operator-pending "o" Operator-pending
"i" Insert "i" Insert
"c" Cmd-line "c" Cmd-line
"s" Select
"x" Visual
"l" langmap |language-mapping| "l" langmap |language-mapping|
"" Normal, Visual and Operator-pending "" Normal, Visual and Operator-pending
When {mode} is omitted, the modes for "" are used. When {mode} is omitted, the modes for "" are used.
When {abbr} is there and it is non-zero use abbreviations When {abbr} is there and it is non-zero use abbreviations
instead of mappings. instead of mappings.
The {name} can have special key names, like in the ":map"
command. The returned String has special characters When {dict} is there and it is non-zero return a dictionary
translated like in the output of the ":map" command listing. containing all the information of the mapping with the
following items:
"lhs" The {lhs} of the mapping.
"rhs" The {rhs} of the mapping as typed.
"silent" 1 for a |:map-silent| mapping, else 0.
"noremap" 1 if the {rhs} of the mapping is remappable.
"expr" 1 for an expression mapping (|:map-<expr>|).
"buffer" 1 for a buffer local mapping (|:map-local|).
"mode" Modes for which the mapping is defined. In
addition to the modes mentioned above, these
characters will be used:
" " Normal, Visual and Operator-pending
"!" Insert and Commandline mode
(|mapmpde-ic|)
"sid" the Script local ID, used for <sid> mappings
(|<SID>|)
The mappings local to the current buffer are checked first, The mappings local to the current buffer are checked first,
then the global mappings. then the global mappings.
This function can be used to map a key even when it's already This function can be used to map a key even when it's already

View File

@@ -7804,7 +7804,7 @@ static struct fst
{"log10", 1, 1, f_log10}, {"log10", 1, 1, f_log10},
#endif #endif
{"map", 2, 2, f_map}, {"map", 2, 2, f_map},
{"maparg", 1, 3, f_maparg}, {"maparg", 1, 4, f_maparg},
{"mapcheck", 1, 3, f_mapcheck}, {"mapcheck", 1, 3, f_mapcheck},
{"match", 2, 4, f_match}, {"match", 2, 4, f_match},
{"matchadd", 2, 4, f_matchadd}, {"matchadd", 2, 4, f_matchadd},
@@ -13292,8 +13292,10 @@ get_maparg(argvars, rettv, exact)
char_u *keys_buf = NULL; char_u *keys_buf = NULL;
char_u *rhs; char_u *rhs;
int mode; int mode;
garray_T ga;
int abbr = FALSE; int abbr = FALSE;
int get_dict = FALSE;
mapblock_T *mp;
int buffer_local;
/* return empty string for failure */ /* return empty string for failure */
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
@@ -13307,7 +13309,11 @@ get_maparg(argvars, rettv, exact)
{ {
which = get_tv_string_buf_chk(&argvars[1], buf); which = get_tv_string_buf_chk(&argvars[1], buf);
if (argvars[2].v_type != VAR_UNKNOWN) if (argvars[2].v_type != VAR_UNKNOWN)
{
abbr = get_tv_number(&argvars[2]); abbr = get_tv_number(&argvars[2]);
if (argvars[3].v_type != VAR_UNKNOWN)
get_dict = get_tv_number(&argvars[3]);
}
} }
else else
which = (char_u *)""; which = (char_u *)"";
@@ -13317,19 +13323,34 @@ get_maparg(argvars, rettv, exact)
mode = get_map_mode(&which, 0); mode = get_map_mode(&which, 0);
keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
rhs = check_map(keys, mode, exact, FALSE, abbr); rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
vim_free(keys_buf); vim_free(keys_buf);
if (rhs != NULL)
if (!get_dict)
{ {
ga_init(&ga); /* Return a string. */
ga.ga_itemsize = 1; if (rhs != NULL)
ga.ga_growsize = 40; rettv->vval.v_string = str2special_save(rhs, FALSE);
while (*rhs != NUL) }
ga_concat(&ga, str2special(&rhs, FALSE)); else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
{
/* Return a dictionary. */
char_u *lhs = str2special_save(mp->m_keys, TRUE);
char_u *mapmode = map_mode_to_chars(mp->m_mode);
dict_T *dict = rettv->vval.v_dict;
ga_append(&ga, NUL); dict_add_nr_str(dict, "lhs", 0L, lhs);
rettv->vval.v_string = (char_u *)ga.ga_data; dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL);
dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL);
dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL);
dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
dict_add_nr_str(dict, "mode", 0L, mapmode);
vim_free(lhs);
vim_free(mapmode);
} }
} }

View File

@@ -3168,6 +3168,7 @@ do_map(maptype, arg, mode, abbrev)
int expr = FALSE; int expr = FALSE;
#endif #endif
int noremap; int noremap;
char_u *orig_rhs;
keys = arg; keys = arg;
map_table = maphash; map_table = maphash;
@@ -3266,6 +3267,7 @@ do_map(maptype, arg, mode, abbrev)
} }
if (*p != NUL) if (*p != NUL)
*p++ = NUL; *p++ = NUL;
p = skipwhite(p); p = skipwhite(p);
rhs = p; rhs = p;
hasarg = (*rhs != NUL); hasarg = (*rhs != NUL);
@@ -3290,6 +3292,7 @@ do_map(maptype, arg, mode, abbrev)
keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special); keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special);
if (hasarg) if (hasarg)
{ {
orig_rhs = rhs;
if (STRICMP(rhs, "<nop>") == 0) /* "<Nop>" means nothing */ if (STRICMP(rhs, "<nop>") == 0) /* "<Nop>" means nothing */
rhs = (char_u *)""; rhs = (char_u *)"";
else else
@@ -3298,7 +3301,7 @@ do_map(maptype, arg, mode, abbrev)
#ifdef FEAT_FKMAP #ifdef FEAT_FKMAP
/* /*
* when in right-to-left mode and alternate keymap option set, * When in right-to-left mode and alternate keymap option set,
* reverse the character flow in the rhs in Farsi. * reverse the character flow in the rhs in Farsi.
*/ */
if (p_altkeymap && curwin->w_p_rl) if (p_altkeymap && curwin->w_p_rl)
@@ -3556,6 +3559,8 @@ do_map(maptype, arg, mode, abbrev)
} }
vim_free(mp->m_str); vim_free(mp->m_str);
mp->m_str = newstr; mp->m_str = newstr;
vim_free(mp->m_orig_str);
mp->m_orig_str = vim_strsave(orig_rhs);
mp->m_noremap = noremap; mp->m_noremap = noremap;
mp->m_silent = silent; mp->m_silent = silent;
mp->m_mode = mode; mp->m_mode = mode;
@@ -3633,10 +3638,12 @@ do_map(maptype, arg, mode, abbrev)
mp->m_keys = vim_strsave(keys); mp->m_keys = vim_strsave(keys);
mp->m_str = vim_strsave(rhs); mp->m_str = vim_strsave(rhs);
mp->m_orig_str = vim_strsave(orig_rhs);
if (mp->m_keys == NULL || mp->m_str == NULL) if (mp->m_keys == NULL || mp->m_str == NULL)
{ {
vim_free(mp->m_keys); vim_free(mp->m_keys);
vim_free(mp->m_str); vim_free(mp->m_str);
vim_free(mp->m_orig_str);
vim_free(mp); vim_free(mp);
retval = 4; /* no mem */ retval = 4; /* no mem */
goto theend; goto theend;
@@ -3682,6 +3689,7 @@ map_free(mpp)
mp = *mpp; mp = *mpp;
vim_free(mp->m_keys); vim_free(mp->m_keys);
vim_free(mp->m_str); vim_free(mp->m_str);
vim_free(mp->m_orig_str);
*mpp = mp->m_next; *mpp = mp->m_next;
vim_free(mp); vim_free(mp);
} }
@@ -3851,12 +3859,57 @@ map_clear_int(buf, mode, local, abbr)
} }
} }
/*
* Return characters to represent the map mode in an allocated string.
* Returns NULL when out of memory.
*/
char_u *
map_mode_to_chars(mode)
int mode;
{
garray_T mapmode;
ga_init2(&mapmode, 1, 7);
if ((mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
ga_append(&mapmode, '!'); /* :map! */
else if (mode & INSERT)
ga_append(&mapmode, 'i'); /* :imap */
else if (mode & LANGMAP)
ga_append(&mapmode, 'l'); /* :lmap */
else if (mode & CMDLINE)
ga_append(&mapmode, 'c'); /* :cmap */
else if ((mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING))
== NORMAL + VISUAL + SELECTMODE + OP_PENDING)
ga_append(&mapmode, ' '); /* :map */
else
{
if (mode & NORMAL)
ga_append(&mapmode, 'n'); /* :nmap */
if (mode & OP_PENDING)
ga_append(&mapmode, 'o'); /* :omap */
if ((mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE)
ga_append(&mapmode, 'v'); /* :vmap */
else
{
if (mode & VISUAL)
ga_append(&mapmode, 'x'); /* :xmap */
if (mode & SELECTMODE)
ga_append(&mapmode, 's'); /* :smap */
}
}
ga_append(&mapmode, NUL);
return (char_u *)mapmode.ga_data;
}
static void static void
showmap(mp, local) showmap(mp, local)
mapblock_T *mp; mapblock_T *mp;
int local; /* TRUE for buffer-local map */ int local; /* TRUE for buffer-local map */
{ {
int len = 1; int len = 1;
char_u *mapchars;
if (msg_didout || msg_silent != 0) if (msg_didout || msg_silent != 0)
{ {
@@ -3864,49 +3917,15 @@ showmap(mp, local)
if (got_int) /* 'q' typed at MORE prompt */ if (got_int) /* 'q' typed at MORE prompt */
return; return;
} }
if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
msg_putchar('!'); /* :map! */ mapchars = map_mode_to_chars(mp->m_mode);
else if (mp->m_mode & INSERT) if (mapchars != NULL)
msg_putchar('i'); /* :imap */
else if (mp->m_mode & LANGMAP)
msg_putchar('l'); /* :lmap */
else if (mp->m_mode & CMDLINE)
msg_putchar('c'); /* :cmap */
else if ((mp->m_mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING))
== NORMAL + VISUAL + SELECTMODE + OP_PENDING)
msg_putchar(' '); /* :map */
else
{ {
len = 0; msg_puts(mapchars);
if (mp->m_mode & NORMAL) len = STRLEN(mapchars);
{ vim_free(mapchars);
msg_putchar('n'); /* :nmap */
++len;
}
if (mp->m_mode & OP_PENDING)
{
msg_putchar('o'); /* :omap */
++len;
}
if ((mp->m_mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE)
{
msg_putchar('v'); /* :vmap */
++len;
}
else
{
if (mp->m_mode & VISUAL)
{
msg_putchar('x'); /* :xmap */
++len;
}
if (mp->m_mode & SELECTMODE)
{
msg_putchar('s'); /* :smap */
++len;
}
}
} }
while (++len <= 3) while (++len <= 3)
msg_putchar(' '); msg_putchar(' ');
@@ -3931,8 +3950,7 @@ showmap(mp, local)
msg_putchar(' '); msg_putchar(' ');
/* Use FALSE below if we only want things like <Up> to show up as such on /* Use FALSE below if we only want things like <Up> to show up as such on
* the rhs, and not M-x etc, TRUE gets both -- webb * the rhs, and not M-x etc, TRUE gets both -- webb */
*/
if (*mp->m_str == NUL) if (*mp->m_str == NUL)
msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8)); msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
else else
@@ -4995,19 +5013,21 @@ check_map_keycodes()
sourcing_name = save_name; sourcing_name = save_name;
} }
#ifdef FEAT_EVAL #if defined(FEAT_EVAL) || defined(PROTO)
/* /*
* Check the string "keys" against the lhs of all mappings * Check the string "keys" against the lhs of all mappings.
* Return pointer to rhs of mapping (mapblock->m_str) * Return pointer to rhs of mapping (mapblock->m_str).
* NULL otherwise * NULL when no mapping found.
*/ */
char_u * char_u *
check_map(keys, mode, exact, ign_mod, abbr) check_map(keys, mode, exact, ign_mod, abbr, mp_ptr, local_ptr)
char_u *keys; char_u *keys;
int mode; int mode;
int exact; /* require exact match */ int exact; /* require exact match */
int ign_mod; /* ignore preceding modifier */ int ign_mod; /* ignore preceding modifier */
int abbr; /* do abbreviations */ int abbr; /* do abbreviations */
mapblock_T **mp_ptr; /* return: pointer to mapblock or NULL */
int *local_ptr; /* return: buffer-local mapping or NULL */
{ {
int hash; int hash;
int len, minlen; int len, minlen;
@@ -5062,10 +5082,16 @@ check_map(keys, mode, exact, ign_mod, abbr)
minlen = mp->m_keylen - 3; minlen = mp->m_keylen - 3;
} }
if (STRNCMP(s, keys, minlen) == 0) if (STRNCMP(s, keys, minlen) == 0)
{
if (mp_ptr != NULL)
*mp_ptr = mp;
if (local_ptr != NULL)
*local_ptr = local;
return mp->m_str; return mp->m_str;
} }
} }
} }
}
return NULL; return NULL;
} }

View File

@@ -1810,7 +1810,8 @@ process_message(void)
* mapped we want to use the mapping instead. */ * mapped we want to use the mapping instead. */
if (vk == VK_F10 if (vk == VK_F10
&& gui.menu_is_active && gui.menu_is_active
&& check_map(k10, State, FALSE, TRUE, FALSE) == NULL) && check_map(k10, State, FALSE, TRUE, FALSE,
NULL, NULL) == NULL)
break; break;
#endif #endif
if (GetKeyState(VK_SHIFT) & 0x8000) if (GetKeyState(VK_SHIFT) & 0x8000)
@@ -1924,7 +1925,8 @@ process_message(void)
/* Check for <F10>: Default effect is to select the menu. When <F10> is /* Check for <F10>: Default effect is to select the menu. When <F10> is
* mapped we need to stop it here to avoid strange effects (e.g., for the * mapped we need to stop it here to avoid strange effects (e.g., for the
* key-up event) */ * key-up event) */
if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE) == NULL) if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE,
NULL, NULL) == NULL)
#endif #endif
DispatchMessage(&msg); DispatchMessage(&msg);
} }

View File

@@ -1477,6 +1477,27 @@ msg_outtrans_special(strstart, from)
return retval; return retval;
} }
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the lhs or rhs of a mapping, with the key codes turned into printable
* strings, in an allocated string.
*/
char_u *
str2special_save(str, is_lhs)
char_u *str;
int is_lhs; /* TRUE for lhs, FALSE for rhs */
{
garray_T ga;
char_u *p = str;
ga_init2(&ga, 1, 40);
while (*p != NUL)
ga_concat(&ga, str2special(&p, is_lhs));
ga_append(&ga, NUL);
return (char_u *)ga.ga_data;
}
#endif
/* /*
* Return the printable string for the key codes at "*sp". * Return the printable string for the key codes at "*sp".
* Used for translating the lhs or rhs of a mapping to printable chars. * Used for translating the lhs or rhs of a mapping to printable chars.

View File

@@ -51,6 +51,7 @@ int do_map __ARGS((int maptype, char_u *arg, int mode, int abbrev));
int get_map_mode __ARGS((char_u **cmdp, int forceit)); int get_map_mode __ARGS((char_u **cmdp, int forceit));
void map_clear __ARGS((char_u *cmdp, char_u *arg, int forceit, int abbr)); void map_clear __ARGS((char_u *cmdp, char_u *arg, int forceit, int abbr));
void map_clear_int __ARGS((buf_T *buf, int mode, int local, int abbr)); void map_clear_int __ARGS((buf_T *buf, int mode, int local, int abbr));
char_u *map_mode_to_chars __ARGS((int mode));
int map_to_exists __ARGS((char_u *str, char_u *modechars, int abbr)); int map_to_exists __ARGS((char_u *str, char_u *modechars, int abbr));
int map_to_exists_mode __ARGS((char_u *rhs, int mode, int abbr)); int map_to_exists_mode __ARGS((char_u *rhs, int mode, int abbr));
char_u *set_context_in_map_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx)); char_u *set_context_in_map_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx));
@@ -61,7 +62,7 @@ void vim_unescape_csi __ARGS((char_u *p));
int makemap __ARGS((FILE *fd, buf_T *buf)); int makemap __ARGS((FILE *fd, buf_T *buf));
int put_escstr __ARGS((FILE *fd, char_u *strstart, int what)); int put_escstr __ARGS((FILE *fd, char_u *strstart, int what));
void check_map_keycodes __ARGS((void)); void check_map_keycodes __ARGS((void));
char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr)); char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr, mapblock_T **mp_ptr, int *local_ptr));
void init_mappings __ARGS((void)); void init_mappings __ARGS((void));
void add_map __ARGS((char_u *map, int mode)); void add_map __ARGS((char_u *map, int mode));
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@@ -33,6 +33,7 @@ char_u *msg_outtrans_one __ARGS((char_u *p, int attr));
int msg_outtrans_len_attr __ARGS((char_u *msgstr, int len, int attr)); int msg_outtrans_len_attr __ARGS((char_u *msgstr, int len, int attr));
void msg_make __ARGS((char_u *arg)); void msg_make __ARGS((char_u *arg));
int msg_outtrans_special __ARGS((char_u *strstart, int from)); int msg_outtrans_special __ARGS((char_u *strstart, int from));
char_u *str2special_save __ARGS((char_u *str, int is_lhs));
char_u *str2special __ARGS((char_u **sp, int from)); char_u *str2special __ARGS((char_u **sp, int from));
void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len)); void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len));
void msg_prt_line __ARGS((char_u *s, int list)); void msg_prt_line __ARGS((char_u *s, int list));

View File

@@ -979,9 +979,10 @@ typedef struct mapblock mapblock_T;
struct mapblock struct mapblock
{ {
mapblock_T *m_next; /* next mapblock in list */ mapblock_T *m_next; /* next mapblock in list */
char_u *m_keys; /* mapped from */ char_u *m_keys; /* mapped from, lhs */
int m_keylen; /* strlen(m_keys) */ int m_keylen; /* strlen(m_keys) */
char_u *m_str; /* mapped to */ char_u *m_str; /* mapped to, rhs */
char_u *m_orig_str; /* rhs as entered by the user */
int m_mode; /* valid mode */ int m_mode; /* valid mode */
int m_noremap; /* if non-zero no re-mapping for m_str */ int m_noremap; /* if non-zero no re-mapping for m_str */
char m_silent; /* <silent> used, don't echo commands */ char m_silent; /* <silent> used, don't echo commands */

16
src/testdir/test75.in Normal file
View File

@@ -0,0 +1,16 @@
" Tests for functions.
STARTTEST
:so small.vim
:" Test maparg() with a string result
:map foo<C-V> is<F4>foo
:vnoremap <script> <buffer> <expr> <silent> bar isbar
:call append('$', maparg('foo<C-V>'))
:call append('$', string(maparg('foo<C-V>', '', 0, 1)))
:call append('$', string(maparg('bar', '', 0, 1)))
:"
:/^eof/+1,$w! test.out
:qa!
ENDTEST
eof

3
src/testdir/test75.ok Normal file
View File

@@ -0,0 +1,3 @@
is<F4>foo
{'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0}
{'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1}

View File

@@ -714,6 +714,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 */
/**/
32,
/**/ /**/
31, 31,
/**/ /**/