mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-03 17:24:29 +00:00 
			
		
		
		
	use set_cursor_shape_bar for cmdline mode fix test of screen_basic_spec.lua & screen.lua comment fix
		
			
				
	
	
		
			418 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			418 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
*msgpack_rpc.txt*							{Nvim}
 | 
						|
 | 
						|
 | 
						|
		 NVIM REFERENCE MANUAL    by Thiago de Arruda
 | 
						|
 | 
						|
 | 
						|
RPC API for Nvim				     *RPC* *rpc* *msgpack-rpc*
 | 
						|
 | 
						|
1. Introduction			|rpc-intro|
 | 
						|
2. API mapping			|rpc-api|
 | 
						|
3. Connecting			|rpc-connecting|
 | 
						|
4. Clients			|rpc-api-client|
 | 
						|
5. Types			|rpc-types|
 | 
						|
6. Remote UIs			|rpc-remote-ui|
 | 
						|
 | 
						|
==============================================================================
 | 
						|
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|
 | 
						|
For the purpose of mapping to msgpack, 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
 | 
						|
 | 
						|
An API method expecting one of these types may be passed an integer instead,
 | 
						|
although they are not interchangeable. For example, a Buffer may be passed as
 | 
						|
an integer, but not a Window or Tabpage.
 | 
						|
 | 
						|
The most reliable way of determining the type codes for the special Nvim types
 | 
						|
is to inspect the `types` key of metadata dictionary returned by the
 | 
						|
`nvim_get_api_info` method at runtime. Here's a sample JSON representation of
 | 
						|
the `types` object:
 | 
						|
>
 | 
						|
  "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*
 | 
						|
 | 
						|
Nvim allows Graphical user interfaces to be implemented by separate processes
 | 
						|
communicating with Nvim over the RPC API. Currently the ui model conists of a
 | 
						|
terminal-like grid with one single, monospace font size, with a few elements
 | 
						|
that could be drawn separately from the grid (for the momemnt only the popup
 | 
						|
menu)
 | 
						|
 | 
						|
After connecting to a nvim instance (typically a spawned, embedded instance)
 | 
						|
use the |nvim_ui_attach|(width, height, options) API method to tell nvim that your
 | 
						|
program wants to draw the nvim screen on a grid with "width" times
 | 
						|
"height" cells. "options" should be a dictionary with the following (all
 | 
						|
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).
 | 
						|
	`popupmenu_external`:	Instead of drawing the completion popupmenu on
 | 
						|
				the grid, Nvim will send higher-level events to
 | 
						|
				the ui and let it draw the popupmenu.
 | 
						|
				Defaults to false.
 | 
						|
 | 
						|
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 are processed (not any intermediate
 | 
						|
state after processing only a part of the array).
 | 
						|
 | 
						|
Screen updates are arrays. The first element a string describing the kind
 | 
						|
of update.
 | 
						|
 | 
						|
["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_change", mode]
 | 
						|
	The mode changed. Currently sent when "insert", "replace", "cmdline" and
 | 
						|
	"normal" modes are entered. A client could for instance change the cursor
 | 
						|
	shape.
 | 
						|
 | 
						|
["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.
 | 
						|
 | 
						|
==============================================================================
 | 
						|
 vim:tw=78:ts=8:noet:ft=help:norl:
 |