diff src/eval.c @ 7935:3f2e0b62003d v7.4.1263

commit https://github.com/vim/vim/commit/4d919d748e4e435edb135aa5ccf6ee7de9212023 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Feb 5 22:36:41 2016 +0100 patch 7.4.1263 Problem: ch_open() hangs when the server isn't running. Solution: Add a timeout. Use a dict to pass arguments. (Yasuhiro Matsumoto)
author Christian Brabandt <cb@256bit.org>
date Fri, 05 Feb 2016 22:45:06 +0100
parents 1f0743f4f88f
children 2e905dfc6999
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -8005,7 +8005,7 @@ static struct fst
 #endif
 #ifdef FEAT_CHANNEL
     {"ch_close",	1, 1, f_ch_close},
-    {"ch_open",		2, 3, f_ch_open},
+    {"ch_open",		1, 2, f_ch_open},
     {"ch_sendexpr",	2, 3, f_ch_sendexpr},
     {"ch_sendraw",	2, 3, f_ch_sendraw},
 #endif
@@ -9743,21 +9743,23 @@ f_ch_open(typval_T *argvars, typval_T *r
     char_u	*address;
     char_u	*mode;
     char_u	*callback = NULL;
-    char_u	buf1[NUMBUFLEN];
     char_u	*p;
+    char	*rest;
     int		port;
-    int		json_mode = FALSE;
+    int		waittime = 0;
+    int		timeout = 2000;
+    int		json_mode = TRUE;
+    int		ch_idx;
 
     /* default: fail */
     rettv->vval.v_number = -1;
 
     address = get_tv_string(&argvars[0]);
-    mode = get_tv_string_buf(&argvars[1], buf1);
-    if (argvars[2].v_type != VAR_UNKNOWN)
-    {
-	callback = get_callback(&argvars[2]);
-	if (callback == NULL)
-	    return;
+    if (argvars[1].v_type != VAR_UNKNOWN
+	 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL))
+    {
+	EMSG(_(e_invarg));
+	return;
     }
 
     /* parse address */
@@ -9768,30 +9770,52 @@ f_ch_open(typval_T *argvars, typval_T *r
 	return;
     }
     *p++ = NUL;
-    port = atoi((char *)p);
-    if (*address == NUL || port <= 0)
+    port = strtol((char *)p, &rest, 10);
+    if (*address == NUL || port <= 0 || *rest != NUL)
     {
 	p[-1] = ':';
 	EMSG2(_(e_invarg2), address);
 	return;
     }
 
-    /* parse mode */
-    if (STRCMP(mode, "json") == 0)
-	json_mode = TRUE;
-    else if (STRCMP(mode, "raw") != 0)
-    {
-	EMSG2(_(e_invarg2), mode);
-	return;
-    }
-
-    rettv->vval.v_number = channel_open((char *)address, port, NULL);
-    if (rettv->vval.v_number >= 0)
-    {
-	channel_set_json_mode(rettv->vval.v_number, json_mode);
+    if (argvars[1].v_type == VAR_DICT)
+    {
+	/* parse argdict */
+	dict_T	*dict = argvars[1].vval.v_dict;
+
+	if (dict_find(dict, (char_u *)"mode", -1) != NULL)
+	{
+	    mode = get_dict_string(dict, (char_u *)"mode", FALSE);
+	    if (STRCMP(mode, "raw") == 0)
+		json_mode = FALSE;
+	    else if (STRCMP(mode, "json") != 0)
+	    {
+		EMSG2(_(e_invarg2), mode);
+		return;
+	    }
+	}
+	if (dict_find(dict, (char_u *)"waittime", -1) != NULL)
+	    waittime = get_dict_number(dict, (char_u *)"waittime");
+	if (dict_find(dict, (char_u *)"timeout", -1) != NULL)
+	    timeout = get_dict_number(dict, (char_u *)"timeout");
+	if (dict_find(dict, (char_u *)"callback", -1) != NULL)
+	    callback = get_dict_string(dict, (char_u *)"callback", FALSE);
+    }
+    if (waittime < 0 || timeout < 0)
+    {
+	EMSG(_(e_invarg));
+	return;
+    }
+
+    ch_idx = channel_open((char *)address, port, waittime, NULL);
+    if (ch_idx >= 0)
+    {
+	channel_set_json_mode(ch_idx, json_mode);
+	channel_set_timeout(ch_idx, timeout);
 	if (callback != NULL && *callback != NUL)
-	    channel_set_callback(rettv->vval.v_number, callback);
-    }
+	    channel_set_callback(ch_idx, callback);
+    }
+    rettv->vval.v_number = ch_idx;
 }
 
 /*