# HG changeset patch # User Christian Brabandt # Date 1456604104 -3600 # Node ID ac0c43e7af20c69ffedac65fe9fdf3dd263e6121 # Parent 285c4ec936b57664eca87d7a878177299cbb7be9 commit https://github.com/vim/vim/commit/c7f0ebc6d1e1cdaed816b88a0d6092c5ace615eb Author: Bram Moolenaar Date: Sat Feb 27 21:10:09 2016 +0100 patch 7.4.1438 Problem: Can't get buffer number of a channel. Solution: Add ch_getbufnr(). diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt --- a/runtime/doc/channel.txt +++ b/runtime/doc/channel.txt @@ -561,11 +561,14 @@ TODO: *job-term* When the IO mode is "buffer" and there is a callback, the text is appended to the buffer before invoking the callback. - *E915* + The name of the buffer is compared the full name of existing buffers. If -there is a match that buffer is used. Otherwise a new buffer is created, -where 'buftype' is set to "nofile" and 'bufhidden' to "hide". If you prefer -other settings, create the buffer first and pass the buffer number. +there is a match that buffer is used. Otherwise a new buffer is created. +Use an empty name to always create a new buffer. |ch_getbufnr()| can then be +used to get the 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. 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 diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1822,6 +1822,7 @@ ch_evalexpr( {channel}, {expr} [, {optio any evaluate {expr} on JSON {channel} ch_evalraw( {channel}, {string} [, {options}]) any evaluate {string} on raw {channel} +ch_getbufnr( {channel}, {what}) Number get buffer number for {channel}/{what} ch_getjob( {channel}) Job get the Job of {channel} ch_log( {msg} [, {channel}]) none write {msg} in the channel log file ch_logfile( {fname} [, {mode}]) none start logging channel activity @@ -2721,6 +2722,13 @@ ch_evalraw({channel}, {string} [, {optio {only available when compiled with the |+channel| feature} +ch_getbufnr({channel}, {what}) *ch_getbufnr()* + Get the buffer number that {channel} is using for {what}. + {what} can be "err" for stderr, "out" for stdout or empty for + socket output. + Returns -1 when there is no buffer. + {only available when compiled with the |+channel| feature} + ch_getjob({channel}) *ch_getjob()* Get the Job associated with {channel}. If there is no job calling |job_status()| on the returned Job diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -787,12 +787,15 @@ channel_set_job(channel_T *channel, job_ static buf_T * find_buffer(char_u *name) { - buf_T *buf = buflist_findname(name); + buf_T *buf = NULL; buf_T *save_curbuf = curbuf; + if (name != NULL && *name != NUL) + buf = buflist_findname(name); if (buf == NULL) { - buf = buflist_new(name, NULL, (linenr_T)0, BLN_LISTED); + buf = buflist_new(name == NULL ? (char_u *)"" : name, + NULL, (linenr_T)0, BLN_LISTED); buf_copy_options(buf, BCO_ENTER); #ifdef FEAT_QUICKFIX clear_string_option(&buf->b_p_bt); @@ -880,7 +883,7 @@ channel_set_options(channel_T *channel, channel->ch_part[PART_OUT].ch_mode = MODE_NL; channel->ch_part[PART_OUT].ch_buffer = find_buffer(opt->jo_io_name[PART_OUT]); - ch_logs(channel, "writing to buffer %s", + ch_logs(channel, "writing to buffer '%s'", (char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname); } } @@ -1357,7 +1360,14 @@ may_invoke_callback(channel_T *channel, callback = channel->ch_part[part].ch_callback; else callback = channel->ch_callback; + buffer = channel->ch_part[part].ch_buffer; + if (buffer != NULL && !buf_valid(buffer)) + { + /* buffer was wiped out */ + channel->ch_part[part].ch_buffer = NULL; + buffer = NULL; + } if (ch_mode == MODE_JSON || ch_mode == MODE_JS) { diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -499,6 +499,7 @@ static void f_ceil(typval_T *argvars, ty static void f_ch_close(typval_T *argvars, typval_T *rettv); static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv); static void f_ch_evalraw(typval_T *argvars, typval_T *rettv); +static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv); # ifdef FEAT_JOB static void f_ch_getjob(typval_T *argvars, typval_T *rettv); # endif @@ -8195,6 +8196,7 @@ static struct fst {"ch_close", 1, 1, f_ch_close}, {"ch_evalexpr", 2, 3, f_ch_evalexpr}, {"ch_evalraw", 2, 3, f_ch_evalraw}, + {"ch_getbufnr", 2, 2, f_ch_getbufnr}, # ifdef FEAT_JOB {"ch_getjob", 1, 1, f_ch_getjob}, # endif @@ -10227,13 +10229,6 @@ get_job_options(typval_T *tv, jobopt_T * return FAIL; } - for (part = PART_OUT; part <= PART_IN; ++part) - if (opt->jo_io[part] == JIO_BUFFER && opt->jo_io_name[part] == NULL) - { - EMSG(_("E915: Missing name for buffer")); - return FAIL; - } - return OK; } #endif @@ -10278,6 +10273,33 @@ f_ch_close(typval_T *argvars, typval_T * } } +/* + * "ch_getbufnr()" function + */ + static void +f_ch_getbufnr(typval_T *argvars, typval_T *rettv) +{ + channel_T *channel = get_channel_arg(&argvars[0]); + + rettv->vval.v_number = -1; + if (channel != NULL) + { + char_u *what = get_tv_string(&argvars[1]); + int part; + + if (STRCMP(what, "err") == 0) + part = PART_ERR; + else if (STRCMP(what, "out") == 0) + part = PART_OUT; + else if (STRCMP(what, "in") == 0) + part = PART_IN; + else + part = PART_SOCK; + if (channel->ch_part[part].ch_buffer != NULL) + rettv->vval.v_number = channel->ch_part[part].ch_buffer->b_fnum; + } +} + # ifdef FEAT_JOB /* * "ch_getjob()" function diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -400,6 +400,32 @@ func Test_pipe_to_buffer() endtry endfunc +func Test_pipe_to_nameless_buffer() + if !has('job') + return + endif + call ch_log('Test_pipe_to_nameless_buffer()') + let job = job_start(s:python . " test_channel_pipe.py", + \ {'out-io': 'buffer'}) + call assert_equal("run", job_status(job)) + try + let handle = job_getchannel(job) + call ch_sendraw(handle, "echo line one\n") + call ch_sendraw(handle, "echo line two\n") + exe ch_getbufnr(handle, "out") . 'sbuf' + for i in range(100) + sleep 10m + if line('$') >= 3 + break + endif + endfor + call assert_equal(['Reading from channel output...', 'line one', 'line two'], getline(1, '$')) + bwipe! + finally + call job_stop(job) + endtry +endfunc + """""""""" let s:unletResponse = '' diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -744,6 +744,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1438, +/**/ 1437, /**/ 1436,