0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

patch 7.4.2298

Problem:    It is not possible to close the "in" part of a channel.
Solution:   Add ch_close_in().
This commit is contained in:
Bram Moolenaar
2016-09-01 15:11:51 +02:00
parent d8b554904d
commit 0874a83e9b
7 changed files with 66 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
*channel.txt* For Vim version 7.4. Last change: 2016 Aug 31 *channel.txt* For Vim version 7.4. Last change: 2016 Sep 01
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -501,6 +501,10 @@ A special mode is when "in_top" is set to zero and "in_bot" is not set: Every
time a line is added to the buffer, the last-but-one line will be send to the time a line is added to the buffer, the last-but-one line will be send to the
job stdin. This allows for editing the last line and sending it when pressing job stdin. This allows for editing the last line and sending it when pressing
Enter. Enter.
*channel-close-in*
When not using the special mode the pipe or socket will be closed after the
last line has been written. This signals the reading end that the input
finished. You can also use |ch_close_in()| to close it sooner.
NUL bytes in the text will be passed to the job (internally Vim stores these NUL bytes in the text will be passed to the job (internally Vim stores these
as NL bytes). as NL bytes).

View File

@@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.4. Last change: 2016 Aug 31 *eval.txt* For Vim version 7.4. Last change: 2016 Sep 01
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -2009,6 +2009,7 @@ call({func}, {arglist} [, {dict}])
any call {func} with arguments {arglist} any call {func} with arguments {arglist}
ceil({expr}) Float round {expr} up ceil({expr}) Float round {expr} up
ch_close({handle}) none close {handle} ch_close({handle}) none close {handle}
ch_close_in({handle}) none close in part of {handle}
ch_evalexpr({handle}, {expr} [, {options}]) ch_evalexpr({handle}, {expr} [, {options}])
any evaluate {expr} on JSON {handle} any evaluate {expr} on JSON {handle}
ch_evalraw({handle}, {string} [, {options}]) ch_evalraw({handle}, {string} [, {options}])
@@ -2980,6 +2981,14 @@ confirm({msg} [, {choices} [, {default} [, {type}]]])
ch_close({handle}) *ch_close()* ch_close({handle}) *ch_close()*
Close {handle}. See |channel-close|. Close {handle}. See |channel-close|.
{handle} can be Channel or a Job that has a Channel. {handle} can be Channel or a Job that has a Channel.
A close callback is not invoked.
{only available when compiled with the |+channel| feature}
ch_close_in({handle}) *ch_close_in()*
Close the "in" part of {handle}. See |channel-close-in|.
{handle} can be Channel or a Job that has a Channel.
A close callback is not invoked.
{only available when compiled with the |+channel| feature} {only available when compiled with the |+channel| feature}

View File

@@ -2735,6 +2735,15 @@ channel_close(channel_T *channel, int invoke_close_cb)
channel->ch_nb_close_cb = NULL; channel->ch_nb_close_cb = NULL;
} }
/*
* Close the "in" part channel "channel".
*/
void
channel_close_in(channel_T *channel)
{
may_close_part(&channel->CH_IN_FD);
}
/* /*
* Clear the read buffer on "channel"/"part". * Clear the read buffer on "channel"/"part".
*/ */

View File

@@ -77,6 +77,7 @@ static void f_ceil(typval_T *argvars, typval_T *rettv);
#endif #endif
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
static void f_ch_close(typval_T *argvars, typval_T *rettv); static void f_ch_close(typval_T *argvars, typval_T *rettv);
static void f_ch_close_in(typval_T *argvars, typval_T *rettv);
static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv); static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv);
static void f_ch_evalraw(typval_T *argvars, typval_T *rettv); static void f_ch_evalraw(typval_T *argvars, typval_T *rettv);
static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv); static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv);
@@ -499,6 +500,7 @@ static struct fst
#endif #endif
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
{"ch_close", 1, 1, f_ch_close}, {"ch_close", 1, 1, f_ch_close},
{"ch_close_in", 1, 1, f_ch_close_in},
{"ch_evalexpr", 2, 3, f_ch_evalexpr}, {"ch_evalexpr", 2, 3, f_ch_evalexpr},
{"ch_evalraw", 2, 3, f_ch_evalraw}, {"ch_evalraw", 2, 3, f_ch_evalraw},
{"ch_getbufnr", 2, 2, f_ch_getbufnr}, {"ch_getbufnr", 2, 2, f_ch_getbufnr},
@@ -1791,6 +1793,18 @@ f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
} }
} }
/*
* "ch_close()" function
*/
static void
f_ch_close_in(typval_T *argvars, typval_T *rettv UNUSED)
{
channel_T *channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0);
if (channel != NULL)
channel_close_in(channel);
}
/* /*
* "ch_getbufnr()" function * "ch_getbufnr()" function
*/ */

View File

@@ -27,6 +27,7 @@ int channel_is_open(channel_T *channel);
char *channel_status(channel_T *channel); char *channel_status(channel_T *channel);
void channel_info(channel_T *channel, dict_T *dict); void channel_info(channel_T *channel, dict_T *dict);
void channel_close(channel_T *channel, int invoke_close_cb); void channel_close(channel_T *channel, int invoke_close_cb);
void channel_close_in(channel_T *channel);
void channel_clear(channel_T *channel); void channel_clear(channel_T *channel);
void channel_free_all(void); void channel_free_all(void);
char_u *channel_read_block(channel_T *channel, int part, int timeout); char_u *channel_read_block(channel_T *channel, int part, int timeout);

View File

@@ -792,22 +792,32 @@ func Test_pipe_from_buffer_nr()
call Run_test_pipe_from_buffer(0) call Run_test_pipe_from_buffer(0)
endfunc endfunc
func Run_pipe_through_sort(all) func Run_pipe_through_sort(all, use_buffer)
if !executable('sort') || !has('job') if !executable('sort') || !has('job')
return return
endif endif
let options = {'out_io': 'buffer', 'out_name': 'sortout'}
if a:use_buffer
split sortin split sortin
call setline(1, ['ccc', 'aaa', 'ddd', 'bbb', 'eee']) call setline(1, ['ccc', 'aaa', 'ddd', 'bbb', 'eee'])
let options = {'in_io': 'buffer', 'in_name': 'sortin', let options.in_io = 'buffer'
\ 'out_io': 'buffer', 'out_name': 'sortout'} let options.in_name = 'sortin'
endif
if !a:all if !a:all
let options.in_top = 2 let options.in_top = 2
let options.in_bot = 4 let options.in_bot = 4
endif endif
let g:job = job_start('sort', options) let g:job = job_start('sort', options)
call assert_equal("run", job_status(g:job)) call assert_equal("run", job_status(g:job))
if !a:use_buffer
call ch_sendraw(g:job, "ccc\naaa\nddd\nbbb\neee\n")
call ch_close_in(g:job)
endif
call WaitFor('job_status(g:job) == "dead"') call WaitFor('job_status(g:job) == "dead"')
call assert_equal("dead", job_status(g:job)) call assert_equal("dead", job_status(g:job))
sp sortout sp sortout
call assert_equal('Reading from channel output...', getline(1)) call assert_equal('Reading from channel output...', getline(1))
if a:all if a:all
@@ -818,18 +828,25 @@ func Run_pipe_through_sort(all)
call job_stop(g:job) call job_stop(g:job)
unlet g:job unlet g:job
if a:use_buffer
bwipe! sortin bwipe! sortin
endif
bwipe! sortout bwipe! sortout
endfunc endfunc
func Test_pipe_through_sort_all() func Test_pipe_through_sort_all()
call ch_log('Test_pipe_through_sort_all()') call ch_log('Test_pipe_through_sort_all()')
call Run_pipe_through_sort(1) call Run_pipe_through_sort(1, 1)
endfunc endfunc
func Test_pipe_through_sort_some() func Test_pipe_through_sort_some()
call ch_log('Test_pipe_through_sort_some()') call ch_log('Test_pipe_through_sort_some()')
call Run_pipe_through_sort(0) call Run_pipe_through_sort(0, 1)
endfunc
func Test_pipe_through_sort_feed()
call ch_log('Test_pipe_through_sort_feed()')
call Run_pipe_through_sort(1, 0)
endfunc endfunc
func Test_pipe_to_nameless_buffer() func Test_pipe_to_nameless_buffer()

View File

@@ -763,6 +763,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 */
/**/
2298,
/**/ /**/
2297, 2297,
/**/ /**/