Patch 7.4.1857
Problem:    When a channel appends to a buffer that is 'nomodifiable' there is
            an error but appending is done anyway.
Solution:   Add the 'modifiable' option.  Refuse to write to a 'nomodifiable'
            when the value is 1.
Files:      src/structs.h, src/channel.c, src/testdir/test_channel.vim,
            runtime/doc/channel.txt


*** ../vim-7.4.1856/src/structs.h       2016-05-24 15:43:46.695296634 +0200
--- src/structs.h       2016-05-29 15:36:14.029360356 +0200
***************
*** 1401,1406 ****
--- 1401,1408 ----
      partial_T *ch_partial;
  
      buf_T     *ch_buffer;     /* buffer to read from or write to */
+     int               ch_nomodifiable; /* TRUE when buffer can be 
'nomodifiable' */
+     int               ch_nomod_error; /* TRUE when e_modifiable was given */
      int               ch_buf_append;  /* write appended lines instead top-bot 
*/
      linenr_T  ch_buf_top;     /* next line to send */
      linenr_T  ch_buf_bot;     /* last line to send */
***************
*** 1477,1482 ****
--- 1479,1486 ----
  #define JO_IN_BUF         0x4000000   /* "in_buf" (JO_OUT_BUF << 2) */
  #define JO_CHANNEL        0x8000000   /* "channel" */
  #define JO_BLOCK_WRITE            0x10000000  /* "block_write" */
+ #define JO_OUT_MODIFIABLE   0x20000000        /* "out_modifiable" */
+ #define JO_ERR_MODIFIABLE   0x40000000        /* "err_modifiable" (JO_OUT_ << 
1) */
  #define JO_ALL                    0x7fffffff
  
  #define JO_MODE_ALL   (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
***************
*** 1500,1505 ****
--- 1504,1510 ----
      char_u    jo_io_name_buf[4][NUMBUFLEN];
      char_u    *jo_io_name[4]; /* not allocated! */
      int               jo_io_buf[4];
+     int               jo_modifiable[4];
      channel_T *jo_channel;
  
      linenr_T  jo_in_top;
*** ../vim-7.4.1856/src/channel.c       2016-05-28 22:22:28.826213562 +0200
--- src/channel.c       2016-05-29 16:11:42.133331082 +0200
***************
*** 1209,1217 ****
        }
        if (buf != NULL)
        {
!           ch_logs(channel, "writing out to buffer '%s'",
                                                       (char *)buf->b_ffname);
!           channel->ch_part[PART_OUT].ch_buffer = buf;
        }
      }
  
--- 1209,1228 ----
        }
        if (buf != NULL)
        {
!           if (opt->jo_set & JO_OUT_MODIFIABLE)
!               channel->ch_part[PART_OUT].ch_nomodifiable =
!                                               !opt->jo_modifiable[PART_OUT];
! 
!           if (!buf->b_p_ma && !channel->ch_part[PART_OUT].ch_nomodifiable)
!           {
!               EMSG(_(e_modifiable));
!           }
!           else
!           {
!               ch_logs(channel, "writing out to buffer '%s'",
                                                       (char *)buf->b_ffname);
!               channel->ch_part[PART_OUT].ch_buffer = buf;
!           }
        }
      }
  
***************
*** 1236,1244 ****
            buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE);
        if (buf != NULL)
        {
!           ch_logs(channel, "writing err to buffer '%s'",
                                                       (char *)buf->b_ffname);
!           channel->ch_part[PART_ERR].ch_buffer = buf;
        }
      }
  
--- 1247,1265 ----
            buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE);
        if (buf != NULL)
        {
!           if (opt->jo_set & JO_ERR_MODIFIABLE)
!               channel->ch_part[PART_ERR].ch_nomodifiable =
!                                               !opt->jo_modifiable[PART_ERR];
!           if (!buf->b_p_ma && !channel->ch_part[PART_ERR].ch_nomodifiable)
!           {
!               EMSG(_(e_modifiable));
!           }
!           else
!           {
!               ch_logs(channel, "writing err to buffer '%s'",
                                                       (char *)buf->b_ffname);
!               channel->ch_part[PART_ERR].ch_buffer = buf;
!           }
        }
      }
  
***************
*** 2107,2117 ****
  }
  
      static void
! append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel)
  {
      buf_T     *save_curbuf = curbuf;
      linenr_T    lnum = buffer->b_ml.ml_line_count;
      int               save_write_to = buffer->b_write_to_channel;
  
      /* If the buffer is also used as input insert above the last
       * line. Don't write these lines. */
--- 2128,2150 ----
  }
  
      static void
! append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, int part)
  {
      buf_T     *save_curbuf = curbuf;
      linenr_T    lnum = buffer->b_ml.ml_line_count;
      int               save_write_to = buffer->b_write_to_channel;
+     chanpart_T  *ch_part = &channel->ch_part[part];
+     int               save_p_ma = buffer->b_p_ma;
+ 
+     if (!buffer->b_p_ma && !ch_part->ch_nomodifiable)
+     {
+       if (!ch_part->ch_nomod_error)
+       {
+           ch_error(channel, "Buffer is not modifiable, cannot append");
+           ch_part->ch_nomod_error = TRUE;
+       }
+       return;
+     }
  
      /* If the buffer is also used as input insert above the last
       * line. Don't write these lines. */
***************
*** 2124,2129 ****
--- 2157,2163 ----
      /* Append to the buffer */
      ch_logn(channel, "appending line %d to buffer", (int)lnum + 1);
  
+     buffer->b_p_ma = TRUE;
      curbuf = buffer;
      u_sync(TRUE);
      /* ignore undo failure, undo is not very useful here */
***************
*** 2132,2137 ****
--- 2166,2175 ----
      ml_append(lnum, msg, 0, FALSE);
      appended_lines_mark(lnum, 1L);
      curbuf = save_curbuf;
+     if (ch_part->ch_nomodifiable)
+       buffer->b_p_ma = FALSE;
+     else
+       buffer->b_p_ma = save_p_ma;
  
      if (buffer->b_nwindows > 0)
      {
***************
*** 2359,2365 ****
                /* JSON or JS mode: re-encode the message. */
                msg = json_encode(listtv, ch_mode);
            if (msg != NULL)
!               append_to_buffer(buffer, msg, channel);
        }
  
        if (callback != NULL)
--- 2397,2403 ----
                /* JSON or JS mode: re-encode the message. */
                msg = json_encode(listtv, ch_mode);
            if (msg != NULL)
!               append_to_buffer(buffer, msg, channel, part);
        }
  
        if (callback != NULL)
***************
*** 3915,3920 ****
--- 3953,3968 ----
                    return FAIL;
                }
            }
+           else if (STRCMP(hi->hi_key, "out_modifiable") == 0
+                   || STRCMP(hi->hi_key, "err_modifiable") == 0)
+           {
+               part = part_from_char(*hi->hi_key);
+ 
+               if (!(supported & JO_OUT_IO))
+                   break;
+               opt->jo_set |= JO_OUT_MODIFIABLE << (part - PART_OUT);
+               opt->jo_modifiable[part] = get_tv_number(item);
+           }
            else if (STRCMP(hi->hi_key, "in_top") == 0
                    || STRCMP(hi->hi_key, "in_bot") == 0)
            {
*** ../vim-7.4.1856/src/testdir/test_channel.vim        2016-05-24 
17:33:29.139206088 +0200
--- src/testdir/test_channel.vim        2016-05-29 15:55:59.973344043 +0200
***************
*** 676,682 ****
    endtry
  endfunc
  
! func Run_test_pipe_to_buffer(use_name)
    if !has('job')
      return
    endif
--- 676,682 ----
    endtry
  endfunc
  
! func Run_test_pipe_to_buffer(use_name, nomod)
    if !has('job')
      return
    endif
***************
*** 691,696 ****
--- 691,699 ----
      quit
      let firstline = ''
    endif
+   if a:nomod
+     let options['out_modifiable'] = 0
+   endif
    let job = job_start(s:python . " test_channel_pipe.py", options)
    call assert_equal("run", job_status(job))
    try
***************
*** 705,710 ****
--- 708,718 ----
        $del
      endif
      call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 
'Goodbye!'], getline(1, '$'))
+     if a:nomod
+       call assert_equal(0, &modifiable)
+     else
+       call assert_equal(1, &modifiable)
+     endif
      bwipe!
    finally
      call job_stop(job)
***************
*** 712,725 ****
  endfunc
  
  func Test_pipe_to_buffer_name()
!   call Run_test_pipe_to_buffer(1)
  endfunc
  
  func Test_pipe_to_buffer_nr()
!   call Run_test_pipe_to_buffer(0)
  endfunc
  
! func Run_test_pipe_err_to_buffer(use_name)
    if !has('job')
      return
    endif
--- 720,737 ----
  endfunc
  
  func Test_pipe_to_buffer_name()
!   call Run_test_pipe_to_buffer(1, 0)
  endfunc
  
  func Test_pipe_to_buffer_nr()
!   call Run_test_pipe_to_buffer(0, 0)
! endfunc
! 
! func Test_pipe_to_buffer_name_nomod()
!   call Run_test_pipe_to_buffer(1, 1)
  endfunc
  
! func Run_test_pipe_err_to_buffer(use_name, nomod)
    if !has('job')
      return
    endif
***************
*** 734,739 ****
--- 746,754 ----
      quit
      let firstline = ''
    endif
+   if a:nomod
+     let options['err_modifiable'] = 0
+   endif
    let job = job_start(s:python . " test_channel_pipe.py", options)
    call assert_equal("run", job_status(job))
    try
***************
*** 745,750 ****
--- 760,770 ----
      sp pipe-err
      call s:waitFor('line("$") >= 5')
      call assert_equal([firstline, 'line one', 'line two', 'this', 'AND 
this'], getline(1, '$'))
+     if a:nomod
+       call assert_equal(0, &modifiable)
+     else
+       call assert_equal(1, &modifiable)
+     endif
      bwipe!
    finally
      call job_stop(job)
***************
*** 752,762 ****
  endfunc
  
  func Test_pipe_err_to_buffer_name()
!   call Run_test_pipe_err_to_buffer(1)
  endfunc
    
  func Test_pipe_err_to_buffer_nr()
!   call Run_test_pipe_err_to_buffer(0)
  endfunc
    
  func Test_pipe_both_to_buffer()
--- 772,786 ----
  endfunc
  
  func Test_pipe_err_to_buffer_name()
!   call Run_test_pipe_err_to_buffer(1, 0)
  endfunc
    
  func Test_pipe_err_to_buffer_nr()
!   call Run_test_pipe_err_to_buffer(0, 0)
! endfunc
!   
! func Test_pipe_err_to_buffer_name_nomod()
!   call Run_test_pipe_err_to_buffer(1, 1)
  endfunc
    
  func Test_pipe_both_to_buffer()
*** ../vim-7.4.1856/runtime/doc/channel.txt     2016-03-14 23:22:31.219768924 
+0100
--- runtime/doc/channel.txt     2016-05-29 15:58:48.653341722 +0200
***************
*** 571,588 ****
  "out_io": "null"      disconnect stdout (goes to /dev/null)
  "out_io": "pipe"      stdout is connected to the channel (default)
  "out_io": "file"      stdout writes to a file
! "out_io": "buffer"    stdout appends to a buffer
  "out_name": "/path/file" the name of the file or buffer to write to
  "out_buf": number     the number of the buffer to write to
  
                                *job-err_io* *err_name* *err_buf*
  "err_io": "out"               stderr messages to go to stdout
  "err_io": "null"      disconnect stderr  (goes to /dev/null)
  "err_io": "pipe"      stderr is connected to the channel (default)
  "err_io": "file"      stderr writes to a file
! "err_io": "buffer"    stderr appends to a buffer
  "err_name": "/path/file" the name of the file or buffer to write to
  "err_buf": number     the number of the buffer to write to
  
  
  Writing to a buffer ~
--- 625,649 ----
  "out_io": "null"      disconnect stdout (goes to /dev/null)
  "out_io": "pipe"      stdout is connected to the channel (default)
  "out_io": "file"      stdout writes to a file
! "out_io": "buffer"    stdout appends to a buffer (see below)
  "out_name": "/path/file" the name of the file or buffer to write to
  "out_buf": number     the number of the buffer to write to
+ "out_modifiable": 0   when writing to a buffer, 'modifiable' will be off
+                       (see below)
  
                                *job-err_io* *err_name* *err_buf*
  "err_io": "out"               stderr messages to go to stdout
  "err_io": "null"      disconnect stderr  (goes to /dev/null)
  "err_io": "pipe"      stderr is connected to the channel (default)
  "err_io": "file"      stderr writes to a file
! "err_io": "buffer"    stderr appends to a buffer (see below)
  "err_name": "/path/file" the name of the file or buffer to write to
  "err_buf": number     the number of the buffer to write to
+ "err_modifiable": 0   when writing to a buffer, 'modifiable' will be off
+                       (see below)
+ 
+ "block_write": number only for testing: pretend every other write to stdin
+                       will block
  
  
  Writing to a buffer ~
***************
*** 606,611 ****
--- 667,681 ----
  For a new buffer 'buftype' is set to "nofile" and 'bufhidden' to "hide".  If
  you prefer other settings, create the buffer first and pass the buffer number.
  
+ The "out_modifiable" and "err_modifiable" options can be used to set the
+ 'modifiable' option off, or write to a buffer that has 'modifiable' off.  That
+ means that lines will be appended to the buffer, but the user can't easily
+ change the buffer.
+ 
+ When an existing buffer is to be written where 'modifiable' is off and the
+ "out_modifiable" or "err_modifiable" options is not zero, an error is given
+ and the buffer will not be written to.
+ 
  When the buffer written to is displayed in a window and the cursor is in the
  first column of the last line, the cursor will be moved to the newly added
  line and the window is scrolled up to show the cursor if needed.
*** ../vim-7.4.1856/src/version.c       2016-05-28 22:47:08.546193208 +0200
--- src/version.c       2016-05-29 15:56:31.177343613 +0200
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     1857,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
7. Finish all your sentences with "in accordance with the prophecy".

 /// 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