summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-06-07 18:29:17 +0200
committerBram Moolenaar <Bram@vim.org>2021-06-07 18:29:17 +0200
commit3a7503c34c65ed15cc08deb5b54aaf2ea51525b4 (patch)
treedaa9ac7e436c54459ab4971578929dc0b30779be
parentf05d2fc539c389c3b8142d9fb06fb0443de14902 (diff)
downloadvim-git-3a7503c34c65ed15cc08deb5b54aaf2ea51525b4.tar.gz
patch 8.2.2957: using getchar() in Vim9 script is problematicv8.2.2957
Problem: Using getchar() in Vim9 script is problematic. Solution: Add getcharstr(). (closes #8343)
-rw-r--r--runtime/doc/eval.txt19
-rw-r--r--src/evalfunc.c4
-rw-r--r--src/getchar.c42
-rw-r--r--src/proto/getchar.pro1
-rw-r--r--src/testdir/test_functions.vim7
-rw-r--r--src/version.c2
6 files changed, 70 insertions, 5 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 890943810..97585ad6c 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2594,10 +2594,12 @@ getbufline({expr}, {lnum} [, {end}])
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
+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
@@ -5232,6 +5234,7 @@ getchar([expr]) *getchar()*
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
@@ -5357,6 +5360,20 @@ getcharsearch() *getcharsearch()*
: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
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 07f158d6d..d08cf43d8 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -945,13 +945,15 @@ static funcentry_T global_functions[] =
{"getchangelist", 0, 1, FEARG_1, NULL,
ret_list_any, f_getchangelist},
{"getchar", 0, 1, 0, NULL,
- ret_number, f_getchar},
+ 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,
diff --git a/src/getchar.c b/src/getchar.c
index 185b73bdb..3b069c438 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2016,10 +2016,10 @@ char_avail(void)
#if defined(FEAT_EVAL) || defined(PROTO)
/*
- * "getchar()" function
+ * "getchar()" and "getcharstr()" functions
*/
- void
-f_getchar(typval_T *argvars, typval_T *rettv)
+ static void
+getchar_common(typval_T *argvars, typval_T *rettv)
{
varnumber_T n;
int error = FALSE;
@@ -2127,6 +2127,42 @@ f_getchar(typval_T *argvars, typval_T *rettv)
}
/*
+ * "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
*/
void
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index cb8b7507e..25aef1c01 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -46,6 +46,7 @@ int vpeekc_nomap(void);
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);
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 023da66ba..130955439 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -1729,6 +1729,13 @@ endfunc
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)
diff --git a/src/version.c b/src/version.c
index b64839e5c..a1b2c2360 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2957,
+/**/
2956,
/**/
2955,