changeset 20213:8d9229c4781a v8.2.0662

patch 8.2.0662: cannot use input() in a channel callback Commit: https://github.com/vim/vim/commit/dfc33a665d3b12689aa971575b8e7de4e5202d83 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Apr 29 22:30:13 2020 +0200 patch 8.2.0662: cannot use input() in a channel callback Problem: Cannot use input() in a channel callback. Solution: Reset vgetc_busy. (closes https://github.com/vim/vim/issues/6010)
author Bram Moolenaar <Bram@vim.org>
date Wed, 29 Apr 2020 22:45:04 +0200
parents 234d86d5f2d0
children 124eaf1822b5
files src/evalfunc.c src/ex_getln.c src/globals.h src/testdir/test_channel.vim src/version.c
diffstat 5 files changed, 34 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -2149,7 +2149,7 @@ f_eval(typval_T *argvars, typval_T *rett
     static void
 f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv)
 {
-    rettv->vval.v_number = vgetc_busy;
+    rettv->vval.v_number = vgetc_busy || input_busy;
 }
 
 static garray_T	redir_execute_ga;
@@ -2566,7 +2566,7 @@ f_feedkeys(typval_T *argvars, typval_T *
 #ifdef FEAT_TIMERS
 			|| timer_busy
 #endif
-			)
+			|| input_busy)
 		    typebuf_was_filled = TRUE;
 	    }
 	    vim_free(keys_esc);
@@ -2887,7 +2887,7 @@ f_funcref(typval_T *argvars, typval_T *r
 }
 
     static type_T *
-ret_f_function(int argcount, type_T **argtypes UNUSED)
+ret_f_function(int argcount, type_T **argtypes)
 {
     if (argcount == 1 && argtypes[0]->tt_type == VAR_STRING)
 	return &t_func_any;
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -4468,6 +4468,8 @@ get_user_input(
 
     rettv->v_type = VAR_STRING;
     rettv->vval.v_string = NULL;
+    if (input_busy)
+	return;  // this doesn't work recursively.
 
 #ifdef NO_CONSOLE_INPUT
     // While starting up, there is no place to enter text. When running tests
@@ -4528,12 +4530,18 @@ get_user_input(
 	if (defstr != NULL)
 	{
 	    int save_ex_normal_busy = ex_normal_busy;
-
+	    int save_vgetc_busy = vgetc_busy;
+	    int save_input_busy = input_busy;
+
+	    input_busy |= vgetc_busy;
 	    ex_normal_busy = 0;
+	    vgetc_busy = 0;
 	    rettv->vval.v_string =
 		getcmdline_prompt(secret ? NUL : '@', p, get_echo_attr(),
 							      xp_type, xp_arg);
 	    ex_normal_busy = save_ex_normal_busy;
+	    vgetc_busy = save_vgetc_busy;
+	    input_busy = save_input_busy;
 	}
 	if (inputdialog && rettv->vval.v_string == NULL
 		&& argvars[1].v_type != VAR_UNKNOWN
--- a/src/globals.h
+++ b/src/globals.h
@@ -1814,6 +1814,9 @@ EXTERN int  in_free_unref_items INIT(= F
 EXTERN int  did_add_timer INIT(= FALSE);
 EXTERN int  timer_busy INIT(= 0);   // when timer is inside vgetc() then > 0
 #endif
+#ifdef FEAT_EVAL
+EXTERN int  input_busy INIT(= 0);   // when inside get_user_input() then > 0
+#endif
 
 #ifdef FEAT_BEVAL_TERM
 EXTERN int  bevalexpr_due_set INIT(= FALSE);
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -6,6 +6,7 @@ CheckFeature channel
 
 source shared.vim
 source screendump.vim
+source view_util.vim
 
 let s:python = PythonProg()
 if s:python == ''
@@ -2297,4 +2298,20 @@ func Test_job_with_list_args()
   %bw!
 endfunc
 
+func ExitCb_cb_with_input(job, status)
+  call feedkeys(":\<C-u>echo input('', 'default')\<CR>\<CR>", 'nx')
+  call assert_equal('default', Screenline(&lines))
+  let g:wait_exit_cb = 0
+endfunc
+
+func Test_cb_with_input()
+  let g:wait_exit_cb = 1
+
+  call job_start('echo "Vim''s test"',
+        \ {'out_cb': 'ExitCb_cb_with_input'})
+  call WaitForAssert({-> assert_equal(0, g:wait_exit_cb)})
+
+  unlet g:wait_exit_cb
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    662,
+/**/
     661,
 /**/
     660,