*channel.txt* For Vim version 8.2. Last change: 2022 Mar 26
VIM REFERENCE MANUAL by Bram Moolenaar
Inter-process communication *channel*
Vim uses channels to communicate with other processes.
A channel uses a socket or pipes. *socket-interface*
Jobs can be used to start processes and communicate with them.
The Netbeans interface also uses a channel. |netbeans|
1. Overview |job-channel-overview|
2. Channel demo |channel-demo|
3. Opening a channel |channel-open|
4. Using a JSON or JS channel |channel-use|
5. Channel commands |channel-commands|
6. Using a RAW or NL channel |channel-raw|
7. More channel functions |channel-more|
8. Channel functions details |channel-functions-details|
9. Starting a job with a channel |job-start|
10. Starting a job without a channel |job-start-nochannel|
11. Job functions |job-functions-details|
12. Job options |job-options|
13. Controlling a job |job-control|
14. Using a prompt buffer |prompt-buffer|
{only when compiled with the |+channel| feature for channel stuff}
You can check this with: `has('channel')`
{only when compiled with the |+job| feature for job stuff}
You can check this with: `has('job')`
==============================================================================
1. Overview *job-channel-overview*
There are four main types of jobs:
1. A daemon, serving several Vim instances.
Vim connects to it with a socket.
2. One job working with one Vim instance, asynchronously.
Uses a socket or pipes.
3. A job performing some work for a short time, asynchronously.
Uses a socket or pipes.
4. Running a filter, synchronously.
Uses pipes.
For when using sockets See |job-start|, |job-start-nochannel| and
|channel-open|. For 2 and 3, one or more jobs using pipes, see |job-start|.
For 4 use the ":{range}!cmd" command, see |filter|.
Over the socket and pipes these protocols are available:
RAW nothing known, Vim cannot tell where a message ends
NL every message ends in a NL (newline) character
JSON JSON encoding |json_encode()|
JS JavaScript style JSON-like encoding |js_encode()|
LSP Language Server Protocol encoding |language-server-protocol|
Common combination are:
- Using a job connected through pipes in NL mode. E.g., to run a style
checker and receive errors and warnings.
- Using a daemon, connecting over a socket in JSON mode. E.g. to lookup
cross-references in a database.
==============================================================================
2. Channel demo *channel-demo* *demoserver.py*
This requires Python. The demo program can be found in
$VIMRUNTIME/tools/demoserver.py
Run it in one terminal. We will call this T1.
Run Vim in another terminal. Connect to the demo server with: >
let channel = ch_open('localhost:8765')
In T1 you should see:
=== socket opened === ~
You can now send a message to the server: >
echo ch_evalexpr(channel, 'hello!')
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:
[1,"hello!"] ~
And the response is:
[1,"got it"] ~
The number will increase every time you send a message.
The server can send a command to Vim. Type this on T1 (literally, including
the quotes):
["ex","echo 'hi there'"] ~
And you should see the message in Vim. You can move the cursor a word forward:
["normal","w"] ~
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!', {'callback': "MyHandler"})
Vim will not wait for a response. Now the server can send the response later
and MyHandler will be invoked.
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 channel!')
When trying out channels it's useful to see what is going on. You can tell
Vim to write lines in log file: >
call ch_logfile('channellog', 'w')
See |ch_logfile()|.
==============================================================================
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.
{address} has the form "hostname:port". E.g., "localhost:8765".
When using an IPv6 address, enclose it within square brackets. E.g.,
"[2001:db8::1]:8765".
{options} is a dictionary with optional entries: *channel-open-options*
"mode" can be: *channel-mode*
"json" - Use JSON, see below; most convenient way. Default.
"js" - Use JS (JavaScript) encoding, more efficient than JSON.
"nl" - Use messages that end in a NL character
"raw" - Use raw messages
"lsp" - Use language server protocol encoding
*channel-callback* *E921*
"callback" A function that is called when a message is received that is
not handled otherwise (e.g. a JSON message with ID zero). It
gets two arguments: the channel 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" or "lsp" 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.
For all callbacks: Use |function()| to bind it to arguments
and/or a Dictionary. Or use the form "dict.function" to bind
the