mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 7.4.1274
Problem: Cannot run a job. Solution: Add job_start(), job_status() and job_stop(). Currently only works for Unix.
This commit is contained in:
315
src/eval.c
315
src/eval.c
@@ -451,6 +451,9 @@ static dict_T *dict_copy(dict_T *orig, int deep, int copyID);
|
||||
static long dict_len(dict_T *d);
|
||||
static char_u *dict2string(typval_T *tv, int copyID);
|
||||
static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate);
|
||||
#ifdef FEAT_JOB
|
||||
static void job_free(job_T *job);
|
||||
#endif
|
||||
static char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
|
||||
static char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);
|
||||
static char_u *string_quote(char_u *str, int function);
|
||||
@@ -619,6 +622,11 @@ static void f_invert(typval_T *argvars, typval_T *rettv);
|
||||
static void f_isdirectory(typval_T *argvars, typval_T *rettv);
|
||||
static void f_islocked(typval_T *argvars, typval_T *rettv);
|
||||
static void f_items(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_JOB
|
||||
static void f_job_start(typval_T *argvars, typval_T *rettv);
|
||||
static void f_job_stop(typval_T *argvars, typval_T *rettv);
|
||||
static void f_job_status(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_join(typval_T *argvars, typval_T *rettv);
|
||||
static void f_jsondecode(typval_T *argvars, typval_T *rettv);
|
||||
static void f_jsonencode(typval_T *argvars, typval_T *rettv);
|
||||
@@ -3062,10 +3070,11 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
|
||||
{
|
||||
switch (tv1->v_type)
|
||||
{
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_DICT:
|
||||
case VAR_FUNC:
|
||||
case VAR_SPECIAL:
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_JOB:
|
||||
break;
|
||||
|
||||
case VAR_LIST:
|
||||
@@ -3844,6 +3853,7 @@ item_lock(typval_T *tv, int deep, int lock)
|
||||
case VAR_FUNC:
|
||||
case VAR_FLOAT:
|
||||
case VAR_SPECIAL:
|
||||
case VAR_JOB:
|
||||
break;
|
||||
|
||||
case VAR_LIST:
|
||||
@@ -5339,6 +5349,7 @@ eval_index(
|
||||
return FAIL;
|
||||
#endif
|
||||
case VAR_SPECIAL:
|
||||
case VAR_JOB:
|
||||
if (verbose)
|
||||
EMSG(_("E909: Cannot index a special variable"));
|
||||
return FAIL;
|
||||
@@ -5446,10 +5457,11 @@ eval_index(
|
||||
|
||||
switch (rettv->v_type)
|
||||
{
|
||||
case VAR_SPECIAL:
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_FUNC:
|
||||
case VAR_FLOAT:
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_SPECIAL:
|
||||
case VAR_JOB:
|
||||
break; /* not evaluating, skipping over subscript */
|
||||
|
||||
case VAR_NUMBER:
|
||||
@@ -6167,9 +6179,6 @@ tv_equal(
|
||||
|
||||
switch (tv1->v_type)
|
||||
{
|
||||
case VAR_UNKNOWN:
|
||||
break;
|
||||
|
||||
case VAR_LIST:
|
||||
++recursive_cnt;
|
||||
r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE);
|
||||
@@ -6190,11 +6199,6 @@ tv_equal(
|
||||
case VAR_NUMBER:
|
||||
return tv1->vval.v_number == tv2->vval.v_number;
|
||||
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
return tv1->vval.v_float == tv2->vval.v_float;
|
||||
#endif
|
||||
|
||||
case VAR_STRING:
|
||||
s1 = get_tv_string_buf(tv1, buf1);
|
||||
s2 = get_tv_string_buf(tv2, buf2);
|
||||
@@ -6202,6 +6206,17 @@ tv_equal(
|
||||
|
||||
case VAR_SPECIAL:
|
||||
return tv1->vval.v_number == tv2->vval.v_number;
|
||||
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
return tv1->vval.v_float == tv2->vval.v_float;
|
||||
#endif
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
return tv1->vval.v_job == tv2->vval.v_job;
|
||||
#endif
|
||||
case VAR_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
|
||||
/* VAR_UNKNOWN can be the result of a invalid expression, let's say it
|
||||
@@ -6924,7 +6939,7 @@ garbage_collect(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Free lists and dictionaries that are no longer referenced.
|
||||
* Free lists, dictionaries and jobs that are no longer referenced.
|
||||
*/
|
||||
static int
|
||||
free_unref_items(int copyID)
|
||||
@@ -6969,6 +6984,7 @@ free_unref_items(int copyID)
|
||||
}
|
||||
ll = ll_next;
|
||||
}
|
||||
|
||||
return did_free;
|
||||
}
|
||||
|
||||
@@ -7694,6 +7710,40 @@ failret:
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef FEAT_JOB
|
||||
static void
|
||||
job_free(job_T *job)
|
||||
{
|
||||
/* TODO: free any handles */
|
||||
|
||||
vim_free(job);
|
||||
}
|
||||
|
||||
static void
|
||||
job_unref(job_T *job)
|
||||
{
|
||||
if (job != NULL && --job->jv_refcount <= 0)
|
||||
job_free(job);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a job. Sets the refcount to one.
|
||||
*/
|
||||
static job_T *
|
||||
job_alloc(void)
|
||||
{
|
||||
job_T *job;
|
||||
|
||||
job = (job_T *)alloc_clear(sizeof(job_T));
|
||||
if (job != NULL)
|
||||
{
|
||||
job->jv_refcount = 1;
|
||||
}
|
||||
return job;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static char *
|
||||
get_var_special_name(int nr)
|
||||
{
|
||||
@@ -7789,12 +7839,13 @@ echo_string(
|
||||
case VAR_STRING:
|
||||
case VAR_NUMBER:
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_JOB:
|
||||
*tofree = NULL;
|
||||
r = get_tv_string_buf(tv, numbuf);
|
||||
break;
|
||||
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
*tofree = NULL;
|
||||
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
|
||||
r = numbuf;
|
||||
@@ -7844,6 +7895,7 @@ tv2string(
|
||||
case VAR_LIST:
|
||||
case VAR_DICT:
|
||||
case VAR_SPECIAL:
|
||||
case VAR_JOB:
|
||||
case VAR_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
@@ -8148,6 +8200,11 @@ static struct fst
|
||||
{"isdirectory", 1, 1, f_isdirectory},
|
||||
{"islocked", 1, 1, f_islocked},
|
||||
{"items", 1, 1, f_items},
|
||||
#ifdef FEAT_CHANNEL
|
||||
{"job_start", 1, 2, f_job_start},
|
||||
{"job_status", 1, 1, f_job_status},
|
||||
{"job_stop", 1, 1, f_job_stop},
|
||||
#endif
|
||||
{"join", 1, 2, f_join},
|
||||
{"jsondecode", 1, 1, f_jsondecode},
|
||||
{"jsonencode", 1, 1, f_jsonencode},
|
||||
@@ -10535,8 +10592,8 @@ f_empty(typval_T *argvars, typval_T *rettv)
|
||||
case VAR_NUMBER:
|
||||
n = argvars[0].vval.v_number == 0;
|
||||
break;
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
n = argvars[0].vval.v_float == 0.0;
|
||||
break;
|
||||
#endif
|
||||
@@ -10552,6 +10609,11 @@ f_empty(typval_T *argvars, typval_T *rettv)
|
||||
n = argvars[0].vval.v_number != VVAL_TRUE;
|
||||
break;
|
||||
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
n = argvars[0].vval.v_job->jv_status != JOB_STARTED;
|
||||
break;
|
||||
#endif
|
||||
case VAR_UNKNOWN:
|
||||
EMSG2(_(e_intern2), "f_empty(UNKNOWN)");
|
||||
n = TRUE;
|
||||
@@ -13060,6 +13122,9 @@ f_has(typval_T *argvars, typval_T *rettv)
|
||||
#ifdef FEAT_INS_EXPAND
|
||||
"insert_expand",
|
||||
#endif
|
||||
#ifdef FEAT_JOB
|
||||
"job",
|
||||
#endif
|
||||
#ifdef FEAT_JUMPLIST
|
||||
"jumplist",
|
||||
#endif
|
||||
@@ -14188,6 +14253,161 @@ f_items(typval_T *argvars, typval_T *rettv)
|
||||
dict_list(argvars, rettv, 2);
|
||||
}
|
||||
|
||||
#ifdef FEAT_JOB
|
||||
/*
|
||||
* "job_start()" function
|
||||
*/
|
||||
static void
|
||||
f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
job_T *job;
|
||||
char_u *cmd = NULL;
|
||||
#if defined(UNIX)
|
||||
# define USE_ARGV
|
||||
char **argv = NULL;
|
||||
int argc = 0;
|
||||
#else
|
||||
garray_T ga;
|
||||
#endif
|
||||
|
||||
rettv->v_type = VAR_JOB;
|
||||
job = job_alloc();
|
||||
rettv->vval.v_job = job;
|
||||
if (job == NULL)
|
||||
return;
|
||||
|
||||
rettv->vval.v_job->jv_status = JOB_FAILED;
|
||||
#ifndef USE_ARGV
|
||||
ga_init2(&ga, 200);
|
||||
#endif
|
||||
|
||||
if (argvars[0].v_type == VAR_STRING)
|
||||
{
|
||||
/* Command is a string. */
|
||||
cmd = argvars[0].vval.v_string;
|
||||
#ifdef USE_ARGV
|
||||
if (mch_parse_cmd(cmd, FALSE, &argv, &argc) == FAIL)
|
||||
return;
|
||||
argv[argc] = NULL;
|
||||
#endif
|
||||
}
|
||||
else if (argvars[0].v_type != VAR_LIST
|
||||
|| argvars[0].vval.v_list == NULL
|
||||
|| argvars[0].vval.v_list->lv_len < 1)
|
||||
{
|
||||
EMSG(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
list_T *l = argvars[0].vval.v_list;
|
||||
listitem_T *li;
|
||||
char_u *s;
|
||||
|
||||
#ifdef USE_ARGV
|
||||
/* Pass argv[] to mch_call_shell(). */
|
||||
argv = (char **)alloc(sizeof(char *) * (l->lv_len + 1));
|
||||
if (argv == NULL)
|
||||
return;
|
||||
#endif
|
||||
for (li = l->lv_first; li != NULL; li = li->li_next)
|
||||
{
|
||||
s = get_tv_string_chk(&li->li_tv);
|
||||
if (s == NULL)
|
||||
goto theend;
|
||||
#ifdef USE_ARGV
|
||||
argv[argc++] = (char *)s;
|
||||
#else
|
||||
if (li != l->lv_first)
|
||||
{
|
||||
s = vim_strsave_shellescape(s, FALSE, TRUE);
|
||||
if (s == NULL)
|
||||
goto theend;
|
||||
}
|
||||
ga_concat(&ga, s);
|
||||
vim_free(s);
|
||||
if (li->li_next != NULL)
|
||||
ga_append(&ga, ' ');
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_ARGV
|
||||
argv[argc] = NULL;
|
||||
#else
|
||||
cmd = ga.ga_data;
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_ARGV
|
||||
mch_start_job(argv, job);
|
||||
#else
|
||||
mch_start_job(cmd, job);
|
||||
#endif
|
||||
|
||||
theend:
|
||||
#ifdef USE_ARGV
|
||||
if (argv != NULL)
|
||||
vim_free(argv);
|
||||
#else
|
||||
vim_free(ga.ga_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* "job_status()" function
|
||||
*/
|
||||
static void
|
||||
f_job_status(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (argvars[0].v_type != VAR_JOB)
|
||||
EMSG(_(e_invarg));
|
||||
else
|
||||
{
|
||||
job_T *job = argvars[0].vval.v_job;
|
||||
|
||||
if (job->jv_status == JOB_ENDED)
|
||||
/* No need to check, dead is dead. */
|
||||
result = "dead";
|
||||
else if (job->jv_status == JOB_FAILED)
|
||||
result = "fail";
|
||||
else
|
||||
result = mch_job_status(job);
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = vim_strsave((char_u *)result);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "job_stop()" function
|
||||
*/
|
||||
static void
|
||||
f_job_stop(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_JOB)
|
||||
EMSG(_(e_invarg));
|
||||
else
|
||||
{
|
||||
char_u *arg;
|
||||
|
||||
if (argvars[1].v_type == VAR_UNKNOWN)
|
||||
arg = (char_u *)"";
|
||||
else
|
||||
{
|
||||
arg = get_tv_string_chk(&argvars[1]);
|
||||
if (arg == NULL)
|
||||
{
|
||||
EMSG(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mch_stop_job(argvars[0].vval.v_job, arg) == FAIL)
|
||||
rettv->vval.v_number = 0;
|
||||
else
|
||||
rettv->vval.v_number = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "join()" function
|
||||
*/
|
||||
@@ -14295,6 +14515,7 @@ f_len(typval_T *argvars, typval_T *rettv)
|
||||
case VAR_SPECIAL:
|
||||
case VAR_FLOAT:
|
||||
case VAR_FUNC:
|
||||
case VAR_JOB:
|
||||
EMSG(_("E701: Invalid type for len()"));
|
||||
break;
|
||||
}
|
||||
@@ -19658,6 +19879,9 @@ f_type(typval_T *argvars, typval_T *rettv)
|
||||
else
|
||||
n = 7;
|
||||
break;
|
||||
#ifdef FEAT_JOB
|
||||
case VAR_JOB: n = 8; break;
|
||||
#endif
|
||||
case VAR_UNKNOWN:
|
||||
EMSG2(_(e_intern2), "f_type(UNKNOWN)");
|
||||
n = -1;
|
||||
@@ -21024,10 +21248,13 @@ free_tv(typval_T *varp)
|
||||
case VAR_DICT:
|
||||
dict_unref(varp->vval.v_dict);
|
||||
break;
|
||||
case VAR_NUMBER:
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
job_unref(varp->vval.v_job);
|
||||
break;
|
||||
#endif
|
||||
case VAR_NUMBER:
|
||||
case VAR_FLOAT:
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_SPECIAL:
|
||||
break;
|
||||
@@ -21065,11 +21292,17 @@ clear_tv(typval_T *varp)
|
||||
case VAR_SPECIAL:
|
||||
varp->vval.v_number = 0;
|
||||
break;
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
varp->vval.v_float = 0.0;
|
||||
break;
|
||||
#endif
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
job_unref(varp->vval.v_job);
|
||||
varp->vval.v_job = NULL;
|
||||
#endif
|
||||
break;
|
||||
case VAR_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
@@ -21112,8 +21345,8 @@ get_tv_number_chk(typval_T *varp, int *denote)
|
||||
{
|
||||
case VAR_NUMBER:
|
||||
return (long)(varp->vval.v_number);
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
EMSG(_("E805: Using a Float as a Number"));
|
||||
break;
|
||||
#endif
|
||||
@@ -21134,6 +21367,11 @@ get_tv_number_chk(typval_T *varp, int *denote)
|
||||
case VAR_SPECIAL:
|
||||
return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
|
||||
break;
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
EMSG(_("E910: Using a Job as a Number"));
|
||||
break;
|
||||
#endif
|
||||
case VAR_UNKNOWN:
|
||||
EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)");
|
||||
break;
|
||||
@@ -21153,10 +21391,8 @@ get_tv_float(typval_T *varp)
|
||||
{
|
||||
case VAR_NUMBER:
|
||||
return (float_T)(varp->vval.v_number);
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
return varp->vval.v_float;
|
||||
#endif
|
||||
case VAR_FUNC:
|
||||
EMSG(_("E891: Using a Funcref as a Float"));
|
||||
break;
|
||||
@@ -21172,6 +21408,11 @@ get_tv_float(typval_T *varp)
|
||||
case VAR_SPECIAL:
|
||||
EMSG(_("E907: Using a special value as a Float"));
|
||||
break;
|
||||
case VAR_JOB:
|
||||
# ifdef FEAT_JOB
|
||||
EMSG(_("E911: Using a Job as a Float"));
|
||||
break;
|
||||
# endif
|
||||
case VAR_UNKNOWN:
|
||||
EMSG2(_(e_intern2), "get_tv_float(UNKNOWN)");
|
||||
break;
|
||||
@@ -21272,8 +21513,8 @@ get_tv_string_buf_chk(typval_T *varp, char_u *buf)
|
||||
case VAR_DICT:
|
||||
EMSG(_("E731: using Dictionary as a String"));
|
||||
break;
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
EMSG(_(e_float_as_string));
|
||||
break;
|
||||
#endif
|
||||
@@ -21284,6 +21525,24 @@ get_tv_string_buf_chk(typval_T *varp, char_u *buf)
|
||||
case VAR_SPECIAL:
|
||||
STRCPY(buf, get_var_special_name(varp->vval.v_number));
|
||||
return buf;
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_JOB
|
||||
{
|
||||
job_T *job = varp->vval.v_job;
|
||||
char *status = job->jv_status == JOB_FAILED ? "fail"
|
||||
: job->jv_status == JOB_ENDED ? "dead"
|
||||
: "run";
|
||||
# ifdef UNIX
|
||||
vim_snprintf((char *)buf, NUMBUFLEN,
|
||||
"process %ld %s", (long)job->jv_pid, status);
|
||||
# else
|
||||
/* TODO */
|
||||
vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
|
||||
# endif
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case VAR_UNKNOWN:
|
||||
EMSG(_("E908: using an invalid value as a String"));
|
||||
break;
|
||||
@@ -21903,10 +22162,16 @@ copy_tv(typval_T *from, typval_T *to)
|
||||
case VAR_SPECIAL:
|
||||
to->vval.v_number = from->vval.v_number;
|
||||
break;
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#ifdef FEAT_FLOAT
|
||||
to->vval.v_float = from->vval.v_float;
|
||||
break;
|
||||
#endif
|
||||
case VAR_JOB:
|
||||
#ifdef FEAT_FLOAT
|
||||
to->vval.v_job = from->vval.v_job;
|
||||
++to->vval.v_job->jv_refcount;
|
||||
break;
|
||||
#endif
|
||||
case VAR_STRING:
|
||||
case VAR_FUNC:
|
||||
@@ -21970,12 +22235,11 @@ item_copy(
|
||||
switch (from->v_type)
|
||||
{
|
||||
case VAR_NUMBER:
|
||||
#ifdef FEAT_FLOAT
|
||||
case VAR_FLOAT:
|
||||
#endif
|
||||
case VAR_STRING:
|
||||
case VAR_FUNC:
|
||||
case VAR_SPECIAL:
|
||||
case VAR_JOB:
|
||||
copy_tv(from, to);
|
||||
break;
|
||||
case VAR_LIST:
|
||||
@@ -24649,6 +24913,7 @@ write_viminfo_varlist(FILE *fp)
|
||||
|
||||
case VAR_UNKNOWN:
|
||||
case VAR_FUNC:
|
||||
case VAR_JOB:
|
||||
continue;
|
||||
}
|
||||
fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
|
||||
|
Reference in New Issue
Block a user