Patch 7.4.2298
Problem:    It is not possible to close the "in" part of a channel.
Solution:   Add ch_close_in().
Files:      src/evalfunc.c, src/channel.c, src/proto/channel.pro,
            src/testdir/test_channel.vim, runtime/doc/eval.txt,
            runtime/doc/channel.txt


*** ../vim-7.4.2297/src/evalfunc.c      2016-08-29 22:48:12.125106388 +0200
--- src/evalfunc.c      2016-09-01 15:01:20.633367595 +0200
***************
*** 77,82 ****
--- 77,83 ----
  #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,504 ****
--- 500,506 ----
  #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,1797 ****
--- 1794,1811 ----
  }
  
  /*
+  * "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
*** ../vim-7.4.2297/src/channel.c       2016-09-01 14:35:19.306759126 +0200
--- src/channel.c       2016-09-01 14:51:50.506250892 +0200
***************
*** 2736,2741 ****
--- 2736,2750 ----
  }
  
  /*
+  * 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
*** ../vim-7.4.2297/src/proto/channel.pro       2016-07-07 20:45:00.740424639 
+0200
--- src/proto/channel.pro       2016-09-01 14:54:28.136900042 +0200
***************
*** 27,32 ****
--- 27,33 ----
  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);
*** ../vim-7.4.2297/src/testdir/test_channel.vim        2016-09-01 
14:35:19.306759126 +0200
--- src/testdir/test_channel.vim        2016-09-01 15:00:37.309738436 +0200
***************
*** 792,813 ****
    call Run_test_pipe_from_buffer(0)
  endfunc
  
! func Run_pipe_through_sort(all)
    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'}
    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))
    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
--- 792,823 ----
    call Run_test_pipe_from_buffer(0)
  endfunc
  
! func Run_pipe_through_sort(all, use_buffer)
    if !executable('sort') || !has('job')
      return
    endif
!   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,835 ****
  
    call job_stop(g:job)
    unlet g:job
!   bwipe! sortin
    bwipe! sortout
  endfunc
  
  func Test_pipe_through_sort_all()
    call ch_log('Test_pipe_through_sort_all()')
!   call Run_pipe_through_sort(1)
  endfunc
  
  func Test_pipe_through_sort_some()
    call ch_log('Test_pipe_through_sort_some()')
!   call Run_pipe_through_sort(0)
  endfunc
  
  func Test_pipe_to_nameless_buffer()
--- 828,852 ----
  
    call job_stop(g:job)
    unlet g:job
!   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, 1)
  endfunc
  
  func Test_pipe_through_sort_some()
    call ch_log('Test_pipe_through_sort_some()')
!   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()
*** ../vim-7.4.2297/runtime/doc/eval.txt        2016-08-29 21:55:16.356528521 
+0200
--- runtime/doc/eval.txt        2016-09-01 14:52:54.545702027 +0200
***************
*** 1973,1999 ****
                                any     call {func} with arguments {arglist}
  ceil({expr})                  Float   round {expr} up
  ch_close({handle})            none    close {handle}
  ch_evalexpr({handle}, {expr} [, {options}])
                                any     evaluate {expr} on JSON {handle}
  ch_evalraw({handle}, {string} [, {options}])
                                any     evaluate {string} on raw {handle}
  ch_getbufnr({handle}, {what}) Number  get buffer number for {handle}/{what}
  ch_getjob({channel})          Job     get the Job of {channel}
! ch_info({handle})             String  info about channel  {handle}
  ch_log({msg} [, {handle}])    none    write {msg} in the channel log file
  ch_logfile({fname} [, {mode}])        none    start logging channel activity
  ch_open({address} [, {options}])
!                               Channel open a channel to {address}
! ch_read({handle} [, {options}]) String  read from  {handle}
  ch_readraw({handle} [, {options}])
!                               String  read raw from  {handle}
  ch_sendexpr({handle}, {expr} [, {options}])
                                any     send {expr} over JSON {handle}
  ch_sendraw({handle}, {string} [, {options}])
                                any     send {string} over raw {handle}
  ch_setoptions({handle}, {options})
                                none    set options for {handle}
! ch_status({handle})           String  status of channel  {handle}
  changenr()                    Number  current change number
  char2nr({expr}[, {utf8}])     Number  ASCII/UTF8 value of first char in {expr}
  cindent({lnum})                       Number  C indent for line {lnum}
--- 2009,2036 ----
                                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}])
                                any     evaluate {string} on raw {handle}
  ch_getbufnr({handle}, {what}) Number  get buffer number for {handle}/{what}
  ch_getjob({channel})          Job     get the Job of {channel}
! ch_info({handle})             String  info about channel {handle}
  ch_log({msg} [, {handle}])    none    write {msg} in the channel log file
  ch_logfile({fname} [, {mode}])        none    start logging channel activity
  ch_open({address} [, {options}])
!                               Channel open a channel to {address}
! ch_read({handle} [, {options}]) String        read from {handle}
  ch_readraw({handle} [, {options}])
!                               String  read raw from {handle}
  ch_sendexpr({handle}, {expr} [, {options}])
                                any     send {expr} over JSON {handle}
  ch_sendraw({handle}, {string} [, {options}])
                                any     send {string} over raw {handle}
  ch_setoptions({handle}, {options})
                                none    set options for {handle}
! ch_status({handle})           String  status of channel {handle}
  changenr()                    Number  current change number
  char2nr({expr}[, {utf8}])     Number  ASCII/UTF8 value of first char in {expr}
  cindent({lnum})                       Number  C indent for line {lnum}
***************
*** 2930,2951 ****
     :endif
  <             In a GUI dialog, buttons are used.  The layout of the buttons
                depends on the 'v' flag in 'guioptions'.  If it is included,
!               the buttons are always put vertically.  Otherwise,  confirm()
                tries to put the buttons in one horizontal line.  If they
                don't fit, a vertical layout is used anyway.  For some systems
                the horizontal layout is always used.
  
! ch_close({channel})                                           *ch_close()*
!               Close {channel}.  See |channel-close|.
                {only available when compiled with the |+channel| feature}
  
! ch_evalexpr({channel}, {expr} [, {options}])                  *ch_evalexpr()*
!               Send {expr} over {channel}.  The {expr} is encoded
                according to the type of channel.  The function cannot be used
!               with a raw channel.  See |channel-use|.  *E912*
                                                                *E917*
                {options} must be a Dictionary.  It must not have a "callback"
!               entry.
  
                ch_evalexpr() waits for a response and returns the decoded
                expression.  When there is an error or timeout it returns an
--- 2973,3006 ----
     :endif
  <             In a GUI dialog, buttons are used.  The layout of the buttons
                depends on the 'v' flag in 'guioptions'.  If it is included,
!               the buttons are always put vertically.  Otherwise,  confirm()
                tries to put the buttons in one horizontal line.  If they
                don't fit, a vertical layout is used anyway.  For some systems
                the horizontal layout is always used.
  
! 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}
! 
! ch_evalexpr({handle}, {expr} [, {options}])                   *ch_evalexpr()*
!               Send {expr} over {handle}.  The {expr} is encoded
                according to the type of channel.  The function cannot be used
!               with a raw channel.  See |channel-use|.
!               {handle} can be Channel or a Job that has a Channel.
                                                                *E917*
                {options} must be a Dictionary.  It must not have a "callback"
!               entry.  It can have a "timeout" entry to specify the timeout
!               for this specific request.
  
                ch_evalexpr() waits for a response and returns the decoded
                expression.  When there is an error or timeout it returns an
*** ../vim-7.4.2297/runtime/doc/channel.txt     2016-08-26 17:58:33.590124381 
+0200
--- runtime/doc/channel.txt     2016-09-01 14:50:09.963112813 +0200
***************
*** 490,495 ****
--- 501,528 ----
  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).
+ 
+ 
+ Reading job output in the close callback ~
+                                                       *read-in-close-cb*
+ If the job can take some time and you don't need intermediate results, you can
+ add a close callback and read the output there: >
+ 
+       func! CloseHandler(channel)
+         while ch_status(a:channel) == 'buffered'
+           echomsg ch_read(a:channel)
+         endwhile
+       endfunc
+       let job = job_start(command, {'close_cb': 'CloseHandler'})
+ 
+ You will want to do something more useful than "echomsg".
  
  ==============================================================================
  9. Starting a job without a channel                   *job-start-nochannel*
*** ../vim-7.4.2297/src/version.c       2016-09-01 14:35:19.306759126 +0200
--- src/version.c       2016-09-01 14:50:41.454842822 +0200
***************
*** 765,766 ****
--- 765,768 ----
  {   /* Add new patch number below this line */
+ /**/
+     2298,
  /**/


-- 
Would you care for a drink?   I mean, if it were, like,
disabled and you had to look after it?

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui