1
0
forked from aniani/vim

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.
This commit is contained in:
Bram Moolenaar
2016-09-07 23:32:23 +02:00
parent 53f1673cd9
commit 169ebb0804
5 changed files with 95 additions and 26 deletions

View File

@@ -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 VIM REFERENCE MANUAL by Bram Moolenaar
@@ -646,6 +646,8 @@ See |job_setoptions()| and |ch_setoptions()|.
"out_buf": number the number of the 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 "out_modifiable": 0 when writing to a buffer, 'modifiable' will be off
(see below) (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* *job-err_io* *err_name* *err_buf*
"err_io": "out" stderr messages to go to stdout "err_io": "out" stderr messages to go to stdout
@@ -657,6 +659,8 @@ See |job_setoptions()| and |ch_setoptions()|.
"err_buf": number the number of the 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 "err_modifiable": 0 when writing to a buffer, 'modifiable' will be off
(see below) (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 "block_write": number only for testing: pretend every other write to stdin
will block will block
@@ -686,8 +690,16 @@ buffer number.
For a new buffer 'buftype' is set to "nofile" and 'bufhidden' to "hide". If 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. 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 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.
'modifiable' option off, or write to a buffer that has 'modifiable' off. That '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 means that lines will be appended to the buffer, but the user can't easily
change the buffer. change the buffer.

View File

@@ -1079,7 +1079,7 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options)
* Returns NULL if there is something very wrong (error already reported). * Returns NULL if there is something very wrong (error already reported).
*/ */
static buf_T * 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 *buf = NULL;
buf_T *save_curbuf = curbuf; buf_T *save_curbuf = curbuf;
@@ -1104,7 +1104,8 @@ find_buffer(char_u *name, int err)
#endif #endif
if (curbuf->b_ml.ml_mfp == NULL) if (curbuf->b_ml.ml_mfp == NULL)
ml_open(curbuf); 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); : "Reading from channel output..."), TRUE);
changed_bytes(1, 0); changed_bytes(1, 0);
curbuf = save_curbuf; curbuf = save_curbuf;
@@ -1196,7 +1197,11 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
} }
else 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) if (buf != NULL)
{ {
@@ -1235,7 +1240,13 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]); EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]);
} }
else 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 (buf != NULL)
{ {
if (opt->jo_set & JO_ERR_MODIFIABLE) if (opt->jo_set & JO_ERR_MODIFIABLE)
@@ -2227,6 +2238,7 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, int part)
int save_write_to = buffer->b_write_to_channel; int save_write_to = buffer->b_write_to_channel;
chanpart_T *ch_part = &channel->ch_part[part]; chanpart_T *ch_part = &channel->ch_part[part];
int save_p_ma = buffer->b_p_ma; 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) if (!buffer->b_p_ma && !ch_part->ch_nomodifiable)
{ {
@@ -2253,9 +2265,16 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, int part)
curbuf = buffer; curbuf = buffer;
u_sync(TRUE); u_sync(TRUE);
/* ignore undo failure, undo is not very useful here */ /* ignore undo failure, undo is not very useful here */
ignored = u_save(lnum, lnum + 1); ignored = u_save(lnum, lnum + 1 + (empty ? 1 : 0));
ml_append(lnum, msg, 0, FALSE); 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); appended_lines_mark(lnum, 1L);
curbuf = save_curbuf; curbuf = save_curbuf;
if (ch_part->ch_nomodifiable) if (ch_part->ch_nomodifiable)
@@ -4083,6 +4102,16 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
opt->jo_set |= JO_OUT_MODIFIABLE << (part - PART_OUT); opt->jo_set |= JO_OUT_MODIFIABLE << (part - PART_OUT);
opt->jo_modifiable[part] = get_tv_number(item); 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 else if (STRCMP(hi->hi_key, "in_top") == 0
|| STRCMP(hi->hi_key, "in_bot") == 0) || STRCMP(hi->hi_key, "in_bot") == 0)
{ {

View File

@@ -1634,6 +1634,10 @@ struct channel_S {
#define JO_ERR_MODIFIABLE 0x40000000 /* "err_modifiable" (JO_OUT_ << 1) */ #define JO_ERR_MODIFIABLE 0x40000000 /* "err_modifiable" (JO_OUT_ << 1) */
#define JO_ALL 0x7fffffff #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_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
#define JO_CB_ALL \ #define JO_CB_ALL \
(JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK) (JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK)
@@ -1645,6 +1649,7 @@ struct channel_S {
typedef struct typedef struct
{ {
int jo_set; /* JO_ bits for values that were set */ 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_mode;
ch_mode_T jo_in_mode; ch_mode_T jo_in_mode;
@@ -1656,6 +1661,7 @@ typedef struct
char_u *jo_io_name[4]; /* not allocated! */ char_u *jo_io_name[4]; /* not allocated! */
int jo_io_buf[4]; int jo_io_buf[4];
int jo_modifiable[4]; int jo_modifiable[4];
int jo_message[4];
channel_T *jo_channel; channel_T *jo_channel;
linenr_T jo_in_top; linenr_T jo_in_top;

View File

@@ -638,21 +638,27 @@ func BufCloseCb(ch)
let g:Ch_bufClosed = 'yes' let g:Ch_bufClosed = 'yes'
endfunc endfunc
func Run_test_pipe_to_buffer(use_name, nomod) func Run_test_pipe_to_buffer(use_name, nomod, do_msg)
if !has('job') if !has('job')
return return
endif endif
call ch_log('Test_pipe_to_buffer()') call ch_log('Test_pipe_to_buffer()')
let g:Ch_bufClosed = 'no' let g:Ch_bufClosed = 'no'
let options = {'out_io': 'buffer', 'close_cb': 'BufCloseCb'} let options = {'out_io': 'buffer', 'close_cb': 'BufCloseCb'}
let expected = ['', 'line one', 'line two', 'this', 'AND this', 'Goodbye!']
if a:use_name if a:use_name
let options['out_name'] = 'pipe-output' 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 else
sp pipe-output sp pipe-output
let options['out_buf'] = bufnr('%') let options['out_buf'] = bufnr('%')
quit quit
let firstline = '' call remove(expected, 0)
endif endif
if a:nomod if a:nomod
let options['out_modifiable'] = 0 let options['out_modifiable'] = 0
@@ -667,7 +673,7 @@ func Run_test_pipe_to_buffer(use_name, nomod)
call ch_sendraw(handle, "quit\n") call ch_sendraw(handle, "quit\n")
sp pipe-output sp pipe-output
call WaitFor('line("$") >= 6 && g:Ch_bufClosed == "yes"') 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 if a:nomod
call assert_equal(0, &modifiable) call assert_equal(0, &modifiable)
else else
@@ -681,31 +687,41 @@ func Run_test_pipe_to_buffer(use_name, nomod)
endfunc endfunc
func Test_pipe_to_buffer_name() func Test_pipe_to_buffer_name()
call Run_test_pipe_to_buffer(1, 0) call Run_test_pipe_to_buffer(1, 0, 1)
endfunc endfunc
func Test_pipe_to_buffer_nr() func Test_pipe_to_buffer_nr()
call Run_test_pipe_to_buffer(0, 0) call Run_test_pipe_to_buffer(0, 0, 1)
endfunc endfunc
func Test_pipe_to_buffer_name_nomod() 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 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') if !has('job')
return return
endif endif
call ch_log('Test_pipe_err_to_buffer()') call ch_log('Test_pipe_err_to_buffer()')
let options = {'err_io': 'buffer'} let options = {'err_io': 'buffer'}
let expected = ['', 'line one', 'line two', 'this', 'AND this']
if a:use_name if a:use_name
let options['err_name'] = 'pipe-err' 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 else
sp pipe-err sp pipe-err
let options['err_buf'] = bufnr('%') let options['err_buf'] = bufnr('%')
quit quit
let firstline = '' call remove(expected, 0)
endif endif
if a:nomod if a:nomod
let options['err_modifiable'] = 0 let options['err_modifiable'] = 0
@@ -720,7 +736,7 @@ func Run_test_pipe_err_to_buffer(use_name, nomod)
call ch_sendraw(handle, "quit\n") call ch_sendraw(handle, "quit\n")
sp pipe-err sp pipe-err
call WaitFor('line("$") >= 5') 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 if a:nomod
call assert_equal(0, &modifiable) call assert_equal(0, &modifiable)
else else
@@ -733,15 +749,19 @@ func Run_test_pipe_err_to_buffer(use_name, nomod)
endfunc endfunc
func Test_pipe_err_to_buffer_name() 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 endfunc
func Test_pipe_err_to_buffer_nr() 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 endfunc
func Test_pipe_err_to_buffer_name_nomod() 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 endfunc
func Test_pipe_both_to_buffer() func Test_pipe_both_to_buffer()
@@ -1407,7 +1427,7 @@ func Test_collapse_buffers()
1,$delete 1,$delete
call job_start('cat test_channel.vim', {'out_io': 'buffer', 'out_name': 'testout'}) call job_start('cat test_channel.vim', {'out_io': 'buffer', 'out_name': 'testout'})
call WaitFor('line("$") > g:linecount') 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! bwipe!
endfunc endfunc
@@ -1425,9 +1445,9 @@ func Test_raw_passes_nul()
1,$delete 1,$delete
call job_start('cat Xtestread', {'out_io': 'buffer', 'out_name': 'testout'}) call job_start('cat Xtestread', {'out_io': 'buffer', 'out_name': 'testout'})
call WaitFor('line("$") > 2') call WaitFor('line("$") > 2')
call assert_equal("asdf\nasdf", getline(2)) call assert_equal("asdf\nasdf", getline(1))
call assert_equal("xxx\n", getline(3)) call assert_equal("xxx\n", getline(2))
call assert_equal("\nyyy", getline(4)) call assert_equal("\nyyy", getline(3))
call delete('Xtestread') call delete('Xtestread')
bwipe! bwipe!

View File

@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2344,
/**/ /**/
2343, 2343,
/**/ /**/