<neovim-editor>
Web Component
This component provides <neovim-editor>
, an HTML custom element built on Polymer and flux.
It provides a frontend for the Neovim editor using Neovim's MessagePack API. It allows you to easily embed a Neovim-backed editor
into your application.
This component assumes you have Node.js installed.
You can use this component for modern desktop application frameworks such as Electron or NW.js.
You can even use it in Electron-based editors such as Atom or VS Code.
This component is designed around the Flux architecture.
You can access the UI event notifications and can call Neovim APIs directly via <neovim-editor>
's APIs.
You can install this component as an npm package.
$ npm install neovim-component
Current supported nvim
version is v0.1.6 or later.
Examples
Each example only takes 100~300 lines.
Minimal Example
Minimal Electron app can be found in the example directory. This is a good start point to use this package and it shows how the component works.
How to run minimal example is:
$ git clone https://github.com/rhysd/neovim-component.git$ cd neovim-component$ npm start
Markdown Editor Example
For a more complicated and realistic example, see the markdown editor example. The markdown previewer is integrated with the Neovim GUI using the <neovim-editor>
component.
Image Popup Example
This is an image popup widget example here. The gi
mapping is defined to show an image under the cursor in a tooltip.
Mini Browser Example
This example shows how to include a mini web-browser using the <webview>
tag from Electron.
Why Did You Create This?
Vim has very powerful editing features, but Vim is an editor (see :help design-not
) and unfortunately lacks support for many graphical tools that writers and programmers like. NyaoVim adds support for graphical features without losing Vim's powerful text editing abilities. Neovim's msgpack APIs provide a perfect way to add a GUI layer using HTML and CSS. NyaoVim is a GUI frontend as a proof of concept.
Architecture
<neovim-editor>
has an editor
property to access the internal APIs of the component.
editor.screen
is a view of the component (using canvas). It receives user input and dispatches input actions to the data store.editor.process
is a process handler to interact with the backing Neovim process via msgpack-rpc APIs. You can call Neovim's APIs via the Neovim client (editor.getClient()
helper).editor.store
is the state of this component. You can access the current state of the editor through this object.
<neovim-editor>
Properties
You can customize <neovim-editor>
with the following properties:
Name | Description | Default |
---|---|---|
width |
Width of the editor in pixels. | null |
height |
Height of the editor in pixels. | null |
font |
Name of the editor's font. | "monospace" |
font-size |
Font-size in pixels. | 12 |
line-height |
Line height rate relative to font size. | 1.3 |
nvim-cmd |
Command used to start Neovim. | "nvim" |
argv |
Arguments passed with the Neovim command. | [] |
on-quit |
Callback function to run when Neovim quits. | null |
on-error |
Callback function for Neovim errors. | null |
disable-alt-key |
Do not send alt key input to Neovim. | false |
disable-meta-key |
Do not send meta key input to Neovim. | false |
cursor-draw-delay |
Delay in millisec before drawing cursor. | 10 |
no-blink-cursor |
Blink cursor or not. | false |
window-title |
Specify first window title. | "Neovim" |
<neovim-editor>
APIs
Receive internal various events
You can receive various events (including UI redraw notifications) from the store.
The store
is a part of flux architecture. It's a global instance of EventEmitter.
You can also access the state of editor via the store
. Note that all values are read only.
Do not change the values of the store
directly, it will break the internal state of the component.
const neovim_element = document;const Store = neovim_elementeditorstore; // Handle cursor movementsStore; // Handle mode changesStore; // Handle text redrawsStore; // Accessing the state of the editor.const bounds = Storesizelines Storesizecols ;const cursor_pos = Storecursorline Storecursorcol ;
Call Neovim APIs
You can call Neovim APIs via the client. When you call APIs via the client, it sends the call to the underlying Neovim process via MessagePack RPC and will return a Promise which resolves to the returned value.
<neovim-component>
uses promised-neovim-client package.
You can see the all API definitions here. If you know further about Neovim APIs, python client implementation may be helpful.
const neovim_element = document;const client = neovim_elementeditor; // Send a commandclient; // Send inputclientinput'<C-w><C-l>'; // Evaluate a Vimscript expressionclient; // Get the 'b:foo' variableclient ; // Query something (windows, buffers, etc.)// Move to the neighbor window and show its information.client ; // Receive an RPC request from Neovimclient;
Editor lifecycle
You can receive notifications related to lifecycle of the editor.
const neovim_element = document; // Called when the Neovim background process attachesneovim_elementeditor; // Called when the Neovim process is disconnected (usually by :quit)neovim_elementeditor; // Called when the <neovim-component> detachesneovim_elementeditor; // Called upon experiencing an error in the internal process neovim_elementeditor;
View APIs
- Resize screen
const editor = documenteditor;editorscreen; // Resize screen to 80 lines and 100 columnseditorscreen; // Resize screen to 1920px x 1080px
- Change font size
const editor = documenteditor;editorscreen; // Change font size to 18px
- Convert pixels to lines/cols.
const editor = documenteditor; const loc = editorscreen;console; // Coordinates in pixels of (line, col) = (80, 24) const pos = editorscreen;const.logpos.col pos.line; // line/col of location (400px, 300px)
- Notify of screen-size changes:
When some process has changed the screen-size you must notify the screen
. The internal <canvas>
element has a fixed size and must update itself if there are size changes. Call screen.checkShouldResize()
if the screen size may have changed
Note that you need not care about resize
event of <body>
element. <neovim-editor>
component automatically detects this particular resize event and updates automatically. screen.checkShouldResize()
will simply be ignored if nothing has actually changed.
const editor = documenteditor; { const e = document; // New element shows up! The screen may be resized by the change. // 'none' -> 'block' estyledisplay = 'block'; // This call tells to editor to adjust itself in the case that it has been resized editorscreen;}
Other APIs
- Setting arguments afterwards:
If your app doesn't use Polymer you can set arguments afterwards using JavaScript
Note that it is better to use argv
property of <neovim-element>
if possible.
const editor = documenteditor;editor;
- Focusing the editor
<neovim-editor>
is just a web-component, so it can be focused just like other elements.
If it loses focus the editor won't receive any input events.
The editor
instance has a method to re-focus the editor in JavaScript.
The store
instance contains the current focus state.
const editor = documenteditor;console;editorstore; // Refocus the editor to ensure it receives user input.editor;
Log Levels
<neovim-component>
prints logs in the browser console. The log level is controlled by the NODE_ENV
environment variable:
NODE_ENV=debug
will log everything.NODE_ENV=production
ignores all logs except for warnings and errors.- Setting
NODE_ENV
to empty string or some other value enables logging for info, warnings, and errors.