@@ -510,6 +510,7 @@ static void f_ch_open(typval_T *argvars, typval_T *rettv);
510510static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
511511static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
512512static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
513+ static void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
513514static void f_ch_status(typval_T *argvars, typval_T *rettv);
514515#endif
515516static void f_changenr(typval_T *argvars, typval_T *rettv);
@@ -8131,6 +8132,7 @@ static struct fst
81318132 {"ch_readraw", 1, 2, f_ch_readraw},
81328133 {"ch_sendexpr", 2, 3, f_ch_sendexpr},
81338134 {"ch_sendraw", 2, 3, f_ch_sendraw},
8135+ {"ch_setoptions", 2, 2, f_ch_setoptions},
81348136 {"ch_status", 1, 1, f_ch_status},
81358137#endif
81368138 {"changenr", 0, 0, f_changenr},
@@ -9870,44 +9872,91 @@ get_callback(typval_T *arg)
98709872}
98719873
98729874/*
9873- * Get the option entries from "dict", and parse them.
9875+ * Get the option entries from the dict in "tv", parse them and put the result
9876+ * in "opt".
9877+ * Only accept options in "supported".
98749878 * If an option value is invalid return FAIL.
98759879 */
98769880 static int
9877- get_job_options(dict_T *dict , jobopt_T *opt)
9881+ get_job_options(typval_T *tv , jobopt_T *opt, int supported )
98789882{
9879- dictitem_T *item;
9883+ typval_T *item;
98809884 char_u *mode;
9885+ dict_T *dict;
9886+ int todo;
9887+ hashitem_T *hi;
98819888
9889+ if (tv->v_type == VAR_UNKNOWN)
9890+ return OK;
9891+ if (tv->v_type != VAR_DICT)
9892+ {
9893+ EMSG(_(e_invarg));
9894+ return FAIL;
9895+ }
9896+ dict = tv->vval.v_dict;
98829897 if (dict == NULL)
98839898 return OK;
98849899
9885- if ((item = dict_find(dict, (char_u *)"mode", -1)) != NULL)
9886- {
9887- mode = get_tv_string(&item->di_tv);
9888- if (STRCMP(mode, "nl") == 0)
9889- opt->jo_mode = MODE_NL;
9890- else if (STRCMP(mode, "raw") == 0)
9891- opt->jo_mode = MODE_RAW;
9892- else if (STRCMP(mode, "js") == 0)
9893- opt->jo_mode = MODE_JS;
9894- else if (STRCMP(mode, "json") == 0)
9895- opt->jo_mode = MODE_JSON;
9896- else
9900+ todo = (int)dict->dv_hashtab.ht_used;
9901+ for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
9902+ if (!HASHITEM_EMPTY(hi))
98979903 {
9898- EMSG2(_(e_invarg2), mode);
9899- return FAIL;
9900- }
9901- }
9904+ item = &HI2DI(hi)->di_tv;
99029905
9903- if ((item = dict_find(dict, (char_u *)"callback", -1)) != NULL)
9904- {
9905- opt->jo_callback = get_callback(&item->di_tv);
9906- if (opt->jo_callback == NULL)
9907- {
9908- EMSG2(_(e_invarg2), "callback");
9909- return FAIL;
9906+ if (STRCMP(hi->hi_key, "mode") == 0)
9907+ {
9908+ if (!(supported & JO_MODE))
9909+ break;
9910+ opt->jo_set |= JO_MODE;
9911+ mode = get_tv_string(item);
9912+ if (STRCMP(mode, "nl") == 0)
9913+ opt->jo_mode = MODE_NL;
9914+ else if (STRCMP(mode, "raw") == 0)
9915+ opt->jo_mode = MODE_RAW;
9916+ else if (STRCMP(mode, "js") == 0)
9917+ opt->jo_mode = MODE_JS;
9918+ else if (STRCMP(mode, "json") == 0)
9919+ opt->jo_mode = MODE_JSON;
9920+ else
9921+ {
9922+ EMSG2(_(e_invarg2), mode);
9923+ return FAIL;
9924+ }
9925+ }
9926+ else if (STRCMP(hi->hi_key, "callback") == 0)
9927+ {
9928+ if (!(supported & JO_CALLBACK))
9929+ break;
9930+ opt->jo_set |= JO_CALLBACK;
9931+ opt->jo_callback = get_callback(item);
9932+ if (opt->jo_callback == NULL)
9933+ {
9934+ EMSG2(_(e_invarg2), "callback");
9935+ return FAIL;
9936+ }
9937+ }
9938+ else if (STRCMP(hi->hi_key, "waittime") == 0)
9939+ {
9940+ if (!(supported & JO_WAITTIME))
9941+ break;
9942+ opt->jo_set |= JO_WAITTIME;
9943+ opt->jo_waittime = get_tv_number(item);
9944+ }
9945+ else if (STRCMP(hi->hi_key, "timeout") == 0)
9946+ {
9947+ if (!(supported & JO_TIMEOUT))
9948+ break;
9949+ opt->jo_set |= JO_TIMEOUT;
9950+ opt->jo_timeout = get_tv_number(item);
9951+ }
9952+ else
9953+ break;
9954+ --todo;
99109955 }
9956+ if (todo > 0)
9957+ {
9958+ EMSG2(_(e_invarg2), hi->hi_key);
9959+ return FAIL;
99119960 }
99129961
99139962 return OK;
@@ -10002,9 +10051,7 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
1000210051 char_u *p;
1000310052 char *rest;
1000410053 int port;
10005- int waittime = 0;
10006- int timeout = 2000;
10007- jobopt_T options;
10054+ jobopt_T opt;
1000810055 channel_T *channel;
1000910056
1001010057 /* default: fail */
@@ -10035,33 +10082,26 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
1003510082 return;
1003610083 }
1003710084
10038- options.jo_mode = MODE_JSON;
10039- options.jo_callback = NULL;
10040- if (argvars[1].v_type == VAR_DICT)
10041- {
10042- dict_T *dict = argvars[1].vval.v_dict;
10043- dictitem_T *item;
10044-
10045- /* parse argdict */
10046- if (get_job_options(dict, &options) == FAIL)
10047- return;
10048- if ((item = dict_find(dict, (char_u *)"waittime", -1)) != NULL)
10049- waittime = get_tv_number(&item->di_tv);
10050- if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL)
10051- timeout = get_tv_number(&item->di_tv);
10052- }
10053- if (timeout < 0)
10085+ /* parse options */
10086+ opt.jo_mode = MODE_JSON;
10087+ opt.jo_callback = NULL;
10088+ opt.jo_waittime = 0;
10089+ opt.jo_timeout = 2000;
10090+ if (get_job_options(&argvars[1], &opt,
10091+ JO_MODE + JO_CALLBACK + JO_WAITTIME + JO_TIMEOUT) == FAIL)
10092+ return;
10093+ if (opt.jo_timeout < 0)
1005410094 {
1005510095 EMSG(_(e_invarg));
1005610096 return;
1005710097 }
1005810098
10059- channel = channel_open((char *)address, port, waittime , NULL);
10099+ channel = channel_open((char *)address, port, opt.jo_waittime , NULL);
1006010100 if (channel != NULL)
1006110101 {
1006210102 rettv->vval.v_channel = channel;
10063- channel_set_options(channel, &options) ;
10064- channel_set_timeout (channel, timeout );
10103+ opt.jo_set = JO_ALL ;
10104+ channel_set_options (channel, &opt );
1006510105 }
1006610106}
1006710107
@@ -10077,30 +10117,13 @@ f_ch_readraw(typval_T *argvars, typval_T *rettv)
1007710117 rettv->v_type = VAR_STRING;
1007810118 rettv->vval.v_string = NULL;
1007910119
10120+ /* TODO: use timeout from the options */
10121+
1008010122 channel = get_channel_arg(&argvars[0]);
1008110123 if (channel != NULL)
1008210124 rettv->vval.v_string = channel_read_block(channel);
1008310125}
1008410126
10085- /*
10086- * "ch_status()" function
10087- */
10088- static void
10089- f_ch_status(typval_T *argvars, typval_T *rettv)
10090- {
10091- /* return an empty string by default */
10092- rettv->v_type = VAR_STRING;
10093-
10094- if (argvars[0].v_type != VAR_CHANNEL)
10095- {
10096- EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
10097- rettv->vval.v_string = NULL;
10098- }
10099- else
10100- rettv->vval.v_string = vim_strsave(
10101- (char_u *)channel_status(argvars[0].vval.v_channel));
10102- }
10103-
1010410127/*
1010510128 * common for "sendexpr()" and "sendraw()"
1010610129 * Returns the channel if the caller should read the response.
@@ -10110,31 +10133,22 @@ f_ch_status(typval_T *argvars, typval_T *rettv)
1011010133send_common(typval_T *argvars, char_u *text, int id, char *fun)
1011110134{
1011210135 channel_T *channel;
10113- char_u *callback = NULL;
10114- jobopt_T options;
10136+ jobopt_T opt;
1011510137
1011610138 channel = get_channel_arg(&argvars[0]);
1011710139 if (channel == NULL)
1011810140 return NULL;
1011910141
10120- if (argvars[2].v_type != VAR_UNKNOWN)
10121- {
10122- if (argvars[2].v_type != VAR_DICT)
10123- {
10124- EMSG(_(e_invarg));
10125- return NULL;
10126- }
10127- options.jo_callback = NULL;
10128- if (get_job_options(argvars[2].vval.v_dict, &options) == FAIL)
10129- return NULL;
10130- callback = options.jo_callback;
10131- }
10142+ opt.jo_callback = NULL;
10143+ if (get_job_options(&argvars[2], &opt, JO_CALLBACK) == FAIL)
10144+ return NULL;
10145+
1013210146 /* Set the callback. An empty callback means no callback and not reading
1013310147 * the response. */
10134- if (callback != NULL && *callback != NUL)
10135- channel_set_req_callback(channel, callback , id);
10148+ if (opt.jo_callback != NULL && *opt.jo_callback != NUL)
10149+ channel_set_req_callback(channel, opt.jo_callback , id);
1013610150
10137- if (channel_send(channel, text, fun) == OK && callback == NULL)
10151+ if (channel_send(channel, text, fun) == OK && opt.jo_callback == NULL)
1013810152 return channel;
1013910153 return NULL;
1014010154}
@@ -10208,6 +10222,42 @@ f_ch_sendraw(typval_T *argvars, typval_T *rettv)
1020810222 if (channel != NULL)
1020910223 rettv->vval.v_string = channel_read_block(channel);
1021010224}
10225+
10226+ /*
10227+ * "ch_setoptions()" function
10228+ */
10229+ static void
10230+ f_ch_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
10231+ {
10232+ channel_T *channel;
10233+ jobopt_T opt;
10234+
10235+ channel = get_channel_arg(&argvars[0]);
10236+ if (channel == NULL)
10237+ return;
10238+ if (get_job_options(&argvars[1], &opt, JO_CALLBACK + JO_TIMEOUT) == FAIL)
10239+ return NULL;
10240+ channel_set_options(channel, &opt);
10241+ }
10242+
10243+ /*
10244+ * "ch_status()" function
10245+ */
10246+ static void
10247+ f_ch_status(typval_T *argvars, typval_T *rettv)
10248+ {
10249+ /* return an empty string by default */
10250+ rettv->v_type = VAR_STRING;
10251+
10252+ if (argvars[0].v_type != VAR_CHANNEL)
10253+ {
10254+ EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
10255+ rettv->vval.v_string = NULL;
10256+ }
10257+ else
10258+ rettv->vval.v_string = vim_strsave(
10259+ (char_u *)channel_status(argvars[0].vval.v_channel));
10260+ }
1021110261#endif
1021210262
1021310263/*
@@ -14535,7 +14585,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1453514585#else
1453614586 garray_T ga;
1453714587#endif
14538- jobopt_T options ;
14588+ jobopt_T opt ;
1453914589
1454014590 rettv->v_type = VAR_JOB;
1454114591 job = job_alloc();
@@ -14546,18 +14596,10 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1454614596 rettv->vval.v_job->jv_status = JOB_FAILED;
1454714597
1454814598 /* Default mode is NL. */
14549- options.jo_mode = MODE_NL;
14550- options.jo_callback = NULL;
14551- if (argvars[1].v_type != VAR_UNKNOWN)
14552- {
14553- if (argvars[1].v_type != VAR_DICT)
14554- {
14555- EMSG(_(e_invarg));
14556- return;
14557- }
14558- if (get_job_options(argvars[1].vval.v_dict, &options) == FAIL)
14559- return;
14560- }
14599+ opt.jo_mode = MODE_NL;
14600+ opt.jo_callback = NULL;
14601+ if (get_job_options(&argvars[1], &opt, JO_MODE + JO_CALLBACK) == FAIL)
14602+ return;
1456114603
1456214604#ifndef USE_ARGV
1456314605 ga_init2(&ga, (int)sizeof(char*), 20);
@@ -14639,12 +14681,12 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1463914681 ga_clear(&ga);
1464014682 }
1464114683# endif
14642- mch_start_job(argv, job, &options );
14684+ mch_start_job(argv, job, &opt );
1464314685#else
1464414686# ifdef FEAT_CHANNEL
1464514687 ch_logs(NULL, "Starting job: %s", (char *)cmd);
1464614688# endif
14647- mch_start_job((char *)cmd, job, &options );
14689+ mch_start_job((char *)cmd, job, &opt );
1464814690#endif
1464914691
1465014692theend:
0 commit comments