Adds vim bindings to nodejs readline.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

readline-vim build status

Adds vim bindings to nodejs readline.


npm install readline-vim


Repl Example:

var rlv = require('readline-vim')
  , repl = require('repl');

var r = repl.start({
    prompt: "vim repl > ",
    input: process.stdin,
    output: process.stdout

// pass the readline component of the repl in order to add vim bindings to it
var vim = rlv(r.rli)
  , map =;

// Add mappings

// [insert mode] allow switching to normal mode by typing 'jk' quickly 
map.insert('jk', 'esc');

// [insert mode] go backward in history via 'ctrl-k' 
map.insert('ctrl-k', 'ctrl-p');

// [insert mode] go backward in history via 'ctrl-k' 
map.insert('ctrl-space', 'ctrl-n');

// [normal mode] go backward in history via space bar
map.normal('space', 'k');

// [normal mode] go forward in history via space bar when ctrl is pressed 
map.normal('ctrl-space', 'j');

Run it via: npm run demo

Table of Contents generated with DocToc

Vim Bindings

A subset of vim keybindings is supported by readline-vim:

Insert Mode

  • Esc, Ctrl-[: normal mode

Normal Mode

  • i, I, a, A: insert mode with the expected side effects


  • h cursor left
  • l cursor right
  • w word right
  • b word left
  • 0 beginning of line
  • $ end of line
  • f, F, t, T followed by letter moves cursor to or up to the given letter

Movements combined with Actions

  • cb: change word left

  • cw: change word right

  • ch: change left

  • cl: change right

  • cc: change line

  • C : change line right

  • db: delete word left

  • dw: delete word right

  • dh: delete left

  • dl: delete right

  • dd: delete line

  • D : delete line right

  • x delete right

  • X delete left


  • r followed by letter replaces letter under the cursor with the given letter (i.e. rx)


  • k go back in history
  • j go forward in history


Immediate Mappings

Immediate mappings execute immediately whe a key (possibly with modifiers) is pressed.

They can be applied in insert and normal mode.

Assuming we defined vim and map as outlined in the usage examle.

// emit [esc] when [ctrl-space] is pressed to switch to normal mode
map.insert('ctrl-space', 'esc');

// emit [k] when [space] is pressed to go backward in history
map.normal('space', 'k');

Sequence Mappings

Sequence mappings are a number of keys without modifiers pressed quickly after another.

They can be applied to insert mode only.

Assuming we defined vim and map as outlined in the usage examle.

// map [jk] pressed in quick succession to [esc] to switch to normal mode
map.insert('jk', 'esc');

The interval allowed between keys in order to count as a sequence can be configured by setting vim.threshold, the default is 200 milliseconds.

Inspecting Mappings

You can inspect your mappings by navigating/printing the object.


The following events are emitted to allow reacting to state changes:

  • normal when mode changes to normal
  • insert when mode changes to insert
  • write when a key is written to the underlying readline (i.e. it wasn't handled by readline-vim and therefore passed through

These events are exposed via, so to subscribe to normal mode changes you would do:'normal', function () {
  // do something here to react

Forcing the Readline into a Mode

You can cause the readline to change to a particular mode and pass a Boolean to indicate if that mode change should be kept a secret (i.e. no event is emitted).

vim.forceInsert();      // changes mode to insert and emits 'insert' event
vim.forceNormal(true);  // changes mode to normal, but emits no event