Skip to content

Commit 40ea1da

Browse files
committed
patch 7.4.1356
Problem: Job and channel options parsing is scattered. Solution: Move all option value parsing to get_job_options();
1 parent ed5a78e commit 40ea1da

File tree

6 files changed

+167
-123
lines changed

6 files changed

+167
-123
lines changed

src/channel.c

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -748,24 +748,6 @@ channel_set_job(channel_T *channel, job_T *job)
748748
channel->ch_job = job;
749749
}
750750

751-
/*
752-
* Set the mode of channel "channel" to "mode".
753-
*/
754-
void
755-
channel_set_mode(channel_T *channel, ch_mode_T mode)
756-
{
757-
channel->ch_mode = mode;
758-
}
759-
760-
/*
761-
* Set the read timeout of channel "channel".
762-
*/
763-
void
764-
channel_set_timeout(channel_T *channel, int timeout)
765-
{
766-
channel->ch_timeout = timeout;
767-
}
768-
769751
/*
770752
* Set the callback for channel "channel".
771753
*/
@@ -782,9 +764,13 @@ channel_set_callback(channel_T *channel, char_u *callback)
782764
void
783765
channel_set_options(channel_T *channel, jobopt_T *options)
784766
{
785-
channel_set_mode(channel, options->jo_mode);
767+
if (options->jo_set & JO_MODE)
768+
channel->ch_mode = options->jo_mode;
769+
if (options->jo_set & JO_TIMEOUT)
770+
channel->ch_timeout = options->jo_timeout;
786771

787-
if (options->jo_callback != NULL && *options->jo_callback != NUL)
772+
if ((options->jo_set & JO_CALLBACK)
773+
&& options->jo_callback != NULL && *options->jo_callback != NUL)
788774
channel_set_callback(channel, options->jo_callback);
789775
}
790776

src/eval.c

Lines changed: 141 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ static void f_ch_open(typval_T *argvars, typval_T *rettv);
510510
static void f_ch_readraw(typval_T *argvars, typval_T *rettv);
511511
static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv);
512512
static void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
513+
static void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
513514
static void f_ch_status(typval_T *argvars, typval_T *rettv);
514515
#endif
515516
static 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)
1011010133
send_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

1465014692
theend:

0 commit comments

Comments
 (0)