Mercurial > vim
diff runtime/doc/channel.txt @ 7788:192ae655ac91 v7.4.1191
commit https://github.com/vim/vim/commit/3b5f929b18492fec291d1ec95a91f54e5912c03b
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jan 28 22:37:01 2016 +0100
patch 7.4.1191
Problem: The channel feature isn't working yet.
Solution: Add the connect(), disconnect(), sendexpr() and sendraw()
functions. Add initial documentation. Add a demo server.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 28 Jan 2016 22:45:04 +0100 |
parents | |
children | 6b0891de44a9 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/runtime/doc/channel.txt @@ -0,0 +1,218 @@ +*channel.txt* For Vim version 7.4. Last change: 2016 Jan 28 + + + 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 simultanious 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 = connect('localhost:8765', 'json') + +In T1 you should see: + === socket opened === ~ + +You can now send a message to the server: > + echo 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): > + NOT IMPLEMENTED YET + ["ex","echo 'hi there'"] +And you should see the message in Vim. + +To handle asynchronous communication a callback needs to be used: > + func MyHandler(handle, msg) + echo "from the handler: " . a:msg + endfunc + call sendexpr(handle, 'hello!', "MyHandler") + +Instead of giving a callback with every send call, it can also be specified +when opening the channel: > + call disconnect(handle) + let handle = connect('localhost:8765', 'json', "MyHandler") + call sendexpr(handle, 'hello!', 0) + +============================================================================== +2. Opening a channel *channel-open* + +To open a channel: + let handle = connect({address}, {mode}, {callback}) + +{address} has the form "hostname:port". E.g., "localhost:8765". + +{mode} can be: *channel-mode* + "json" - Use JSON, see below; most convenient way + "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 = connect("localhost:8765", 'json', "Handle") + +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 sethandler(handle, {callback}) +When {callback} is empty (zero or an empty string) the handler is removed. + +Once done with the channel, disconnect it like this: > + call disconnect(handle) + +============================================================================== +3. Using a JSON channel *channel-use* + +If {mode} is "json" then a message can be sent synchronously like this: > + let response = sendexpr(handle, {expr}) +This awaits a response from the other side. + +To send a message, without handling a response: > + call sendexpr(handle, {expr}, 0) + +To send a message and letting the response handled by a specific function, +asynchronously: > + call 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 disconnect() the string "DETACH" is sent, if still possible. +The channel will then be inactive. + +============================================================================== +4. Vim commands *channel-commands* + +NOT IMPLEMENTED YET + +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: + ["ex", {Ex command}] + ["normal", {Normal mode command}] + ["eval", {number}, {expression}] + ["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"] + +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. +You can also invoke |feedkeys()| to insert anything. + +The "normal" command is executed like with |:normal|. + +The "eval" command will result in sending back the result of the expression: + [{number}, {result}] +Here {number} is the same as what was in the request. + +The "expr" command is similar, 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 = 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 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 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: