Patch 8.2.2957

6 views
Skip to first unread message

Bram Moolenaar

unread,
Jun 7, 2021, 12:30:23 PM6/7/21
to vim...@googlegroups.com

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 <expr> , 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 -- Br...@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 ///
Reply all
Reply to author
Forward
0 new messages