changeset 10147:65afd399ffa7 v7.4.2344

commit https://github.com/vim/vim/commit/169ebb080454357279ad5ad21ac532deaec605e8 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Sep 7 23:32:23 2016 +0200 patch 7.4.2344 Problem: The "Reading from channel output..." message can be unwanted. Appending to a buffer leaves an empty first line behind. Solution: Add the "out_msg" and "err_msg" options. Writing the first line overwrites the first, empty line.
author Christian Brabandt <cb@256bit.org>
date Wed, 07 Sep 2016 23:45:05 +0200
parents f812ea9d4c28
children 65403e63cf77
files runtime/doc/channel.txt src/channel.c src/structs.h src/testdir/test_channel.vim src/version.c
diffstat 5 files changed, 96 insertions(+), 27 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 Sep 01
+*channel.txt*      For Vim version 7.4.  Last change: 2016 Sep 07
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -646,6 +646,8 @@ See |job_setoptions()| and |ch_setoption
 "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)
+"out_msg": 0		when writing to a new buffer, the first line will be
+			set to "Reading from channel output..."
 
 				*job-err_io* *err_name* *err_buf*
 "err_io": "out"		stderr messages to go to stdout
@@ -657,6 +659,8 @@ See |job_setoptions()| and |ch_setoption
 "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)
+"err_msg": 0		when writing to a new buffer, the first line will be
+			set to "Reading from channel error..."
 
 "block_write": number	only for testing: pretend every other write to stdin
 			will block
@@ -686,8 +690,16 @@ buffer number.
 
 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.
+					*out_modifiable* *err_modifiable*
+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.
+					*out_msg* *err_msg*
+The "out_msg" option can be used to specify whether a new buffer will have the
+first line set to "Reading from channel output...".  The default is to add the
+message.  "err_msg" does the same for channel error.
 
-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.
--- a/src/channel.c
+++ b/src/channel.c
@@ -1079,7 +1079,7 @@ channel_set_job(channel_T *channel, job_
  * Returns NULL if there is something very wrong (error already reported).
  */
     static buf_T *
-find_buffer(char_u *name, int err)
+find_buffer(char_u *name, int err, int msg)
 {
     buf_T *buf = NULL;
     buf_T *save_curbuf = curbuf;
@@ -1104,7 +1104,8 @@ find_buffer(char_u *name, int err)
 #endif
 	if (curbuf->b_ml.ml_mfp == NULL)
 	    ml_open(curbuf);
-	ml_replace(1, (char_u *)(err ? "Reading from channel error..."
+	if (msg)
+	    ml_replace(1, (char_u *)(err ? "Reading from channel error..."
 				   : "Reading from channel output..."), TRUE);
 	changed_bytes(1, 0);
 	curbuf = save_curbuf;
@@ -1196,7 +1197,11 @@ channel_set_options(channel_T *channel, 
 	}
 	else
 	{
-	    buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE);
+	    int msg = TRUE;
+
+	    if (opt->jo_set2 & JO2_OUT_MSG)
+		msg = opt->jo_message[PART_OUT];
+	    buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE, msg);
 	}
 	if (buf != NULL)
 	{
@@ -1235,7 +1240,13 @@ channel_set_options(channel_T *channel, 
 		EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]);
 	}
 	else
-	    buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE);
+	{
+	    int msg = TRUE;
+
+	    if (opt->jo_set2 & JO2_ERR_MSG)
+		msg = opt->jo_message[PART_ERR];
+	    buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE, msg);
+	}
 	if (buf != NULL)
 	{
 	    if (opt->jo_set & JO_ERR_MODIFIABLE)
@@ -2227,6 +2238,7 @@ append_to_buffer(buf_T *buffer, char_u *
     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;
+    int		empty = (buffer->b_ml.ml_flags & ML_EMPTY);
 
     if (!buffer->b_p_ma && !ch_part->ch_nomodifiable)
     {
@@ -2253,9 +2265,16 @@ append_to_buffer(buf_T *buffer, char_u *
     curbuf = buffer;
     u_sync(TRUE);
     /* ignore undo failure, undo is not very useful here */
-    ignored = u_save(lnum, lnum + 1);
-
-    ml_append(lnum, msg, 0, FALSE);
+    ignored = u_save(lnum, lnum + 1 + (empty ? 1 : 0));
+
+    if (empty)
+    {
+	/* The buffer is empty, replace the first (dummy) line. */
+	ml_replace(lnum, msg, TRUE);
+	lnum = 0;
+    }
+    else
+	ml_append(lnum, msg, 0, FALSE);
     appended_lines_mark(lnum, 1L);
     curbuf = save_curbuf;
     if (ch_part->ch_nomodifiable)
@@ -4083,6 +4102,16 @@ get_job_options(typval_T *tv, jobopt_T *
 		opt->jo_set |= JO_OUT_MODIFIABLE << (part - PART_OUT);
 		opt->jo_modifiable[part] = get_tv_number(item);
 	    }
+	    else if (STRCMP(hi->hi_key, "out_msg") == 0
+		    || STRCMP(hi->hi_key, "err_msg") == 0)
+	    {
+		part = part_from_char(*hi->hi_key);
+
+		if (!(supported & JO_OUT_IO))
+		    break;
+		opt->jo_set2 |= JO2_OUT_MSG << (part - PART_OUT);
+		opt->jo_message[part] = get_tv_number(item);
+	    }
 	    else if (STRCMP(hi->hi_key, "in_top") == 0
 		    || STRCMP(hi->hi_key, "in_bot") == 0)
 	    {
--- a/src/structs.h
+++ b/src/structs.h
@@ -1634,6 +1634,10 @@ struct channel_S {
 #define JO_ERR_MODIFIABLE   0x40000000	/* "err_modifiable" (JO_OUT_ << 1) */
 #define JO_ALL		    0x7fffffff
 
+#define JO2_OUT_MSG	    0x0001	/* "out_msg" */
+#define JO2_ERR_MSG	    0x0002	/* "err_msg" (JO_OUT_ << 1) */
+#define JO2_ALL		    0x0003
+
 #define JO_MODE_ALL	(JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
 #define JO_CB_ALL \
     (JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK)
@@ -1645,6 +1649,7 @@ struct channel_S {
 typedef struct
 {
     int		jo_set;		/* JO_ bits for values that were set */
+    int		jo_set2;	/* JO2_ bits for values that were set */
 
     ch_mode_T	jo_mode;
     ch_mode_T	jo_in_mode;
@@ -1656,6 +1661,7 @@ typedef struct
     char_u	*jo_io_name[4];	/* not allocated! */
     int		jo_io_buf[4];
     int		jo_modifiable[4];
+    int		jo_message[4];
     channel_T	*jo_channel;
 
     linenr_T	jo_in_top;
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -638,21 +638,27 @@ func BufCloseCb(ch)
   let g:Ch_bufClosed = 'yes'
 endfunc
 
-func Run_test_pipe_to_buffer(use_name, nomod)
+func Run_test_pipe_to_buffer(use_name, nomod, do_msg)
   if !has('job')
     return
   endif
   call ch_log('Test_pipe_to_buffer()')
   let g:Ch_bufClosed = 'no'
   let options = {'out_io': 'buffer', 'close_cb': 'BufCloseCb'}
+  let expected = ['', 'line one', 'line two', 'this', 'AND this', 'Goodbye!']
   if a:use_name
     let options['out_name'] = 'pipe-output'
-    let firstline = 'Reading from channel output...'
+    if a:do_msg
+      let expected[0] = 'Reading from channel output...'
+    else
+      let options['out_msg'] = 0
+      call remove(expected, 0)
+    endif
   else
     sp pipe-output
     let options['out_buf'] = bufnr('%')
     quit
-    let firstline = ''
+    call remove(expected, 0)
   endif
   if a:nomod
     let options['out_modifiable'] = 0
@@ -667,7 +673,7 @@ func Run_test_pipe_to_buffer(use_name, n
     call ch_sendraw(handle, "quit\n")
     sp pipe-output
     call WaitFor('line("$") >= 6 && g:Ch_bufClosed == "yes"')
-    call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
+    call assert_equal(expected, getline(1, '$'))
     if a:nomod
       call assert_equal(0, &modifiable)
     else
@@ -681,31 +687,41 @@ func Run_test_pipe_to_buffer(use_name, n
 endfunc
 
 func Test_pipe_to_buffer_name()
-  call Run_test_pipe_to_buffer(1, 0)
+  call Run_test_pipe_to_buffer(1, 0, 1)
 endfunc
 
 func Test_pipe_to_buffer_nr()
-  call Run_test_pipe_to_buffer(0, 0)
+  call Run_test_pipe_to_buffer(0, 0, 1)
 endfunc
 
 func Test_pipe_to_buffer_name_nomod()
-  call Run_test_pipe_to_buffer(1, 1)
+  call Run_test_pipe_to_buffer(1, 1, 1)
 endfunc
 
-func Run_test_pipe_err_to_buffer(use_name, nomod)
+func Test_pipe_to_buffer_name_nomsg()
+  call Run_test_pipe_to_buffer(1, 0, 1)
+endfunc
+
+func Run_test_pipe_err_to_buffer(use_name, nomod, do_msg)
   if !has('job')
     return
   endif
   call ch_log('Test_pipe_err_to_buffer()')
   let options = {'err_io': 'buffer'}
+  let expected = ['', 'line one', 'line two', 'this', 'AND this']
   if a:use_name
     let options['err_name'] = 'pipe-err'
-    let firstline = 'Reading from channel error...'
+    if a:do_msg
+      let expected[0] = 'Reading from channel error...'
+    else
+      let options['err_msg'] = 0
+      call remove(expected, 0)
+    endif
   else
     sp pipe-err
     let options['err_buf'] = bufnr('%')
     quit
-    let firstline = ''
+    call remove(expected, 0)
   endif
   if a:nomod
     let options['err_modifiable'] = 0
@@ -720,7 +736,7 @@ func Run_test_pipe_err_to_buffer(use_nam
     call ch_sendraw(handle, "quit\n")
     sp pipe-err
     call WaitFor('line("$") >= 5')
-    call assert_equal([firstline, 'line one', 'line two', 'this', 'AND this'], getline(1, '$'))
+    call assert_equal(expected, getline(1, '$'))
     if a:nomod
       call assert_equal(0, &modifiable)
     else
@@ -733,15 +749,19 @@ func Run_test_pipe_err_to_buffer(use_nam
 endfunc
 
 func Test_pipe_err_to_buffer_name()
-  call Run_test_pipe_err_to_buffer(1, 0)
+  call Run_test_pipe_err_to_buffer(1, 0, 1)
 endfunc
   
 func Test_pipe_err_to_buffer_nr()
-  call Run_test_pipe_err_to_buffer(0, 0)
+  call Run_test_pipe_err_to_buffer(0, 0, 1)
 endfunc
   
 func Test_pipe_err_to_buffer_name_nomod()
-  call Run_test_pipe_err_to_buffer(1, 1)
+  call Run_test_pipe_err_to_buffer(1, 1, 1)
+endfunc
+  
+func Test_pipe_err_to_buffer_name_nomsg()
+  call Run_test_pipe_err_to_buffer(1, 0, 0)
 endfunc
   
 func Test_pipe_both_to_buffer()
@@ -1407,7 +1427,7 @@ func Test_collapse_buffers()
   1,$delete
   call job_start('cat test_channel.vim', {'out_io': 'buffer', 'out_name': 'testout'})
   call WaitFor('line("$") > g:linecount')
-  call assert_inrange(g:linecount + 1, g:linecount + 2, line('$'))
+  call assert_inrange(g:linecount, g:linecount + 1, line('$'))
   bwipe!
 endfunc
 
@@ -1425,9 +1445,9 @@ func Test_raw_passes_nul()
   1,$delete
   call job_start('cat Xtestread', {'out_io': 'buffer', 'out_name': 'testout'})
   call WaitFor('line("$") > 2')
-  call assert_equal("asdf\nasdf", getline(2))
-  call assert_equal("xxx\n", getline(3))
-  call assert_equal("\nyyy", getline(4))
+  call assert_equal("asdf\nasdf", getline(1))
+  call assert_equal("xxx\n", getline(2))
+  call assert_equal("\nyyy", getline(3))
 
   call delete('Xtestread')
   bwipe!
--- 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 */
 /**/
+    2344,
+/**/
     2343,
 /**/
     2342,