mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 13:58:18 +00:00
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:
@@ -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
|
||||||
|
@@ -13,7 +13,7 @@ Nvim's facilities for job control *job-control*
|
|||||||
1. Introduction *job-control-intro*
|
1. Introduction *job-control-intro*
|
||||||
|
|
||||||
Job control is a simple way to perform multitasking in vimscript. Wikipedia
|
Job control is a simple way to perform multitasking in vimscript. Wikipedia
|
||||||
contains a more generic/detailed description:
|
contains a more generic/detailed description:
|
||||||
|
|
||||||
"Job control in computing refers to the control of multiple tasks or Jobs on a
|
"Job control in computing refers to the control of multiple tasks or Jobs on a
|
||||||
computer system, ensuring that they each have access to adequate resources to
|
computer system, ensuring that they each have access to adequate resources to
|
||||||
@@ -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,8 +43,8 @@ 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'
|
||||||
let str = 'shell '. v:job_data[0].' stdout: '.join(v:job_data[2])
|
let str = 'shell '. v:job_data[0].' stdout: '.join(v:job_data[2])
|
||||||
@@ -53,27 +53,27 @@ event. The best way to understand is with a complete example:
|
|||||||
else
|
else
|
||||||
let str = 'shell '.v:job_data[0].' exited'
|
let str = 'shell '.v:job_data[0].' exited'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call append(line('$'), str)
|
call append(line('$'), str)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
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:
|
||||||
|
@@ -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()|.
|
||||||
|
Reference in New Issue
Block a user