]> granicus.if.org Git - vim/commitdiff
patch 7.4.1624 v7.4.1624
authorBram Moolenaar <Bram@vim.org>
Sun, 20 Mar 2016 19:57:45 +0000 (20:57 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 20 Mar 2016 19:57:45 +0000 (20:57 +0100)
Problem:    Can't get info about a channel.
Solution:   Add ch_info().

runtime/doc/eval.txt
src/channel.c
src/eval.c
src/proto/channel.pro
src/testdir/test_channel.vim
src/version.c

index 43e25faad11efa9aa329f265ce02f957ef015c30..642f0ad768ef9018ced38921790a8126616d853c 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 7.4.  Last change: 2016 Mar 15
+*eval.txt*     For Vim version 7.4.  Last change: 2016 Mar 20
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -753,7 +753,12 @@ recursively.  Ignoring case means case is ignored when comparing item values.
 
                                                        *E693* *E694*
 A |Funcref| can only be compared with a |Funcref| and only "equal" and "not
-equal" can be used.  Case is never ignored.
+equal" can be used.  Case is never ignored.  Whether arguments or a Dictionary
+are bound (with a partial) is ignored.  This is so that when a function is
+made a member of a Dictionary it is still considered to be the same function.
+To compare partials to see if they bind the same argument and Dictionary
+values use string(): >
+       echo string(Partial1) == string(Partial2)
 
 When using "is" or "isnot" with a |List| or a |Dictionary| this checks if the
 expressions are referring to the same |List| or |Dictionary| instance.  A copy
@@ -1822,6 +1827,7 @@ ch_evalraw( {handle}, {string} [, {options}])
                                any     evaluate {string} on raw {handle}
 ch_getbufnr( {handle}, {what}) Number  get buffer number for {handle}/{what}
 ch_getjob( {channel})          Job     get the Job of {channel}
+ch_info( {handle})             String  info about channel  {handle}
 ch_log( {msg} [, {handle}])    none    write {msg} in the channel log file
 ch_logfile( {fname} [, {mode}])        none    start logging channel activity
 ch_open( {address} [, {options}]) Channel open a channel to {address}
@@ -1832,7 +1838,7 @@ ch_sendexpr( {handle}, {expr} [, {options}])
 ch_sendraw( {handle}, {string} [, {options}])
                                any     send {string} over raw {handle}
 ch_setoptions( {handle}, {options})  none  set options for {handle}
-ch_status( {handle})           String  status of  {handle}
+ch_status( {handle})           String  status of channel  {handle}
 changenr()                     Number  current change number
 char2nr( {expr}[, {utf8}])     Number  ASCII/UTF8 value of first char in {expr}
 cindent( {lnum})               Number  C indent for line {lnum}
@@ -2759,6 +2765,32 @@ ch_getjob({channel})                                             *ch_getjob()*
                {only available when compiled with the |+channel| and
                |+job| features}
 
+ch_info({handle})                                              *ch_info()*
+               Returns a Dictionary with information about {handle}.  The
+               items are:
+                  "id"           number of the channel
+                  "status"       "open" (any part is open) or "closed"
+               When opened with ch_open():
+                  "hostname"     the hostname of the address
+                  "port"         the port of the address
+                  "sock_status"  "open" or "closed"
+                  "sock_mode"    "NL", "RAW", "JSON" or "JS"
+                  "sock_io"      "socket"
+                  "sock_timeout" timeout in msec
+               When opened with job_start():
+                  "out_status"   "open" or "closed"
+                  "out_mode"     "NL", "RAW", "JSON" or "JS"
+                  "out_io"       "null", "pipe", "file" or "buffer"
+                  "out_timeout"  timeout in msec
+                  "err_status"   "open" or "closed"
+                  "err_mode"     "NL", "RAW", "JSON" or "JS"
+                  "err_io"       "out", "null", "pipe", "file" or "buffer"
+                  "err_timeout"  timeout in msec
+                  "in_status"    "open" or "closed"
+                  "in_mode"      "NL", "RAW", "JSON" or "JS"
+                  "in_io"        "null", "pipe", "file" or "buffer"
+                  "in_timeout"   timeout in msec
+
 ch_log({msg} [, {handle}])                                     *ch_log()*
                Write {msg} in the channel log file, if it was opened with
                |ch_logfile()|.
@@ -3594,6 +3626,18 @@ function({name} [, {arglist}] [, {dict}])
 <              Invokes the function as with: >
                        call Callback('one', 'two', 'name')
 
+<              The function() call can be nested to add more arguments to the
+               Funcref.  The extra arguments are appended to the list of
+               arguments.  Example: >
+                       func Callback(arg1, arg2, name)
+                       ...
+                       let Func = function('Callback', ['one'])
+                       let Func2 = function(Func, ['two'])
+                       ...
+                       call Func2('name')
+<              Invokes the function as with: >
+                       call Callback('one', 'two', 'name')
+
 <              The Dictionary is only useful when calling a "dict" function.
                In that case the {dict} is passed in as "self". Example: >
                        function Callback() dict
@@ -7050,6 +7094,10 @@ timer_start({time}, {callback} [, {options}])
                intervals.
                {only available when compiled with the |+timers| feature}
 
+timer_stop({timer})                                    *timer_stop()*
+               Stop a timer.  {timer} is an ID returned by timer_start().
+               The timer callback will no longer be invoked.
+
 tolower({expr})                                                *tolower()*
                The result is a copy of the String given, with all uppercase
                characters turned into lowercase (just like applying |gu| to
index 15c7c74d01fcd4ef21cb324ab37e734ed20454ee..be0dc1938384783069177a28f8aa966601313606 100644 (file)
@@ -838,6 +838,8 @@ channel_open(
 
     channel->CH_SOCK_FD = (sock_T)sd;
     channel->ch_nb_close_cb = nb_close_cb;
+    channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
+    channel->ch_port = port_in;
 
 #ifdef FEAT_GUI
     channel_gui_register_one(channel, PART_SOCK);
@@ -1138,6 +1140,10 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
        ch_logs(channel, "writing err to buffer '%s'",
                      (char *)channel->ch_part[PART_ERR].ch_buffer->b_ffname);
     }
+
+    channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT];
+    channel->ch_part[PART_ERR].ch_io = opt->jo_io[PART_ERR];
+    channel->ch_part[PART_IN].ch_io = opt->jo_io[PART_IN];
 }
 
 /*
@@ -2088,6 +2094,69 @@ channel_status(channel_T *channel)
     return "closed";
 }
 
+    static void
+channel_part_info(channel_T *channel, dict_T *dict, char *name, int part)
+{
+    chanpart_T *chanpart = &channel->ch_part[part];
+    char       namebuf[20];
+    int                tail;
+    char       *s;
+
+    STRCPY(namebuf, name);
+    STRCAT(namebuf, "_");
+    tail = STRLEN(namebuf);
+
+    STRCPY(namebuf + tail, "status");
+    dict_add_nr_str(dict, namebuf, 0,
+               (char_u *)(chanpart->ch_fd == INVALID_FD ? "closed" : "open"));
+
+    STRCPY(namebuf + tail, "mode");
+    switch (chanpart->ch_mode)
+    {
+       case MODE_NL: s = "NL"; break;
+       case MODE_RAW: s = "RAW"; break;
+       case MODE_JSON: s = "JSON"; break;
+       case MODE_JS: s = "JS"; break;
+    }
+    dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
+
+    STRCPY(namebuf + tail, "io");
+    if (part == PART_SOCK)
+       s = "socket";
+    else switch (chanpart->ch_io)
+    {
+       case JIO_NULL: s = "null"; break;
+       case JIO_PIPE: s = "pipe"; break;
+       case JIO_FILE: s = "file"; break;
+       case JIO_BUFFER: s = "buffer"; break;
+       case JIO_OUT: s = "out"; break;
+    }
+    dict_add_nr_str(dict, namebuf, 0, (char_u *)s);
+
+    STRCPY(namebuf + tail, "timeout");
+    dict_add_nr_str(dict, namebuf, chanpart->ch_timeout, NULL);
+}
+
+    void
+channel_info(channel_T *channel, dict_T *dict)
+{
+    dict_add_nr_str(dict, "id", channel->ch_id, NULL);
+    dict_add_nr_str(dict, "status", 0, (char_u *)channel_status(channel));
+
+    if (channel->ch_hostname != NULL)
+    {
+       dict_add_nr_str(dict, "hostname", 0, (char_u *)channel->ch_hostname);
+       dict_add_nr_str(dict, "port", channel->ch_port, NULL);
+       channel_part_info(channel, dict, "sock", PART_SOCK);
+    }
+    else
+    {
+       channel_part_info(channel, dict, "out", PART_OUT);
+       channel_part_info(channel, dict, "err", PART_ERR);
+       channel_part_info(channel, dict, "in", PART_IN);
+    }
+}
+
 /*
  * Close channel "channel".
  * Trigger the close callback if "invoke_close_cb" is TRUE.
@@ -2195,6 +2264,8 @@ channel_clear_one(channel_T *channel, int part)
 channel_clear(channel_T *channel)
 {
     ch_log(channel, "Clearing channel");
+    vim_free(channel->ch_hostname);
+    channel->ch_hostname = NULL;
     channel_clear_one(channel, PART_SOCK);
     channel_clear_one(channel, PART_OUT);
     channel_clear_one(channel, PART_ERR);
index 22ddafa872a1ccf3d3ec2facaf40b283d6f34cdb..b2338331f55c5a6c11be4e3cda69bb7b2eec4f12 100644 (file)
@@ -501,6 +501,7 @@ 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);
 static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
+static void f_ch_info(typval_T *argvars, typval_T *rettv);
 static void f_ch_log(typval_T *argvars, typval_T *rettv);
 static void f_ch_logfile(typval_T *argvars, typval_T *rettv);
 static void f_ch_open(typval_T *argvars, typval_T *rettv);
@@ -8141,6 +8142,7 @@ static struct fst
     {"ch_evalraw",     2, 3, f_ch_evalraw},
     {"ch_getbufnr",    2, 2, f_ch_getbufnr},
     {"ch_getjob",      1, 1, f_ch_getjob},
+    {"ch_info",                1, 1, f_ch_info},
     {"ch_log",         1, 2, f_ch_log},
     {"ch_logfile",     1, 2, f_ch_logfile},
     {"ch_open",                1, 2, f_ch_open},
@@ -10028,6 +10030,18 @@ f_ch_getjob(typval_T *argvars, typval_T *rettv)
     }
 }
 
+/*
+ * "ch_info()" function
+ */
+    static void
+f_ch_info(typval_T *argvars, typval_T *rettv UNUSED)
+{
+    channel_T *channel = get_channel_arg(&argvars[0], TRUE);
+
+    if (channel != NULL && rettv_dict_alloc(rettv) != FAIL)
+       channel_info(channel, rettv->vval.v_dict);
+}
+
 /*
  * "ch_log()" function
  */
index b98fb5801771958d64df8b62ebae41ff39e563ed..e33490875675d35d0d93e1c384b6473c68fbadfa 100644 (file)
@@ -20,6 +20,7 @@ int channel_collapse(channel_T *channel, int part);
 int channel_can_write_to(channel_T *channel);
 int channel_is_open(channel_T *channel);
 char *channel_status(channel_T *channel);
+void channel_info(channel_T *channel, dict_T *dict);
 void channel_close(channel_T *channel, int invoke_close_cb);
 char_u *channel_peek(channel_T *channel, int part);
 void channel_clear(channel_T *channel);
index c4e23c97fa3b58d84484fd617bcc684649817b49..0fd7de9dd139e35ed5ce329378166c9236051f06 100644 (file)
@@ -120,9 +120,16 @@ func s:communicate(port)
     return
   endif
   if has('job')
-    " check that no job is handled correctly
+    " check that getjob without a job is handled correctly
     call assert_equal('no process', string(ch_getjob(handle)))
   endif
+  let dict = ch_info(handle)
+  call assert_true(dict.id != 0)
+  call assert_equal('open', dict.status)
+  call assert_equal(a:port, string(dict.port))
+  call assert_equal('open', dict.sock_status)
+  call assert_equal('socket', dict.sock_io)
+
   " Simple string request and reply.
   call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
 
index d7277034ac812cca7b4e3650b89025b5154e19cb..d465d8151bd46f7953932f4f6c98bc10bd4caebb 100644 (file)
@@ -748,6 +748,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1624,
 /**/
     1623,
 /**/