mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
patch 9.0.0449: there is no easy way to translate a key code into a string
Problem: There is no easy way to translate a string with a key code into a readable string. Solution: Add the keytrans() function. (closes #11114)
This commit is contained in:
@ -325,6 +325,8 @@ js_encode({expr}) String encode JS style JSON
|
||||
json_decode({string}) any decode JSON
|
||||
json_encode({expr}) String encode JSON
|
||||
keys({dict}) List keys in {dict}
|
||||
keytrans({string}) String translate internal keycodes to a form
|
||||
that can be used by |:map|
|
||||
len({expr}) Number the length of {expr}
|
||||
libcall({lib}, {func}, {arg}) String call {func} in library {lib} with {arg}
|
||||
libcallnr({lib}, {func}, {arg}) Number idem, but return a Number
|
||||
@ -5205,6 +5207,16 @@ keys({dict}) *keys()*
|
||||
Can also be used as a |method|: >
|
||||
mydict->keys()
|
||||
|
||||
keytrans({string}) *keytrans()*
|
||||
Turn the internal byte representation of keys into a form that
|
||||
can be used for |:map|. E.g. >
|
||||
:let xx = "\<C-Home>"
|
||||
:echo keytrans(xx)
|
||||
< <C-Home>
|
||||
|
||||
Can also be used as a |method|: >
|
||||
"\<C-Home>"->keytrans()
|
||||
|
||||
< *len()* *E701*
|
||||
len({expr}) The result is a Number, which is the length of the argument.
|
||||
When {expr} is a String or a Number the length in bytes is
|
||||
|
@ -89,6 +89,7 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv);
|
||||
static void f_interrupt(typval_T *argvars, typval_T *rettv);
|
||||
static void f_invert(typval_T *argvars, typval_T *rettv);
|
||||
static void f_islocked(typval_T *argvars, typval_T *rettv);
|
||||
static void f_keytrans(typval_T *argvars, typval_T *rettv);
|
||||
static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_libcall(typval_T *argvars, typval_T *rettv);
|
||||
static void f_libcallnr(typval_T *argvars, typval_T *rettv);
|
||||
@ -2058,6 +2059,8 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_json_encode},
|
||||
{"keys", 1, 1, FEARG_1, arg1_dict_any,
|
||||
ret_list_string, f_keys},
|
||||
{"keytrans", 1, 1, FEARG_1, arg1_string,
|
||||
ret_string, f_keytrans},
|
||||
{"last_buffer_nr", 0, 0, 0, NULL, // obsolete
|
||||
ret_number, f_last_buffer_nr},
|
||||
{"len", 1, 1, FEARG_1, arg1_len,
|
||||
@ -7135,6 +7138,24 @@ f_islocked(typval_T *argvars, typval_T *rettv)
|
||||
clear_lval(&lv);
|
||||
}
|
||||
|
||||
/*
|
||||
* "keytrans()" function
|
||||
*/
|
||||
static void
|
||||
f_keytrans(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *escaped;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
if (check_for_string_arg(argvars, 0) == FAIL
|
||||
|| argvars[0].vval.v_string == NULL)
|
||||
return;
|
||||
// Need to escape K_SPECIAL and CSI for mb_unescape().
|
||||
escaped = vim_strsave_escape_csi(argvars[0].vval.v_string);
|
||||
rettv->vval.v_string = str2special_save(escaped, TRUE, TRUE);
|
||||
vim_free(escaped);
|
||||
}
|
||||
|
||||
/*
|
||||
* "last_buffer_nr()" function.
|
||||
*/
|
||||
|
@ -2317,7 +2317,7 @@ mapblock2dict(
|
||||
int buffer_local, // false if not buffer local mapping
|
||||
int abbr) // true if abbreviation
|
||||
{
|
||||
char_u *lhs = str2special_save(mp->m_keys, TRUE);
|
||||
char_u *lhs = str2special_save(mp->m_keys, TRUE, FALSE);
|
||||
char_u *mapmode = map_mode_to_chars(mp->m_mode);
|
||||
|
||||
dict_add_string(dict, "lhs", lhs);
|
||||
@ -2409,7 +2409,7 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
|
||||
if (*rhs == NUL)
|
||||
rettv->vval.v_string = vim_strsave((char_u *)"<Nop>");
|
||||
else
|
||||
rettv->vval.v_string = str2special_save(rhs, FALSE);
|
||||
rettv->vval.v_string = str2special_save(rhs, FALSE, FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
@ -2478,7 +2478,7 @@ f_maplist(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
keys_buf = NULL;
|
||||
did_simplify = FALSE;
|
||||
|
||||
lhs = str2special_save(mp->m_keys, TRUE);
|
||||
lhs = str2special_save(mp->m_keys, TRUE, FALSE);
|
||||
(void)replace_termcodes(lhs, &keys_buf, flags, &did_simplify);
|
||||
vim_free(lhs);
|
||||
|
||||
|
@ -2890,7 +2890,7 @@ menuitem_getinfo(char_u *menu_name, vimmenu_T *menu, int modes, dict_T *dict)
|
||||
*menu->strings[bit] == NUL
|
||||
? (char_u *)"<Nop>"
|
||||
: (tofree = str2special_save(
|
||||
menu->strings[bit], FALSE)));
|
||||
menu->strings[bit], FALSE, FALSE)));
|
||||
vim_free(tofree);
|
||||
}
|
||||
if (status == OK)
|
||||
|
@ -1759,7 +1759,7 @@ msg_outtrans_special(
|
||||
++str;
|
||||
}
|
||||
else
|
||||
text = (char *)str2special(&str, from);
|
||||
text = (char *)str2special(&str, from, FALSE);
|
||||
if (text[0] != NUL && text[1] == NUL)
|
||||
// single-byte character or illegal byte
|
||||
text = (char *)transchar_byte((char_u)text[0]);
|
||||
@ -1782,14 +1782,16 @@ msg_outtrans_special(
|
||||
char_u *
|
||||
str2special_save(
|
||||
char_u *str,
|
||||
int is_lhs) // TRUE for lhs, FALSE for rhs
|
||||
int replace_spaces, // TRUE to replace " " with "<Space>".
|
||||
// used for the lhs of mapping and keytrans().
|
||||
int replace_lt) // TRUE to replace "<" with "<lt>".
|
||||
{
|
||||
garray_T ga;
|
||||
char_u *p = str;
|
||||
|
||||
ga_init2(&ga, 1, 40);
|
||||
while (*p != NUL)
|
||||
ga_concat(&ga, str2special(&p, is_lhs));
|
||||
ga_concat(&ga, str2special(&p, replace_spaces, replace_lt));
|
||||
ga_append(&ga, NUL);
|
||||
return (char_u *)ga.ga_data;
|
||||
}
|
||||
@ -1804,7 +1806,9 @@ str2special_save(
|
||||
char_u *
|
||||
str2special(
|
||||
char_u **sp,
|
||||
int from) // TRUE for lhs of mapping
|
||||
int replace_spaces, // TRUE to replace " " with "<Space>".
|
||||
// used for the lhs of mapping and keytrans().
|
||||
int replace_lt) // TRUE to replace "<" with "<lt>".
|
||||
{
|
||||
int c;
|
||||
static char_u buf[7];
|
||||
@ -1861,8 +1865,10 @@ str2special(
|
||||
*sp = str + (*str == NUL ? 0 : 1);
|
||||
|
||||
// Make special keys and C0 control characters in <> form, also <M-Space>.
|
||||
// Use <Space> only for lhs of a mapping.
|
||||
if (special || c < ' ' || (from && c == ' '))
|
||||
if (special
|
||||
|| c < ' '
|
||||
|| (replace_spaces && c == ' ')
|
||||
|| (replace_lt && c == '<'))
|
||||
return get_special_key_name(c, modifiers);
|
||||
buf[0] = c;
|
||||
buf[1] = NUL;
|
||||
@ -1880,7 +1886,7 @@ str2specialbuf(char_u *sp, char_u *buf, int len)
|
||||
*buf = NUL;
|
||||
while (*sp)
|
||||
{
|
||||
s = str2special(&sp, FALSE);
|
||||
s = str2special(&sp, FALSE, FALSE);
|
||||
if ((int)(STRLEN(s) + STRLEN(buf)) < len)
|
||||
STRCAT(buf, s);
|
||||
}
|
||||
|
@ -3994,7 +3994,8 @@ get_option_value(
|
||||
if (stringval != NULL)
|
||||
{
|
||||
if ((char_u **)varp == &p_pt) // 'pastetoggle'
|
||||
*stringval = str2special_save(*(char_u **)(varp), FALSE);
|
||||
*stringval = str2special_save(*(char_u **)(varp), FALSE,
|
||||
FALSE);
|
||||
#ifdef FEAT_CRYPT
|
||||
// never return the value of the crypt key
|
||||
else if ((char_u **)varp == &curbuf->b_p_key
|
||||
@ -4879,7 +4880,7 @@ put_setstring(
|
||||
{
|
||||
s = *valuep;
|
||||
while (*s != NUL)
|
||||
if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
|
||||
if (put_escstr(fd, str2special(&s, FALSE, FALSE), 2) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
// expand the option value, replace $HOME by ~
|
||||
|
@ -37,8 +37,8 @@ char_u *msg_outtrans_one(char_u *p, int attr);
|
||||
int msg_outtrans_len_attr(char_u *msgstr, int len, int attr);
|
||||
void msg_make(char_u *arg);
|
||||
int msg_outtrans_special(char_u *strstart, int from, int maxlen);
|
||||
char_u *str2special_save(char_u *str, int is_lhs);
|
||||
char_u *str2special(char_u **sp, int from);
|
||||
char_u *str2special_save(char_u *str, int replace_spaces, int replace_lt);
|
||||
char_u *str2special(char_u **sp, int replace_spaces, int replace_lt);
|
||||
void str2specialbuf(char_u *sp, char_u *buf, int len);
|
||||
void msg_prt_line(char_u *s, int list);
|
||||
void msg_puts(char *s);
|
||||
|
@ -2764,6 +2764,32 @@ func Test_eval()
|
||||
call assert_fails("call eval('5 a')", 'E488:')
|
||||
endfunc
|
||||
|
||||
" Test for the keytrans() function
|
||||
func Test_keytrans()
|
||||
call assert_equal('<Space>', keytrans(' '))
|
||||
call assert_equal('<lt>', keytrans('<'))
|
||||
call assert_equal('<lt>Tab>', keytrans('<Tab>'))
|
||||
call assert_equal('<Tab>', keytrans("\<Tab>"))
|
||||
call assert_equal('<C-V>', keytrans("\<C-V>"))
|
||||
call assert_equal('<BS>', keytrans("\<BS>"))
|
||||
call assert_equal('<Home>', keytrans("\<Home>"))
|
||||
call assert_equal('<C-Home>', keytrans("\<C-Home>"))
|
||||
call assert_equal('<M-Home>', keytrans("\<M-Home>"))
|
||||
call assert_equal('<C-Space>', keytrans("\<C-Space>"))
|
||||
call assert_equal('<M-Space>', keytrans("\<*M-Space>"))
|
||||
call assert_equal('<M-x>', "\<*M-x>"->keytrans())
|
||||
call assert_equal('<C-I>', "\<*C-I>"->keytrans())
|
||||
call assert_equal('<S-3>', "\<*S-3>"->keytrans())
|
||||
call assert_equal('π', 'π'->keytrans())
|
||||
call assert_equal('<M-π>', "\<M-π>"->keytrans())
|
||||
call assert_equal('ě', 'ě'->keytrans())
|
||||
call assert_equal('<M-ě>', "\<M-ě>"->keytrans())
|
||||
call assert_equal('', ''->keytrans())
|
||||
call assert_equal('', test_null_string()->keytrans())
|
||||
call assert_fails('call keytrans(1)', 'E1174:')
|
||||
call assert_fails('call keytrans()', 'E119:')
|
||||
endfunc
|
||||
|
||||
" Test for the nr2char() function
|
||||
func Test_nr2char()
|
||||
set encoding=latin1
|
||||
|
@ -703,6 +703,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
449,
|
||||
/**/
|
||||
448,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user