To: vim_dev@googlegroups.com Subject: Patch 9.0.0449 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0449 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) Files: runtime/doc/builtin.txt, runtime/doc/usr_41.txt, src/evalfunc.c, src/map.c, src/menu.c, src/message.c, src/option.c, src/proto/message.pro, src/testdir/test_functions.vim *** ../vim-9.0.0448/runtime/doc/builtin.txt 2022-09-09 18:46:41.558660414 +0100 --- runtime/doc/builtin.txt 2022-09-12 13:28:33.439747660 +0100 *************** *** 325,330 **** --- 325,332 ---- 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 *************** *** 5195,5200 **** --- 5207,5222 ---- 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 = "\" + :echo keytrans(xx) + < + + Can also be used as a |method|: > + "\"->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 *** ../vim-9.0.0448/runtime/doc/usr_41.txt 2022-08-27 12:22:19.975008573 +0100 --- runtime/doc/usr_41.txt 2022-09-12 13:28:33.439747660 +0100 *************** *** 736,741 **** --- 737,744 ---- fnameescape() escape a file name for use with a Vim command tr() translate characters from one set to another strtrans() translate a string to make it printable + keytrans() translate internal keycodes to a form that + can be used by |:map| tolower() turn a string to lowercase toupper() turn a string to uppercase charclass() class of a character *************** *** 1349,1355 **** did_filetype() check if a FileType autocommand was used eventhandler() check if invoked by an event handler getpid() get process ID of Vim ! getscriptinfo() get list of sourced vim scripts getimstatus() check if IME status is active interrupt() interrupt script execution windowsversion() get MS-Windows version --- 1352,1358 ---- did_filetype() check if a FileType autocommand was used eventhandler() check if invoked by an event handler getpid() get process ID of Vim ! getscriptinfo() get list of sourced vim scripts getimstatus() check if IME status is active interrupt() interrupt script execution windowsversion() get MS-Windows version *** ../vim-9.0.0448/src/evalfunc.c 2022-09-09 18:46:41.558660414 +0100 --- src/evalfunc.c 2022-09-12 13:28:33.439747660 +0100 *************** *** 89,94 **** --- 89,95 ---- 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,2063 **** --- 2059,2066 ---- 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, *************** *** 7136,7141 **** --- 7139,7162 ---- } /* + * "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. */ static void *** ../vim-9.0.0448/src/map.c 2022-08-31 16:40:14.250932016 +0100 --- src/map.c 2022-09-12 13:28:33.439747660 +0100 *************** *** 2317,2323 **** 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 *mapmode = map_mode_to_chars(mp->m_mode); dict_add_string(dict, "lhs", lhs); --- 2317,2323 ---- int buffer_local, // false if not buffer local mapping int abbr) // true if abbreviation { ! 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,2415 **** if (*rhs == NUL) rettv->vval.v_string = vim_strsave((char_u *)""); else ! rettv->vval.v_string = str2special_save(rhs, FALSE); } } --- 2409,2415 ---- if (*rhs == NUL) rettv->vval.v_string = vim_strsave((char_u *)""); else ! rettv->vval.v_string = str2special_save(rhs, FALSE, FALSE); } } *************** *** 2478,2484 **** keys_buf = NULL; did_simplify = FALSE; ! lhs = str2special_save(mp->m_keys, TRUE); (void)replace_termcodes(lhs, &keys_buf, flags, &did_simplify); vim_free(lhs); --- 2478,2484 ---- keys_buf = NULL; did_simplify = FALSE; ! lhs = str2special_save(mp->m_keys, TRUE, FALSE); (void)replace_termcodes(lhs, &keys_buf, flags, &did_simplify); vim_free(lhs); *** ../vim-9.0.0448/src/menu.c 2022-08-14 14:16:07.995582211 +0100 --- src/menu.c 2022-09-12 13:28:33.443747653 +0100 *************** *** 2890,2896 **** *menu->strings[bit] == NUL ? (char_u *)"" : (tofree = str2special_save( ! menu->strings[bit], FALSE))); vim_free(tofree); } if (status == OK) --- 2890,2896 ---- *menu->strings[bit] == NUL ? (char_u *)"" : (tofree = str2special_save( ! menu->strings[bit], FALSE, FALSE))); vim_free(tofree); } if (status == OK) *** ../vim-9.0.0448/src/message.c 2022-09-11 21:35:47.554255165 +0100 --- src/message.c 2022-09-12 13:28:33.443747653 +0100 *************** *** 1759,1765 **** ++str; } else ! text = (char *)str2special(&str, from); if (text[0] != NUL && text[1] == NUL) // single-byte character or illegal byte text = (char *)transchar_byte((char_u)text[0]); --- 1759,1765 ---- ++str; } else ! 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,1795 **** char_u * str2special_save( 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; } --- 1782,1797 ---- char_u * str2special_save( char_u *str, ! int replace_spaces, // TRUE to replace " " with "". ! // used for the lhs of mapping and keytrans(). ! int replace_lt) // TRUE to replace "<" with "". { garray_T ga; char_u *p = str; ga_init2(&ga, 1, 40); while (*p != NUL) ! ga_concat(&ga, str2special(&p, replace_spaces, replace_lt)); ga_append(&ga, NUL); return (char_u *)ga.ga_data; } *************** *** 1804,1810 **** char_u * str2special( char_u **sp, ! int from) // TRUE for lhs of mapping { int c; static char_u buf[7]; --- 1806,1814 ---- char_u * str2special( char_u **sp, ! int replace_spaces, // TRUE to replace " " with "". ! // used for the lhs of mapping and keytrans(). ! int replace_lt) // TRUE to replace "<" with "". { int c; static char_u buf[7]; *************** *** 1861,1868 **** *sp = str + (*str == NUL ? 0 : 1); // Make special keys and C0 control characters in <> form, also . ! // Use only for lhs of a mapping. ! if (special || c < ' ' || (from && c == ' ')) return get_special_key_name(c, modifiers); buf[0] = c; buf[1] = NUL; --- 1865,1874 ---- *sp = str + (*str == NUL ? 0 : 1); // Make special keys and C0 control characters in <> form, also . ! if (special ! || c < ' ' ! || (replace_spaces && c == ' ') ! || (replace_lt && c == '<')) return get_special_key_name(c, modifiers); buf[0] = c; buf[1] = NUL; *************** *** 1880,1886 **** *buf = NUL; while (*sp) { ! s = str2special(&sp, FALSE); if ((int)(STRLEN(s) + STRLEN(buf)) < len) STRCAT(buf, s); } --- 1886,1892 ---- *buf = NUL; while (*sp) { ! s = str2special(&sp, FALSE, FALSE); if ((int)(STRLEN(s) + STRLEN(buf)) < len) STRCAT(buf, s); } *** ../vim-9.0.0448/src/option.c 2022-08-31 14:46:07.911016920 +0100 --- src/option.c 2022-09-12 13:28:33.443747653 +0100 *************** *** 3994,4000 **** if (stringval != NULL) { if ((char_u **)varp == &p_pt) // 'pastetoggle' ! *stringval = str2special_save(*(char_u **)(varp), FALSE); #ifdef FEAT_CRYPT // never return the value of the crypt key else if ((char_u **)varp == &curbuf->b_p_key --- 3994,4001 ---- if (stringval != NULL) { if ((char_u **)varp == &p_pt) // 'pastetoggle' ! *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,4885 **** { s = *valuep; while (*s != NUL) ! if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL) return FAIL; } // expand the option value, replace $HOME by ~ --- 4880,4886 ---- { s = *valuep; while (*s != NUL) ! if (put_escstr(fd, str2special(&s, FALSE, FALSE), 2) == FAIL) return FAIL; } // expand the option value, replace $HOME by ~ *** ../vim-9.0.0448/src/proto/message.pro 2022-08-31 14:46:07.907016957 +0100 --- src/proto/message.pro 2022-09-12 13:28:33.443747653 +0100 *************** *** 37,44 **** 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); void str2specialbuf(char_u *sp, char_u *buf, int len); void msg_prt_line(char_u *s, int list); void msg_puts(char *s); --- 37,44 ---- 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 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); *** ../vim-9.0.0448/src/testdir/test_functions.vim 2022-09-02 21:55:45.503049444 +0100 --- src/testdir/test_functions.vim 2022-09-12 13:28:33.443747653 +0100 *************** *** 2764,2769 **** --- 2764,2795 ---- call assert_fails("call eval('5 a')", 'E488:') endfunc + " Test for the keytrans() function + func Test_keytrans() + call assert_equal('', keytrans(' ')) + call assert_equal('', keytrans('<')) + call assert_equal('Tab>', keytrans('')) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\")) + call assert_equal('', keytrans("\<*M-Space>")) + call assert_equal('', "\<*M-x>"->keytrans()) + call assert_equal('', "\<*C-I>"->keytrans()) + call assert_equal('', "\<*S-3>"->keytrans()) + call assert_equal('π', 'π'->keytrans()) + call assert_equal('', "\"->keytrans()) + call assert_equal('ě', 'ě'->keytrans()) + call assert_equal('', "\"->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 *** ../vim-9.0.0448/src/version.c 2022-09-12 12:43:20.289108044 +0100 --- src/version.c 2022-09-12 13:34:23.159037194 +0100 *************** *** 705,706 **** --- 705,708 ---- { /* Add new patch number below this line */ + /**/ + 449, /**/ -- hundred-and-one symptoms of being an internet addict: 49. You never have to deal with busy signals when calling your ISP...because you never log off. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///