]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 7.4.1341 v7.4.1341
authorBram Moolenaar <Bram@vim.org>
Tue, 16 Feb 2016 20:03:07 +0000 (21:03 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 16 Feb 2016 20:03:07 +0000 (21:03 +0100)
Problem:    It's difficult to add more arguments to ch_sendraw() and
            ch_sendexpr().
Solution:   Make the third option a dictionary.

runtime/doc/channel.txt
runtime/doc/eval.txt
src/channel.c
src/eval.c
src/os_unix.c
src/os_win32.c
src/proto/channel.pro
src/structs.h
src/testdir/test_channel.vim
src/version.c

index 7938087b1b7337d2eeceaa9f6ca8d504e374e513..a52c739ad7799a13d08904665e81b9deaff3f968 100644 (file)
@@ -1,4 +1,4 @@
-*channel.txt*      For Vim version 7.4.  Last change: 2016 Feb 15
+*channel.txt*      For Vim version 7.4.  Last change: 2016 Feb 16
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -117,7 +117,7 @@ Use |ch_status()| to see if the channel could be opened.
 
 "mode" can be:                                         *channel-mode*
        "json" - Use JSON, see below; most convenient way. Default.
-       "js"   - Use JavaScript encoding, more efficient than JSON.
+       "js"   - Use JS (JavaScript) encoding, more efficient than JSON.
        "nl"   - Use messages that end in a NL character
        "raw"  - Use raw messages
 
@@ -188,11 +188,11 @@ If there is an error reading or writing a channel it will be closed.
 ==============================================================================
 4. Using a JSON or JS channel                                  *channel-use*
 
-If {mode} is "json" then a message can be sent synchronously like this: >
+If mode is JSON then a message can be sent synchronously like this: >
     let response = ch_sendexpr(channel, {expr})
 This awaits a response from the other side.
 
-When {mode} is "js" this works the same, except that the messages use
+When mode is JS this works the same, except that the messages use
 JavaScript encoding.  See |js_encode()| for the difference.
 
 To send a message, without handling a response: >
@@ -242,7 +242,7 @@ is then completely responsible for correct encoding and decoding.
 ==============================================================================
 5. Channel commands                                    *channel-commands*
 
-With a "json" channel the process can send commands to Vim that will be
+With a JSON channel the process can send commands to Vim that will be
 handled by Vim internally, it does not require a handler for the channel.
 
 Possible commands are:                         *E903* *E904* *E905*
@@ -316,14 +316,15 @@ Example:
 ==============================================================================
 6. Using a RAW or NL channel                           *channel-raw*
 
-If {mode} is "raw" then a message can be send like this: >
+If mode is RAW or NL then a message can be send like this: >
     let response = ch_sendraw(channel, {string})
+
 The {string} is sent as-is.  The response will be what can be read from the
 channel right away.  Since Vim doesn't know how to recognize the end of the
 message you need to take care of it yourself.  The timeout applies for reading
 the first byte, after that it will not wait for anything more.
 
-If {mode} is "nl" you can send a message in a similar way.  You are expected
+If mode is "nl" you can send a message in a similar way.  You are expected
 to put in the NL after each message.  Thus you can also send several messages
 ending in a NL at once.  The response will be the text up to and including the
 first NL.  This can also be just the NL for an empty response.
@@ -450,6 +451,7 @@ The {options} argument in job_start() is a dictionary.  All entries are
 optional.  The same options can be used with job_setoptions(job, {options}).
 
 TODO:                                          *job-out-cb*
+"callback": handler
 "out-cb": handler      Callback for when there is something to read on
                        stdout.
 TODO:                                          *job-err-cb*
@@ -484,7 +486,7 @@ TODO:                                               *job-out-io*
 "out-buffer": "name"   buffer to append to
 
 TODO:                                          *job-err-io*
-"err-io": "out"                same as stdout (default)
+"err-io": "out"                same type as stdout (default)
 "err-io": "null"       disconnect stderr
 "err-io": "pipe"       stderr is connected to the channel
 "err-io": "file"       stderr writes to a file
index 6feb137a2f23796f232244a4c5ef000b30d8218f..9ec893f74477246985d76b2a48be2aee64fd6272 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 7.4.  Last change: 2016 Feb 13
+*eval.txt*     For Vim version 7.4.  Last change: 2016 Feb 16
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1821,9 +1821,9 @@ ch_close( {handle})               none    close a channel
 ch_logfile( {fname} [, {mode}])        none    start logging channel activity
 ch_open( {address} [, {argdict})] Number open a channel to {address}
 ch_readraw( {handle})          String  read from channel {handle}
-ch_sendexpr( {handle}, {expr} [, {callback}])
+ch_sendexpr( {handle}, {expr} [, {options}])
                                any     send {expr} over JSON channel {handle}
-ch_sendraw( {handle}, {string} [, {callback}])
+ch_sendraw( {handle}, {string} [, {options}])
                                any     send {string} over raw channel {handle}
 ch_status( {handle})           String  status of channel {handle}
 changenr()                     Number  current change number
@@ -2725,28 +2725,32 @@ ch_readraw({handle})                                            *ch_readraw()*
                within that time an empty string is returned.
                TODO: depends on channel mode.
 
-ch_sendexpr({handle}, {expr} [, {callback}])                   *ch_sendexpr()*
+ch_sendexpr({handle}, {expr} [, {options}])                    *ch_sendexpr()*
                Send {expr} over channel {handle}.  The {expr} is encoded
                according to the type of channel.  The function cannot be used
                with a raw channel.  See |channel-use|.  *E912*
 
-               When {callback} is given returns immediately.  Without
-               {callback} waits for a response and returns the decoded
-               expression.  When there is an error or timeout returns an
-               empty string.
+               {options} must be a Dictionary.
+               When "callback" is a Funcref or the name of a function,
+               ch_sendexpr() returns immediately.  The callback is invoked
+               when the response is received.  See |channel-callback|.
+
+               Without "callback" ch_sendexpr() waits for a response and
+               returns the decoded expression.  When there is an error or
+               timeout it returns an empty string.
 
-               When {callback} is zero no response is expected.
-               Otherwise {callback} must be a Funcref or the name of a
-               function.  It is called when the response is received.  See
-               |channel-callback|.
+               When "callback" is zero no response is expected.
 
                {only available when compiled with the |+channel| feature}
 
-ch_sendraw({handle}, {string} [, {callback}])          *ch_sendraw()*
+ch_sendraw({handle}, {string} [, {options}])           *ch_sendraw()*
                Send {string} over channel {handle}.
                Works like |ch_sendexpr()|, but does not encode the request or
                decode the response.  The caller is responsible for the
-               correct contents.  See |channel-use|.
+               correct contents.  Also does not add a newline for a channel
+               in NL mode, the caller must do that.  The NL in the response
+               is removed.
+               See |channel-use|.
 
                {only available when compiled with the |+channel| feature}
 
@@ -7274,7 +7278,7 @@ listcmds          Compiled with commands for the buffer list |:files|
                        and the argument list |arglist|.
 localmap               Compiled with local mappings and abbr. |:map-local|
 lua                    Compiled with Lua interface |Lua|.
-mac                    Macintosh version of Vim.
+mac                    Any Macintosh version of Vim.
 macunix                        Compiled for OS X, with darwin
 osx                    Compiled for OS X, with or without darwin
 menu                   Compiled with support for |:menu|.
index 3cfe1bea314822f62a3e99ec2e0ea24d252e39c2..d4663d86e8b96dff105d4797aad566ff7bd3c034 100644 (file)
@@ -696,6 +696,18 @@ channel_set_callback(channel_T *channel, char_u *callback)
     channel->ch_callback = vim_strsave(callback);
 }
 
+/*
+ * Set various properties from an "options" argument.
+ */
+    void
+channel_set_options(channel_T *channel, jobopt_T *options)
+{
+    channel_set_mode(channel, options->jo_mode);
+
+    if (options->jo_callback != NULL && *options->jo_callback != NUL)
+       channel_set_callback(channel, options->jo_callback);
+}
+
 /*
  * Set the callback for channel "channel" for the response with "id".
  */
index 8e4e5400abc398db8352574ba69a445d98354d32..f47b09609147cc9528d97e33564f14270fbe2684 100644 (file)
@@ -9930,15 +9930,18 @@ f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED)
 }
 
 /*
- * Get the "mode" entry from "dict", if it exists, and parse the mode name.
- * If the mode is invalide return FAIL.
+ * Get the option entries from "dict", and parse them.
+ * If an option value is invalid return FAIL.
  */
     static int
-get_mode_arg(dict_T *dict, jobopt_T *opt)
+get_job_options(dict_T *dict, jobopt_T *opt)
 {
     dictitem_T *item;
     char_u     *mode;
 
+    if (dict == NULL)
+       return OK;
+
     if ((item = dict_find(dict, (char_u *)"mode", -1)) != NULL)
     {
        mode = get_tv_string(&item->di_tv);
@@ -9956,6 +9959,17 @@ get_mode_arg(dict_T *dict, jobopt_T *opt)
            return FAIL;
        }
     }
+
+    if ((item = dict_find(dict, (char_u *)"callback", -1)) != NULL)
+    {
+       opt->jo_callback = get_callback(&item->di_tv);
+       if (opt->jo_callback == NULL)
+       {
+           EMSG2(_(e_invarg2), "callback");
+           return FAIL;
+       }
+    }
+
     return OK;
 }
 
@@ -9966,7 +9980,6 @@ get_mode_arg(dict_T *dict, jobopt_T *opt)
 f_ch_open(typval_T *argvars, typval_T *rettv)
 {
     char_u     *address;
-    char_u     *callback = NULL;
     char_u     *p;
     char       *rest;
     int                port;
@@ -10004,20 +10017,19 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
     }
 
     options.jo_mode = MODE_JSON;
+    options.jo_callback = NULL;
     if (argvars[1].v_type == VAR_DICT)
     {
        dict_T      *dict = argvars[1].vval.v_dict;
        dictitem_T  *item;
 
        /* parse argdict */
-       if (get_mode_arg(dict, &options) == FAIL)
+       if (get_job_options(dict, &options) == FAIL)
            return;
        if ((item = dict_find(dict, (char_u *)"waittime", -1)) != NULL)
            waittime = get_tv_number(&item->di_tv);
        if ((item = dict_find(dict, (char_u *)"timeout", -1)) != NULL)
            timeout = get_tv_number(&item->di_tv);
-       if ((item = dict_find(dict, (char_u *)"callback", -1)) != NULL)
-           callback = get_callback(&item->di_tv);
     }
     if (waittime < 0 || timeout < 0)
     {
@@ -10029,10 +10041,8 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
     if (channel != NULL)
     {
        rettv->vval.v_channel = channel;
-       channel_set_mode(channel, options.jo_mode);
+       channel_set_options(channel, &options);
        channel_set_timeout(channel, timeout);
-       if (callback != NULL && *callback != NUL)
-           channel_set_callback(channel, callback);
     }
 }
 
@@ -10082,6 +10092,7 @@ send_common(typval_T *argvars, char_u *text, int id, char *fun)
 {
     channel_T  *channel;
     char_u     *callback = NULL;
+    jobopt_T   options;
 
     channel = get_channel_arg(&argvars[0]);
     if (channel == NULL)
@@ -10089,9 +10100,15 @@ send_common(typval_T *argvars, char_u *text, int id, char *fun)
 
     if (argvars[2].v_type != VAR_UNKNOWN)
     {
-       callback = get_callback(&argvars[2]);
-       if (callback == NULL)
+       if (argvars[2].v_type != VAR_DICT)
+       {
+           EMSG(_(e_invarg));
+           return NULL;
+       }
+       options.jo_callback = NULL;
+       if (get_job_options(argvars[2].vval.v_dict, &options) == FAIL)
            return NULL;
+       callback = options.jo_callback;
     }
     /* Set the callback. An empty callback means no callback and not reading
      * the response. */
@@ -14511,17 +14528,15 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
 
     /* Default mode is NL. */
     options.jo_mode = MODE_NL;
+    options.jo_callback = NULL;
     if (argvars[1].v_type != VAR_UNKNOWN)
     {
-       dict_T      *dict;
-
        if (argvars[1].v_type != VAR_DICT)
        {
            EMSG(_(e_invarg));
            return;
        }
-       dict = argvars[1].vval.v_dict;
-       if (get_mode_arg(dict, &options) == FAIL)
+       if (get_job_options(argvars[1].vval.v_dict, &options) == FAIL)
            return;
     }
 
index 0059c9eeeb05a41f206abcb4b4895bd20cfd9590..1f0f2c8046705032b86ac45c107ef6c97ee28609 100644 (file)
@@ -5127,7 +5127,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
 # ifdef FEAT_CHANNEL
     channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]);
     channel_set_job(channel, job);
-    channel_set_mode(channel, options->jo_mode);
+    channel_set_options(channel, options);
 #  ifdef FEAT_GUI
     channel_gui_register(channel);
 #  endif
index eaa8ba5f5e3c0baf1fada2a14abf3999e98b0bec..63d7d60cb5a5126f68bcda3eb719b20a3c8ea766 100644 (file)
@@ -5125,7 +5125,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
     job->jv_channel = channel;
     channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], (sock_T)efd[0]);
     channel_set_job(channel, job);
-    channel_set_mode(channel, options->jo_mode);
+    channel_set_options(channel, options);
 
 #   ifdef FEAT_GUI
      channel_gui_register(channel);
index e1c88627f84a693baaeb0f624c058cf88e614897..a4acfe6d1b456df77dd6a200d5a80b41baab940e 100644 (file)
@@ -7,9 +7,10 @@ void channel_gui_register_all(void);
 channel_T *channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void));
 void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
 void channel_set_job(channel_T *channel, job_T *job);
-void channel_set_mode(channel_T *channel, ch_mode_T ch_mode);
+void channel_set_mode(channel_T *channel, ch_mode_T mode);
 void channel_set_timeout(channel_T *channel, int timeout);
 void channel_set_callback(channel_T *channel, char_u *callback);
+void channel_set_options(channel_T *channel, jobopt_T *options);
 void channel_set_req_callback(channel_T *channel, char_u *callback, int id);
 char_u *channel_get(channel_T *channel);
 int channel_collapse(channel_T *channel);
index eb72f90f241f0ce33fab9dacc9c1cb6c05f9c131..802180bb7ade47132c671e90fe07f06a1bef1280 100644 (file)
@@ -1373,11 +1373,12 @@ struct channel_S {
 };
 
 /*
- * Options for job commands.
+ * Options for job and channel commands.
  */
 typedef struct
 {
-    ch_mode_T  jo_mode;
+    ch_mode_T  jo_mode;        /* "mode" */
+    char_u     *jo_callback;   /* "callback", not allocated! */
 } jobopt_T;
 
 
index e9c2a98e70a3f8c2a53be9f8793d03a2941d2088..7cd32c81b5bf59aba9535ab399bb058e11dceb9f 100644 (file)
@@ -117,7 +117,7 @@ func s:communicate(port)
   call assert_equal('added more', getline('$'))
 
   " Send a request with a specific handler.
-  call ch_sendexpr(handle, 'hello!', 's:RequestHandler')
+  call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
   sleep 10m
   if !exists('s:responseHandle')
     call assert_false(1, 's:responseHandle was not set')
@@ -128,7 +128,7 @@ func s:communicate(port)
 
   unlet s:responseHandle
   let s:responseMsg = ''
-  call ch_sendexpr(handle, 'hello!', function('s:RequestHandler'))
+  call ch_sendexpr(handle, 'hello!', {'callback': function('s:RequestHandler')})
   sleep 10m
   if !exists('s:responseHandle')
     call assert_false(1, 's:responseHandle was not set')
@@ -171,7 +171,7 @@ func s:communicate(port)
   call assert_equal('ok', ch_sendexpr(handle, 'empty-request'))
 
   " make the server quit, can't check if this works, should not hang.
-  call ch_sendexpr(handle, '!quit!', 0)
+  call ch_sendexpr(handle, '!quit!', {'callback': 0})
 endfunc
 
 func Test_communicate()
@@ -242,7 +242,7 @@ func s:channel_handler(port)
   call assert_equal('we called you', s:reply)
 
   " Test that it works while not waiting on a numbered message.
-  call ch_sendexpr(handle, 'call me again', 0)
+  call ch_sendexpr(handle, 'call me again', {'callback': 0})
   sleep 10m
   call assert_equal('we did call you', s:reply)
 endfunc
@@ -292,11 +292,11 @@ func Test_raw_pipe()
   call assert_equal("run", job_status(job))
   try
     let handle = job_getchannel(job)
-    call ch_sendraw(handle, "echo something\n", 0)
+    call ch_sendraw(handle, "echo something\n", {'callback': 0})
     let msg = ch_readraw(handle)
     call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
 
-    call ch_sendraw(handle, "double this\n", 0)
+    call ch_sendraw(handle, "double this\n", {'callback': 0})
     let msg = ch_readraw(handle)
     call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
 
@@ -315,10 +315,10 @@ func Test_nl_pipe()
   call assert_equal("run", job_status(job))
   try
     let handle = job_getchannel(job)
-    call ch_sendraw(handle, "echo something\n", 0)
+    call ch_sendraw(handle, "echo something\n", {'callback': 0})
     call assert_equal("something", ch_readraw(handle))
 
-    call ch_sendraw(handle, "double this\n", 0)
+    call ch_sendraw(handle, "double this\n", {'callback': 0})
     call assert_equal("this", ch_readraw(handle))
     call assert_equal("AND this", ch_readraw(handle))
 
@@ -340,7 +340,7 @@ endfunc
 " Test that "unlet handle" in a handler doesn't crash Vim.
 func s:unlet_handle(port)
   let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
-  call ch_sendexpr(s:channelfd, "test", function('s:UnletHandler'))
+  call ch_sendexpr(s:channelfd, "test", {'callback': function('s:UnletHandler')})
   sleep 10m
   call assert_equal('what?', s:unletResponse)
 endfunc
@@ -360,7 +360,7 @@ endfunc
 " Test that "unlet handle" in a handler doesn't crash Vim.
 func s:close_handle(port)
   let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
-  call ch_sendexpr(s:channelfd, "test", function('s:CloseHandler'))
+  call ch_sendexpr(s:channelfd, "test", {'callback': function('s:CloseHandler')})
   sleep 10m
   call assert_equal('what?', s:unletResponse)
 endfunc
index 9821bdfc9fc1801294c121d263d7645f0bea185a..f7c008ce2586e48e21f9daf765b5725895c67b7e 100644 (file)
@@ -747,6 +747,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1341,
 /**/
     1340,
 /**/