Patch 7.4.1341
Problem: It's difficult to add more arguments to ch_sendraw() and
ch_sendexpr().
Solution: Make the third option a dictionary.
Files: src/eval.c, src/structs.h, src/channel.c, src/os_unix.c,
src/os_win32.c, src/proto/channel.pro,
src/testdir/test_channel.vim, runtime/doc/eval.txt
*** ../vim-7.4.1340/src/eval.c 2016-02-16 19:37:24.445233506 +0100
--- src/eval.c 2016-02-16 20:53:30.309425831 +0100
***************
*** 9930,9944 ****
}
/*
! * Get the "mode" entry from "dict", if it exists, and parse the mode name.
! * If the mode is invalide return FAIL.
*/
static int
! get_mode_arg(dict_T *dict, jobopt_T *opt)
{
dictitem_T *item;
char_u *mode;
if ((item = dict_find(dict, (char_u *)"mode", -1)) != NULL)
{
mode = get_tv_string(&item->di_tv);
--- 9930,9947 ----
}
/*
! * Get the option entries from "dict", and parse them.
! * If an option value is invalid return FAIL.
*/
static int
! 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,9961 ****
--- 9959,9975 ----
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,9972 ****
f_ch_open(typval_T *argvars, typval_T *rettv)
{
char_u *address;
- char_u *callback = NULL;
char_u *p;
char *rest;
int port;
--- 9980,9985 ----
***************
*** 10004,10023 ****
}
options.jo_mode = MODE_JSON;
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)
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)
{
--- 10017,10035 ----
}
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_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 (waittime < 0 || timeout < 0)
{
***************
*** 10029,10038 ****
if (channel != NULL)
{
rettv->vval.v_channel = channel;
! channel_set_mode(channel, options.jo_mode);
channel_set_timeout(channel, timeout);
- if (callback != NULL && *callback != NUL)
- channel_set_callback(channel, callback);
}
}
--- 10041,10048 ----
if (channel != NULL)
{
rettv->vval.v_channel = channel;
! channel_set_options(channel, &options);
channel_set_timeout(channel, timeout);
}
}
***************
*** 10082,10087 ****
--- 10092,10098 ----
{
channel_T *channel;
char_u *callback = NULL;
+ jobopt_T options;
channel = get_channel_arg(&argvars[0]);
if (channel == NULL)
***************
*** 10089,10097 ****
if (argvars[2].v_type != VAR_UNKNOWN)
{
! callback = get_callback(&argvars[2]);
! if (callback == NULL)
return NULL;
}
/* Set the callback. An empty callback means no callback and not reading
* the response. */
--- 10100,10114 ----
if (argvars[2].v_type != VAR_UNKNOWN)
{
! 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,14527 ****
/* Default mode is NL. */
options.jo_mode = MODE_NL;
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)
return;
}
--- 14528,14542 ----
/* Default mode is NL. */
options.jo_mode = MODE_NL;
+ options.jo_callback = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
{
if (argvars[1].v_type != VAR_DICT)
{
EMSG(_(e_invarg));
return;
}
! if (get_job_options(argvars[1].vval.v_dict, &options) == FAIL)
return;
}
*** ../vim-7.4.1340/src/structs.h 2016-02-16 19:25:07.580925715 +0100
--- src/structs.h 2016-02-16 20:34:24.021499966 +0100
***************
*** 1373,1383 ****
};
/*
! * Options for job commands.
*/
typedef struct
{
! ch_mode_T jo_mode;
} jobopt_T;
--- 1373,1384 ----
};
/*
! * Options for job and channel commands.
*/
typedef struct
{
! ch_mode_T jo_mode; /* "mode" */
! char_u *jo_callback; /* "callback", not allocated! */
} jobopt_T;
*** ../vim-7.4.1340/src/channel.c 2016-02-16 19:25:07.580925715 +0100
--- src/channel.c 2016-02-16 20:43:11.751946370 +0100
***************
*** 697,702 ****
--- 697,714 ----
}
/*
+ * 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".
*/
void
*** ../vim-7.4.1340/src/os_unix.c 2016-02-16 19:44:14.732951080 +0100
--- src/os_unix.c 2016-02-16 20:44:19.763229009 +0100
***************
*** 5127,5133 ****
# 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);
# ifdef FEAT_GUI
channel_gui_register(channel);
# endif
--- 5127,5133 ----
# ifdef FEAT_CHANNEL
channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]);
channel_set_job(channel, job);
! channel_set_options(channel, options);
# ifdef FEAT_GUI
channel_gui_register(channel);
# endif
*** ../vim-7.4.1340/src/os_win32.c 2016-02-16 20:31:27.223345909 +0100
--- src/os_win32.c 2016-02-16 20:45:31.702470333 +0100
***************
*** 5125,5131 ****
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);
# ifdef FEAT_GUI
channel_gui_register(channel);
--- 5125,5131 ----
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_options(channel, options);
# ifdef FEAT_GUI
channel_gui_register(channel);
*** ../vim-7.4.1340/src/proto/channel.pro 2016-02-16 19:25:07.580925715
+0100
--- src/proto/channel.pro 2016-02-16 20:43:52.371517915 +0100
***************
*** 7,15 ****
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_timeout(channel_T *channel, int timeout);
void channel_set_callback(channel_T *channel, char_u *callback);
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);
--- 7,16 ----
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 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);
*** ../vim-7.4.1340/src/testdir/test_channel.vim 2016-02-16
19:25:07.584925674 +0100
--- src/testdir/test_channel.vim 2016-02-16 20:57:00.983206848 +0100
***************
*** 117,123 ****
call assert_equal('added more', getline('$'))
" Send a request with a specific handler.
! call ch_sendexpr(handle, 'hello!', 's:RequestHandler')
sleep 10m
if !exists('s:responseHandle')
call assert_false(1, 's:responseHandle was not set')
--- 117,123 ----
call assert_equal('added more', getline('$'))
" Send a request with a specific handler.
! call ch_sendexpr(handle, 'hello!', {'callback': 's:RequestHandler'})
sleep 10m
if !exists('s:responseHandle')
call assert_false(1, 's:responseHandle was not set')
***************
*** 128,134 ****
unlet s:responseHandle
let s:responseMsg = ''
! call ch_sendexpr(handle, 'hello!', function('s:RequestHandler'))
sleep 10m
if !exists('s:responseHandle')
call assert_false(1, 's:responseHandle was not set')
--- 128,134 ----
unlet s:responseHandle
let s:responseMsg = ''
! 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,177 ****
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)
endfunc
func Test_communicate()
--- 171,177 ----
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!', {'callback': 0})
endfunc
func Test_communicate()
***************
*** 242,248 ****
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)
sleep 10m
call assert_equal('we did call you', s:reply)
endfunc
--- 242,248 ----
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', {'callback': 0})
sleep 10m
call assert_equal('we did call you', s:reply)
endfunc
***************
*** 292,302 ****
call assert_equal("run", job_status(job))
try
let handle = job_getchannel(job)
! call ch_sendraw(handle, "echo something\n", 0)
let msg = ch_readraw(handle)
call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
! call ch_sendraw(handle, "double this\n", 0)
let msg = ch_readraw(handle)
call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
--- 292,302 ----
call assert_equal("run", job_status(job))
try
let handle = job_getchannel(job)
! 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", {'callback': 0})
let msg = ch_readraw(handle)
call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
***************
*** 315,324 ****
call assert_equal("run", job_status(job))
try
let handle = job_getchannel(job)
! call ch_sendraw(handle, "echo something\n", 0)
call assert_equal("something", ch_readraw(handle))
! call ch_sendraw(handle, "double this\n", 0)
call assert_equal("this", ch_readraw(handle))
call assert_equal("AND this", ch_readraw(handle))
--- 315,324 ----
call assert_equal("run", job_status(job))
try
let handle = job_getchannel(job)
! call ch_sendraw(handle, "echo something\n", {'callback': 0})
call assert_equal("something", ch_readraw(handle))
! 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,346 ****
" 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'))
sleep 10m
call assert_equal('what?', s:unletResponse)
endfunc
--- 340,346 ----
" 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", {'callback':
function('s:UnletHandler')})
sleep 10m
call assert_equal('what?', s:unletResponse)
endfunc
***************
*** 360,366 ****
" 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'))
sleep 10m
call assert_equal('what?', s:unletResponse)
endfunc
--- 360,366 ----
" 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", {'callback':
function('s:CloseHandler')})
sleep 10m
call assert_equal('what?', s:unletResponse)
endfunc
*** ../vim-7.4.1340/runtime/doc/eval.txt 2016-02-16 14:07:36.186482678
+0100
--- runtime/doc/eval.txt 2016-02-16 20:48:54.952327482 +0100
***************
*** 1809,1818 ****
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}])
any send {expr} over JSON channel {handle}
! ch_sendraw( {handle}, {string} [, {callback}])
any send {string} over raw 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}
--- 1821,1831 ----
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} [, {options}])
any send {expr} over JSON channel {handle}
! 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
char2nr( {expr}[, {utf8}]) Number ASCII/UTF8 value of first char in {expr}
cindent( {lnum}) Number C indent for line {lnum}
***************
*** 1945,1950 ****
--- 1958,1964 ----
isdirectory( {directory}) Number TRUE if {directory} is a directory
islocked( {expr}) Number TRUE if {expr} is locked
items( {dict}) List key-value pairs in {dict}
+ job_getchannel( {job}) Number get the channel handle for {job}
job_start( {command} [, {options}]) Job start a job
job_status( {job}) String get the status of a job
job_stop( {job} [, {how}]) Number stop a job
***************
*** 2671,2679 ****
ch_logfile( {fname} [, {mode}])
*ch_logfile()*
Start logging channel activity to {fname}.
When {mode} is omitted or "a" append to the file.
When {mode} is "w" start with an empty file.
! When {fname} is an empty string: stop logging.
ch_open({address} [, {argdict}]) *ch_open()*
Open a channel to {address}. See |channel|.
--- 2688,2700 ----
ch_logfile( {fname} [, {mode}])
*ch_logfile()*
Start logging channel activity to {fname}.
+ When {fname} is an empty string: stop logging.
+
When {mode} is omitted or "a" append to the file.
When {mode} is "w" start with an empty file.
!
! The file is flushed after every message, on Unix you can use
! "tail -f" to see what is going on in real time.
ch_open({address} [, {argdict}]) *ch_open()*
Open a channel to {address}. See |channel|.
***************
*** 2704,2734 ****
within that time an empty string is returned.
TODO: depends on channel mode.
! ch_sendexpr({handle}, {expr} [, {callback}]) *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.
! 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|.
{only available when compiled with the |+channel| feature}
! ch_sendraw({handle}, {string} [, {callback}]) *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|.
{only available when compiled with the |+channel| feature}
*copy()*
copy({expr}) Make a copy of {expr}. For Numbers and Strings this isn't
different from using {expr} directly.
--- 2725,2765 ----
within that time an empty string is returned.
TODO: depends on channel mode.
! 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*
! {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.
{only available when compiled with the |+channel| feature}
! 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. 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}
+ ch_status({handle}) *ch_status()*
+ Return the status of channel {handle}:
+ "fail" failed to open the channel
+ "open" channel can be used
+ "closed" channel can not be used
+
*copy()*
copy({expr}) Make a copy of {expr}. For Numbers and Strings this isn't
different from using {expr} directly.
***************
*** 4263,4269 ****
order.
! job_start({command} [, {options}]) *job_start()*
Start a job and return a Job object. Unlike |system()| and
|:!cmd| this does not wait for the job to finish.
--- 4353,4363 ----
order.
! job_getchannel({job}) *job_getchannel()*
! Get the channel handle that {job} is using.
! {only available when compiled with the |+job| feature}
!
! job_start({command} [, {options}]) *job_start()*
Start a job and return a Job object. Unlike |system()| and
|:!cmd| this does not wait for the job to finish.
*** ../vim-7.4.1340/src/version.c 2016-02-16 20:31:27.223345909 +0100
--- src/version.c 2016-02-16 20:57:36.194836056 +0100
***************
*** 749,750 ****
--- 749,752 ----
{ /* Add new patch number below this line */
+ /**/
+ 1341,
/**/
--
Facepalm statement #5: "Petrol getting more expensive? Not for me, I'm always
tanking for 20 dollars"
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.