To: vim_dev@googlegroups.com Subject: Patch 8.2.2957 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2957 Problem: Using getchar() in Vim9 script is problematic. Solution: Add getcharstr(). (closes #8343) Files: runtime/doc/eval.txt, src/evalfunc.c, src/getchar.c, src/proto/getchar.pro, src/testdir/test_getchar.vim *** ../vim-8.2.2956/runtime/doc/eval.txt 2021-04-02 18:55:52.058322772 +0200 --- runtime/doc/eval.txt 2021-06-07 18:16:30.065813629 +0200 *************** *** 2588,2597 **** getbufvar({expr}, {varname} [, {def}]) any variable {varname} in buffer {expr} getchangelist([{expr}]) List list of change list items ! getchar([expr]) Number get one character from the user getcharmod() Number modifiers for the last typed character getcharpos({expr}) List position of cursor, mark, etc. getcharsearch() Dict last character search getcmdline() String return the current command-line getcmdpos() Number return cursor position in command-line getcmdtype() String return current command-line type --- 2594,2605 ---- getbufvar({expr}, {varname} [, {def}]) any variable {varname} in buffer {expr} getchangelist([{expr}]) List list of change list items ! getchar([expr]) Number or String ! get one character from the user getcharmod() Number modifiers for the last typed character getcharpos({expr}) List position of cursor, mark, etc. getcharsearch() Dict last character search + getcharstr([expr]) String get one character from the user getcmdline() String return the current command-line getcmdpos() Number return cursor position in command-line getcmdtype() String return current command-line type *************** *** 5219,5224 **** --- 5234,5240 ---- Return zero otherwise. If [expr] is 1, only check if a character is available, it is not consumed. Return zero if no character available. + If you prefer always getting a string use |getcharstr()|. Without [expr] and when [expr] is 0 a whole character or special key is returned. If it is a single character, the *************** *** 5312,5317 **** --- 5328,5336 ---- Get the position for {expr}. Same as |getpos()| but the column number in the returned List is a character index instead of a byte index. + If |getpos()| returns a very large column number, such as + 2147483647, then getcharpos() will return the character index + of the last character. Example: With the cursor on '세' in line 5 with text "여보세요": > *************** *** 5341,5346 **** --- 5360,5379 ---- :nnoremap , getcharsearch().forward ? ',' : ';' < Also see |setcharsearch()|. + + getcharstr([expr]) *getcharstr()* + Get a single character from the user or input stream as a + string. + If [expr] is omitted, wait until a character is available. + If [expr] is 0 or false, only get a character when one is + available. Return an empty string otherwise. + If [expr] is 1 or true, only check if a character is + available, it is not consumed. Return an empty string + if no character is available. + Otherwise this works like |getchar()|, except that a number + result is converted to a string. + + getcmdline() *getcmdline()* Return the current command-line. Only works when the command line is being edited, thus requires use of |c_CTRL-\_e| or *** ../vim-8.2.2956/src/evalfunc.c 2021-06-06 14:14:35.348774346 +0200 --- src/evalfunc.c 2021-06-07 18:17:54.129617644 +0200 *************** *** 945,957 **** {"getchangelist", 0, 1, FEARG_1, NULL, ret_list_any, f_getchangelist}, {"getchar", 0, 1, 0, NULL, ! ret_number, f_getchar}, {"getcharmod", 0, 0, 0, NULL, ret_number, f_getcharmod}, {"getcharpos", 1, 1, FEARG_1, NULL, ret_list_number, f_getcharpos}, {"getcharsearch", 0, 0, 0, NULL, ret_dict_any, f_getcharsearch}, {"getcmdline", 0, 0, 0, NULL, ret_string, f_getcmdline}, {"getcmdpos", 0, 0, 0, NULL, --- 945,959 ---- {"getchangelist", 0, 1, FEARG_1, NULL, ret_list_any, f_getchangelist}, {"getchar", 0, 1, 0, NULL, ! ret_any, f_getchar}, {"getcharmod", 0, 0, 0, NULL, ret_number, f_getcharmod}, {"getcharpos", 1, 1, FEARG_1, NULL, ret_list_number, f_getcharpos}, {"getcharsearch", 0, 0, 0, NULL, ret_dict_any, f_getcharsearch}, + {"getcharstr", 0, 1, 0, NULL, + ret_string, f_getcharstr}, {"getcmdline", 0, 0, 0, NULL, ret_string, f_getcmdline}, {"getcmdpos", 0, 0, 0, NULL, *** ../vim-8.2.2956/src/getchar.c 2021-05-05 19:58:12.921605195 +0200 --- src/getchar.c 2021-06-07 18:23:45.340787101 +0200 *************** *** 2016,2025 **** #if defined(FEAT_EVAL) || defined(PROTO) /* ! * "getchar()" function */ ! void ! f_getchar(typval_T *argvars, typval_T *rettv) { varnumber_T n; int error = FALSE; --- 2016,2025 ---- #if defined(FEAT_EVAL) || defined(PROTO) /* ! * "getchar()" and "getcharstr()" functions */ ! static void ! getchar_common(typval_T *argvars, typval_T *rettv) { varnumber_T n; int error = FALSE; *************** *** 2126,2131 **** --- 2126,2167 ---- } } + /* + * "getchar()" function + */ + void + f_getchar(typval_T *argvars, typval_T *rettv) + { + getchar_common(argvars, rettv); + } + + /* + * "getcharstr()" function + */ + void + f_getcharstr(typval_T *argvars, typval_T *rettv) + { + getchar_common(argvars, rettv); + + if (rettv->v_type == VAR_NUMBER) + { + char_u temp[7]; // mbyte-char: 6, NUL: 1 + varnumber_T n = rettv->vval.v_number; + int i = 0; + + if (n != 0) + { + if (has_mbyte) + i += (*mb_char2bytes)(n, temp + i); + else + temp[i++] = n; + } + temp[i++] = NUL; + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strsave(temp); + } + } + /* * "getcharmod()" function */ *** ../vim-8.2.2956/src/proto/getchar.pro 2020-11-12 14:20:32.025927280 +0100 --- src/proto/getchar.pro 2021-06-07 18:23:23.188839918 +0200 *************** *** 46,51 **** --- 46,52 ---- int vpeekc_any(void); int char_avail(void); void f_getchar(typval_T *argvars, typval_T *rettv); + void f_getcharstr(typval_T *argvars, typval_T *rettv); void f_getcharmod(typval_T *argvars, typval_T *rettv); void parse_queued_messages(void); void vungetc(int c); *** ../vim-8.2.2956/src/testdir/test_functions.vim 2021-06-06 14:14:35.352774336 +0200 --- src/testdir/test_functions.vim 2021-06-07 18:26:08.496444798 +0200 *************** *** 1729,1734 **** --- 1729,1741 ---- func Test_getchar() call feedkeys('a', '') call assert_equal(char2nr('a'), getchar()) + call assert_equal(0, getchar(0)) + call assert_equal(0, getchar(1)) + + call feedkeys('a', '') + call assert_equal('a', getcharstr()) + call assert_equal('', getcharstr(0)) + call assert_equal('', getcharstr(1)) call setline(1, 'xxxx') call test_setmouse(1, 3) *** ../vim-8.2.2956/src/version.c 2021-06-06 22:02:12.594908500 +0200 --- src/version.c 2021-06-07 18:22:57.576900929 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2957, /**/ -- This message contains 78% recycled characters. /// 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 ///