]> granicus.if.org Git - vim/commitdiff
patch 8.2.2957: using getchar() in Vim9 script is problematic v8.2.2957
authorBram Moolenaar <Bram@vim.org>
Mon, 7 Jun 2021 16:29:17 +0000 (18:29 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 7 Jun 2021 16:29:17 +0000 (18:29 +0200)
Problem:    Using getchar() in Vim9 script is problematic.
Solution:   Add getcharstr(). (closes #8343)

runtime/doc/eval.txt
src/evalfunc.c
src/getchar.c
src/proto/getchar.pro
src/testdir/test_functions.vim
src/version.c

index 890943810dd57cc47a712a2e03c7f9885c9aebbe..97585ad6c59ca8fc4c529c4e3774cab02d3763dc 100644 (file)
@@ -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
index 07f158d6d7337a4afbbd13d3d548c9fa6a8b83b1..d08cf43d823680911ea3ebbdd833fd7a147ff498 100644 (file)
@@ -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,
index 185b73bdb02765b46446df11e99d17aa99e3f7f5..3b069c4386ead10577b57426076ec325d001d4af 100644 (file)
@@ -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;
@@ -2126,6 +2126,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
  */
index cb8b7507e14d24b4e893892a3d885f452118b7d9..25aef1c01af636f50b6020f7742dc0f7dae662cc 100644 (file)
@@ -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);
index 023da66ba14570b4914fe5e5b6a9af2fcd10ddf4..1309554395316cb006ef52802a32b3465b4c2f72 100644 (file)
@@ -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)
index b64839e5cd6bb64ef64018b33600aef306162679..a1b2c2360080145e9763f51f29db04d6c2c4c251 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2957,
 /**/
     2956,
 /**/