changeset 10054:d4b7232fc63a v7.4.2298

commit https://github.com/vim/vim/commit/0874a83e9be1b39fdb217f02b427bf1d6133a4d8 Author: Bram Moolenaar <Bram@vim.org> 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().
author Christian Brabandt <cb@256bit.org>
date Thu, 01 Sep 2016 15:15:08 +0200
parents ce81fd2d3556
children 7990eba2d4e6
files runtime/doc/channel.txt runtime/doc/eval.txt src/channel.c src/evalfunc.c src/proto/channel.pro src/testdir/test_channel.vim src/version.c
diffstat 7 files changed, 66 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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).
--- 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}
 
--- 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
--- 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
--- 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);
--- 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()
--- 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,