Merge pull request #1710 from Pyrohh/improve-docs-job-control

Misc. improvements to job control & msgpack rpc docs [ci skip]
This commit is contained in:
Justin M. Keyes
2015-01-11 17:12:05 -05:00
3 changed files with 62 additions and 65 deletions

View File

@@ -5100,12 +5100,12 @@ rpcnotify({channel}, {event}[, {args}...]) {Nvim} *rpcnotify()*
rpcrequest({channel}, {method}[, {args}...]) {Nvim} *rpcrequest()* rpcrequest({channel}, {method}[, {args}...]) {Nvim} *rpcrequest()*
Sends a request to {channel} to invoke {method} via Sends a request to {channel} to invoke {method} via
|msgpack-rpc| and blocks until a response is received. |msgpack-rpc| and blocks until a response is received.
Example: > Example: >
:let result = rpcrequest(rpc_chan, "func", 1, 2, 3) :let result = rpcrequest(rpc_chan, "func", 1, 2, 3)
rpcstart({prog}[, {argv}]) {Nvim} *rpcstart()* rpcstart({prog}[, {argv}]) {Nvim} *rpcstart()*
Spawns {prog} as a job(optionally passing the {argv} list), Spawns {prog} as a job (optionally passing the list {argv}),
and opens a |msgpack-rpc| channel with the spawned process and opens a |msgpack-rpc| channel with the spawned process's
stdin/stdout. It returns: stdin/stdout. It returns:
- The channel id on success, which is used by |rpcrequest()|, - The channel id on success, which is used by |rpcrequest()|,
|rpcnotify()| and |rpcstop()| |rpcnotify()| and |rpcstop()|
@@ -5114,10 +5114,9 @@ rpcstart({prog}[, {argv}]) {Nvim} *rpcstart()*
:let rpc_chan = rpcstart('prog', ['arg1', 'arg2']) :let rpc_chan = rpcstart('prog', ['arg1', 'arg2'])
rpcstop({channel}) {Nvim} *rpcstop()* rpcstop({channel}) {Nvim} *rpcstop()*
Closes a |msgpack-rpc| channel, possibly created via Closes a |msgpack-rpc| {channel}, possibly created via
|rpcstart()| (Though it will also close channels created by |rpcstart()|. Also closes channels created by connections to
connections to |$NVIM_LISTEN_ADDRESS|). It accepts the rpc |$NVIM_LISTEN_ADDRESS|.
channel id as only argument.
screenattr(row, col) *screenattr()* screenattr(row, col) *screenattr()*
Like screenchar(), but return the attribute. This is a rather Like screenchar(), but return the attribute. This is a rather

View File

@@ -27,8 +27,8 @@ control multiple processes without blocking the current Nvim instance.
Nvim's job control was designed to be simple and familiar to vimscript Nvim's job control was designed to be simple and familiar to vimscript
programmers, instead of being very powerful but complex. Unlike Vim's programmers, instead of being very powerful but complex. Unlike Vim's
facilities for calling with external commands, job control does not depend facilities for calling with external commands, job control does not depend on
on installed shells, calling OS functions for process management directly. available shells, instead relying on OS functionality for process management.
Internally, Nvim job control is powered by libuv, which has a nice Internally, Nvim job control is powered by libuv, which has a nice
cross-platform API for managing processes. See https://github.com/libuv/libuv cross-platform API for managing processes. See https://github.com/libuv/libuv
@@ -43,7 +43,7 @@ event. The best way to understand is with a complete example:
> >
set nocp set nocp
let job1 = jobstart('shell1', 'bash') let job1 = jobstart('shell1', 'bash')
let job2 = jobstart('shell2', 'bash', ['-c', 'for ((i = 0; i < 10; i++)); do echo -n hello $i!; sleep 2; done']) let job2 = jobstart('shell2', 'bash', ['-c', 'for ((i = 0; i < 10; i++)); do echo hello $i!; sleep 1; done'])
function JobHandler() function JobHandler()
if v:job_data[1] == 'stdout' if v:job_data[1] == 'stdout'
@@ -59,21 +59,21 @@ event. The best way to understand is with a complete example:
au JobActivity shell* call JobHandler() au JobActivity shell* call JobHandler()
< <
To test the above, copy it to the ~/jobcontrol.vim file and start with a clean To test the above, copy it to the file ~/jobcontrol.vim and start with a clean
nvim instance: nvim instance:
> >
nvim -u NONE -S ~/jobcontrol.vim nvim -u NONE -S ~/jobcontrol.vim
< <
Here's what is happening: Here's what is happening:
- Two bash instances are spawned by |jobstart()| and their stdin/stdout/stderr - Two bash instances are spawned by |jobstart()| with their stdin/stdout/stderr
are connected to nvim. connected to nvim.
- The first shell is idle, waiting to read commands from it's stdin - The first shell is idle, waiting to read commands from its stdin.
- The second shell is passed the -c option to execute a command and exit. In - The second shell is started with the -c argument, causing it to execute a
our case, the command is a for loop that will print numbers and exit after command then exit. In this case, the command is a for loop that will print 0
a while. through 9 then exit.
- The JobHandler function is called by the JobActivity autocommand(notice how - The |JobHandler()| function is called by the `JobActivity` autocommand (notice
the shell* pattern matches the `shell1` and `shell2` names passed to how the shell* pattern matches the names `shell1` and `shell2` passed to
|jobstart()|), and it takes care of displaying stdout/stderr received from |jobstart()|), and it takes care of displaying stdout/stderr received from
the shells. the shells.
- The v:job_data is an array set by the JobActivity event. It has the - The v:job_data is an array set by the JobActivity event. It has the
@@ -86,16 +86,16 @@ Here's what is happening:
To send data to the job's stdin, one can use the |jobsend()| function, like To send data to the job's stdin, one can use the |jobsend()| function, like
this: this:
> >
:call jobsend(job1, 'ls\n') :call jobsend(job1, "ls\n")
:call jobsend(job1, 'invalid-command\n') :call jobsend(job1, "invalid-command\n")
:call jobsend(job1, 'exit\n') :call jobsend(job1, "exit\n")
< <
A job may be killed at any time with the |jobstop()| function: A job may be killed at any time with the |jobstop()| function:
> >
:call jobstop(job1) :call jobstop(job1)
< <
When |jobstop()| is called, it will send `SIGTERM` to the job. If a job When |jobstop()| is called, `SIGTERM` will be sent to the job. If a job does
doesn't exit after a while, `SIGKILL` will be sent. not exit after 2 seconds, `SIGKILL` will be sent.
============================================================================== ==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl: vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -4,10 +4,10 @@
NVIM REFERENCE MANUAL by Thiago de Arruda NVIM REFERENCE MANUAL by Thiago de Arruda
The Msgpack-RPC Interface to Nvim *msgpack-rpc* The Msgpack-RPC Interface to Nvim *msgpack-rpc*
1. Introduction |msgpack-rpc-intro| 1. Introduction |msgpack-rpc-intro|
2. API |msgpack-rpc-api| 2. API |msgpack-rpc-api|
3. Connecting |msgpack-rpc-connecting| 3. Connecting |msgpack-rpc-connecting|
4. Clients |msgpack-rpc-clients| 4. Clients |msgpack-rpc-clients|
5. Types |msgpack-rpc-types| 5. Types |msgpack-rpc-types|
@@ -40,9 +40,9 @@ Nvim's msgpack-rpc interface can be seen as a more powerful version of Vim's
The Nvim C API is automatically exposed to the msgpack-rpc interface by the The Nvim C API is automatically exposed to the msgpack-rpc interface by the
build system, which parses headers at src/nvim/api from the project root. A build system, which parses headers at src/nvim/api from the project root. A
dispatch function is generated, which matches msgpack-rpc method names dispatch function is generated, which matches msgpack-rpc method names with
with non-static API functions, converting/validating arguments and return non-static API functions, converting/validating arguments and return values
values back to msgpack. back to msgpack.
Client libraries will normally provide wrappers that hide msgpack-rpc details Client libraries will normally provide wrappers that hide msgpack-rpc details
from programmers, which can be automatically generated by reading bundled API from programmers, which can be automatically generated by reading bundled API
@@ -60,7 +60,7 @@ There are two ways to obtain API metadata:
separate compilation step. separate compilation step.
Here's a simple way to get human-readable description of the API (requires Here's a simple way to get human-readable description of the API (requires
python and the pyyaml/msgpack-python pip packages): python and the `pyyaml`/`msgpack-python` pip packages):
> >
nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))' > api.yaml nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))' > api.yaml
@@ -69,21 +69,19 @@ python and the pyyaml/msgpack-python pip packages):
There are four ways to open msgpack-rpc streams to nvim: There are four ways to open msgpack-rpc streams to nvim:
1. Through nvim's stdin/stdout when started with the `--embed` option. This is 1. Through Nvim's stdin/stdout when started with the `--embed` option. This is
how other programs can embed nvim. how other programs can embed nvim.
2. Through stdin/stdout of a program spawned by the |rpcstart()| function. 2. Through the stdin/stdout of a program spawned by the |rpcstart()| function.
3. Through the socket automatically created with each instance. To find out 3. Through the socket automatically created with each instance. To find out
the socket location (which is random by default) from a running nvim the socket location (which is random by default) from a running nvim
instance, one can inspect the *$NVIM_LISTEN_ADDRESS* environment variable instance, one can inspect the |$NVIM_LISTEN_ADDRESS| environment variable:
like this:
> >
:echo $NVIM_LISTEN_ADDRESS :echo $NVIM_LISTEN_ADDRESS
< <
4. Through a TCP/IP socket. To make nvim listen on a TCP/IP socket, you need 4. Through a TCP/IP socket. To make nvim listen on a TCP/IP socket, set the
to set the $NVIM_LISTEN_ADDRESS environment variable before starting, like |$NVIM_LISTEN_ADDRESS| environment variable in a shell before starting:
this:
> >
NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim
< <
@@ -120,34 +118,34 @@ functions can be called interactively:
============================================================================== ==============================================================================
4. Implementing new clients *msgpack-rpc-clients* 4. Implementing new clients *msgpack-rpc-clients*
Nvim is still alpha and there's no in-depth documentation explaining how to Nvim is still in alpha, so there's no in-depth documentation explaining how to
properly implement a client library. The python client (neovim pip package) properly implement a client library yet. The python client (the pip package
will be always up-to-date with the latest API changes, so its source code is "neovim") will always be up-to-date with the latest API changes, so its source
the best documentation currently available. There are some guidelines however: code is the best documentation currently available. There are some guidelines
however:
- Separate the transport layer from the rest of the library (see - Separate the transport layer from the rest of the library. See
|msgpack-rpc-connecting| for details of how a client can connect to nvim). |msgpack-rpc-connecting| for details on how clients can connect to nvim.
- Use a msgpack library that implements the spec version 5, Nvim uses the - Use a MessagePack library that implements at least version 5 of the
BIN/EXT types. MessagePack spec, which supports the `bin` and `ext` types used by nvim.
- Read API metadata in order to create client-side wrappers for all - Read API metadata in order to create client-side wrappers for all
msgpack-rpc methods. msgpack-rpc methods.
- Use a single-threaded event loop library/pattern. - Use a single-threaded event loop library/pattern.
- Use a fiber/coroutine library for the language you are implementing a client - Use a fiber/coroutine library for the language being used for implementing a
for. These greatly simplify concurrency and allow the library to expose a client. These greatly simplify concurrency and allow the library to expose a
blocking API on top of a non-blocking event loop without the complexity blocking API on top of a non-blocking event loop without the complexity that
that comes with preemptive multitasking. comes with preemptive multitasking.
- Don't assume anything about the order that responses to msgpack-rpc requests - Don't assume anything about the order that responses to msgpack-rpc requests
will arrive. will arrive.
- Clients should expect to receive msgpack-rpc requests, which need to be - Clients should expect to receive msgpack-rpc requests, which need to be
handled immediately because Nvim is blocked while waiting for the client handled immediately because Nvim is blocked while waiting for the client
response. response.
- Clients should expect to receive msgpack-rpc notifications, but these don't - Clients should expect to receive msgpack-rpc notifications, but these don't
need to be handled immediately because they won't block Nvim (though you need to be handled immediately because they won't block Nvim (although they
probably want to handle them immediately anyway). should probably be handled immediately anyway).
Most of the complexity could be handled by a msgpack-rpc library that supports Most of the complexity could be handled by a msgpack-rpc library that supports
server->client requests and notifications, but it's not clear if this is part server to client requests and notifications, but it's not clear if this is part
of the msgpack-rpc spec. At least the ruby msgpack-rpc library does not seem of the msgpack-rpc spec. At least the ruby msgpack-rpc library does not seem
to support it: to support it:
https://github.com/msgpack-rpc/msgpack-rpc-ruby/blob/master/lib/msgpack/rpc/transport/tcp.rb#L150-L158 https://github.com/msgpack-rpc/msgpack-rpc-ruby/blob/master/lib/msgpack/rpc/transport/tcp.rb#L150-L158
@@ -217,7 +215,7 @@ that makes this task easier:
- Methods that operate instances of Nvim's types are prefixed with the type - Methods that operate instances of Nvim's types are prefixed with the type
name in lower case, e.g. `buffer_get_line` represents the `get_line` method name in lower case, e.g. `buffer_get_line` represents the `get_line` method
of a Buffer instance. of a Buffer instance.
- Global methods are prefixed with `vim`, e.g.`vim_list_buffers`. - Global methods are prefixed with `vim`, e.g. `vim_list_buffers`.
So, for an object-oriented language, a client library would have the classes So, for an object-oriented language, a client library would have the classes
that represent Nvim's types, and the methods of each class could be defined that represent Nvim's types, and the methods of each class could be defined
@@ -227,13 +225,13 @@ class with methods mapped to functions prefixed with `vim_`
============================================================================== ==============================================================================
7. Vimscript functions *msgpack-rpc-vim-functions* 7. Vimscript functions *msgpack-rpc-vim-functions*
Four functions related to msgpack-rpc are available to vimscript: Four functions related to msgpack-rpc are available in vimscript:
1. |rpcstart()|: Similarly to |jobstart()|, this will spawn a co-process with 1. |rpcstart()|: Similarly to |jobstart()|, this will spawn a co-process with
its standard handles connected to Nvim. The difference is that it's not its standard handles connected to Nvim. The difference is that it's not
possible to process raw data to/from the process stdin/stdout/stderr (since possible to process raw data to/from the process's stdin/stdout/stderr.
the job's stdin/stdout combo are used as a msgpack channel that is This is because the job's stdin and stdout are used as a single msgpack
processed directly by Nvim C code). channel that is processed directly by Nvim.
2. |rpcstop()|: Same as |jobstop()|, but operates on handles returned by 2. |rpcstop()|: Same as |jobstop()|, but operates on handles returned by
|rpcstart()|. |rpcstart()|.