Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 1 | *channel.txt* For Vim version 7.4. Last change: 2016 Feb 07 |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 2 | |
| 3 | |
| 4 | VIM REFERENCE MANUAL by Bram Moolenaar |
| 5 | |
| 6 | |
| 7 | Inter-process communication *channel* |
| 8 | |
| 9 | DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT |
| 10 | |
| 11 | Vim uses channels to communicate with other processes. |
| 12 | A channel uses a socket. *socket-interface* |
| 13 | |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 14 | Vim current supports up to 10 simultaneous channels. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 15 | The Netbeans interface also uses a channel. |netbeans| |
| 16 | |
| 17 | 1. Demo |channel-demo| |
| 18 | 2. Opening a channel |channel-open| |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 19 | 3. Using a JSON or JS channel |channel-use| |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 20 | 4. Vim commands |channel-commands| |
| 21 | 5. Using a raw channel |channel-use| |
| 22 | 6. Job control |job-control| |
| 23 | |
| 24 | {Vi does not have any of these features} |
| 25 | {only available when compiled with the |+channel| feature} |
| 26 | |
| 27 | ============================================================================== |
| 28 | 1. Demo *channel-demo* |
| 29 | |
| 30 | This requires Python. The demo program can be found in |
| 31 | $VIMRUNTIME/tools/demoserver.py |
| 32 | Run it in one terminal. We will call this T1. |
| 33 | |
| 34 | Run Vim in another terminal. Connect to the demo server with: > |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 35 | let handle = ch_open('localhost:8765') |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 36 | |
| 37 | In T1 you should see: |
| 38 | === socket opened === ~ |
| 39 | |
| 40 | You can now send a message to the server: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 41 | echo ch_sendexpr(handle, 'hello!') |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 42 | |
| 43 | The message is received in T1 and a response is sent back to Vim. |
| 44 | You can see the raw messages in T1. What Vim sends is: |
| 45 | [1,"hello!"] ~ |
| 46 | And the response is: |
| 47 | [1,"got it"] ~ |
| 48 | The number will increase every time you send a message. |
| 49 | |
| 50 | The server can send a command to Vim. Type this on T1 (literally, including |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 51 | the quotes): |
| 52 | ["ex","echo 'hi there'"] ~ |
| 53 | And you should see the message in Vim. You can move the cursor a word forward: |
| 54 | ["normal","w"] ~ |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 55 | |
| 56 | To handle asynchronous communication a callback needs to be used: > |
| 57 | func MyHandler(handle, msg) |
| 58 | echo "from the handler: " . a:msg |
| 59 | endfunc |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 60 | call ch_sendexpr(handle, 'hello!', "MyHandler") |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 61 | |
| 62 | Instead of giving a callback with every send call, it can also be specified |
| 63 | when opening the channel: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 64 | call ch_close(handle) |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 65 | let handle = ch_open('localhost:8765', {'callback': "MyHandler"}) |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 66 | call ch_sendexpr(handle, 'hello!', 0) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 67 | |
| 68 | ============================================================================== |
| 69 | 2. Opening a channel *channel-open* |
| 70 | |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 71 | To open a channel: > |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 72 | let handle = ch_open({address} [, {argdict}]) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 73 | |
| 74 | {address} has the form "hostname:port". E.g., "localhost:8765". |
| 75 | |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 76 | {argdict} is a dictionary with optional entries: |
| 77 | |
| 78 | "mode" can be: *channel-mode* |
| 79 | "json" - Use JSON, see below; most convenient way. Default. |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 80 | "js" - Use JavaScript encoding, more efficient than JSON. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 81 | "raw" - Use raw messages |
| 82 | |
| 83 | *channel-callback* |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 84 | "callback" is a function that is called when a message is received that is not |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 85 | handled otherwise. It gets two arguments: the channel handle and the received |
| 86 | message. Example: > |
| 87 | func Handle(handle, msg) |
| 88 | echo 'Received: ' . a:msg |
| 89 | endfunc |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 90 | let handle = ch_open("localhost:8765", {"callback": "Handle"}) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 91 | |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 92 | "waittime" is the time to wait for the connection to be made in milliseconds. |
| 93 | The default is zero, don't wait, which is useful if the server is supposed to |
| 94 | be running already. A negative number waits forever. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 95 | |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 96 | "timeout" is the time to wait for a request when blocking, using |
Bram Moolenaar | 835dc63 | 2016-02-07 14:27:38 +0100 | [diff] [blame] | 97 | ch_sendexpr(). Again in milliseconds. The default is 2000 (2 seconds). |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 98 | |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 99 | When "mode" is "json" or "js" the "msg" argument is the body of the received |
| 100 | message, converted to Vim types. |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 101 | When "mode" is "raw" the "msg" argument is the whole message as a string. |
| 102 | |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 103 | When "mode" is "json" or "js" the "callback" is optional. When omitted it is |
| 104 | only possible to receive a message after sending one. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 105 | |
| 106 | The handler can be added or changed later: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 107 | call ch_setcallback(handle, {callback}) |
Bram Moolenaar | 835dc63 | 2016-02-07 14:27:38 +0100 | [diff] [blame] | 108 | When "callback" is empty (zero or an empty string) the handler is removed. |
Bram Moolenaar | 4d919d7 | 2016-02-05 22:36:41 +0100 | [diff] [blame] | 109 | NOT IMPLEMENTED YET |
| 110 | |
| 111 | The timeout can be changed later: > |
| 112 | call ch_settimeout(handle, {msec}) |
| 113 | NOT IMPLEMENTED YET |
Bram Moolenaar | 835dc63 | 2016-02-07 14:27:38 +0100 | [diff] [blame] | 114 | *E906* |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 115 | Once done with the channel, disconnect it like this: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 116 | call ch_close(handle) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 117 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 118 | Currently up to 10 channels can be in use at the same time. *E897* |
| 119 | |
Bram Moolenaar | cbebd48 | 2016-02-07 23:02:56 +0100 | [diff] [blame] | 120 | When the channel can't be opened you will get an error message. There is a |
| 121 | difference between MS-Windows and Unix: On Unix when the port doesn't exist |
| 122 | ch_open() fails quickly. On MS-Windows "waittime" applies. |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 123 | *E898* *E899* *E900* *E901* *E902* |
| 124 | |
| 125 | If there is an error reading or writing a channel it will be closed. |
| 126 | *E896* *E630* *E631* |
| 127 | |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 128 | ============================================================================== |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 129 | 3. Using a JSON or JS channel *channel-use* |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 130 | |
| 131 | If {mode} is "json" then a message can be sent synchronously like this: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 132 | let response = ch_sendexpr(handle, {expr}) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 133 | This awaits a response from the other side. |
| 134 | |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 135 | When {mode} is "js" this works the same, except that the messages use |
| 136 | JavaScript encoding. See |jsencode()| for the difference. |
| 137 | |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 138 | To send a message, without handling a response: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 139 | call ch_sendexpr(handle, {expr}, 0) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 140 | |
| 141 | To send a message and letting the response handled by a specific function, |
| 142 | asynchronously: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 143 | call ch_sendexpr(handle, {expr}, {callback}) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 144 | |
| 145 | The {expr} is converted to JSON and wrapped in an array. An example of the |
| 146 | message that the receiver will get when {expr} is the string "hello": |
| 147 | [12,"hello"] ~ |
| 148 | |
| 149 | The format of the JSON sent is: |
| 150 | [{number},{expr}] |
| 151 | |
| 152 | In which {number} is different every time. It must be used in the response |
| 153 | (if any): |
| 154 | |
| 155 | [{number},{response}] |
| 156 | |
| 157 | This way Vim knows which sent message matches with which received message and |
| 158 | can call the right handler. Also when the messages arrive out of order. |
| 159 | |
| 160 | The sender must always send valid JSON to Vim. Vim can check for the end of |
| 161 | the message by parsing the JSON. It will only accept the message if the end |
| 162 | was received. |
| 163 | |
| 164 | When the process wants to send a message to Vim without first receiving a |
| 165 | message, it must use the number zero: |
| 166 | [0,{response}] |
| 167 | |
| 168 | Then channel handler will then get {response} converted to Vim types. If the |
| 169 | channel does not have a handler the message is dropped. |
| 170 | |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 171 | On read error or ch_close() the string "DETACH" is sent, if still possible. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 172 | The channel will then be inactive. |
| 173 | |
Bram Moolenaar | cbebd48 | 2016-02-07 23:02:56 +0100 | [diff] [blame] | 174 | It is also possible to use ch_sendraw() on a JSON or JS channel. The caller |
| 175 | is then completely responsible for correct encoding and decoding. |
| 176 | |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 177 | ============================================================================== |
| 178 | 4. Vim commands *channel-commands* |
| 179 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 180 | PARTLY IMPLEMENTED: only "ex" and "normal" work |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 181 | |
| 182 | With a "json" channel the process can send commands to Vim that will be |
| 183 | handled by Vim internally, it does not require a handler for the channel. |
| 184 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 185 | Possible commands are: *E903* *E904* *E905* |
| 186 | ["redraw" {forced}] |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 187 | ["ex", {Ex command}] |
| 188 | ["normal", {Normal mode command}] |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 189 | ["eval", {expression}, {number}] |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 190 | ["expr", {expression}] |
| 191 | |
| 192 | With all of these: Be careful what these commands do! You can easily |
| 193 | interfere with what the user is doing. To avoid trouble use |mode()| to check |
| 194 | that the editor is in the expected state. E.g., to send keys that must be |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 195 | inserted as text, not executed as a command: |
| 196 | ["ex","if mode() == 'i' | call feedkeys('ClassName') | endif"] ~ |
| 197 | |
| 198 | Errors in these commands are normally not reported to avoid them messing up |
| 199 | the display. If you do want to see them, set the 'verbose' option to 3 or |
| 200 | higher. |
| 201 | |
| 202 | |
| 203 | Command "redraw" ~ |
| 204 | |
| 205 | The other commands do not update the screen, so that you can send a sequence |
| 206 | of commands without the cursor moving around. You must end with the "redraw" |
| 207 | command to show any changed text and show the cursor where it belongs. |
| 208 | |
| 209 | The argument is normally an empty string: |
| 210 | ["redraw", ""] ~ |
| 211 | To first clear the screen pass "force": |
| 212 | ["redraw", "force"] ~ |
| 213 | |
| 214 | |
| 215 | Command "ex" ~ |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 216 | |
| 217 | The "ex" command is executed as any Ex command. There is no response for |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 218 | completion or error. You could use functions in an |autoload| script: |
| 219 | ["ex","call myscript#MyFunc(arg)"] |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 220 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 221 | You can also use "call |feedkeys()|" to insert any key sequence. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 222 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 223 | |
| 224 | Command "normal" ~ |
| 225 | |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 226 | The "normal" command is executed like with ":normal!", commands are not |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 227 | mapped. Example to open the folds under the cursor: |
| 228 | ["normal" "zO"] |
| 229 | |
| 230 | |
| 231 | Command "eval" ~ |
| 232 | |
| 233 | The "eval" command an be used to get the result of an expression. For |
| 234 | example, to get the number of lines in the current buffer: |
| 235 | ["eval","line('$')"] ~ |
| 236 | |
| 237 | it will send back the result of the expression: |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 238 | [{number}, {result}] |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 239 | Here {number} is the same as what was in the request. Use a negative number |
| 240 | to avoid confusion with message that Vim sends. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 241 | |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 242 | {result} is the result of the evaluation and is JSON encoded. If the |
Bram Moolenaar | 595e64e | 2016-02-07 19:19:53 +0100 | [diff] [blame] | 243 | evaluation fails or the result can't be encoded in JSON it is the string |
| 244 | "ERROR". |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 245 | |
| 246 | |
| 247 | Command "expr" ~ |
| 248 | |
| 249 | The "expr" command is similar to "eval", but does not send back any response. |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 250 | Example: |
Bram Moolenaar | fb1f626 | 2016-01-31 20:24:32 +0100 | [diff] [blame] | 251 | ["expr","setline('$', ['one', 'two', 'three'])"] ~ |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 252 | |
| 253 | ============================================================================== |
| 254 | 5. Using a raw channel *channel-raw* |
| 255 | |
| 256 | If {mode} is "raw" then a message can be send like this: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 257 | let response = ch_sendraw(handle, {string}) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 258 | The {string} is sent as-is. The response will be what can be read from the |
| 259 | channel right away. Since Vim doesn't know how to recognize the end of the |
| 260 | message you need to take care of it yourself. |
| 261 | |
| 262 | To send a message, without expecting a response: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 263 | call ch_sendraw(handle, {string}, 0) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 264 | The process can send back a response, the channel handler will be called with |
| 265 | it. |
| 266 | |
| 267 | To send a message and letting the response handled by a specific function, |
| 268 | asynchronously: > |
Bram Moolenaar | 681baaf | 2016-02-04 20:57:07 +0100 | [diff] [blame] | 269 | call ch_sendraw(handle, {string}, {callback}) |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 270 | |
| 271 | This {string} can also be JSON, use |jsonencode()| to create it and |
| 272 | |jsondecode()| to handle a received JSON message. |
| 273 | |
Bram Moolenaar | cbebd48 | 2016-02-07 23:02:56 +0100 | [diff] [blame] | 274 | It is not possible to use |ch_sendexpr()| on a raw channel. |
| 275 | |
Bram Moolenaar | 3b5f929 | 2016-01-28 22:37:01 +0100 | [diff] [blame] | 276 | ============================================================================== |
| 277 | 6. Job control *job-control* |
| 278 | |
| 279 | NOT IMPLEMENTED YET |
| 280 | |
| 281 | To start another process: > |
| 282 | call startjob({command}) |
| 283 | |
| 284 | This does not wait for {command} to exit. |
| 285 | |
| 286 | TODO: |
| 287 | |
| 288 | let handle = startjob({command}, 's') # uses stdin/stdout |
| 289 | let handle = startjob({command}, '', {address}) # uses socket |
| 290 | let handle = startjob({command}, 'd', {address}) # start if connect fails |
| 291 | |
| 292 | |
| 293 | vim:tw=78:ts=8:ft=help:norl: |