diff options
-rw-r--r-- | runtime/doc/msgpack_rpc.txt | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index 01d4e10cea..ab77e08bc7 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -241,4 +241,192 @@ Even for statically compiled clients it is good practice to avoid hardcoding the type codes, because a client may be built against one Nvim version but connect to another with different type codes. +============================================================================== +6. Live Updates *live-updates* *rpc-live-updates* + +A dedicated API has been created to allow co-processes to be notified in +real-time when the user changes a buffer in any way. It is difficult and +error-prone to try and do this with autocommands such as |TextChanged|. + + *live-updates-enabling* +Setting Up~ + +If your API client is a standalone co-process, it can use the +`"nvim_buf_live_updates"`API method to activate Live Update events for a +specific buffer. For example, in python > + + import sys, neovim + nvim = neovim.attach('stdio') + bufnr = sys.argv[1] + nvim.buffers[bufnr].live_updates(True) + +After the `"nvim_buf_live_updates"` method is called, neovim will send a +series of notifications containing the entire buffer's contents and any +subsequent changes. The buffer's contents are sent via notifications because +if you were to use the other API methods to retrieve the buffer contents, the +buffer could be changed again before you turn on live updates. This can cause +a delay if your plugin activates live updates for a very large buffer, but it +is the the most efficient way to maintain a copy of the entire buffer's +contents inside your plugin. + + *live-updates-disabling* +Turning Off~ + +You can use `"nvim_buf_live_updates"` with an argument of `False` to turn off +notifications. One final notification will be sent to indicate that live +updates are no longer active for the specified buffer. Alternatively, you can +just close the channel. + + *live-updates-limitations* +Limitations~ + +Note that any of the following actions will also turn off live updates because +the buffer contents are unloaded from memory: + + - Closing all a buffer's windows (unless 'hidden' is enabled). + - Using |:edit| to reload the buffer + - reloading the buffer after it is changed from outside neovim. + + *live-updates-events* +Handling Events~ + +The co-process will start receiving the notification events which will be +equivilent to the following |rpcnotify()| calls: + +1. rpcnotify({channel}, "LiveUpdateStart", *LiveUpdateStart* + [{buf}, {changedtick}, {linedata}, {more}]) + + Neovim will send at least one of these notifications to provide you + with the original buffer contents. If the buffer is very large, neovim + will send the contents through in multiple events to avoid loading the + entire buffer's contents into memory at once. + + {buf} is an API handle for the buffer. + + {changedtick} is the value of |b:changedtick| for the buffer. If you + send an API command back to neovim you can check the value of + |b:changedtick| as part of your request to ensure that no other + changes have been made. See |live-update-race-conditions| for more + information. + + {linedata} is a list of strings containing the buffer's contents. If + this list contains 100 strings, then they represent lines 1-100 of the + buffer. Newline characters are not included in the strings, so empty + lines will be given as empty strings. If you receive another + `"LiveUpdateStart"` notification with another {linedata} list, then + these lines represent the next N lines of the buffer. I.e., a second + notification with another list of 100 strings will represent lines + 101-200 of the buffer. + + {linedata} will always have at least 1 item, but the maximum length is + determined by neovim and not guaranteed to be any particular size. + Also the number of {linedata} items may vary between notifications, so + your plugin must be prepared to receive the line data in whatever size + lists neovim decides to split it into. + + {more} is a boolean which tells you whether or not to expect more + `"LiveUpdateStart"` notifications. When {more} is false, you can + be certain that you now have the entire buffer's contents. + +2. rpcnotify({channel}, "LiveUpdate", *LiveUpdate* + [{buf}, {changedtick}, {firstline}, {numreplaced}, {linedata}]) + + Indicates that {numreplaced} lines starting at line {firstline} have + been replaced with the new line data contained in the {linedata} list. + All buffer changes (even adding single characters) will be transmitted + as whole-line changes. + + {buf} is an API handle for the buffer. + + {changedtick} is the value of |b:changedtick| for the buffer. If you + send an API command back to neovim you can check the value of + |b:changedtick| as part of your request to ensure that no other + changes have been made. + + {firstline} is the integer line number of the first line that was + replaced. Note that {firstline} is zero-indexed, so if line `1` was + replaced then {firstline} will be `0` instead of `1`. {firstline} is + guaranteed to always be less than or equal to the number of lines that + were in the buffer before the lines were replaced. + + {numreplaced} is a positive integer indicating how many lines were + replaced. It will be `0` if new lines were added to the buffer but + none were replaced. If {numreplaced} is `0` then the new lines were + added + before the zero-indexed line number in {firstline}. + + {linedata} is a list of strings containing the contents of the new + buffer lines. Newline characters are not included in the strings, so + empty lines will be given as empty strings. If {numreplaced} is `1` or + more, then {linedata} may be an empty list (indicating that lines were + deleted from the buffer). But if {numreplaced} is `0` (indicating that + lines were added to the buffer) then {linedata} is guaranteed to + contain at least 1 item. + + Note: sometimes {changedtick} will be |v:null|, which means that the + buffer text *looks* like it has changed, but actually hasn't. In this + case the lines in {linedata} contain the modified text that is shown + to the user, but doesn't reflect the actual buffer contents. Currently + this behaviour is only used for the 'inccommand' option. + +3. rpcnotify({channel}, "LiveUpdateTick", *LiveUpdateTick* + [{buf}, {changedtick}]) + + Indicates that |b:changedtick| was incremented for the buffer {buf}, + but no text was changed. This is currently only used by undo/redo. + + {buf} is an API handle for the buffer. + + {changedtick} is the new value of |b:changedtick| for that buffer. + +4. rpcnotify({channel}, "LiveUpdateEnd", [{buf}]) *LiveUpdateEnd* + + {buf} is an API handle for the buffer. + + Indicates that live updates for the nominated buffer have been + disabled, either by calling the api function `"nvim_buf_live_updates"` + with argument `false`, or because the buffer was unloaded (see + |live-updates-disabling| and |live-updates-limitations| for more + information). + + *live-updates-examples* +Example Events~ + +If live updates are activated a new empty buffer, the following +|LiveUpdateStart| event will be sent: > + + rpcnotify({channel}, "LiveUpdateStart", [{buf}, [""], v:false]) + +If the user adds 2 new lines to the start of a buffer, the following event +would be generated: > + + rpcnotify({channel}, "LiveUpdate", [{buf}, 0, 0, ["line1", "line2"]]) + +If the puts the cursor on a line containing the text `"Hello world"` and adds +a `!` character to the end using insert mode, the following event would be +generated: > + + rpcnotify({channel}, "LiveUpdate", + [{buf}, {linenr}, 1, ["Hello world!"]]) + +If the user moves their cursor to line 3 of a buffer and deletes 20 lines +using `20dd`, the following event will be generated: > + + rpcnotify({channel}, "LiveUpdate", [{buf}, 2, 20, []]) + +If the user selects lines 3-5 of a buffer using |linewise-visual| mode and +then presses `p` to paste in a new block of 6 lines, then the following event +would be sent to the co-process: > + + rpcnotify({channel}, "LiveUpdate", + [{buf}, 2, 3, ['pasted line 1', 'pasted line 2', + 'pasted line 3', 'pasted line 4', + 'pasted line 5', 'pasted line 6']]) + +If the user uses :edit to reload a buffer then the following event would be +generated: > + + rpcnotify({channel}, "LiveUpdateEnd", [{buf}]) + + vim:tw=78:ts=8:ft=help:norl: |