| *channel.txt* For Vim version 7.4. Last change: 2016 Feb 06 |
| |
| |
| VIM REFERENCE MANUAL by Bram Moolenaar |
| |
| |
| Inter-process communication *channel* |
| |
| DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT |
| |
| Vim uses channels to communicate with other processes. |
| A channel uses a socket. *socket-interface* |
| |
| Vim current supports up to 10 simultaneous channels. |
| The Netbeans interface also uses a channel. |netbeans| |
| |
| 1. Demo |channel-demo| |
| 2. Opening a channel |channel-open| |
| 3. Using a JSON channel |channel-use| |
| 4. Vim commands |channel-commands| |
| 5. Using a raw channel |channel-use| |
| 6. Job control |job-control| |
| |
| {Vi does not have any of these features} |
| {only available when compiled with the |+channel| feature} |
| |
| ============================================================================== |
| 1. Demo *channel-demo* |
| |
| 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 handle = ch_open('localhost:8765') |
| |
| In T1 you should see: |
| === socket opened === ~ |
| |
| You can now send a message to the server: > |
| echo ch_sendexpr(handle, '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(handle, msg) |
| echo "from the handler: " . a:msg |
| endfunc |
| call ch_sendexpr(handle, 'hello!', "MyHandler") |
| |
| Instead of giving a callback with every send call, it can also be specified |
| when opening the channel: > |
| call ch_close(handle) |
| let handle = ch_open('localhost:8765', {'callback': "MyHandler"}) |
| call ch_sendexpr(handle, 'hello!', 0) |
| |
| ============================================================================== |
| 2. Opening a channel *channel-open* |
| |
| To open a channel: > |
| let handle = ch_open({address} [, {argdict}]) |
| |
| {address} has the form "hostname:port". E.g., "localhost:8765". |
| |
| {argdict} is a dictionary with optional entries: |
| |
| "mode" can be: *channel-mode* |
| "json" - Use JSON, see below; most convenient way. Default. |
| "raw" - Use raw messages |
| |
| *channel-callback* |
| "callback" is 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: > |
| func Handle(handle, msg) |
| echo 'Received: ' . a:msg |
| endfunc |
| let handle = ch_open("localhost:8765", 'json', "Handle") |
| |
| "waittime" is 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 negative number waits forever. |
| |
| "timeout" is the time to wait for a request when blocking, using |
| ch_sendexpr(). Again in milliseconds. The default is 2000 (2 seconds). |
| |
| When "mode" is "json" 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" the "callback" is optional. When omitted it is only |
| possible to receive a message after sending one. |
| |
| The handler can be added or changed later: > |
| call ch_setcallback(handle, {callback}) |
| When "callback" is empty (zero or an empty string) the handler is removed. |
| NOT IMPLEMENTED YET |
| |
| The timeout can be changed later: > |
| call ch_settimeout(handle, {msec}) |
| NOT IMPLEMENTED YET |
| *E906* |
| Once done with the channel, disconnect it like this: > |
| call ch_close(handle) |
| |
| 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. |
| *E898* *E899* *E900* *E901* *E902* |
| |
| If there is an error reading or writing a channel it will be closed. |
| *E896* *E630* *E631* |
| |
| ============================================================================== |
| 3. Using a JSON channel *channel-use* |
| |
| If {mode} is "json" then a message can be sent synchronously like this: > |
| let response = ch_sendexpr(handle, {expr}) |
| This awaits a response from the other side. |
| |
| To send a message, without handling a response: > |
| call ch_sendexpr(handle, {expr}, 0) |
| |
| To send a message and letting the response handled by a specific function, |
| asynchronously: > |
| call ch_sendexpr(handle, {expr}, {callback}) |
| |
| The {expr} is converted to JSON and wrapped in an array. An example of the |
| message that the receiver will get when {expr} is the string "hello": |
| [12,"hello"] ~ |
| |
| The format of the JSON sent is: |
| [{number},{expr}] |
| |
| In which {number} is different every time. It must be used in the response |
| (if any): |
| |
| [{number},{response}] |
| |
| This way Vim knows which sent message matches with which received message and |
| can call the right handler. Also when the messages arrive out of order. |
| |
| The sender must always send valid JSON to Vim. Vim can check for the end of |
| the message by parsing the JSON. It will only accept the message if the end |
| was received. |
| |
| When the process wants to send a message to Vim without first receiving a |
| message, it must use the number zero: |
| [0,{response}] |
| |
| Then channel handler will then get {response} converted to Vim types. If the |
| channel does not have a handler the message is dropped. |
| |
| On read error or ch_close() the string "DETACH" is sent, if still possible. |
| The channel will then be inactive. |
| |
| ============================================================================== |
| 4. Vim commands *channel-commands* |
| |
| PARTLY IMPLEMENTED: only "ex" and "normal" work |
| |
| With a "json" channel the process can send commands to Vim that will be |
| handled by Vim internally, it does not require a handler for the channel. |
| |
| Possible commands are: *E903* *E904* *E905* |
| ["redraw" {forced}] |
| ["ex", {Ex command}] |
| ["normal", {Normal mode command}] |
| ["eval", {expression}, {number}] |
| ["expr", {expression}] |
| |
| With all of these: Be careful what these commands do! You can easily |
| interfere with what the user is doing. To avoid trouble use |mode()| to check |
| that the editor is in the expected state. E.g., to send keys that must be |
| inserted as text, not executed as a command: |
| ["ex","if mode() == 'i' | call feedkeys('ClassName') | endif"] ~ |
| |
| Errors in these commands are normally not reported to avoid them messing up |
| the display. If you do want to see them, set the 'verbose' option to 3 or |
| higher. |
| |
| |
| Command "redraw" ~ |
| |
| The other commands do not update the screen, so that you can send a sequence |
| of commands without the cursor moving around. You must end with the "redraw" |
| command to show any changed text and show the cursor where it belongs. |
| |
| The argument is normally an empty string: |
| ["redraw", ""] ~ |
| To first clear the screen pass "force": |
| ["redraw", "force"] ~ |
| |
| |
| Command "ex" ~ |
| |
| The "ex" command is executed as any Ex command. There is no response for |
| completion or error. You could use functions in an |autoload| script: |
| ["ex","call myscript#MyFunc(arg)"] |
| |
| You can also use "call |feedkeys()|" to insert any key sequence. |
| |
| |
| Command "normal" ~ |
| |
| The "normal" command is executed like with ":normal!", commands are not |
| mapped. Example to open the folds under the cursor: |
| ["normal" "zO"] |
| |
| |
| Command "eval" ~ |
| |
| The "eval" command an be used to get the result of an expression. For |
| example, to get the number of lines in the current buffer: |
| ["eval","line('$')"] ~ |
| |
| it will send back the result of the expression: |
| [{number}, {result}] |
| Here {number} is the same as what was in the request. Use a negative number |
| to avoid confusion with message that Vim sends. |
| |
| {result} is the result of the evaluation and is JSON encoded. If the |
| evaluation fails it is the string "ERROR". |
| |
| |
| Command "expr" ~ |
| |
| The "expr" command is similar to "eval", but does not send back any response. |
| Example: |
| ["expr","setline('$', ['one', 'two', 'three'])"] ~ |
| |
| ============================================================================== |
| 5. Using a raw channel *channel-raw* |
| |
| If {mode} is "raw" then a message can be send like this: > |
| let response = ch_sendraw(handle, {string}) |
| 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 |
| message you need to take care of it yourself. |
| |
| To send a message, without expecting a response: > |
| call ch_sendraw(handle, {string}, 0) |
| The process can send back a response, the channel handler will be called with |
| it. |
| |
| To send a message and letting the response handled by a specific function, |
| asynchronously: > |
| call ch_sendraw(handle, {string}, {callback}) |
| |
| This {string} can also be JSON, use |jsonencode()| to create it and |
| |jsondecode()| to handle a received JSON message. |
| |
| ============================================================================== |
| 6. Job control *job-control* |
| |
| NOT IMPLEMENTED YET |
| |
| To start another process: > |
| call startjob({command}) |
| |
| This does not wait for {command} to exit. |
| |
| TODO: |
| |
| let handle = startjob({command}, 's') # uses stdin/stdout |
| let handle = startjob({command}, '', {address}) # uses socket |
| let handle = startjob({command}, 'd', {address}) # start if connect fails |
| |
| |
| vim:tw=78:ts=8:ft=help:norl: |