forked from aniani/vim
patch 7.4.1506
Problem: Job cannot read from a file. Solution: Implement reading from a file for Unix.
This commit is contained in:
12
src/eval.c
12
src/eval.c
@@ -15118,6 +15118,7 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
garray_T ga;
|
garray_T ga;
|
||||||
#endif
|
#endif
|
||||||
jobopt_T opt;
|
jobopt_T opt;
|
||||||
|
int part;
|
||||||
|
|
||||||
rettv->v_type = VAR_JOB;
|
rettv->v_type = VAR_JOB;
|
||||||
job = job_alloc();
|
job = job_alloc();
|
||||||
@@ -15135,6 +15136,17 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
|
|||||||
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
|
+ JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Check that when io is "file" that there is a file name. */
|
||||||
|
for (part = PART_OUT; part <= PART_IN; ++part)
|
||||||
|
if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT)))
|
||||||
|
&& opt.jo_io[part] == JIO_FILE
|
||||||
|
&& (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT)))
|
||||||
|
|| *opt.jo_io_name[part] == NUL))
|
||||||
|
{
|
||||||
|
EMSG(_("E920: -io file requires -name to be set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
|
if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER)
|
||||||
{
|
{
|
||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
|
@@ -5045,6 +5045,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
int fd_out[2]; /* for stdout */
|
int fd_out[2]; /* for stdout */
|
||||||
int fd_err[2]; /* for stderr */
|
int fd_err[2]; /* for stderr */
|
||||||
channel_T *channel = NULL;
|
channel_T *channel = NULL;
|
||||||
|
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
|
||||||
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
|
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
|
||||||
|
|
||||||
/* default is to fail */
|
/* default is to fail */
|
||||||
@@ -5055,8 +5056,22 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
|
|
||||||
/* TODO: without the channel feature connect the child to /dev/null? */
|
/* TODO: without the channel feature connect the child to /dev/null? */
|
||||||
/* Open pipes for stdin, stdout, stderr. */
|
/* Open pipes for stdin, stdout, stderr. */
|
||||||
if (pipe(fd_in) < 0 || pipe(fd_out) < 0
|
if (use_file_for_in)
|
||||||
|| (!use_out_for_err && pipe(fd_err) < 0))
|
{
|
||||||
|
char_u *fname = options->jo_io_name[PART_IN];
|
||||||
|
|
||||||
|
fd_in[0] = mch_open((char *)fname, O_RDONLY, 0);
|
||||||
|
if (fd_in[0] < 0)
|
||||||
|
{
|
||||||
|
EMSG2(_(e_notopen), fname);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pipe(fd_in) < 0)
|
||||||
|
goto failed;
|
||||||
|
if (pipe(fd_out) < 0)
|
||||||
|
goto failed;
|
||||||
|
if (!use_out_for_err && pipe(fd_err) < 0)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
channel = add_channel();
|
channel = add_channel();
|
||||||
@@ -5088,7 +5103,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
/* TODO: re-enable this when pipes connect without a channel */
|
/* TODO: re-enable this when pipes connect without a channel */
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
/* set up stdin for the child */
|
/* set up stdin for the child */
|
||||||
close(fd_in[1]);
|
if (!use_file_for_in)
|
||||||
|
close(fd_in[1]);
|
||||||
close(0);
|
close(0);
|
||||||
ignored = dup(fd_in[0]);
|
ignored = dup(fd_in[0]);
|
||||||
close(fd_in[0]);
|
close(fd_in[0]);
|
||||||
@@ -5130,12 +5146,15 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
|
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
/* child stdin, stdout and stderr */
|
/* child stdin, stdout and stderr */
|
||||||
close(fd_in[0]);
|
if (!use_file_for_in)
|
||||||
|
close(fd_in[0]);
|
||||||
close(fd_out[1]);
|
close(fd_out[1]);
|
||||||
if (!use_out_for_err)
|
if (!use_out_for_err)
|
||||||
close(fd_err[1]);
|
close(fd_err[1]);
|
||||||
channel_set_pipes(channel, fd_in[1], fd_out[0],
|
channel_set_pipes(channel,
|
||||||
use_out_for_err ? INVALID_FD : fd_err[0]);
|
use_file_for_in ? INVALID_FD : fd_in[1],
|
||||||
|
fd_out[0],
|
||||||
|
use_out_for_err ? INVALID_FD : fd_err[0]);
|
||||||
channel_set_job(channel, job, options);
|
channel_set_job(channel, job, options);
|
||||||
# ifdef FEAT_GUI
|
# ifdef FEAT_GUI
|
||||||
channel_gui_register(channel);
|
channel_gui_register(channel);
|
||||||
@@ -5151,7 +5170,8 @@ failed: ;
|
|||||||
if (fd_in[0] >= 0)
|
if (fd_in[0] >= 0)
|
||||||
{
|
{
|
||||||
close(fd_in[0]);
|
close(fd_in[0]);
|
||||||
close(fd_in[1]);
|
if (!use_file_for_in)
|
||||||
|
close(fd_in[1]);
|
||||||
}
|
}
|
||||||
if (fd_out[0] >= 0)
|
if (fd_out[0] >= 0)
|
||||||
{
|
{
|
||||||
|
@@ -5000,6 +5000,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
|
|||||||
HANDLE jo;
|
HANDLE jo;
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
channel_T *channel;
|
channel_T *channel;
|
||||||
|
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
|
||||||
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
|
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
|
||||||
HANDLE ifd[2];
|
HANDLE ifd[2];
|
||||||
HANDLE ofd[2];
|
HANDLE ofd[2];
|
||||||
@@ -5035,13 +5036,25 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
|
|||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = TRUE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
|
if (use_file_for_in)
|
||||||
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)
|
{
|
||||||
|| !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
|
char_u *fname = options->jo_io_name[PART_IN];
|
||||||
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)
|
|
||||||
|| (!use_out_for_err
|
// TODO
|
||||||
|
EMSG2(_(e_notopen), fname);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
|
||||||
|
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
|
||||||
|
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if (!use_out_for_err
|
||||||
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
|
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
|
||||||
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0))))
|
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
|
||||||
goto failed;
|
goto failed;
|
||||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
si.hStdInput = ifd[0];
|
si.hStdInput = ifd[0];
|
||||||
|
@@ -524,6 +524,31 @@ func Test_nl_err_to_out_pipe()
|
|||||||
endtry
|
endtry
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_nl_read_file()
|
||||||
|
if !has('job')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
" TODO: make this work for MS-Windows.
|
||||||
|
if !has('unix')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call ch_log('Test_nl_read_file()')
|
||||||
|
call writefile(['echo something', 'echoerr wrong', 'double this'], 'Xinput')
|
||||||
|
let job = job_start(s:python . " test_channel_pipe.py",
|
||||||
|
\ {'in-io': 'file', 'in-name': 'Xinput'})
|
||||||
|
call assert_equal("run", job_status(job))
|
||||||
|
try
|
||||||
|
let handle = job_getchannel(job)
|
||||||
|
call assert_equal("something", ch_readraw(handle))
|
||||||
|
call assert_equal("wrong", ch_readraw(handle, {'part': 'err'}))
|
||||||
|
call assert_equal("this", ch_readraw(handle))
|
||||||
|
call assert_equal("AND this", ch_readraw(handle))
|
||||||
|
finally
|
||||||
|
call job_stop(job)
|
||||||
|
call delete('Xinput')
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_pipe_to_buffer()
|
func Test_pipe_to_buffer()
|
||||||
if !has('job')
|
if !has('job')
|
||||||
return
|
return
|
||||||
@@ -556,7 +581,6 @@ func Test_pipe_from_buffer()
|
|||||||
if !has('job')
|
if !has('job')
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
call ch_logfile('channellog', 'w')
|
|
||||||
call ch_log('Test_pipe_from_buffer()')
|
call ch_log('Test_pipe_from_buffer()')
|
||||||
|
|
||||||
sp pipe-input
|
sp pipe-input
|
||||||
@@ -574,7 +598,6 @@ call ch_logfile('channellog', 'w')
|
|||||||
finally
|
finally
|
||||||
call job_stop(job)
|
call job_stop(job)
|
||||||
endtry
|
endtry
|
||||||
call ch_logfile('')
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_pipe_to_nameless_buffer()
|
func Test_pipe_to_nameless_buffer()
|
||||||
|
@@ -743,6 +743,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1506,
|
||||||
/**/
|
/**/
|
||||||
1505,
|
1505,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user