@@ -451,9 +451,6 @@ static dict_T *dict_copy(dict_T *orig, int deep, int copyID);
451451static long dict_len(dict_T *d);
452452static char_u *dict2string(typval_T *tv, int copyID);
453453static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate);
454- #ifdef FEAT_JOB
455- static void job_free(job_T *job);
456- #endif
457454static char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
458455static char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
459456static char_u *string_quote(char_u *str, int function);
@@ -633,6 +630,7 @@ static void f_items(typval_T *argvars, typval_T *rettv);
633630# ifdef FEAT_CHANNEL
634631static void f_job_getchannel(typval_T *argvars, typval_T *rettv);
635632# endif
633+ static void f_job_setoptions(typval_T *argvars, typval_T *rettv);
636634static void f_job_start(typval_T *argvars, typval_T *rettv);
637635static void f_job_stop(typval_T *argvars, typval_T *rettv);
638636static void f_job_status(typval_T *argvars, typval_T *rettv);
@@ -7751,7 +7749,9 @@ channel_unref(channel_T *channel)
77517749}
77527750#endif
77537751
7754- #ifdef FEAT_JOB
7752+ #if defined(FEAT_JOB) || defined(PROTO)
7753+ static job_T *first_job = NULL;
7754+
77557755 static void
77567756job_free(job_T *job)
77577757{
@@ -7765,6 +7765,15 @@ job_free(job_T *job)
77657765 }
77667766# endif
77677767 mch_clear_job(job);
7768+
7769+ if (job->jv_next != NULL)
7770+ job->jv_next->jv_prev = job->jv_prev;
7771+ if (job->jv_prev == NULL)
7772+ first_job = job->jv_next;
7773+ else
7774+ job->jv_prev->jv_next = job->jv_next;
7775+
7776+ vim_free(job->jv_stoponexit);
77687777 vim_free(job);
77697778}
77707779
@@ -7776,7 +7785,7 @@ job_unref(job_T *job)
77767785}
77777786
77787787/*
7779- * Allocate a job. Sets the refcount to one.
7788+ * Allocate a job. Sets the refcount to one and sets options default .
77807789 */
77817790 static job_T *
77827791job_alloc(void)
@@ -7785,10 +7794,45 @@ job_alloc(void)
77857794
77867795 job = (job_T *)alloc_clear(sizeof(job_T));
77877796 if (job != NULL)
7797+ {
77887798 job->jv_refcount = 1;
7799+ job->jv_stoponexit = vim_strsave((char_u *)"term");
7800+
7801+ if (first_job != NULL)
7802+ {
7803+ first_job->jv_prev = job;
7804+ job->jv_next = first_job;
7805+ }
7806+ first_job = job;
7807+ }
77897808 return job;
77907809}
77917810
7811+ static void
7812+ job_set_options(job_T *job, jobopt_T *opt)
7813+ {
7814+ if (opt->jo_set & JO_STOPONEXIT)
7815+ {
7816+ vim_free(job->jv_stoponexit);
7817+ if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL)
7818+ job->jv_stoponexit = NULL;
7819+ else
7820+ job->jv_stoponexit = vim_strsave(opt->jo_stoponexit);
7821+ }
7822+ }
7823+
7824+ /*
7825+ * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag.
7826+ */
7827+ void
7828+ job_stop_on_exit()
7829+ {
7830+ job_T *job;
7831+
7832+ for (job = first_job; job != NULL; job = job->jv_next)
7833+ if (job->jv_stoponexit != NULL && *job->jv_stoponexit != NUL)
7834+ mch_stop_job(job, job->jv_stoponexit);
7835+ }
77927836#endif
77937837
77947838 static char *
@@ -7797,9 +7841,9 @@ get_var_special_name(int nr)
77977841 switch (nr)
77987842 {
77997843 case VVAL_FALSE: return "v:false";
7800- case VVAL_TRUE: return "v:true";
7801- case VVAL_NONE: return "v:none";
7802- case VVAL_NULL: return "v:null";
7844+ case VVAL_TRUE: return "v:true";
7845+ case VVAL_NONE: return "v:none";
7846+ case VVAL_NULL: return "v:null";
78037847 }
78047848 EMSG2(_(e_intern2), "get_var_special_name()");
78057849 return "42";
@@ -8260,6 +8304,7 @@ static struct fst
82608304# ifdef FEAT_CHANNEL
82618305 {"job_getchannel", 1, 1, f_job_getchannel},
82628306# endif
8307+ {"job_setoptions", 2, 2, f_job_setoptions},
82638308 {"job_start", 1, 2, f_job_start},
82648309 {"job_status", 1, 1, f_job_status},
82658310 {"job_stop", 1, 2, f_job_stop},
@@ -10050,6 +10095,19 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
1005010095 opt->jo_set |= JO_ID;
1005110096 opt->jo_id = get_tv_number(item);
1005210097 }
10098+ else if (STRCMP(hi->hi_key, "stoponexit") == 0)
10099+ {
10100+ if (!(supported & JO_STOPONEXIT))
10101+ break;
10102+ opt->jo_set |= JO_STOPONEXIT;
10103+ opt->jo_stoponexit = get_tv_string_buf_chk(item,
10104+ opt->jo_soe_buf);
10105+ if (opt->jo_stoponexit == NULL)
10106+ {
10107+ EMSG2(_(e_invarg2), "stoponexit");
10108+ return FAIL;
10109+ }
10110+ }
1005310111 else
1005410112 break;
1005510113 --todo;
@@ -14733,6 +14791,26 @@ f_items(typval_T *argvars, typval_T *rettv)
1473314791}
1473414792
1473514793#ifdef FEAT_JOB
14794+ /*
14795+ * Get the job from the argument.
14796+ * Returns NULL if the job is invalid.
14797+ */
14798+ static job_T *
14799+ get_job_arg(typval_T *tv)
14800+ {
14801+ job_T *job;
14802+
14803+ if (tv->v_type != VAR_JOB)
14804+ {
14805+ EMSG2(_(e_invarg2), get_tv_string(tv));
14806+ return NULL;
14807+ }
14808+ job = tv->vval.v_job;
14809+
14810+ if (job == NULL)
14811+ EMSG(_("E916: not a valid job"));
14812+ return job;
14813+ }
1473614814
1473714815# ifdef FEAT_CHANNEL
1473814816/*
@@ -14741,12 +14819,10 @@ f_items(typval_T *argvars, typval_T *rettv)
1474114819 static void
1474214820f_job_getchannel(typval_T *argvars, typval_T *rettv)
1474314821{
14744- if (argvars[0].v_type != VAR_JOB)
14745- EMSG(_(e_invarg));
14746- else
14747- {
14748- job_T *job = argvars[0].vval.v_job;
14822+ job_T *job = get_job_arg(&argvars[0]);
1474914823
14824+ if (job != NULL)
14825+ {
1475014826 rettv->v_type = VAR_CHANNEL;
1475114827 rettv->vval.v_channel = job->jv_channel;
1475214828 if (job->jv_channel != NULL)
@@ -14755,6 +14831,23 @@ f_job_getchannel(typval_T *argvars, typval_T *rettv)
1475514831}
1475614832# endif
1475714833
14834+ /*
14835+ * "job_setoptions()" function
14836+ */
14837+ static void
14838+ f_job_setoptions(typval_T *argvars, typval_T *rettv UNUSED)
14839+ {
14840+ job_T *job = get_job_arg(&argvars[0]);
14841+ jobopt_T opt;
14842+
14843+ if (job == NULL)
14844+ return;
14845+ clear_job_options(&opt);
14846+ if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT) == FAIL)
14847+ return;
14848+ job_set_options(job, &opt);
14849+ }
14850+
1475814851/*
1475914852 * "job_start()" function
1476014853 */
@@ -14784,8 +14877,9 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1478414877 clear_job_options(&opt);
1478514878 opt.jo_mode = MODE_NL;
1478614879 if (get_job_options(&argvars[1], &opt,
14787- JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL) == FAIL)
14880+ JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT ) == FAIL)
1478814881 return;
14882+ job_set_options(job, &opt);
1478914883
1479014884#ifndef USE_ARGV
1479114885 ga_init2(&ga, (int)sizeof(char*), 20);
@@ -14889,14 +14983,11 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
1488914983 static void
1489014984f_job_status(typval_T *argvars, typval_T *rettv)
1489114985{
14892- char *result;
14986+ job_T *job = get_job_arg(&argvars[0]);
14987+ char *result;
1489314988
14894- if (argvars[0].v_type != VAR_JOB)
14895- EMSG(_(e_invarg));
14896- else
14989+ if (job != NULL)
1489714990 {
14898- job_T *job = argvars[0].vval.v_job;
14899-
1490014991 if (job->jv_status == JOB_ENDED)
1490114992 /* No need to check, dead is dead. */
1490214993 result = "dead";
@@ -14915,9 +15006,9 @@ f_job_status(typval_T *argvars, typval_T *rettv)
1491515006 static void
1491615007f_job_stop(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1491715008{
14918- if ( argvars[0].v_type != VAR_JOB)
14919- EMSG(_(e_invarg));
14920- else
15009+ job_T *job = get_job_arg(& argvars[0]);
15010+
15011+ if (job != NULL)
1492115012 {
1492215013 char_u *arg;
1492315014
@@ -14932,7 +15023,7 @@ f_job_stop(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1493215023 return;
1493315024 }
1493415025 }
14935- if (mch_stop_job(argvars[0].vval.v_job , arg) == FAIL)
15026+ if (mch_stop_job(job , arg) == FAIL)
1493615027 rettv->vval.v_number = 0;
1493715028 else
1493815029 rettv->vval.v_number = 1;
0 commit comments