0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 7.4.1435

Problem:    It is confusing that ch_sendexpr() and ch_sendraw() wait for a
            response.
Solution:   Add ch_evalexpr() and ch_evalraw().
This commit is contained in:
Bram Moolenaar 2016-02-27 19:21:24 +01:00
parent b6ff81188d
commit 8b1862a316
5 changed files with 179 additions and 69 deletions

View File

@ -1,4 +1,4 @@
*channel.txt* For Vim version 7.4. Last change: 2016 Feb 23 *channel.txt* For Vim version 7.4. Last change: 2016 Feb 27
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -74,7 +74,7 @@ In T1 you should see:
=== socket opened === ~ === socket opened === ~
You can now send a message to the server: > You can now send a message to the server: >
echo ch_sendexpr(channel, 'hello!') echo ch_evalexpr(channel, 'hello!')
The message is received in T1 and a response is sent back to Vim. The message is received in T1 and a response is sent back to Vim.
You can see the raw messages in T1. What Vim sends is: You can see the raw messages in T1. What Vim sends is:
@ -101,7 +101,7 @@ Instead of giving a callback with every send call, it can also be specified
when opening the channel: > when opening the channel: >
call ch_close(channel) call ch_close(channel)
let channel = ch_open('localhost:8765', {'callback': "MyHandler"}) let channel = ch_open('localhost:8765', {'callback': "MyHandler"})
call ch_sendexpr(channel, 'hello!', {'callback': 0}) call ch_sendexpr(channel, 'hello!')
============================================================================== ==============================================================================
3. Opening a channel *channel-open* 3. Opening a channel *channel-open*
@ -171,7 +171,7 @@ Use |ch_status()| to see if the channel could be opened.
msec at least. msec at least.
"timeout" The time to wait for a request when blocking, E.g. when using "timeout" The time to wait for a request when blocking, E.g. when using
ch_sendexpr(). In milliseconds. The default is 2000 (2 ch_evalexpr(). In milliseconds. The default is 2000 (2
seconds). seconds).
*out-timeout* *err-timeout* *out-timeout* *err-timeout*
"out-timeout" Timeout for stdout. Only when using pipes. "out-timeout" Timeout for stdout. Only when using pipes.
@ -214,7 +214,7 @@ If there is an error reading or writing a channel it will be closed.
4. Using a JSON or JS channel *channel-use* 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}) let response = ch_evalexpr(channel, {expr})
This awaits a response from the other side. 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
@ -222,7 +222,7 @@ JavaScript encoding. See |js_encode()| for the difference.
To send a message, without handling a response or letting the channel callback To send a message, without handling a response or letting the channel callback
handle the response: > handle the response: >
call ch_sendexpr(channel, {expr}, {'callback': 0}) call ch_sendexpr(channel, {expr})
To send a message and letting the response handled by a specific function, To send a message and letting the response handled by a specific function,
asynchronously: > asynchronously: >
@ -263,8 +263,9 @@ On read error or ch_close(), when using a socket, the string "DETACH" is sent,
if still possible. The channel will then be inactive. For a JSON and JS mode if still possible. The channel will then be inactive. For a JSON and JS mode
channel quotes are used around DETACH, otherwise there are no quotes. channel quotes are used around DETACH, otherwise there are no quotes.
It is also possible to use ch_sendraw() on a JSON or JS channel. The caller It is also possible to use ch_sendraw() and ch_evalraw() on a JSON or JS
is then completely responsible for correct encoding and decoding. channel. The caller is then completely responsible for correct encoding and
decoding.
============================================================================== ==============================================================================
5. Channel commands *channel-commands* 5. Channel commands *channel-commands*
@ -363,7 +364,7 @@ Leave out the fourth argument if no response is to be sent:
6. Using a RAW or NL channel *channel-raw* 6. Using a RAW or NL channel *channel-raw*
If mode is RAW or NL 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}) let response = ch_evalraw(channel, {string})
The {string} is sent as-is. The response will be what can be read from the 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 channel right away. Since Vim doesn't know how to recognize the end of the
@ -377,18 +378,18 @@ first NL. This can also be just the NL for an empty response.
If no NL was read before the channel timeout an empty string is returned. If no NL was read before the channel timeout an empty string is returned.
To send a message, without expecting a response: > To send a message, without expecting a response: >
call ch_sendraw(channel, {string}, 0) call ch_sendraw(channel, {string})
The process can send back a response, the channel handler will be called with The process can send back a response, the channel handler will be called with
it. it.
To send a message and letting the response handled by a specific function, To send a message and letting the response handled by a specific function,
asynchronously: > asynchronously: >
call ch_sendraw(channel, {string}, {callback}) call ch_sendraw(channel, {string}, {'callback': 'MyHandler'})
This {string} can also be JSON, use |json_encode()| to create it and This {string} can also be JSON, use |json_encode()| to create it and
|json_decode()| to handle a received JSON message. |json_decode()| to handle a received JSON message.
It is not possible to use |ch_sendexpr()| on a raw channel. It is not possible to use |ch_evalexpr()| or |ch_sendexpr()| on a raw channel.
============================================================================== ==============================================================================
7. More channel functions *channel-more* 7. More channel functions *channel-more*
@ -447,8 +448,8 @@ If you want to handle both stderr and stdout with one handler use the
"callback" option: > "callback" option: >
let job = job_start(command, {"callback": "MyHandler"}) let job = job_start(command, {"callback": "MyHandler"})
You can send a message to the command with ch_sendraw(). If the channel is in You can send a message to the command with ch_evalraw(). If the channel is in
JSON or JS mode you can use ch_sendexpr(). JSON or JS mode you can use ch_evalexpr().
There are several options you can use, see |job-options|. There are several options you can use, see |job-options|.
For example, to start a job and write its output in buffer "dummy": > For example, to start a job and write its output in buffer "dummy": >

View File

@ -1818,6 +1818,10 @@ call( {func}, {arglist} [, {dict}])
any call {func} with arguments {arglist} any call {func} with arguments {arglist}
ceil( {expr}) Float round {expr} up ceil( {expr}) Float round {expr} up
ch_close( {channel}) none close {channel} ch_close( {channel}) none close {channel}
ch_evalexpr( {channel}, {expr} [, {options}])
any evaluate {expr} on JSON {channel}
ch_evalraw( {channel}, {string} [, {options}])
any evaluate {string} on raw {channel}
ch_getjob( {channel}) Job get the Job of {channel} ch_getjob( {channel}) Job get the Job of {channel}
ch_log( {msg} [, {channel}]) none write {msg} in the channel log file ch_log( {msg} [, {channel}]) none write {msg} in the channel log file
ch_logfile( {fname} [, {mode}]) none start logging channel activity ch_logfile( {fname} [, {mode}]) none start logging channel activity
@ -2692,6 +2696,31 @@ ch_close({channel}) *ch_close()*
Close {channel}. See |channel-close|. Close {channel}. See |channel-close|.
{only available when compiled with the |+channel| feature} {only available when compiled with the |+channel| feature}
ch_evalexpr({channel}, {expr} [, {options}]) *ch_evalexpr()*
Send {expr} over {channel}. The {expr} is encoded
according to the type of channel. The function cannot be used
with a raw channel. See |channel-use|. *E912*
*E917*
{options} must be a Dictionary. It must not have a "callback"
entry.
ch_evalexpr() waits for a response and returns the decoded
expression. When there is an error or timeout it returns an
empty string.
{only available when compiled with the |+channel| feature}
ch_evalraw({channel}, {string} [, {options}]) *ch_evalraw()*
Send {string} over {channel}.
Works like |ch_evalexpr()|, 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_getjob({channel}) *ch_getjob()* ch_getjob({channel}) *ch_getjob()*
Get the Job associated with {channel}. Get the Job associated with {channel}.
If there is no job calling |job_status()| on the returned Job If there is no job calling |job_status()| on the returned Job
@ -2769,16 +2798,11 @@ ch_sendexpr({channel}, {expr} [, {options}]) *ch_sendexpr()*
according to the type of channel. The function cannot be used according to the type of channel. The function cannot be used
with a raw channel. See |channel-use|. *E912* with a raw channel. See |channel-use|. *E912*
{options} must be a Dictionary. {options} must be a Dictionary. The "callback" item is a
When "callback" is a Funcref or the name of a function, Funcref or the name of a function it is invoked when the
ch_sendexpr() returns immediately. The callback is invoked response is received. See |channel-callback|.
when the response is received. See |channel-callback|. Without "callback" the channel handler is invoked, otherwise
any received message is dropped.
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} {only available when compiled with the |+channel| feature}
@ -7391,7 +7415,6 @@ scrollbind Compiled with 'scrollbind' support.
showcmd Compiled with 'showcmd' support. showcmd Compiled with 'showcmd' support.
signs Compiled with |:sign| support. signs Compiled with |:sign| support.
smartindent Compiled with 'smartindent' support. smartindent Compiled with 'smartindent' support.
sniff Compiled with SNiFF interface support.
spell Compiled with spell checking support |spell|. spell Compiled with spell checking support |spell|.
startuptime Compiled with |--startuptime| support. startuptime Compiled with |--startuptime| support.
statusline Compiled with support for 'statusline', 'rulerformat' statusline Compiled with support for 'statusline', 'rulerformat'

View File

@ -507,6 +507,8 @@ static void f_ceil(typval_T *argvars, typval_T *rettv);
#endif #endif
#ifdef FEAT_CHANNEL #ifdef FEAT_CHANNEL
static void f_ch_close(typval_T *argvars, typval_T *rettv); 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);
# ifdef FEAT_JOB # ifdef FEAT_JOB
static void f_ch_getjob(typval_T *argvars, typval_T *rettv); static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
# endif # endif
@ -8201,6 +8203,8 @@ static struct fst
#endif #endif
#ifdef FEAT_CHANNEL #ifdef FEAT_CHANNEL
{"ch_close", 1, 1, f_ch_close}, {"ch_close", 1, 1, f_ch_close},
{"ch_evalexpr", 2, 3, f_ch_evalexpr},
{"ch_evalraw", 2, 3, f_ch_evalraw},
# ifdef FEAT_JOB # ifdef FEAT_JOB
{"ch_getjob", 1, 1, f_ch_getjob}, {"ch_getjob", 1, 1, f_ch_getjob},
# endif # endif
@ -10485,7 +10489,13 @@ f_ch_readraw(typval_T *argvars, typval_T *rettv)
* Otherwise returns NULL. * Otherwise returns NULL.
*/ */
static channel_T * static channel_T *
send_common(typval_T *argvars, char_u *text, int id, char *fun, int *part_read) send_common(
typval_T *argvars,
char_u *text,
int id,
int eval,
char *fun,
int *part_read)
{ {
channel_T *channel; channel_T *channel;
jobopt_T opt; jobopt_T opt;
@ -10502,9 +10512,17 @@ send_common(typval_T *argvars, char_u *text, int id, char *fun, int *part_read)
return NULL; return NULL;
/* Set the callback. An empty callback means no callback and not reading /* Set the callback. An empty callback means no callback and not reading
* the response. */ * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not
* allowed. */
if (opt.jo_callback != NULL && *opt.jo_callback != NUL) if (opt.jo_callback != NULL && *opt.jo_callback != NUL)
{
if (eval)
{
EMSG2(_("E917: Cannot use a callback with %s()"), fun);
return NULL;
}
channel_set_req_callback(channel, part_send, opt.jo_callback, id); channel_set_req_callback(channel, part_send, opt.jo_callback, id);
}
if (channel_send(channel, part_send, text, fun) == OK if (channel_send(channel, part_send, text, fun) == OK
&& opt.jo_callback == NULL) && opt.jo_callback == NULL)
@ -10513,10 +10531,10 @@ send_common(typval_T *argvars, char_u *text, int id, char *fun, int *part_read)
} }
/* /*
* "ch_sendexpr()" function * common for "ch_evalexpr()" and "ch_sendexpr()"
*/ */
static void static void
f_ch_sendexpr(typval_T *argvars, typval_T *rettv) ch_expr_common(typval_T *argvars, typval_T *rettv, int eval)
{ {
char_u *text; char_u *text;
typval_T *listtv; typval_T *listtv;
@ -10539,7 +10557,7 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
ch_mode = channel_get_mode(channel, part_send); ch_mode = channel_get_mode(channel, part_send);
if (ch_mode == MODE_RAW || ch_mode == MODE_NL) if (ch_mode == MODE_RAW || ch_mode == MODE_NL)
{ {
EMSG(_("E912: cannot use ch_sendexpr() with a raw or nl channel")); EMSG(_("E912: cannot use ch_evalexpr()/ch_sendexpr() with a raw or nl channel"));
return; return;
} }
@ -10549,9 +10567,10 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
if (text == NULL) if (text == NULL)
return; return;
channel = send_common(argvars, text, id, "sendexpr", &part_read); channel = send_common(argvars, text, id, eval,
eval ? "ch_evalexpr" : "ch_sendexpr", &part_read);
vim_free(text); vim_free(text);
if (channel != NULL) if (channel != NULL && eval)
{ {
/* TODO: timeout from options */ /* TODO: timeout from options */
timeout = channel_get_timeout(channel, part_read); timeout = channel_get_timeout(channel, part_read);
@ -10570,10 +10589,28 @@ f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
} }
/* /*
* "ch_sendraw()" function * "ch_evalexpr()" function
*/ */
static void static void
f_ch_sendraw(typval_T *argvars, typval_T *rettv) f_ch_evalexpr(typval_T *argvars, typval_T *rettv)
{
ch_expr_common(argvars, rettv, TRUE);
}
/*
* "ch_sendexpr()" function
*/
static void
f_ch_sendexpr(typval_T *argvars, typval_T *rettv)
{
ch_expr_common(argvars, rettv, FALSE);
}
/*
* common for "ch_evalraw()" and "ch_sendraw()"
*/
static void
ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
{ {
char_u buf[NUMBUFLEN]; char_u buf[NUMBUFLEN];
char_u *text; char_u *text;
@ -10586,8 +10623,9 @@ f_ch_sendraw(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
text = get_tv_string_buf(&argvars[1], buf); text = get_tv_string_buf(&argvars[1], buf);
channel = send_common(argvars, text, 0, "sendraw", &part_read); channel = send_common(argvars, text, 0, eval,
if (channel != NULL) eval ? "ch_evalraw" : "ch_sendraw", &part_read);
if (channel != NULL && eval)
{ {
/* TODO: timeout from options */ /* TODO: timeout from options */
timeout = channel_get_timeout(channel, part_read); timeout = channel_get_timeout(channel, part_read);
@ -10595,6 +10633,24 @@ f_ch_sendraw(typval_T *argvars, typval_T *rettv)
} }
} }
/*
* "ch_evalraw()" function
*/
static void
f_ch_evalraw(typval_T *argvars, typval_T *rettv)
{
ch_raw_common(argvars, rettv, TRUE);
}
/*
* "ch_sendraw()" function
*/
static void
f_ch_sendraw(typval_T *argvars, typval_T *rettv)
{
ch_raw_common(argvars, rettv, FALSE);
}
/* /*
* "ch_setoptions()" function * "ch_setoptions()" function
*/ */

View File

@ -110,17 +110,17 @@ func s:communicate(port)
endif endif
" Simple string request and reply. " Simple string request and reply.
call assert_equal('got it', ch_sendexpr(handle, 'hello!')) call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
" Request that triggers sending two ex commands. These will usually be " Request that triggers sending two ex commands. These will usually be
" handled before getting the response, but it's not guaranteed, thus wait a " handled before getting the response, but it's not guaranteed, thus wait a
" tiny bit for the commands to get executed. " tiny bit for the commands to get executed.
call assert_equal('ok', ch_sendexpr(handle, 'make change')) call assert_equal('ok', ch_evalexpr(handle, 'make change'))
sleep 10m sleep 10m
call assert_equal('added1', getline(line('$') - 1)) call assert_equal('added1', getline(line('$') - 1))
call assert_equal('added2', getline('$')) call assert_equal('added2', getline('$'))
call assert_equal('ok', ch_sendexpr(handle, 'do normal')) call assert_equal('ok', ch_evalexpr(handle, 'do normal'))
sleep 10m sleep 10m
call assert_equal('added more', getline('$')) call assert_equal('added more', getline('$'))
@ -154,37 +154,37 @@ func s:communicate(port)
call ch_setoptions(handle, {'callback': ''}) call ch_setoptions(handle, {'callback': ''})
" Send an eval request that works. " Send an eval request that works.
call assert_equal('ok', ch_sendexpr(handle, 'eval-works')) call assert_equal('ok', ch_evalexpr(handle, 'eval-works'))
sleep 10m sleep 10m
call assert_equal([-1, 'foo123'], ch_sendexpr(handle, 'eval-result')) call assert_equal([-1, 'foo123'], ch_evalexpr(handle, 'eval-result'))
" Send an eval request that fails. " Send an eval request that fails.
call assert_equal('ok', ch_sendexpr(handle, 'eval-fails')) call assert_equal('ok', ch_evalexpr(handle, 'eval-fails'))
sleep 10m sleep 10m
call assert_equal([-2, 'ERROR'], ch_sendexpr(handle, 'eval-result')) call assert_equal([-2, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
" Send an eval request that works but can't be encoded. " Send an eval request that works but can't be encoded.
call assert_equal('ok', ch_sendexpr(handle, 'eval-error')) call assert_equal('ok', ch_evalexpr(handle, 'eval-error'))
sleep 10m sleep 10m
call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result')) call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
" Send a bad eval request. There will be no response. " Send a bad eval request. There will be no response.
call assert_equal('ok', ch_sendexpr(handle, 'eval-bad')) call assert_equal('ok', ch_evalexpr(handle, 'eval-bad'))
sleep 10m sleep 10m
call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result')) call assert_equal([-3, 'ERROR'], ch_evalexpr(handle, 'eval-result'))
" Send an expr request " Send an expr request
call assert_equal('ok', ch_sendexpr(handle, 'an expr')) call assert_equal('ok', ch_evalexpr(handle, 'an expr'))
sleep 10m sleep 10m
call assert_equal('one', getline(line('$') - 2)) call assert_equal('one', getline(line('$') - 2))
call assert_equal('two', getline(line('$') - 1)) call assert_equal('two', getline(line('$') - 1))
call assert_equal('three', getline('$')) call assert_equal('three', getline('$'))
" Request a redraw, we don't check for the effect. " Request a redraw, we don't check for the effect.
call assert_equal('ok', ch_sendexpr(handle, 'redraw')) call assert_equal('ok', ch_evalexpr(handle, 'redraw'))
call assert_equal('ok', ch_sendexpr(handle, 'redraw!')) call assert_equal('ok', ch_evalexpr(handle, 'redraw!'))
call assert_equal('ok', ch_sendexpr(handle, 'empty-request')) call assert_equal('ok', ch_evalexpr(handle, 'empty-request'))
" Reading while there is nothing available. " Reading while there is nothing available.
call assert_equal(v:none, ch_read(handle, {'timeout': 0})) call assert_equal(v:none, ch_read(handle, {'timeout': 0}))
@ -195,14 +195,14 @@ func s:communicate(port)
call assert_true(reltimefloat(elapsed) < 0.6) call assert_true(reltimefloat(elapsed) < 0.6)
" Send without waiting for a response, then wait for a response. " Send without waiting for a response, then wait for a response.
call ch_sendexpr(handle, 'wait a bit', {'callback': 0}) call ch_sendexpr(handle, 'wait a bit')
let resp = ch_read(handle) let resp = ch_read(handle)
call assert_equal(type([]), type(resp)) call assert_equal(type([]), type(resp))
call assert_equal(type(11), type(resp[0])) call assert_equal(type(11), type(resp[0]))
call assert_equal('waited', resp[1]) call assert_equal('waited', resp[1])
" make the server quit, can't check if this works, should not hang. " make the server quit, can't check if this works, should not hang.
call ch_sendexpr(handle, '!quit!', {'callback': 0}) call ch_sendexpr(handle, '!quit!')
endfunc endfunc
func Test_communicate() func Test_communicate()
@ -218,18 +218,18 @@ func s:two_channels(port)
return return
endif endif
call assert_equal('got it', ch_sendexpr(handle, 'hello!')) call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
let newhandle = ch_open('localhost:' . a:port, s:chopt) let newhandle = ch_open('localhost:' . a:port, s:chopt)
if ch_status(newhandle) == "fail" if ch_status(newhandle) == "fail"
call assert_false(1, "Can't open second channel") call assert_false(1, "Can't open second channel")
return return
endif endif
call assert_equal('got it', ch_sendexpr(newhandle, 'hello!')) call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
call assert_equal('got it', ch_sendexpr(handle, 'hello!')) call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
call ch_close(handle) call ch_close(handle)
call assert_equal('got it', ch_sendexpr(newhandle, 'hello!')) call assert_equal('got it', ch_evalexpr(newhandle, 'hello!'))
call ch_close(newhandle) call ch_close(newhandle)
endfunc endfunc
@ -247,7 +247,7 @@ func s:server_crash(port)
return return
endif endif
call ch_sendexpr(handle, '!crash!') call ch_evalexpr(handle, '!crash!')
sleep 10m sleep 10m
endfunc endfunc
@ -271,12 +271,12 @@ func s:channel_handler(port)
endif endif
" Test that it works while waiting on a numbered message. " Test that it works while waiting on a numbered message.
call assert_equal('ok', ch_sendexpr(handle, 'call me')) call assert_equal('ok', ch_evalexpr(handle, 'call me'))
sleep 10m sleep 10m
call assert_equal('we called you', s:reply) call assert_equal('we called you', s:reply)
" Test that it works while not waiting on a numbered message. " Test that it works while not waiting on a numbered message.
call ch_sendexpr(handle, 'call me again', {'callback': 0}) call ch_sendexpr(handle, 'call me again')
sleep 10m sleep 10m
call assert_equal('we did call you', s:reply) call assert_equal('we did call you', s:reply)
endfunc endfunc
@ -334,15 +334,15 @@ func Test_raw_pipe()
call assert_equal("run", job_status(job)) call assert_equal("run", job_status(job))
try try
let handle = job_getchannel(job) let handle = job_getchannel(job)
call ch_sendraw(handle, "echo something\n", {'callback': 0}) call ch_sendraw(handle, "echo something\n")
let msg = ch_readraw(handle) let msg = ch_readraw(handle)
call assert_equal("something\n", substitute(msg, "\r", "", 'g')) call assert_equal("something\n", substitute(msg, "\r", "", 'g'))
call ch_sendraw(handle, "double this\n", {'callback': 0}) call ch_sendraw(handle, "double this\n")
let msg = ch_readraw(handle) let msg = ch_readraw(handle)
call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g')) call assert_equal("this\nAND this\n", substitute(msg, "\r", "", 'g'))
let reply = ch_sendraw(handle, "quit\n") let reply = ch_evalraw(handle, "quit\n")
call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g')) call assert_equal("Goodbye!\n", substitute(reply, "\r", "", 'g'))
finally finally
call job_stop(job) call job_stop(job)
@ -358,20 +358,48 @@ func Test_nl_pipe()
call assert_equal("run", job_status(job)) call assert_equal("run", job_status(job))
try try
let handle = job_getchannel(job) let handle = job_getchannel(job)
call ch_sendraw(handle, "echo something\n", {'callback': 0}) call ch_sendraw(handle, "echo something\n")
call assert_equal("something", ch_readraw(handle)) call assert_equal("something", ch_readraw(handle))
call ch_sendraw(handle, "double this\n", {'callback': 0}) call ch_sendraw(handle, "double this\n")
call assert_equal("this", ch_readraw(handle)) call assert_equal("this", ch_readraw(handle))
call assert_equal("AND this", ch_readraw(handle)) call assert_equal("AND this", ch_readraw(handle))
let reply = ch_sendraw(handle, "quit\n") let reply = ch_evalraw(handle, "quit\n")
call assert_equal("Goodbye!", reply) call assert_equal("Goodbye!", reply)
finally finally
call job_stop(job) call job_stop(job)
endtry endtry
endfunc endfunc
func Test_pipe_to_buffer()
if !has('job')
return
endif
call ch_log('Test_pipe_to_buffer()')
let job = job_start(s:python . " test_channel_pipe.py",
\ {'out-io': 'buffer', 'out-name': 'pipe-output'})
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")
call ch_sendraw(handle, "double this\n")
call ch_sendraw(handle, "quit\n")
sp pipe-output
for i in range(100)
sleep 10m
if line('$') >= 6
break
endif
endfor
call assert_equal(['Reading from channel output...', 'line one', 'line two', 'this', 'AND this', 'Goodbye!'], getline(1, '$'))
bwipe!
finally
call job_stop(job)
endtry
endfunc
"""""""""" """"""""""
let s:unletResponse = '' let s:unletResponse = ''
@ -434,7 +462,7 @@ func s:open_delay(port)
call assert_false(1, "Can't open channel") call assert_false(1, "Can't open channel")
return return
endif endif
call assert_equal('got it', ch_sendexpr(channel, 'hello!')) call assert_equal('got it', ch_evalexpr(channel, 'hello!'))
call ch_close(channel) call ch_close(channel)
endfunc endfunc
@ -457,7 +485,7 @@ function s:test_call(port)
return return
endif endif
call assert_equal('ok', ch_sendexpr(handle, 'call-func')) call assert_equal('ok', ch_evalexpr(handle, 'call-func'))
sleep 20m sleep 20m
call assert_equal([1, 2, 3], s:call_ret) call assert_equal([1, 2, 3], s:call_ret)
endfunc endfunc
@ -507,7 +535,7 @@ function s:test_close_callback(port)
endif endif
call ch_setoptions(handle, {'close-cb': 'MyCloseCb'}) call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
call assert_equal('', ch_sendexpr(handle, 'close me')) call assert_equal('', ch_evalexpr(handle, 'close me'))
sleep 20m sleep 20m
call assert_equal('closed', s:ch_close_ret) call assert_equal('closed', s:ch_close_ret)
endfunc endfunc

View File

@ -743,6 +743,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1435,
/**/ /**/
1434, 1434,
/**/ /**/