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.
diff --git a/src/channel.c b/src/channel.c
index 2cc46fe..973d234 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1209,9 +1209,20 @@
}
if (buf != NULL)
{
- ch_logs(channel, "writing out to buffer '%s'",
+ 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;
+ channel->ch_part[PART_OUT].ch_buffer = buf;
+ }
}
}
@@ -1236,9 +1247,19 @@
buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE);
if (buf != NULL)
{
- ch_logs(channel, "writing err to buffer '%s'",
+ 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;
+ channel->ch_part[PART_ERR].ch_buffer = buf;
+ }
}
}
@@ -2107,11 +2128,23 @@
}
static void
-append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel)
+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,6 +2157,7 @@
/* 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,6 +2166,10 @@
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,7 +2397,7 @@
/* JSON or JS mode: re-encode the message. */
msg = json_encode(listtv, ch_mode);
if (msg != NULL)
- append_to_buffer(buffer, msg, channel);
+ append_to_buffer(buffer, msg, channel, part);
}
if (callback != NULL)
@@ -3915,6 +3953,16 @@
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)
{
diff --git a/src/structs.h b/src/structs.h
index 12a8a43..d5f8adc 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1401,6 +1401,8 @@
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,6 +1479,8 @@
#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,6 +1504,7 @@
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;
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 363b5cd..ed3fa6d 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -676,7 +676,7 @@
endtry
endfunc
-func Run_test_pipe_to_buffer(use_name)
+func Run_test_pipe_to_buffer(use_name, nomod)
if !has('job')
return
endif
@@ -691,6 +691,9 @@
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,6 +708,11 @@
$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,14 +720,18 @@
endfunc
func Test_pipe_to_buffer_name()
- call Run_test_pipe_to_buffer(1)
+ call Run_test_pipe_to_buffer(1, 0)
endfunc
func Test_pipe_to_buffer_nr()
- call Run_test_pipe_to_buffer(0)
+ call Run_test_pipe_to_buffer(0, 0)
endfunc
-func Run_test_pipe_err_to_buffer(use_name)
+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,6 +746,9 @@
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,6 +760,11 @@
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,11 +772,15 @@
endfunc
func Test_pipe_err_to_buffer_name()
- call Run_test_pipe_err_to_buffer(1)
+ 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)
+ 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()
diff --git a/src/version.c b/src/version.c
index e47ab53..c3afbad 100644
--- a/src/version.c
+++ b/src/version.c
@@ -754,6 +754,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1857,
+/**/
1856,
/**/
1855,