# HG changeset patch # User Christian Brabandt # Date 1472735708 -7200 # Node ID d4b7232fc63a51b7cd8adea06cdff61cd3a18080 # Parent ce81fd2d3556919871bb428ee010bbf21891bc67 commit https://github.com/vim/vim/commit/0874a83e9be1b39fdb217f02b427bf1d6133a4d8 Author: Bram Moolenaar Date: Thu Sep 1 15:11:51 2016 +0200 patch 7.4.2298 Problem: It is not possible to close the "in" part of a channel. Solution: Add ch_close_in(). diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -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 @@ -501,6 +501,10 @@ A special mode is when "in_top" is set t 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 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 as NL bytes). diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -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 @@ -2009,6 +2009,7 @@ call({func}, {arglist} [, {dict}]) any call {func} with arguments {arglist} ceil({expr}) Float round {expr} up ch_close({handle}) none close {handle} +ch_close_in({handle}) none close in part of {handle} ch_evalexpr({handle}, {expr} [, {options}]) any evaluate {expr} on JSON {handle} ch_evalraw({handle}, {string} [, {options}]) @@ -2980,6 +2981,14 @@ confirm({msg} [, {choices} [, {default} ch_close({handle}) *ch_close()* Close {handle}. See |channel-close|. {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} diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -2736,6 +2736,15 @@ channel_close(channel_T *channel, int in } /* + * 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". */ static void diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -77,6 +77,7 @@ static void f_ceil(typval_T *argvars, ty #endif #ifdef FEAT_JOB_CHANNEL 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_evalraw(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 #ifdef FEAT_JOB_CHANNEL {"ch_close", 1, 1, f_ch_close}, + {"ch_close_in", 1, 1, f_ch_close_in}, {"ch_evalexpr", 2, 3, f_ch_evalexpr}, {"ch_evalraw", 2, 3, f_ch_evalraw}, {"ch_getbufnr", 2, 2, f_ch_getbufnr}, @@ -1792,6 +1794,18 @@ f_ch_close(typval_T *argvars, typval_T * } /* + * "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 */ static void diff --git a/src/proto/channel.pro b/src/proto/channel.pro --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -27,6 +27,7 @@ int channel_is_open(channel_T *channel); char *channel_status(channel_T *channel); void channel_info(channel_T *channel, dict_T *dict); 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_free_all(void); char_u *channel_read_block(channel_T *channel, int part, int timeout); diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -792,22 +792,32 @@ func Test_pipe_from_buffer_nr() call Run_test_pipe_from_buffer(0) endfunc -func Run_pipe_through_sort(all) +func Run_pipe_through_sort(all, use_buffer) if !executable('sort') || !has('job') return endif - split sortin - call setline(1, ['ccc', 'aaa', 'ddd', 'bbb', 'eee']) - let options = {'in_io': 'buffer', 'in_name': 'sortin', - \ 'out_io': 'buffer', 'out_name': 'sortout'} + let options = {'out_io': 'buffer', 'out_name': 'sortout'} + if a:use_buffer + split sortin + call setline(1, ['ccc', 'aaa', 'ddd', 'bbb', 'eee']) + let options.in_io = 'buffer' + let options.in_name = 'sortin' + endif if !a:all let options.in_top = 2 let options.in_bot = 4 endif let g:job = job_start('sort', options) 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 assert_equal("dead", job_status(g:job)) + sp sortout call assert_equal('Reading from channel output...', getline(1)) if a:all @@ -818,18 +828,25 @@ func Run_pipe_through_sort(all) call job_stop(g:job) unlet g:job - bwipe! sortin + if a:use_buffer + bwipe! sortin + endif bwipe! sortout endfunc func 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 func 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 func Test_pipe_to_nameless_buffer() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2298, +/**/ 2297, /**/ 2296,