Skip to content

Commit 03602ec

Browse files
committed
patch 7.4.1624
Problem: Can't get info about a channel. Solution: Add ch_info().
1 parent e9d6a29 commit 03602ec

6 files changed

Lines changed: 147 additions & 4 deletions

File tree

runtime/doc/eval.txt

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 15
1+
*eval.txt* For Vim version 7.4. Last change: 2016 Mar 20
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -753,7 +753,12 @@ recursively. Ignoring case means case is ignored when comparing item values.
753753

754754
*E693* *E694*
755755
A |Funcref| can only be compared with a |Funcref| and only "equal" and "not
756-
equal" can be used. Case is never ignored.
756+
equal" can be used. Case is never ignored. Whether arguments or a Dictionary
757+
are bound (with a partial) is ignored. This is so that when a function is
758+
made a member of a Dictionary it is still considered to be the same function.
759+
To compare partials to see if they bind the same argument and Dictionary
760+
values use string(): >
761+
echo string(Partial1) == string(Partial2)
757762
758763
When using "is" or "isnot" with a |List| or a |Dictionary| this checks if the
759764
expressions are referring to the same |List| or |Dictionary| instance. A copy
@@ -1822,6 +1827,7 @@ ch_evalraw( {handle}, {string} [, {options}])
18221827
any evaluate {string} on raw {handle}
18231828
ch_getbufnr( {handle}, {what}) Number get buffer number for {handle}/{what}
18241829
ch_getjob( {channel}) Job get the Job of {channel}
1830+
ch_info( {handle}) String info about channel {handle}
18251831
ch_log( {msg} [, {handle}]) none write {msg} in the channel log file
18261832
ch_logfile( {fname} [, {mode}]) none start logging channel activity
18271833
ch_open( {address} [, {options}]) Channel open a channel to {address}
@@ -1832,7 +1838,7 @@ ch_sendexpr( {handle}, {expr} [, {options}])
18321838
ch_sendraw( {handle}, {string} [, {options}])
18331839
any send {string} over raw {handle}
18341840
ch_setoptions( {handle}, {options}) none set options for {handle}
1835-
ch_status( {handle}) String status of {handle}
1841+
ch_status( {handle}) String status of channel {handle}
18361842
changenr() Number current change number
18371843
char2nr( {expr}[, {utf8}]) Number ASCII/UTF8 value of first char in {expr}
18381844
cindent( {lnum}) Number C indent for line {lnum}
@@ -2759,6 +2765,32 @@ ch_getjob({channel}) *ch_getjob()*
27592765
{only available when compiled with the |+channel| and
27602766
|+job| features}
27612767

2768+
ch_info({handle}) *ch_info()*
2769+
Returns a Dictionary with information about {handle}. The
2770+
items are:
2771+
"id" number of the channel
2772+
"status" "open" (any part is open) or "closed"
2773+
When opened with ch_open():
2774+
"hostname" the hostname of the address
2775+
"port" the port of the address
2776+
"sock_status" "open" or "closed"
2777+
"sock_mode" "NL", "RAW", "JSON" or "JS"
2778+
"sock_io" "socket"
2779+
"sock_timeout" timeout in msec
2780+
When opened with job_start():
2781+
"out_status" "open" or "closed"
2782+
"out_mode" "NL", "RAW", "JSON" or "JS"
2783+
"out_io" "null", "pipe", "file" or "buffer"
2784+
"out_timeout" timeout in msec
2785+
"err_status" "open" or "closed"
2786+
"err_mode" "NL", "RAW", "JSON" or "JS"
2787+
"err_io" "out", "null", "pipe", "file" or "buffer"
2788+
"err_timeout" timeout in msec
2789+
"in_status" "open" or "closed"
2790+
"in_mode" "NL", "RAW", "JSON" or "JS"
2791+
"in_io" "null", "pipe", "file" or "buffer"
2792+
"in_timeout" timeout in msec
2793+
27622794
ch_log({msg} [, {handle}]) *ch_log()*
27632795
Write {msg} in the channel log file, if it was opened with
27642796
|ch_logfile()|.
@@ -3594,6 +3626,18 @@ function({name} [, {arglist}] [, {dict}])
35943626
< Invokes the function as with: >
35953627
call Callback('one', 'two', 'name')
35963628
3629+
< The function() call can be nested to add more arguments to the
3630+
Funcref. The extra arguments are appended to the list of
3631+
arguments. Example: >
3632+
func Callback(arg1, arg2, name)
3633+
...
3634+
let Func = function('Callback', ['one'])
3635+
let Func2 = function(Func, ['two'])
3636+
...
3637+
call Func2('name')
3638+
< Invokes the function as with: >
3639+
call Callback('one', 'two', 'name')
3640+
35973641
< The Dictionary is only useful when calling a "dict" function.
35983642
In that case the {dict} is passed in as "self". Example: >
35993643
function Callback() dict
@@ -7050,6 +7094,10 @@ timer_start({time}, {callback} [, {options}])
70507094
intervals.
70517095
{only available when compiled with the |+timers| feature}
70527096

7097+
timer_stop({timer}) *timer_stop()*
7098+
Stop a timer. {timer} is an ID returned by timer_start().
7099+
The timer callback will no longer be invoked.
7100+
70537101
tolower({expr}) *tolower()*
70547102
The result is a copy of the String given, with all uppercase
70557103
characters turned into lowercase (just like applying |gu| to

src/channel.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,8 @@ channel_open(
838838

839839
channel->CH_SOCK_FD = (sock_T)sd;
840840
channel->ch_nb_close_cb = nb_close_cb;
841+
channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
842+
channel->ch_port = port_in;
841843

842844
#ifdef FEAT_GUI
843845
channel_gui_register_one(channel, PART_SOCK);
@@ -1138,6 +1140,10 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
11381140
ch_logs(channel, "writing err to buffer '%s'",
11391141
(char *)channel->ch_part[PART_ERR].ch_buffer->b_ffname);
11401142
}
1143+
1144+
channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT];
1145+
channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR];
1146+
channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN];
11411147
}
11421148

11431149
/*
@@ -2088,6 +2094,69 @@ channel_status(channel_T *channel)
20882094
return "closed";
20892095
}
20902096

2097+
static void
2098+
channel_part_info(channel_T *channel, dict_T *dict, char *name, int part)
2099+
{
2100+
chanpart_T *chanpart = &channel->ch_part[part];
2101+
char namebuf[20];
2102+
int tail;
2103+
char *s;
2104+
2105+
STRCPY(namebuf, name);
2106+
STRCAT(namebuf, "_");
2107+
tail = STRLEN(namebuf);
2108+
2109+
STRCPY(namebuf + tail, "status");
2110+
dict_add_nr_str(dict, namebuf, 0,
2111+
(char_u *)(chanpart->ch_fd == INVALID_FD ? "closed" : "open"));
2112+
2113+
STRCPY(namebuf + tail, "mode");
2114+
switch (chanpart->ch_mode)
2115+
{
2116+
case MODE_NL: s = "NL"; break;
2117+
case MODE_RAW: s = "RAW"; break;
2118+
case MODE_JSON: s = "JSON"; break;
2119+
case MODE_JS: s = "JS"; break;
2120+
}
2121+
dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
2122+
2123+
STRCPY(namebuf + tail, "io");
2124+
if (part == PART_SOCK)
2125+
s = "socket";
2126+
else switch (chanpart->ch_io)
2127+
{
2128+
case JIO_NULL: s = "null"; break;
2129+
case JIO_PIPE: s = "pipe"; break;
2130+
case JIO_FILE: s = "file"; break;
2131+
case JIO_BUFFER: s = "buffer"; break;
2132+
case JIO_OUT: s = "out"; break;
2133+
}
2134+
dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
2135+
2136+
STRCPY(namebuf + tail, "timeout");
2137+
dict_add_nr_str(dict, namebuf, chanpart->ch_timeout, NULL);
2138+
}
2139+
2140+
void
2141+
channel_info(channel_T *channel, dict_T *dict)
2142+
{
2143+
dict_add_nr_str(dict, "id", channel->ch_id, NULL);
2144+
dict_add_nr_str(dict, "status", 0, (char_u *)channel_status(channel));
2145+
2146+
if (channel->ch_hostname != NULL)
2147+
{
2148+
dict_add_nr_str(dict, "hostname", 0, (char_u *)channel->ch_hostname);
2149+
dict_add_nr_str(dict, "port", channel->ch_port, NULL);
2150+
channel_part_info(channel, dict, "sock", PART_SOCK);
2151+
}
2152+
else
2153+
{
2154+
channel_part_info(channel, dict, "out", PART_OUT);
2155+
channel_part_info(channel, dict, "err", PART_ERR);
2156+
channel_part_info(channel, dict, "in", PART_IN);
2157+
}
2158+
}
2159+
20912160
/*
20922161
* Close channel "channel".
20932162
* Trigger the close callback if "invoke_close_cb" is TRUE.
@@ -2195,6 +2264,8 @@ channel_clear_one(channel_T *channel, int part)
21952264
channel_clear(channel_T *channel)
21962265
{
21972266
ch_log(channel, "Clearing channel");
2267+
vim_free(channel->ch_hostname);
2268+
channel->ch_hostname = NULL;
21982269
channel_clear_one(channel, PART_SOCK);
21992270
channel_clear_one(channel, PART_OUT);
22002271
channel_clear_one(channel, PART_ERR);

src/eval.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv);
501501
static void f_ch_evalraw(typval_T *argvars, typval_T *rettv);
502502
static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv);
503503
static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
504+
static void f_ch_info(typval_T *argvars, typval_T *rettv);
504505
static void f_ch_log(typval_T *argvars, typval_T *rettv);
505506
static void f_ch_logfile(typval_T *argvars, typval_T *rettv);
506507
static void f_ch_open(typval_T *argvars, typval_T *rettv);
@@ -8141,6 +8142,7 @@ static struct fst
81418142
{"ch_evalraw", 2, 3, f_ch_evalraw},
81428143
{"ch_getbufnr", 2, 2, f_ch_getbufnr},
81438144
{"ch_getjob", 1, 1, f_ch_getjob},
8145+
{"ch_info", 1, 1, f_ch_info},
81448146
{"ch_log", 1, 2, f_ch_log},
81458147
{"ch_logfile", 1, 2, f_ch_logfile},
81468148
{"ch_open", 1, 2, f_ch_open},
@@ -10028,6 +10030,18 @@ f_ch_getjob(typval_T *argvars, typval_T *rettv)
1002810030
}
1002910031
}
1003010032

10033+
/*
10034+
* "ch_info()" function
10035+
*/
10036+
static void
10037+
f_ch_info(typval_T *argvars, typval_T *rettv UNUSED)
10038+
{
10039+
channel_T *channel = get_channel_arg(&argvars[0], TRUE);
10040+
10041+
if (channel != NULL && rettv_dict_alloc(rettv) != FAIL)
10042+
channel_info(channel, rettv->vval.v_dict);
10043+
}
10044+
1003110045
/*
1003210046
* "ch_log()" function
1003310047
*/

src/proto/channel.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ int channel_collapse(channel_T *channel, int part);
2020
int channel_can_write_to(channel_T *channel);
2121
int channel_is_open(channel_T *channel);
2222
char *channel_status(channel_T *channel);
23+
void channel_info(channel_T *channel, dict_T *dict);
2324
void channel_close(channel_T *channel, int invoke_close_cb);
2425
char_u *channel_peek(channel_T *channel, int part);
2526
void channel_clear(channel_T *channel);

src/testdir/test_channel.vim

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,16 @@ func s:communicate(port)
120120
return
121121
endif
122122
if has('job')
123-
" check that no job is handled correctly
123+
" check that getjob without a job is handled correctly
124124
call assert_equal('no process', string(ch_getjob(handle)))
125125
endif
126+
let dict = ch_info(handle)
127+
call assert_true(dict.id != 0)
128+
call assert_equal('open', dict.status)
129+
call assert_equal(a:port, string(dict.port))
130+
call assert_equal('open', dict.sock_status)
131+
call assert_equal('socket', dict.sock_io)
132+
126133
" Simple string request and reply.
127134
call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
128135

src/version.c

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

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1624,
751753
/**/
752754
1623,
753755
/**/

0 commit comments

Comments
 (0)