mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.1426
Problem: The "out-io" option for jobs is not implemented yet. Solution: Implement the "buffer" value: append job output to a buffer.
This commit is contained in:
parent
6e722e2f94
commit
187db50d04
@ -130,6 +130,8 @@ Use |ch_status()| to see if the channel could be opened.
|
||||
overwritten. Therefore set "mode" first and the part specific
|
||||
mode later.
|
||||
|
||||
Note: when writing to a file or buffer NL mode is always used.
|
||||
|
||||
*channel-callback*
|
||||
"callback" A function that is called when a message is received that is
|
||||
not handled otherwise. It gets two arguments: the channel
|
||||
@ -198,6 +200,7 @@ Once done with the channel, disconnect it like this: >
|
||||
When a socket is used this will close the socket for both directions. When
|
||||
pipes are used (stdin/stdout/stderr) they are all closed. This might not be
|
||||
what you want! Stopping the job with job_stop() might be better.
|
||||
All readahead is discarded, callbacks will no longer be invoked.
|
||||
|
||||
When the channel can't be opened you will get an error message. There is a
|
||||
difference between MS-Windows and Unix: On Unix when the port doesn't exist
|
||||
@ -327,7 +330,7 @@ It will send back the result of the expression:
|
||||
[-2, "last line"] ~
|
||||
The format is:
|
||||
[{number}, {result}]
|
||||
*E915*
|
||||
|
||||
Here {number} is the same as what was in the request. Use a negative number
|
||||
to avoid confusion with message that Vim sends. Use a different number on
|
||||
every request to be able to match the request with the response.
|
||||
@ -397,7 +400,7 @@ are:
|
||||
"closed" The channel was closed.
|
||||
|
||||
TODO:
|
||||
To objain the job associated with a channel: ch_getjob(channel)
|
||||
To obtain the job associated with a channel: ch_getjob(channel)
|
||||
|
||||
To read one message from a channel: >
|
||||
let output = ch_read(channel)
|
||||
@ -448,10 +451,13 @@ You can send a message to the command with ch_sendraw(). If the channel is in
|
||||
JSON or JS mode you can use ch_sendexpr().
|
||||
|
||||
There are several options you can use, see |job-options|.
|
||||
For example, to start a job and write its output in buffer "dummy": >
|
||||
let logjob = job_start("tail -f /tmp/log",
|
||||
\ {'out-io': 'buffer', 'out-name': 'dummy'})
|
||||
sbuf dummy
|
||||
|
||||
TODO:
|
||||
To run a job and read its output once it is done: >
|
||||
|
||||
let job = job_start({command}, {'exit-cb': 'MyHandler'})
|
||||
func MyHandler(job, status)
|
||||
let channel = job_getchannel()
|
||||
@ -508,7 +514,7 @@ See |job_setoptions()| and |ch_setoptions()|.
|
||||
*job-err-cb*
|
||||
"err-cb": handler Callback for when there is something to read on
|
||||
stderr.
|
||||
TODO: *job-close-cb*
|
||||
*job-close-cb*
|
||||
"close-cb": handler Callback for when the channel is closed. Same as
|
||||
"close-cb" on ch_open().
|
||||
*job-exit-cb*
|
||||
@ -527,28 +533,44 @@ TODO: *job-term*
|
||||
"term": "open" Start a terminal and connect the job
|
||||
stdin/stdout/stderr to it.
|
||||
|
||||
TODO: *job-in-io*
|
||||
"in-io": "null" disconnect stdin
|
||||
*job-in-io*
|
||||
"in-io": "null" disconnect stdin TODO
|
||||
"in-io": "pipe" stdin is connected to the channel (default)
|
||||
"in-io": "file" stdin reads from a file
|
||||
"in-file": "/path/file" the file to read from
|
||||
"in-io": "file" stdin reads from a file TODO
|
||||
"in-io": "buffer" stdin reads from a buffer TODO
|
||||
"in-name": "/path/file" the name of he file or buffer to read from
|
||||
"in-buf": number the number of the buffer to read from TODO
|
||||
|
||||
TODO: *job-out-io*
|
||||
"out-io": "null" disconnect stdout
|
||||
*job-out-io*
|
||||
"out-io": "null" disconnect stdout TODO
|
||||
"out-io": "pipe" stdout is connected to the channel (default)
|
||||
"out-io": "file" stdout writes to a file
|
||||
"out-file": "/path/file" the file to write to
|
||||
"out-io": "file" stdout writes to a file TODO
|
||||
"out-io": "buffer" stdout appends to a buffer
|
||||
"out-buffer": "name" buffer to append to
|
||||
"out-name": "/path/file" the name of the file or buffer to write to
|
||||
"out-buf": number the number of the buffer to write to TODO
|
||||
|
||||
TODO: *job-err-io*
|
||||
"err-io": "out" same type as stdout (default)
|
||||
"err-io": "null" disconnect stderr
|
||||
"err-io": "pipe" stderr is connected to the channel
|
||||
"err-io": "file" stderr writes to a file
|
||||
"err-file": "/path/file" the file to write to
|
||||
"err-io": "buffer" stderr appends to a buffer
|
||||
"err-buffer": "name" buffer to append to
|
||||
*job-err-io*
|
||||
"err-io": "out" same as stdout TODO
|
||||
"err-io": "null" disconnect stderr TODO
|
||||
"err-io": "pipe" stderr is connected to the channel (default)
|
||||
"err-io": "file" stderr writes to a file TODO
|
||||
"err-io": "buffer" stderr appends to a buffer TODO
|
||||
"err-name": "/path/file" the name of the file or buffer to write to
|
||||
"err-buf": number the number of the buffer to write to TODO
|
||||
|
||||
When the IO mode is "buffer" and there is a callback, the text is appended to
|
||||
the buffer before invoking the callback.
|
||||
*E915*
|
||||
The name of the buffer is compared the full name of existing buffers. If
|
||||
there is a match that buffer is used. Otherwise a new buffer is created,
|
||||
where 'buftype' is set to "nofile" and 'bufhidden' to "hide". If you prefer
|
||||
other settings, create the buffer first and pass the buffer number.
|
||||
|
||||
When the buffer written to is displayed in a window and the cursor is in the
|
||||
first column of the last line, the cursor will be moved to the newly added
|
||||
line and the window is scrolled up to show the cursor if needed.
|
||||
|
||||
Undo is synced for every added line.
|
||||
|
||||
==============================================================================
|
||||
11. Controlling a job *job-control*
|
||||
|
140
src/channel.c
140
src/channel.c
@ -52,6 +52,10 @@
|
||||
# define fd_close(sd) close(sd)
|
||||
#endif
|
||||
|
||||
/* Whether a redraw is needed for appending a line to a buffer. */
|
||||
static int channel_need_redraw = FALSE;
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
static int
|
||||
fd_read(sock_T fd, char *buf, size_t len)
|
||||
@ -342,6 +346,7 @@ channel_may_free(channel_T *channel)
|
||||
channel_free(channel_T *channel)
|
||||
{
|
||||
channel_close(channel, TRUE);
|
||||
channel_clear(channel);
|
||||
if (channel->ch_next != NULL)
|
||||
channel->ch_next->ch_prev = channel->ch_prev;
|
||||
if (channel->ch_prev == NULL)
|
||||
@ -776,6 +781,35 @@ channel_set_job(channel_T *channel, job_T *job)
|
||||
channel->ch_job = job;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a buffer matching "name" or create a new one.
|
||||
*/
|
||||
static buf_T *
|
||||
find_buffer(char_u *name)
|
||||
{
|
||||
buf_T *buf = buflist_findname(name);
|
||||
buf_T *save_curbuf = curbuf;
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
buf = buflist_new(name, NULL, (linenr_T)0, BLN_LISTED);
|
||||
buf_copy_options(buf, BCO_ENTER);
|
||||
#ifdef FEAT_QUICKFIX
|
||||
clear_string_option(&buf->b_p_bt);
|
||||
buf->b_p_bt = vim_strsave((char_u *)"nofile");
|
||||
clear_string_option(&buf->b_p_bh);
|
||||
buf->b_p_bh = vim_strsave((char_u *)"hide");
|
||||
#endif
|
||||
curbuf = buf;
|
||||
ml_open(curbuf);
|
||||
ml_replace(1, (char_u *)"Reading from channel output...", TRUE);
|
||||
changed_bytes(1, 0);
|
||||
curbuf = save_curbuf;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set various properties from an "opt" argument.
|
||||
*/
|
||||
@ -839,6 +873,16 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
|
||||
else
|
||||
*cbp = NULL;
|
||||
}
|
||||
|
||||
if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
|
||||
{
|
||||
/* writing output to a buffer. Force mode to NL. */
|
||||
channel->ch_part[PART_OUT].ch_mode = MODE_NL;
|
||||
channel->ch_part[PART_OUT].ch_buffer =
|
||||
find_buffer(opt->jo_io_name[PART_OUT]);
|
||||
ch_logs(channel, "writing to buffer %s",
|
||||
(char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1303,6 +1347,7 @@ may_invoke_callback(channel_T *channel, int part)
|
||||
int seq_nr = -1;
|
||||
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
|
||||
char_u *callback = NULL;
|
||||
buf_T *buffer = NULL;
|
||||
|
||||
if (channel->ch_nb_close_cb != NULL)
|
||||
/* this channel is handled elsewhere (netbeans) */
|
||||
@ -1312,6 +1357,7 @@ may_invoke_callback(channel_T *channel, int part)
|
||||
callback = channel->ch_part[part].ch_callback;
|
||||
else
|
||||
callback = channel->ch_callback;
|
||||
buffer = channel->ch_part[part].ch_buffer;
|
||||
|
||||
if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
|
||||
{
|
||||
@ -1361,8 +1407,8 @@ may_invoke_callback(channel_T *channel, int part)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there is no callback drop the message. */
|
||||
if (callback == NULL)
|
||||
/* If there is no callback or buffer drop the message. */
|
||||
if (callback == NULL && buffer == NULL)
|
||||
{
|
||||
while ((msg = channel_get(channel, part)) != NULL)
|
||||
vim_free(msg);
|
||||
@ -1386,8 +1432,11 @@ may_invoke_callback(channel_T *channel, int part)
|
||||
return FALSE; /* incomplete message */
|
||||
}
|
||||
if (nl[1] == NUL)
|
||||
/* get the whole buffer */
|
||||
{
|
||||
/* get the whole buffer, drop the NL */
|
||||
msg = channel_get(channel, part);
|
||||
*nl = NUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy the message into allocated memory and remove it from
|
||||
@ -1431,11 +1480,54 @@ may_invoke_callback(channel_T *channel, int part)
|
||||
if (!done)
|
||||
ch_log(channel, "Dropping message without callback");
|
||||
}
|
||||
else if (callback != NULL)
|
||||
else if (callback != NULL || buffer != NULL)
|
||||
{
|
||||
/* invoke the channel callback */
|
||||
ch_log(channel, "Invoking channel callback");
|
||||
invoke_callback(channel, callback, argv);
|
||||
if (buffer != NULL)
|
||||
{
|
||||
buf_T *save_curbuf = curbuf;
|
||||
linenr_T lnum = buffer->b_ml.ml_line_count;
|
||||
|
||||
/* Append to the buffer */
|
||||
ch_logn(channel, "appending line %d to buffer", (int)lnum + 1);
|
||||
|
||||
curbuf = buffer;
|
||||
u_sync(TRUE);
|
||||
u_save(lnum, lnum + 1);
|
||||
|
||||
ml_append(lnum, msg, 0, FALSE);
|
||||
appended_lines_mark(lnum, 1L);
|
||||
curbuf = save_curbuf;
|
||||
|
||||
if (buffer->b_nwindows > 0)
|
||||
{
|
||||
win_T *wp;
|
||||
win_T *save_curwin;
|
||||
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
{
|
||||
if (wp->w_buffer == buffer
|
||||
&& wp->w_cursor.lnum == lnum
|
||||
&& wp->w_cursor.col == 0)
|
||||
{
|
||||
++wp->w_cursor.lnum;
|
||||
save_curwin = curwin;
|
||||
curwin = wp;
|
||||
curbuf = curwin->w_buffer;
|
||||
scroll_cursor_bot(0, FALSE);
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
}
|
||||
redraw_buf_later(buffer, VALID);
|
||||
channel_need_redraw = TRUE;
|
||||
}
|
||||
}
|
||||
if (callback != NULL)
|
||||
{
|
||||
/* invoke the channel callback */
|
||||
ch_log(channel, "Invoking channel callback");
|
||||
invoke_callback(channel, callback, argv);
|
||||
}
|
||||
}
|
||||
else
|
||||
ch_log(channel, "Dropping message");
|
||||
@ -1493,6 +1585,7 @@ channel_status(channel_T *channel)
|
||||
/*
|
||||
* Close channel "channel".
|
||||
* Trigger the close callback if "invoke_close_cb" is TRUE.
|
||||
* Does not clear the buffers.
|
||||
*/
|
||||
void
|
||||
channel_close(channel_T *channel, int invoke_close_cb)
|
||||
@ -1548,7 +1641,6 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
||||
}
|
||||
|
||||
channel->ch_nb_close_cb = NULL;
|
||||
channel_clear(channel);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2159,6 +2251,24 @@ channel_select_check(int ret_in, void *rfds_in)
|
||||
}
|
||||
# endif /* !WIN32 && HAVE_SELECT */
|
||||
|
||||
/*
|
||||
* Return TRUE if "channel" has JSON or other typeahead.
|
||||
*/
|
||||
static int
|
||||
channel_has_readahead(channel_T *channel, int part)
|
||||
{
|
||||
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
|
||||
|
||||
if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
|
||||
{
|
||||
jsonq_T *head = &channel->ch_part[part].ch_json_head;
|
||||
jsonq_T *item = head->jq_next;
|
||||
|
||||
return item != NULL;
|
||||
}
|
||||
return channel_peek(channel, part) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute queued up commands.
|
||||
* Invoked from the main loop when it's safe to execute received commands.
|
||||
@ -2172,6 +2282,7 @@ channel_parse_messages(void)
|
||||
int r;
|
||||
int part = PART_SOCK;
|
||||
|
||||
ch_log(NULL, "looking for messages on channels");
|
||||
while (channel != NULL)
|
||||
{
|
||||
if (channel->ch_refcount == 0 && !channel_still_useful(channel))
|
||||
@ -2182,7 +2293,8 @@ channel_parse_messages(void)
|
||||
part = PART_SOCK;
|
||||
continue;
|
||||
}
|
||||
if (channel->ch_part[part].ch_fd != INVALID_FD)
|
||||
if (channel->ch_part[part].ch_fd != INVALID_FD
|
||||
|| channel_has_readahead(channel, part))
|
||||
{
|
||||
/* Increase the refcount, in case the handler causes the channel
|
||||
* to be unreferenced or closed. */
|
||||
@ -2208,6 +2320,16 @@ channel_parse_messages(void)
|
||||
part = PART_SOCK;
|
||||
}
|
||||
}
|
||||
|
||||
if (channel_need_redraw && must_redraw)
|
||||
{
|
||||
channel_need_redraw = FALSE;
|
||||
update_screen(0);
|
||||
setcursor();
|
||||
cursor_on();
|
||||
out_flush();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
67
src/eval.c
67
src/eval.c
@ -9976,12 +9976,45 @@ handle_mode(typval_T *item, jobopt_T *opt, ch_mode_T *modep, int jo)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_io(typval_T *item, int part, jobopt_T *opt)
|
||||
{
|
||||
char_u *val = get_tv_string(item);
|
||||
|
||||
opt->jo_set |= JO_OUT_IO << (part - PART_OUT);
|
||||
if (STRCMP(val, "null") == 0)
|
||||
opt->jo_io[part] = JIO_NULL;
|
||||
else if (STRCMP(val, "pipe") == 0)
|
||||
opt->jo_io[part] = JIO_PIPE;
|
||||
else if (STRCMP(val, "file") == 0)
|
||||
opt->jo_io[part] = JIO_FILE;
|
||||
else if (STRCMP(val, "buffer") == 0)
|
||||
opt->jo_io[part] = JIO_BUFFER;
|
||||
else if (STRCMP(val, "out") == 0 && part == PART_ERR)
|
||||
opt->jo_io[part] = JIO_OUT;
|
||||
else
|
||||
{
|
||||
EMSG2(_(e_invarg2), val);
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_job_options(jobopt_T *opt)
|
||||
{
|
||||
vim_memset(opt, 0, sizeof(jobopt_T));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the PART_ number from the first character of an option name.
|
||||
*/
|
||||
static int
|
||||
part_from_char(int c)
|
||||
{
|
||||
return c == 'i' ? PART_IN : c == 'o' ? PART_OUT: PART_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the option entries from the dict in "tv", parse them and put the result
|
||||
* in "opt".
|
||||
@ -9996,6 +10029,7 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
|
||||
dict_T *dict;
|
||||
int todo;
|
||||
hashitem_T *hi;
|
||||
int part;
|
||||
|
||||
opt->jo_set = 0;
|
||||
if (tv->v_type == VAR_UNKNOWN)
|
||||
@ -10046,6 +10080,27 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
|
||||
== FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
else if (STRCMP(hi->hi_key, "in-io") == 0
|
||||
|| STRCMP(hi->hi_key, "out-io") == 0
|
||||
|| STRCMP(hi->hi_key, "err-io") == 0)
|
||||
{
|
||||
if (!(supported & JO_OUT_IO))
|
||||
break;
|
||||
if (handle_io(item, part_from_char(*hi->hi_key), opt) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
else if (STRCMP(hi->hi_key, "in-name") == 0
|
||||
|| STRCMP(hi->hi_key, "out-name") == 0
|
||||
|| STRCMP(hi->hi_key, "err-name") == 0)
|
||||
{
|
||||
part = part_from_char(*hi->hi_key);
|
||||
|
||||
if (!(supported & JO_OUT_IO))
|
||||
break;
|
||||
opt->jo_set |= JO_OUT_NAME << (part - PART_OUT);
|
||||
opt->jo_io_name[part] =
|
||||
get_tv_string_buf_chk(item, opt->jo_io_name_buf[part]);
|
||||
}
|
||||
else if (STRCMP(hi->hi_key, "callback") == 0)
|
||||
{
|
||||
if (!(supported & JO_CALLBACK))
|
||||
@ -10178,6 +10233,13 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
for (part = PART_OUT; part <= PART_IN; ++part)
|
||||
if (opt->jo_io[part] == JIO_BUFFER && opt->jo_io_name[part] == NULL)
|
||||
{
|
||||
EMSG(_("E915: Missing name for buffer"));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@ -10216,7 +10278,10 @@ f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
channel_T *channel = get_channel_arg(&argvars[0]);
|
||||
|
||||
if (channel != NULL)
|
||||
{
|
||||
channel_close(channel, FALSE);
|
||||
channel_clear(channel);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FEAT_JOB
|
||||
@ -14948,7 +15013,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
opt.jo_mode = MODE_NL;
|
||||
if (get_job_options(&argvars[1], &opt,
|
||||
JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL
|
||||
+ JO_STOPONEXIT + JO_EXIT_CB) == FAIL)
|
||||
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
|
||||
return;
|
||||
job_set_options(job, &opt);
|
||||
|
||||
|
@ -99,8 +99,11 @@ netbeans_close(void)
|
||||
{
|
||||
netbeans_send_disconnect();
|
||||
if (nb_channel != NULL)
|
||||
{
|
||||
/* Close the socket and remove the input handlers. */
|
||||
channel_close(nb_channel, TRUE);
|
||||
channel_clear(nb_channel);
|
||||
}
|
||||
nb_channel = NULL;
|
||||
}
|
||||
|
||||
|
@ -1347,6 +1347,7 @@ typedef struct {
|
||||
|
||||
cbq_T ch_cb_head; /* dummy node for per-request callbacks */
|
||||
char_u *ch_callback; /* call when a msg is not handled */
|
||||
buf_T *ch_buffer; /* buffer to read from or write to */
|
||||
} chanpart_T;
|
||||
|
||||
struct channel_S {
|
||||
@ -1395,6 +1396,12 @@ struct channel_S {
|
||||
#define JO_ID 0x2000 /* "id" */
|
||||
#define JO_STOPONEXIT 0x4000 /* "stoponexit" */
|
||||
#define JO_EXIT_CB 0x8000 /* "exit-cb" */
|
||||
#define JO_OUT_IO 0x10000 /* "out-io" */
|
||||
#define JO_ERR_IO 0x20000 /* "err-io" (JO_OUT_IO << 1) */
|
||||
#define JO_IN_IO 0x40000 /* "in-io" (JO_OUT_IO << 2) */
|
||||
#define JO_OUT_NAME 0x80000 /* "out-name" */
|
||||
#define JO_ERR_NAME 0x100000 /* "err-name" (JO_OUT_NAME << 1) */
|
||||
#define JO_IN_NAME 0x200000 /* "in-name" (JO_OUT_NAME << 2) */
|
||||
#define JO_ALL 0xffffff
|
||||
|
||||
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
||||
@ -1402,6 +1409,14 @@ struct channel_S {
|
||||
(JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK)
|
||||
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
|
||||
|
||||
typedef enum {
|
||||
JIO_NULL,
|
||||
JIO_PIPE,
|
||||
JIO_FILE,
|
||||
JIO_BUFFER,
|
||||
JIO_OUT
|
||||
} job_io_T;
|
||||
|
||||
/*
|
||||
* Options for job and channel commands.
|
||||
*/
|
||||
@ -1413,6 +1428,11 @@ typedef struct
|
||||
ch_mode_T jo_in_mode;
|
||||
ch_mode_T jo_out_mode;
|
||||
ch_mode_T jo_err_mode;
|
||||
|
||||
job_io_T jo_io[4]; /* PART_OUT, PART_ERR, PART_IN */
|
||||
char_u jo_io_name_buf[4][NUMBUFLEN];
|
||||
char_u *jo_io_name[4]; /* not allocated! */
|
||||
|
||||
char_u *jo_callback; /* not allocated! */
|
||||
char_u *jo_out_cb; /* not allocated! */
|
||||
char_u *jo_err_cb; /* not allocated! */
|
||||
|
@ -748,6 +748,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1426,
|
||||
/**/
|
||||
1425,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user