Skip to content

Commit c7f0ebc

Browse files
committed
patch 7.4.1438
Problem: Can't get buffer number of a channel. Solution: Add ch_getbufnr().
1 parent 136f29a commit c7f0ebc

File tree

6 files changed

+85
-14
lines changed

6 files changed

+85
-14
lines changed

runtime/doc/channel.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,11 +561,14 @@ TODO: *job-term*
561561

562562
When the IO mode is "buffer" and there is a callback, the text is appended to
563563
the buffer before invoking the callback.
564-
*E915*
564+
565565
The name of the buffer is compared the full name of existing buffers. If
566-
there is a match that buffer is used. Otherwise a new buffer is created,
567-
where 'buftype' is set to "nofile" and 'bufhidden' to "hide". If you prefer
568-
other settings, create the buffer first and pass the buffer number.
566+
there is a match that buffer is used. Otherwise a new buffer is created.
567+
Use an empty name to always create a new buffer. |ch_getbufnr()| can then be
568+
used to get the buffer number.
569+
570+
For a new buffer 'buftype' is set to "nofile" and 'bufhidden' to "hide". If
571+
you prefer other settings, create the buffer first and pass the buffer number.
569572

570573
When the buffer written to is displayed in a window and the cursor is in the
571574
first column of the last line, the cursor will be moved to the newly added

runtime/doc/eval.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,7 @@ ch_evalexpr( {channel}, {expr} [, {options}])
18221822
any evaluate {expr} on JSON {channel}
18231823
ch_evalraw( {channel}, {string} [, {options}])
18241824
any evaluate {string} on raw {channel}
1825+
ch_getbufnr( {channel}, {what}) Number get buffer number for {channel}/{what}
18251826
ch_getjob( {channel}) Job get the Job of {channel}
18261827
ch_log( {msg} [, {channel}]) none write {msg} in the channel log file
18271828
ch_logfile( {fname} [, {mode}]) none start logging channel activity
@@ -2721,6 +2722,13 @@ ch_evalraw({channel}, {string} [, {options}]) *ch_evalraw()*
27212722

27222723
{only available when compiled with the |+channel| feature}
27232724

2725+
ch_getbufnr({channel}, {what}) *ch_getbufnr()*
2726+
Get the buffer number that {channel} is using for {what}.
2727+
{what} can be "err" for stderr, "out" for stdout or empty for
2728+
socket output.
2729+
Returns -1 when there is no buffer.
2730+
{only available when compiled with the |+channel| feature}
2731+
27242732
ch_getjob({channel}) *ch_getjob()*
27252733
Get the Job associated with {channel}.
27262734
If there is no job calling |job_status()| on the returned Job

src/channel.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -787,12 +787,15 @@ channel_set_job(channel_T *channel, job_T *job)
787787
static buf_T *
788788
find_buffer(char_u *name)
789789
{
790-
buf_T *buf = buflist_findname(name);
790+
buf_T *buf = NULL;
791791
buf_T *save_curbuf = curbuf;
792792

793+
if (name != NULL && *name != NUL)
794+
buf = buflist_findname(name);
793795
if (buf == NULL)
794796
{
795-
buf = buflist_new(name, NULL, (linenr_T)0, BLN_LISTED);
797+
buf = buflist_new(name == NULL ? (char_u *)"" : name,
798+
NULL, (linenr_T)0, BLN_LISTED);
796799
buf_copy_options(buf, BCO_ENTER);
797800
#ifdef FEAT_QUICKFIX
798801
clear_string_option(&buf->b_p_bt);
@@ -880,7 +883,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
880883
channel->ch_part[PART_OUT].ch_mode = MODE_NL;
881884
channel->ch_part[PART_OUT].ch_buffer =
882885
find_buffer(opt->jo_io_name[PART_OUT]);
883-
ch_logs(channel, "writing to buffer %s",
886+
ch_logs(channel, "writing to buffer '%s'",
884887
(char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname);
885888
}
886889
}
@@ -1357,7 +1360,14 @@ may_invoke_callback(channel_T *channel, int part)
13571360
callback = channel->ch_part[part].ch_callback;
13581361
else
13591362
callback = channel->ch_callback;
1363+
13601364
buffer = channel->ch_part[part].ch_buffer;
1365+
if (buffer != NULL && !buf_valid(buffer))
1366+
{
1367+
/* buffer was wiped out */
1368+
channel->ch_part[part].ch_buffer = NULL;
1369+
buffer = NULL;
1370+
}
13611371

13621372
if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
13631373
{

src/eval.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ static void f_ceil(typval_T *argvars, typval_T *rettv);
499499
static void f_ch_close(typval_T *argvars, typval_T *rettv);
500500
static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv);
501501
static void f_ch_evalraw(typval_T *argvars, typval_T *rettv);
502+
static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv);
502503
# ifdef FEAT_JOB
503504
static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
504505
# endif
@@ -8195,6 +8196,7 @@ static struct fst
81958196
{"ch_close", 1, 1, f_ch_close},
81968197
{"ch_evalexpr", 2, 3, f_ch_evalexpr},
81978198
{"ch_evalraw", 2, 3, f_ch_evalraw},
8199+
{"ch_getbufnr", 2, 2, f_ch_getbufnr},
81988200
# ifdef FEAT_JOB
81998201
{"ch_getjob", 1, 1, f_ch_getjob},
82008202
# endif
@@ -10227,13 +10229,6 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
1022710229
return FAIL;
1022810230
}
1022910231

10230-
for (part = PART_OUT; part <= PART_IN; ++part)
10231-
if (opt->jo_io[part] == JIO_BUFFER && opt->jo_io_name[part] == NULL)
10232-
{
10233-
EMSG(_("E915: Missing name for buffer"));
10234-
return FAIL;
10235-
}
10236-
1023710232
return OK;
1023810233
}
1023910234
#endif
@@ -10278,6 +10273,33 @@ f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
1027810273
}
1027910274
}
1028010275

10276+
/*
10277+
* "ch_getbufnr()" function
10278+
*/
10279+
static void
10280+
f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
10281+
{
10282+
channel_T *channel = get_channel_arg(&argvars[0]);
10283+
10284+
rettv->vval.v_number = -1;
10285+
if (channel != NULL)
10286+
{
10287+
char_u *what = get_tv_string(&argvars[1]);
10288+
int part;
10289+
10290+
if (STRCMP(what, "err") == 0)
10291+
part = PART_ERR;
10292+
else if (STRCMP(what, "out") == 0)
10293+
part = PART_OUT;
10294+
else if (STRCMP(what, "in") == 0)
10295+
part = PART_IN;
10296+
else
10297+
part = PART_SOCK;
10298+
if (channel->ch_part[part].ch_buffer != NULL)
10299+
rettv->vval.v_number = channel->ch_part[part].ch_buffer->b_fnum;
10300+
}
10301+
}
10302+
1028110303
# ifdef FEAT_JOB
1028210304
/*
1028310305
* "ch_getjob()" function

src/testdir/test_channel.vim

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,32 @@ func Test_pipe_to_buffer()
400400
endtry
401401
endfunc
402402

403+
func Test_pipe_to_nameless_buffer()
404+
if !has('job')
405+
return
406+
endif
407+
call ch_log('Test_pipe_to_nameless_buffer()')
408+
let job = job_start(s:python . " test_channel_pipe.py",
409+
\ {'out-io': 'buffer'})
410+
call assert_equal("run", job_status(job))
411+
try
412+
let handle = job_getchannel(job)
413+
call ch_sendraw(handle, "echo line one\n")
414+
call ch_sendraw(handle, "echo line two\n")
415+
exe ch_getbufnr(handle, "out") . 'sbuf'
416+
for i in range(100)
417+
sleep 10m
418+
if line('$') >= 3
419+
break
420+
endif
421+
endfor
422+
call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$'))
423+
bwipe!
424+
finally
425+
call job_stop(job)
426+
endtry
427+
endfunc
428+
403429
""""""""""
404430

405431
let s:unletResponse = ''

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1438,
746748
/**/
747749
1437,
748750
/**/

0 commit comments

Comments
 (0)