summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-02-21 20:10:26 +0100
committerBram Moolenaar <Bram@vim.org>2016-02-21 20:10:26 +0100
commit02e83b438ea7071fdb176dabbaefea319ab2d686 (patch)
tree478494aa134dcb518284d0b990f3f69a47f8432d
parenteab089d22f172ddd2d33367a998e68c2f1c6c989 (diff)
downloadvim-git-02e83b438ea7071fdb176dabbaefea319ab2d686.tar.gz
patch 7.4.1382v7.4.1382
Problem: Can't get the job of a channel. Solution: Add ch_getjob().
-rw-r--r--runtime/doc/channel.txt81
-rw-r--r--runtime/doc/eval.txt115
-rw-r--r--src/eval.c25
-rw-r--r--src/version.c2
4 files changed, 151 insertions, 72 deletions
diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt
index aca6b0877..aa31816fc 100644
--- a/runtime/doc/channel.txt
+++ b/runtime/doc/channel.txt
@@ -1,4 +1,4 @@
-*channel.txt* For Vim version 7.4. Last change: 2016 Feb 20
+*channel.txt* For Vim version 7.4. Last change: 2016 Feb 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -93,7 +93,7 @@ To handle asynchronous communication a callback needs to be used: >
func MyHandler(channel, msg)
echo "from the handler: " . a:msg
endfunc
- call ch_sendexpr(channel, 'hello!', "MyHandler")
+ call ch_sendexpr(channel, 'hello!', {'callback': "MyHandler"})
Vim will not wait for a response. Now the server can send the response later
and MyHandler will be invoked.
@@ -101,13 +101,15 @@ Instead of giving a callback with every send call, it can also be specified
when opening the channel: >
call ch_close(channel)
let channel = ch_open('localhost:8765', {'callback': "MyHandler"})
- call ch_sendexpr(channel, 'hello!', 0)
+ call ch_sendexpr(channel, 'hello!', {'callback': 0})
==============================================================================
3. Opening a channel *channel-open*
To open a channel: >
let channel = ch_open({address} [, {options}])
+ if ch_status(channel) == "open"
+ " use the channel
Use |ch_status()| to see if the channel could be opened.
@@ -131,25 +133,32 @@ Use |ch_status()| to see if the channel could be opened.
*channel-callback*
"callback" A function that is called when a message is received that is
not handled otherwise. It gets two arguments: the channel
- handle and the received message. Example: >
+ and the received message. Example: >
func Handle(channel, msg)
echo 'Received: ' . a:msg
endfunc
let channel = ch_open("localhost:8765", {"callback": "Handle"})
<
+ When "mode" is "json" or "js" the "msg" argument is the body
+ of the received message, converted to Vim types.
+ When "mode" is "nl" the "msg" argument is one message,
+ excluding the NL.
+ When "mode" is "raw" the "msg" argument is the whole message
+ as a string.
+ *out-cb*
"out-cb" A function like "callback" but used for stdout. Only for when
the channel uses pipes. When "out-cb" wasn't set the channel
callback is used.
-
+ *err-cb*
"err-cb" A function like "callback" but used for stderr. Only for when
the channel uses pipes. When "err-cb" wasn't set the channel
callback is used.
- TODO:
+ TODO: *close-cb*
"close-cb" A function that is called when the channel gets closed, other
than by calling ch_close(). It should be defined like this: >
func MyCloseHandler(channel)
-
+< *waittime*
"waittime" The time to wait for the connection to be made in
milliseconds. The default is zero, don't wait, which is
useful if the server is supposed to be running already. A
@@ -158,41 +167,34 @@ Use |ch_status()| to see if the channel could be opened.
"timeout" The time to wait for a request when blocking, E.g. when using
ch_sendexpr(). In milliseconds. The default is 2000 (2
seconds).
-
+ *out-timeout* *err-timeout*
"out-timeout" Timeout for stdout. Only when using pipes.
"err-timeout" Timeout for stderr. Only when using pipes.
Note: when setting "timeout" the part specific mode is
overwritten. Therefore set "timeout" first and the part
specific mode later.
-When "mode" is "json" or "js" the "msg" argument is the body of the received
-message, converted to Vim types.
-When "mode" is "raw" the "msg" argument is the whole message as a string.
-
When "mode" is "json" or "js" the "callback" is optional. When omitted it is
only possible to receive a message after sending one.
-To change the channel options after opening it use ch_setoptions(). The
-arguments are similar to what is passed to ch_open(), but "waittime" cannot be
-given, since that only applies to opening the channel.
+To change the channel options after opening it use |ch_setoptions()|. The
+arguments are similar to what is passed to |ch_open()|, but "waittime" cannot
+be given, since that only applies to opening the channel.
-The handler can be added or changed: >
+For example, the handler can be added or changed: >
call ch_setoptions(channel, {'callback': callback})
When "callback" is empty (zero or an empty string) the handler is removed.
The timeout can be changed: >
call ch_setoptions(channel, {'timeout': msec})
<
- *E906*
+ *channel-close* *E906*
Once done with the channel, disconnect it like this: >
call ch_close(channel)
When a socket is used this will close the socket for both directions. When
pipes are used (stdin/stdout/stderr) they are all closed. This might not be
what you want! Stopping the job with job_stop() might be better.
-TODO:
-Currently up to 10 channels can be in use at the same time. *E897*
-
When the channel can't be opened you will get an error message. There is a
difference between MS-Windows and Unix: On Unix when the port doesn't exist
ch_open() fails quickly. On MS-Windows "waittime" applies.
@@ -211,12 +213,13 @@ This awaits a response from the other side.
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: >
- call ch_sendexpr(channel, {expr}, 0)
+To send a message, without handling a response or letting the channel callback
+handle the response: >
+ call ch_sendexpr(channel, {expr}, {'callback': 0})
To send a message and letting the response handled by a specific function,
asynchronously: >
- call ch_sendexpr(channel, {expr}, {callback})
+ call ch_sendexpr(channel, {expr}, {'callback': Handler})
Vim will match the response with the request using the message ID. Once the
response is received the callback will be invoked. Further responses with the
@@ -424,13 +427,18 @@ The function will be called with the channel and a message. You would define
it like this: >
func MyHandler(channel, msg)
-Without the handler you need to read the output with ch_read().
+Without the handler you need to read the output with |ch_read()| or
+|ch_readraw()|.
-The handler defined for "out-cb" will also receive stderr. If you want to
+The handler defined for "out-cb" will not receive stderr. If you want to
handle that separately, add an "err-cb" handler: >
let job = job_start(command, {"out-cb": "MyHandler",
\ "err-cb": "ErrHandler"})
+If you want to handle both stderr and stdout with one handler use the
+"callback" option: >
+ let job = job_start(command, {"callback": "MyHandler"})
+
You can send a message to the command with ch_sendraw(). If the channel is in
JSON or JS mode you can use ch_sendexpr().
@@ -481,7 +489,10 @@ This gives the job some time to make the port available.
10. Job options *job-options*
The {options} argument in job_start() is a dictionary. All entries are
-optional. The same options can be used with job_setoptions(job, {options}).
+optional. Some options can be used after the job has started, using
+job_setoptions(job, {options}). Many options can be used with the channel
+related to the job, using ch_setoptions(channel, {options}).
+See |job_setoptions()| and |ch_setoptions()|.
*job-callback*
"callback": handler Callback for something to read on any part of the
@@ -495,13 +506,18 @@ optional. The same options can be used with job_setoptions(job, {options}).
TODO: *job-close-cb*
"close-cb": handler Callback for when the channel is closed. Same as
"close-cb" on ch_open().
-TODO: *job-exit-cb*
+ *job-exit-cb*
"exit-cb": handler Callback for when the job ends. The arguments are the
job and the exit status.
-TODO: *job-killonexit*
-"killonexit": 1 Stop the job when Vim exits.
-"killonexit": 0 Do not stop the job when Vim exits.
- The default is 1.
+ Vim checks about every 10 seconds for jobs that ended.
+ The callback can also be triggered by calling
+ |job_status()|.
+ *job-stoponexit*
+"stoponexit": {signal} Send {signal} to the job when Vim exits. See
+ |job_stop()| for possible values.
+"stoponexit": "" Do not stop the job when Vim exits.
+ The default is "term".
+
TODO: *job-term*
"term": "open" Start a terminal and connect the job
stdin/stdout/stderr to it.
@@ -529,9 +545,6 @@ TODO: *job-err-io*
"err-io": "buffer" stderr appends to a buffer
"err-buffer": "name" buffer to append to
-TODO: more options
-
-
==============================================================================
11. Controlling a job *job-control*
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f5885da14..022a5da7a 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 7.4. Last change: 2016 Feb 19
+*eval.txt* For Vim version 7.4. Last change: 2016 Feb 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -59,11 +59,11 @@ Dictionary An associative, unordered array: Each entry has a key and a
Funcref A reference to a function |Funcref|.
Example: function("strlen")
-Special v:false, v:true, v:none and v:null
+Special |v:false|, |v:true|, |v:none| and |v:null|. *Special*
-Job Used for a job, see |job_start()|.
+Job Used for a job, see |job_start()|. *Job*
-Channel Used for a channel, see |ch_open()|.
+Channel Used for a channel, see |ch_open()|. *Channel*
The Number and String types are converted automatically, depending on how they
are used.
@@ -1817,17 +1817,19 @@ byteidxcomp( {expr}, {nr}) Number byte index of {nr}'th char in {expr}
call( {func}, {arglist} [, {dict}])
any call {func} with arguments {arglist}
ceil( {expr}) Float round {expr} up
-ch_close( {handle}) none close a channel
+ch_close( {channel}) none close {channel}
+ch_getjob( {channel}) Job get the Job of {channel}
ch_log( {msg} [, {channel}]) 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}
-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_setoptions( {handle}, {options}) none set options for channel {handle}
-ch_status( {handle}) String status of channel {handle}
+ch_read( {channel} [, {options}]) String read from {channel}
+ch_readraw( {channel} [, {options}]) String read raw from {channel}
+ch_sendexpr( {channel}, {expr} [, {options}])
+ any send {expr} over JSON {channel}
+ch_sendraw( {channel}, {string} [, {options}])
+ any send {string} over raw {channel}
+ch_setoptions( {channel}, {options}) none set options for {channel}
+ch_status( {channel}) String status of {channel}
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}
@@ -1960,10 +1962,11 @@ invert( {expr}) Number bitwise invert
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
+job_getchannel( {job}) Channel get the channel handle for {job}
+job_setoptions( {job}, {options}) none set options for {job}
+job_start( {command} [, {options}]) Job start a job
+job_status( {job}) String get the status of {job}
+job_stop( {job} [, {how}]) Number stop {job}
join( {list} [, {sep}]) String join {list} items into one String
js_decode( {string}) any decode JS style JSON
js_encode( {expr}) String encode JS style JSON
@@ -2684,10 +2687,18 @@ confirm({msg} [, {choices} [, {default} [, {type}]]])
don't fit, a vertical layout is used anyway. For some systems
the horizontal layout is always used.
-ch_close({handle}) *ch_close()*
- Close channel {handle}. See |channel|.
+ch_close({channel}) *ch_close()*
+ Close {channel}. See |channel-close|.
{only available when compiled with the |+channel| feature}
+ch_getjob({channel}) *ch_getjob()*
+ Get the Job associated with {channel}.
+ If there is no job calling |job_status()| on the returned Job
+ will result in "fail".
+
+ {only available when compiled with the |+channel| and
+ |+job| features}
+
ch_log({msg} [, {channel}]) *ch_log()*
Write {msg} in the channel log file, if it was opened with
|ch_logfile()|.
@@ -2706,8 +2717,8 @@ ch_logfile({fname} [, {mode}]) *ch_logfile()*
ch_open({address} [, {options}]) *ch_open()*
Open a channel to {address}. See |channel|.
- Returns the channel handle on success. Returns a negative
- number for failure.
+ Returns a Channel. Use |ch_status()| to check for
+ failure.
{address} has the form "hostname:port", e.g.,
"localhost:8765".
@@ -2722,19 +2733,38 @@ ch_open({address} [, {options}]) *ch_open()*
waittime Specify connect timeout as milliseconds.
Negative means forever.
Default: 0 (don't wait)
- timeout Specify response read timeout value as
+ timeout Specify response read timeout value in
milliseconds.
Default: 2000.
{only available when compiled with the |+channel| feature}
-ch_readraw({handle}) *ch_readraw()*
- Read from channel {handle} and return the received message.
- This uses the channel timeout. When there is nothing to read
- within that time an empty string is returned.
- TODO: depends on channel mode.
+ch_read({channel} [, {options}]) *ch_read()*
+ Read from {channel} and return the received message.
-ch_sendexpr({handle}, {expr} [, {options}]) *ch_sendexpr()*
- Send {expr} over channel {handle}. The {expr} is encoded
+ This uses the channel timeout. When there is nothing to read
+ within that time an empty string is returned. To specify a
+ different timeout in msec use the "timeout" option:
+ {"timeout": 123} ~
+ To read from the error output use the "part" option:
+ {"part": "err"} ~
+ To read a message with a specific ID, on a JS or JSON channel:
+ {"id": 99} ~
+ When no ID is specified or the ID is -1, the first message is
+ returned. This overrules any callback waiting for this
+ message.
+
+ For a RAW channel this returns whatever is available, since
+ Vim does not know where a message ends.
+ For a NL channel this returns one message.
+ For a JS or JSON channel this returns one decoded message.
+ This includes any sequence number.
+
+ch_readraw({channel} [, {options}]) *ch_readraw()*
+ Like ch_read() but for a JS and JSON channel does not decode
+ the message.
+
+ch_sendexpr({channel}, {expr} [, {options}]) *ch_sendexpr()*
+ 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*
@@ -2751,8 +2781,8 @@ ch_sendexpr({handle}, {expr} [, {options}]) *ch_sendexpr()*
{only available when compiled with the |+channel| feature}
-ch_sendraw({handle}, {string} [, {options}]) *ch_sendraw()*
- Send {string} over channel {handle}.
+ch_sendraw({channel}, {string} [, {options}]) *ch_sendraw()*
+ Send {string} over {channel}.
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
@@ -2762,18 +2792,21 @@ ch_sendraw({handle}, {string} [, {options}]) *ch_sendraw()*
{only available when compiled with the |+channel| feature}
-ch_setoptions({handle}, {options}) *ch_setoptions()*
- Set options on channel {handle}:
+ch_setoptions({channel}, {options}) *ch_setoptions()*
+ Set options on {channel}:
"callback" the channel callback
"timeout" default read timeout in msec
+ "mode" mode for the whole channel
See |ch_open()| for more explanation.
+ Note that changing the mode may cause queued messages to be
+ lost.
+
These options cannot be changed:
- "mode" cannot be changed once channel is open
"waittime" only applies to "ch_open()|
-ch_status({handle}) *ch_status()*
- Return the status of channel {handle}:
+ch_status({channel}) *ch_status()*
+ Return the status of {channel}:
"fail" failed to open the channel
"open" channel can be used
"closed" channel can not be used
@@ -4370,11 +4403,15 @@ items({dict}) *items()*
entry and the value of this entry. The |List| is in arbitrary
order.
-
job_getchannel({job}) *job_getchannel()*
Get the channel handle that {job} is using.
{only available when compiled with the |+job| feature}
+job_setoptions({job}, {options}) *job_setoptions()*
+ Change options for {job}. Supported are:
+ "stoponexit" |job-stoponexit|
+ "exit-cb" |job-exit-cb|
+
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.
@@ -4415,11 +4452,14 @@ job_start({command} [, {options}]) *job_start()*
{only available when compiled with the |+job| feature}
-job_status({job}) *job_status()*
+job_status({job}) *job_status()* *E916*
Returns a String with the status of {job}:
"run" job is running
"fail" job failed to start
"dead" job died or was stopped after running
+
+ If an exit callback was set with the "exit-cb" option and the
+ job is now detected to be "dead" the callback will be invoked.
{only available when compiled with the |+job| feature}
@@ -7375,7 +7415,6 @@ vms VMS version of Vim.
vreplace Compiled with |gR| and |gr| commands.
wildignore Compiled with 'wildignore' option.
wildmenu Compiled with 'wildmenu' option.
-win16 Win16 version of Vim (MS-Windows 3.1).
win32 Win32 version of Vim (MS-Windows 95 and later, 32 or
64 bits)
win32unix Win32 version of Vim, using Unix files (Cygwin)
diff --git a/src/eval.c b/src/eval.c
index cc7b9455f..bb9a4c569 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -501,6 +501,9 @@ static void f_ceil(typval_T *argvars, typval_T *rettv);
#endif
#ifdef FEAT_CHANNEL
static void f_ch_close(typval_T *argvars, typval_T *rettv);
+# ifdef FEAT_JOB
+static void f_ch_getjob(typval_T *argvars, typval_T *rettv);
+# endif
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);
@@ -8186,6 +8189,9 @@ static struct fst
#endif
#ifdef FEAT_CHANNEL
{"ch_close", 1, 1, f_ch_close},
+# ifdef FEAT_JOB
+ {"ch_getjob", 1, 1, f_ch_getjob},
+# endif
{"ch_log", 1, 2, f_ch_log},
{"ch_logfile", 1, 2, f_ch_logfile},
{"ch_open", 1, 2, f_ch_open},
@@ -10186,6 +10192,25 @@ f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
channel_close(channel);
}
+# ifdef FEAT_JOB
+/*
+ * "ch_getjob()" function
+ */
+ static void
+f_ch_getjob(typval_T *argvars, typval_T *rettv)
+{
+ channel_T *channel = get_channel_arg(&argvars[0]);
+
+ if (channel != NULL)
+ {
+ rettv->v_type = VAR_JOB;
+ rettv->vval.v_job = channel->ch_job;
+ if (channel->ch_job != NULL)
+ ++channel->ch_job->jv_refcount;
+ }
+}
+# endif
+
/*
* "ch_log()" function
*/
diff --git a/src/version.c b/src/version.c
index 144dc18b7..5e6878f2f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -748,6 +748,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1382,
+/**/
1381,
/**/
1380,