mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			446 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			446 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| *msgpack_rpc.txt*	Nvim
 | ||
| 
 | ||
| 
 | ||
| 		 NVIM REFERENCE MANUAL    by Thiago de Arruda
 | ||
| 
 | ||
| 
 | ||
| RPC API for Nvim				     *RPC* *rpc* *msgpack-rpc*
 | ||
| 
 | ||
| 				      Type <M-]> to see the table of contents.
 | ||
| 
 | ||
| ==============================================================================
 | ||
| 1. Introduction						            *rpc-intro*
 | ||
| 
 | ||
| The primary way to control Nvim programmatically is the RPC API, which speaks
 | ||
| MessagePack-RPC ("msgpack-rpc"), a messaging protocol that uses the
 | ||
| MessagePack serialization format:
 | ||
|   https://github.com/msgpack/msgpack/blob/0b8f5ac/spec.md
 | ||
| 
 | ||
| All kinds of Nvim "clients" use the RPC API: user interfaces (GUIs), remote
 | ||
| plugins, scripts like "nvr" (https://github.com/mhinz/neovim-remote), and even
 | ||
| `nvim` itself can control other `nvim` instances. By connecting to the RPC API
 | ||
| programs can:
 | ||
| 
 | ||
|   - Call any API function
 | ||
|   - Listen for events
 | ||
|   - Receive remote calls from Nvim
 | ||
| 
 | ||
| The RPC API is like a more powerful version of Vim's `clientserver` feature.
 | ||
| 
 | ||
| ==============================================================================
 | ||
| 2. API mapping							    *rpc-api*
 | ||
| 
 | ||
| The Nvim C |API| is automatically exposed to the RPC API by the build system,
 | ||
| which parses headers at src/nvim/api/*. A dispatch function is generated which
 | ||
| matches RPC API method names with public API functions, converting/validating
 | ||
| arguments and return values back to msgpack.
 | ||
| 
 | ||
| Client libraries (|api-client|s) normally provide wrappers that hide
 | ||
| msgpack-rpc details from application developers. The wrappers can be
 | ||
| automatically generated by reading bundled API metadata from a compiled Nvim
 | ||
| instance.
 | ||
| 
 | ||
| There are three ways to obtain API metadata:
 | ||
| 
 | ||
|   1. Connect to a running Nvim instance and call `nvim_get_api_info` via
 | ||
|      msgpack-rpc. This is best for clients written in dynamic languages which
 | ||
|      can define functions at runtime.
 | ||
| 
 | ||
|   2. Start Nvim with the |--api-info| option. Useful for clients written in
 | ||
|      statically-compiled languages.
 | ||
| 
 | ||
|   3. Use the |api_info()| vimscript function.
 | ||
| 
 | ||
| To get a human-readable list of API functions: >
 | ||
|     :new|put =map(api_info().functions, 'v:val.name')
 | ||
| <
 | ||
| To get a formatted dump of the API using python (requires the `pyyaml` and
 | ||
| `msgpack-python` packages): >
 | ||
|     nvim --api-info | python -c 'import msgpack, sys, yaml; print yaml.dump(msgpack.unpackb(sys.stdin.read()))'
 | ||
| <
 | ||
| ==============================================================================
 | ||
| 3. Connecting						      *rpc-connecting*
 | ||
| 
 | ||
| There are several ways to open a msgpack-rpc channel to an Nvim instance:
 | ||
| 
 | ||
|   1. Through stdin/stdout when `nvim` is started with `--embed`. This is how
 | ||
|      applications can embed Nvim.
 | ||
| 
 | ||
|   2. Through stdin/stdout of some other process spawned by |jobstart()|.
 | ||
|      Set the "rpc" key to |v:true| in the options dict to use the job's stdin
 | ||
|      and stdout as a single msgpack channel that is processed directly by
 | ||
|      Nvim.  Then it is not possible to process raw data to or from the
 | ||
|      process's stdin and stdout. stderr can still be used, though.
 | ||
| 
 | ||
|   3. Through the socket automatically created with each instance. The socket
 | ||
|      location is stored in |v:servername|.
 | ||
| 
 | ||
|   4. Through a TCP/IP socket. To make Nvim listen on a TCP/IP socket, set the
 | ||
|      |$NVIM_LISTEN_ADDRESS| environment variable before starting Nvim: >
 | ||
|         NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim
 | ||
| <
 | ||
| Connecting to the socket is the easiest way a programmer can test the API,
 | ||
| which can be done through any msgpack-rpc client library or full-featured
 | ||
| |api-client|. Here's a Ruby script that prints 'hello world!' in the current
 | ||
| Nvim instance:
 | ||
| >
 | ||
|     #!/usr/bin/env ruby
 | ||
|     # Requires msgpack-rpc: gem install msgpack-rpc
 | ||
|     #
 | ||
|     # To run this script, execute it from a running Nvim instance (notice the
 | ||
|     # trailing '&' which is required since Nvim won't process events while
 | ||
|     # running a blocking command):
 | ||
|     #
 | ||
|     #	:!./hello.rb &
 | ||
|     #
 | ||
|     # Or from another shell by setting NVIM_LISTEN_ADDRESS:
 | ||
|     # $ NVIM_LISTEN_ADDRESS=[address] ./hello.rb
 | ||
| 
 | ||
|     require 'msgpack/rpc'
 | ||
|     require 'msgpack/rpc/transport/unix'
 | ||
| 
 | ||
|     nvim = MessagePack::RPC::Client.new(MessagePack::RPC::UNIXTransport.new, ENV['NVIM_LISTEN_ADDRESS'])
 | ||
|     result = nvim.call(:nvim_command, 'echo "hello world!"')
 | ||
| <
 | ||
| A better way is to use the Python REPL with the `neovim` package, where API
 | ||
| functions can be called interactively:
 | ||
| >
 | ||
|     >>> from neovim import attach
 | ||
|     >>> nvim = attach('socket', path='[address]')
 | ||
|     >>> nvim.command('echo "hello world!"')
 | ||
| <
 | ||
| You can also embed an Nvim instance via |jobstart()|, and communicate using
 | ||
| |rpcrequest()| and |rpcnotify()|:
 | ||
| >
 | ||
|     let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true})
 | ||
|     echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"')
 | ||
|     call jobstop(nvim)
 | ||
| <
 | ||
| ==============================================================================
 | ||
| 4. Implementing API clients			*rpc-api-client* *api-client*
 | ||
| 
 | ||
| "API clients" wrap the Nvim API to provide idiomatic "SDKs" for their
 | ||
| respective platforms (see |dev-jargon|). You can build a new API client for
 | ||
| your favorite platform or programming language.
 | ||
| 
 | ||
| Existing API clients are listed here:
 | ||
|     https://github.com/neovim/neovim/wiki/Related-projects#api-clients
 | ||
| 
 | ||
| The Python client is the reference implementation for API clients. It is
 | ||
| always up-to-date with the Nvim API, so its source code and test suite are
 | ||
| authoritative references.
 | ||
|     https://github.com/neovim/python-client
 | ||
| 
 | ||
| API client implementation guidelines ~
 | ||
| 
 | ||
|   - Separate the transport layer from the rest of the library. See
 | ||
|     |rpc-connecting| for details on how clients can connect to Nvim.
 | ||
|   - Use a MessagePack library that implements at least version 5 of the
 | ||
|     MessagePack spec, which supports the `bin` and `ext` types used by Nvim.
 | ||
|   - Read API metadata in order to create client-side wrappers for all
 | ||
|     msgpack-rpc methods.
 | ||
|   - Use a single-threaded event loop library/pattern.
 | ||
|   - Use a fiber/coroutine library for the language being used for implementing
 | ||
|     a client. These greatly simplify concurrency and allow the library to
 | ||
|     expose a blocking API on top of a non-blocking event loop without the
 | ||
|     complexity that comes with preemptive multitasking.
 | ||
|   - Don't assume anything about the order that responses to msgpack-rpc
 | ||
|     requests will arrive.
 | ||
|   - Clients should expect msgpack-rpc requests, which need to be handled
 | ||
|     immediately because Nvim is blocked while waiting for the client response.
 | ||
|   - Clients should expect to receive msgpack-rpc notifications, but these
 | ||
|     don't need to be handled immediately because they won't block Nvim
 | ||
|     (although they should probably be handled immediately anyway).
 | ||
| 
 | ||
| Note: Most of the complexity could be handled by a msgpack-rpc library that
 | ||
| supports server to client requests and notifications, but it's not clear if
 | ||
| this is part of the msgpack-rpc spec. At least the Ruby msgpack-rpc library
 | ||
| does not seem to support it:
 | ||
| https://github.com/msgpack-rpc/msgpack-rpc-ruby/blob/master/lib/msgpack/rpc/transport/tcp.rb#L150-L158
 | ||
| 
 | ||
| API metadata object ~
 | ||
| 
 | ||
| API clients exist to hide msgpack-rpc details. The API metadata object
 | ||
| contains information that makes this task easier (see also |rpc-types|):
 | ||
| 
 | ||
|   - The "version" key contains the Nvim version, API level, and API
 | ||
|     backwards-compatibility level.
 | ||
|   - The "functions" key contains a list of metadata objects for individual
 | ||
|     functions.
 | ||
|   - Each function metadata object has |rpc-types| information about the return
 | ||
|     value and parameters. These can be used for generating strongly-typed APIs
 | ||
|     in static languages.
 | ||
|   - Container types may be decorated with type/size constraints, e.g.
 | ||
|     ArrayOf(Buffer) or ArrayOf(Integer, 2). This can be useful to generate
 | ||
|     even more strongly-typed APIs.
 | ||
|   - Functions that are considered to be methods that operate on instances of
 | ||
|     Nvim special types (msgpack EXT) will have the `"method"` attribute set to
 | ||
|     `true`. The reciever type is the type of the first argument. The method
 | ||
|     names are prefixed with `nvim_` plus a shortened type name, e.g.
 | ||
|     `nvim_buf_get_lines` represents the `get_lines` method of a Buffer instance.
 | ||
|     - Global functions have `"method"` set to `false` and are prefixed with just
 | ||
|     `nvim_`, e.g. `nvim_get_buffers`.
 | ||
| 
 | ||
| So for an object-oriented language, an API client contains the classes
 | ||
| representing Nvim special types, and the methods of each class could be
 | ||
| defined by stripping the prefix for the type as defined in the `types` metadata
 | ||
| (this will always be the first two "_"-separated parts of the function name).
 | ||
| There could also be a singleton Vim class with methods where the `nvim_`
 | ||
| prefix is stripped off.
 | ||
| 
 | ||
| ==============================================================================
 | ||
| 5. Types							    *rpc-types*
 | ||
| 
 | ||
| The Nvim C API uses custom types for all functions. |api-types|
 | ||
| At the RPC layer, the types can be split into two groups:
 | ||
| 
 | ||
|   - Basic types that map natively to msgpack (and probably have a default
 | ||
|     representation in msgpack-supported programming languages)
 | ||
|   - Special Nvim types that map to msgpack EXT with custom type codes.
 | ||
| 
 | ||
| Basic types ~
 | ||
| 
 | ||
|   Nil                               -> msgpack nil
 | ||
|   Boolean                           -> msgpack boolean
 | ||
|   Integer (signed 64-bit integer)   -> msgpack integer
 | ||
|   Float (IEEE 754 double precision) -> msgpack float
 | ||
|   String                            -> msgpack string
 | ||
|   Array                             -> msgpack array
 | ||
|   Dictionary                        -> msgpack map
 | ||
| 
 | ||
| Special types (msgpack EXT) ~
 | ||
| 
 | ||
|   Buffer                            -> enum value kObjectTypeBuffer
 | ||
|   Window                            -> enum value kObjectTypeWindow
 | ||
|   Tabpage                           -> enum value kObjectTypeTabpage
 | ||
| 
 | ||
| API functions expecting one of the special EXT types may be passed an integer
 | ||
| instead, but not another EXT type. E.g. Buffer may be passed as an integer but
 | ||
| not as a Window or Tabpage. The EXT object data is the object id encoded as
 | ||
| a msgpack integer: For buffers this is the |bufnr()| and for windows the
 | ||
| |window-ID|. For tabpages the id is an internal handle, not the tabpage
 | ||
| number.
 | ||
| 
 | ||
| To determine the type codes of the special EXT types, inspect the `types` key
 | ||
| of the |api-metadata| at runtime. Example JSON representation: >
 | ||
| 
 | ||
|   "types": {
 | ||
|     "Buffer": {
 | ||
|       "id": 0,
 | ||
|       "prefix": "nvim_buf_"
 | ||
|     },
 | ||
|     "Window": {
 | ||
|       "id": 1,
 | ||
|       "prefix": "nvim_win_"
 | ||
|     },
 | ||
|     "Tabpage": {
 | ||
|       "id": 2,
 | ||
|       "prefix": "nvim_tabpage_"
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
| 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. Remote UIs					           *rpc-remote-ui*
 | ||
| 
 | ||
| GUIs can be implemented as external processes communicating with Nvim over the
 | ||
| RPC API. The UI model consists of a terminal-like grid with a single,
 | ||
| monospace font size. Some elements (UI "widgets") can be drawn separately from
 | ||
| the grid ("externalized").
 | ||
| 
 | ||
| After connecting to Nvim (usually a spawned, embedded instance) use the
 | ||
| |nvim_ui_attach| API method to tell Nvim that your program wants to draw the
 | ||
| Nvim screen on a grid of width × height cells. `options` must be
 | ||
| a dictionary with these (optional) keys:
 | ||
| 	`rgb`			Controls what color format to use.
 | ||
| 				Set to true (default) to use 24-bit rgb
 | ||
| 				colors.
 | ||
| 				Set to false to use terminal color codes (at
 | ||
| 				most 256 different colors).
 | ||
| 	`ext_popupmenu`		Externalize the popupmenu. |ui-ext-popupmenu|
 | ||
| 	`ext_tabline`		Externalize the tabline. |ui-ext-tabline|
 | ||
| 				Externalized widgets will not be drawn by
 | ||
| 				Nvim; only high-level data will be published
 | ||
| 				in new UI event kinds.
 | ||
| 
 | ||
| Nvim will then send msgpack-rpc notifications, with the method name "redraw"
 | ||
| and a single argument, an array of screen updates (described below).  These
 | ||
| should be processed in order. Preferably the user should only be able to see
 | ||
| the screen state after all updates in the same "redraw" event are processed
 | ||
| (not any intermediate state after processing only a part of the array).
 | ||
| 
 | ||
| Future versions of Nvim may add new update kinds and may append new parameters
 | ||
| to existing update kinds. Clients must be prepared to ignore such extensions
 | ||
| to be forward-compatible. |api-contract|
 | ||
| 
 | ||
| Screen updates are tuples whose first element is the string name of the update
 | ||
| kind.
 | ||
| 
 | ||
| ["resize", width, height]
 | ||
| 	The grid is resized to `width` and `height` cells.
 | ||
| 
 | ||
| ["clear"]
 | ||
| 	Clear the screen.
 | ||
| 
 | ||
| ["eol_clear"]
 | ||
| 	Clear from the cursor position to the end of the current line.
 | ||
| 
 | ||
| ["cursor_goto", row, col]
 | ||
| 	Move the cursor to position (row, col). Currently, the same cursor is
 | ||
| 	used to define the position for text insertion and the visible cursor.
 | ||
| 	However, only the last cursor position, after processing the entire
 | ||
| 	array in the "redraw" event, is intended to be a visible cursor
 | ||
| 	position.
 | ||
| 
 | ||
| ["update_fg", color]
 | ||
| ["update_bg", color]
 | ||
| ["update_sp", color]
 | ||
| 	Set the default foreground, background and special colors
 | ||
| 	respectively.
 | ||
| 
 | ||
| ["highlight_set", attrs]
 | ||
| 	Set the attributes that the next text put on the screen will have.
 | ||
| 	`attrs` is a dict with the keys below. Any absent key is reset
 | ||
| 	to its default value. Color defaults are set by the `update_fg` etc
 | ||
| 	updates. All boolean keys default to false.
 | ||
| 
 | ||
| 	`foreground`:	foreground color.
 | ||
| 	`background`:	backround color.
 | ||
| 	`special`:	color to use for underline and undercurl, when present.
 | ||
| 	`reverse`:	reverse video. Foreground and background colors are
 | ||
| 			switched.
 | ||
| 	`italic`:	italic text.
 | ||
| 	`bold`:		bold text.
 | ||
| 	`underline`:	underlined text. The line has `special` color.
 | ||
| 	`undercurl`:	undercurled text. The curl has `special` color.
 | ||
| 
 | ||
| ["put", text]
 | ||
| 	The (utf-8 encoded) string `text` is put at the cursor position
 | ||
| 	(and the cursor is advanced), with the highlights as set by the
 | ||
| 	last `highlight_set` update.
 | ||
| 
 | ||
| ["set_scroll_region", top, bot, left, right]
 | ||
| 	Define the scroll region used by `scroll` below.
 | ||
| 
 | ||
| ["scroll", count]
 | ||
| 	Scroll the text in the scroll region. The diagrams below illustrate
 | ||
| 	what will happen, depending on the scroll direction. "=" is used to
 | ||
| 	represent the SR(scroll region) boundaries and "-" the moved rectangles.
 | ||
| 	Note that dst and src share a common region.
 | ||
| 
 | ||
| 	If count is bigger than 0, move a rectangle in the SR up, this can
 | ||
| 	happen while scrolling down.
 | ||
| >
 | ||
| 		+-------------------------+
 | ||
| 		| (clipped above SR)      |            ^
 | ||
| 		|=========================| dst_top    |
 | ||
| 		| dst (still in SR)       |            |
 | ||
| 		+-------------------------+ src_top    |
 | ||
| 		| src (moved up) and dst  |            |
 | ||
| 		|-------------------------| dst_bot    |
 | ||
| 		| src (cleared)           |            |
 | ||
| 		+=========================+ src_bot
 | ||
| <
 | ||
| 	If count is less than zero, move a rectangle in the SR down, this can
 | ||
| 	happen while scrolling up.
 | ||
| >
 | ||
| 		+=========================+ src_top
 | ||
| 		| src (cleared)           |            |
 | ||
| 		|------------------------ | dst_top    |
 | ||
| 		| src (moved down) and dst|            |
 | ||
| 		+-------------------------+ src_bot    |
 | ||
| 		| dst (still in SR)       |            |
 | ||
| 		|=========================| dst_bot    |
 | ||
| 		| (clipped below SR)      |            v
 | ||
| 		+-------------------------+
 | ||
| <
 | ||
| ["set_title", title]
 | ||
| ["set_icon", icon]
 | ||
| 	Set the window title, and icon (minimized) window title, respectively.
 | ||
| 	In windowing systems not distinguishing between the two, "set_icon"
 | ||
| 	can be ignored.
 | ||
| 
 | ||
| ["mouse_on"]
 | ||
| ["mouse_off"]
 | ||
| 	Tells the client whether mouse support, as determined by |'mouse'|
 | ||
| 	option, is considered to be active in the current mode. This is mostly
 | ||
| 	useful for a terminal frontend, or other situations where nvim mouse
 | ||
| 	would conflict with other usages of the mouse. It is safe for a client
 | ||
| 	to ignore this and always send mouse events.
 | ||
| 
 | ||
| ["busy_on"]
 | ||
| ["busy_off"]
 | ||
| 	Nvim started or stopped being busy, and possibly not responsible to user
 | ||
| 	input. This could be indicated to the user by hiding the cursor.
 | ||
| 
 | ||
| ["suspend"]
 | ||
| 	|:suspend| command or |Ctrl-Z| mapping is used. A terminal client (or other
 | ||
| 	client where it makes sense) could suspend itself.  Other clients can
 | ||
| 	safely ignore it.
 | ||
| 
 | ||
| ["bell"]
 | ||
| ["visual_bell"]
 | ||
| 	Notify the user with an audible or visual bell, respectively.
 | ||
| 
 | ||
| ["update_menu"]
 | ||
| 	The menu mappings changed.
 | ||
| 
 | ||
| ["mode_info_set", cursor_style_enabled, mode_info]
 | ||
| `cursor_style_enabled` is a boolean indicating if the UI should set the cursor
 | ||
| style. `mode_info` is a list of mode property maps. The current mode is given
 | ||
| by the `mode_idx` field of the `mode_change` event.
 | ||
| 
 | ||
| Each mode property map may contain these keys:
 | ||
| 	KEY		DESCRIPTION ~
 | ||
| 	`cursor_shape`:	"block", "horizontal", "vertical"
 | ||
| 	`cell_percentage`: Cell % occupied by the cursor.
 | ||
| 	`blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|.
 | ||
| 	`hl_id`:	Cursor highlight group.
 | ||
| 	`hl_lm`:	Cursor highlight group if 'langmap' is active.
 | ||
| 	`short_name`:	Mode code name, see 'guicursor'.
 | ||
| 	`name`:		Mode descriptive name.
 | ||
| 	`mouse_shape`:	(To be implemented.)
 | ||
| 
 | ||
| Some keys are missing in some modes.
 | ||
| 
 | ||
| ["mode_change", mode, mode_idx]
 | ||
| The mode changed.  The first parameter `mode` is a string representing the
 | ||
| current mode. `mode_idx` is an index into the array received in the
 | ||
| `mode_info_set` event. UIs should change the cursor style according to the
 | ||
| properties specified in the corresponding item. The set of modes reported will
 | ||
| change in new versions of Nvim, for instance more submodes and temporary
 | ||
| states might be represented as separate modes.
 | ||
| 
 | ||
| 							*ui-ext-popupmenu*
 | ||
| ["popupmenu_show", items, selected, row, col]
 | ||
| 	When `popupmenu_external` is set to true, nvim will not draw the
 | ||
| 	popupmenu on the grid, instead when the popupmenu is to be displayed
 | ||
| 	this update is sent. `items` is an array of the items to show, the
 | ||
| 	items are themselves arrays of the form [word, kind, menu, info]
 | ||
| 	as defined at |complete-items|, except that `word` is replaced by
 | ||
| 	`abbr` if present.  `selected` is the initially selected item, either a
 | ||
| 	zero-based index into the array of items, or -1 if no item is
 | ||
| 	selected. `row` and `col` is the anchor position, where the first
 | ||
| 	character of the completed word will be.
 | ||
| 
 | ||
| ["popupmenu_select", selected]
 | ||
| 	An item in the currently displayed popupmenu is selected. `selected`
 | ||
| 	is either a zero-based index into the array of items from the last
 | ||
| 	`popupmenu_show` event, or -1 if no item is selected.
 | ||
| 
 | ||
| ["popupmenu_hide"]
 | ||
| 	The popupmenu is hidden.
 | ||
| 
 | ||
| 							*ui-ext-tabline*
 | ||
| ["tabline_update", curtab, tabs]
 | ||
| 	Tabline was updated. UIs should present this data in a custom tabline
 | ||
| 	widget.
 | ||
| 	curtab:	  Current Tabpage
 | ||
| 	tabs:	  List of Dicts [{ "tab": Tabpage, "name": String }, ...]
 | ||
| 
 | ||
| ==============================================================================
 | ||
|  vim:tw=78:ts=8:noet:ft=help:norl:
 | 
