Skip to content
This repository was archived by the owner on Aug 22, 2023. It is now read-only.

Customization

Jimmy Liu edited this page May 31, 2018 · 18 revisions

This wiki is a place to share snippets that enhance the usability of the vim - IPython integration, but aren't so general that they are part of the binding.

Disable automatic insertion of closing brackets and quotes

Jupyter automatically pairs the delimiters ( [ { ' " when typed in code cells. Add the following to ~/.jupyter/custom/custom.js to disable this feature:

IPython.CodeCell.options_default.cm_config.autoCloseBrackets = false;

See https://codemirror.net/doc/manual.html#addon_closebrackets for a complete description of this option.

Swap j/k and gj/gk

require([ 'nbextensions/vim_binding/vim_binding', // depends your installation ], function() { // Swap j/k and gj/gk (Note that <Plug> mappings) CodeMirror.Vim.map("j", "<Plug>(vim-binding-gj)", "normal"); CodeMirror.Vim.map("k", "<Plug>(vim-binding-gk)", "normal"); CodeMirror.Vim.map("gj", "<Plug>(vim-binding-j)", "normal"); CodeMirror.Vim.map("gk", "<Plug>(vim-binding-k)", "normal"); });

Emacs like binding in Insert Mode

require([ 'nbextensions/vim_binding/vim_binding', ], function() { // Emacs like binding CodeMirror.Vim.map("<C-a>", "<Esc>^i", "insert"); CodeMirror.Vim.map("<C-e>", "<Esc>$a", "insert"); //CodeMirror.Vim.map("<C-f>", "<Esc>lwi", "insert"); // This seems more likely to M-f (move forward one word) //CodeMirror.Vim.map("<C-b>", "<Esc>lbi", "insert"); // This seems more likely to M-b (move backward one word) CodeMirror.Vim.map("<C-f>", "<Esc>2li", "insert"); CodeMirror.Vim.map("<C-b>", "<Esc>i", "insert"); CodeMirror.Vim.map("<C-d>", "<Esc>lxi", "insert"); CodeMirror.Vim.map("<C-h>", "<Esc>xi", "insert"); });

Move around in Insert mode with Ctrl-h/j/k/l

require([ 'nbextensions/vim_binding/vim_binding', ], function() { // Use Ctrl-h/l/j/k to move around in Insert mode CodeMirror.Vim.defineAction('[i]<C-h>', function(cm) { var head = cm.getCursor(); CodeMirror.Vim.handleKey(cm, '<Esc>'); if (head.ch <= 1) { CodeMirror.Vim.handleKey(cm, 'i'); } else { CodeMirror.Vim.handleKey(cm, 'h'); CodeMirror.Vim.handleKey(cm, 'a'); } }); CodeMirror.Vim.defineAction('[i]<C-l>', function(cm) { var head = cm.getCursor(); CodeMirror.Vim.handleKey(cm, '<Esc>'); if (head.ch === 0) { CodeMirror.Vim.handleKey(cm, 'a'); } else { CodeMirror.Vim.handleKey(cm, 'l'); CodeMirror.Vim.handleKey(cm, 'a'); } }); CodeMirror.Vim.mapCommand("<C-h>", "action", "[i]<C-h>", {}, { "context": "insert" }); CodeMirror.Vim.mapCommand("<C-l>", "action", "[i]<C-l>", {}, { "context": "insert" }); CodeMirror.Vim.map("<C-j>", "<Esc>ja", "insert"); CodeMirror.Vim.map("<C-k>", "<Esc>ka", "insert"); // Use Ctrl-h/l/j/k to move around in Normal mode // otherwise it would trigger browser shortcuts CodeMirror.Vim.map("<C-h>", "h", "normal"); CodeMirror.Vim.map("<C-l>", "l", "normal"); // Updated for v2.0.0 // While jupyter-vim-binding use <C-j>/<C-k> to move around cell // The following key mappings should not be defined //CodeMirror.Vim.map("<C-j>", "j", "normal"); //CodeMirror.Vim.map("<C-k>", "k", "normal"); });

Selecting all

require([ 'nbextensions/vim_binding/vim_binding', ], function() { CodeMirror.Vim.map("<C-a>", "ggVG", "normal"); });

Map Y to yy in insert mode

require([ 'nbextensions/vim_binding/vim_binding', ], function() { CodeMirror.Vim.map("Y", "yy", "normal"); });

Enable <C-c> mapping to exit insert mode

The default configuration adds a setting to ignore the chord. The following code removes that setting and provides a mapping.

// enable the 'Ctrl-C' mapping // change the code mirror configuration var cm_config = require("notebook/js/cell").Cell.options_default.cm_config; delete cm_config.extraKeys['Ctrl-C']; // change settings for existing cells Jupyter.notebook.get_cells().map(function(cell) { var cm = cell.code_mirror; if (cm) { delete cm.getOption('extraKeys')['Ctrl-C']; } }); // map the keys CodeMirror.Vim.map("<C-c>", "<Esc>", "insert");

Run cell scrolls the cell to top (scroll output into view)

// Run and scroll to top Jupyter.keyboard_manager.actions.register({ 'help': 'run selected cells', 'handler': function(env, event) { env.notebook.command_mode(); var actions = Jupyter.keyboard_manager.actions; actions.call('jupyter-notebook:run-cell', event, env); actions.call('jupyter-notebook:scroll-cell-top', event, env); env.notebook.edit_mode(); } }, 'run-and-top', 'vim-binding'); // Run and scroll to top and select next Jupyter.keyboard_manager.actions.register({ 'help': 'run selected cells', 'handler': function(env, event) { env.notebook.command_mode(); var actions = Jupyter.keyboard_manager.actions; actions.call('jupyter-notebook:run-cell', event, env); actions.call('jupyter-notebook:scroll-cell-top', event, env); actions.call('jupyter-notebook:select-next-cell', event, env); env.notebook.edit_mode(); } }, 'run-and-next-and-top', 'vim-binding'); // Add two keyboard shortcuts for the new actions require([ 'nbextensions/vim_binding/vim_binding', 'base/js/namespace', ], function(vim_binding, ns) { // Add post callback vim_binding.on_ready_callbacks.push(function(){ var km = ns.keyboard_manager; // Indicate the key combination to run the commans km.edit_shortcuts.add_shortcut('ctrl-enter', 'vim-binding:run-and-top', true); km.edit_shortcuts.add_shortcut('shift-enter', 'vim-binding:run-and-next-and-top', true); // Update Help km.edit_shortcuts.events.trigger('rebuild.QuickHelp'); }); });

Show trailing spaces

// custom.js require([ 'base/js/namespace', 'notebook/js/cell', 'codemirror/addon/edit/trailingspace' ], function(ns, cell) { var cm_config = cell.Cell.options_default.cm_config; cm_config.showTrailingSpace = true; ns.notebook.get_cells().map(function(cell) { var cm = cell.code_mirror; if (cm) { cm.setOption('showTrailingSpace', true); } }); });
/* custom.css */ .cm-trailingspace { border-bottom: 1px solid #ccc; }

Adding custom actions

require(['codemirror/keymap/vim'], function() { // a CodeMirror.Vim.defineAction("hello", function(){console.log("hello")}); // 'a' is the key you map the action to CodeMirror.Vim.mapCommand("a", "action", "hello", {}, {context: "normal"}); });

Adding custom operators

// custom operator for commenting // (similar to commentary by Tim Pope) // this woks with visual selection ('vipgc') and with motions ('gcip') require(['nbextensions/vim_binding/vim_binding'], function() { CodeMirror.Vim.defineOperator("comment_op", function(cm) { cm.toggleComment(); }); CodeMirror.Vim.mapCommand("gc", "operator", "comment_op", {}); });

Calling a Jupyter shortcut

require(['base/js/namespace'], function(ns) { ns.keyboard_manager.actions.call('jupyter-notebook:run-cell-and-insert-below'); });

Using :q to leave Vim mode and re-enter Jupyter mode

require([ 'base/js/namespace', 'codemirror/keymap/vim', 'nbextensions/vim_binding/vim_binding' ], function(ns) { CodeMirror.Vim.defineEx("quit", "q", function(cm){ ns.notebook.command_mode(); ns.notebook.focus_cell(); }); });

Use Ctrl + s to save in Vim normal and insert mode

require([ 'nbextensions/vim_binding/vim_binding', 'base/js/namespace', ], function(vim_binding, ns) { // Add post callback vim_binding.on_ready_callbacks.push(function(){ var km = ns.keyboard_manager; // Indicate the key combination to run the commands km.edit_shortcuts.add_shortcut('ctrl-s', 'jupyter-notebook:save-notebook', true); // Update Help km.edit_shortcuts.events.trigger('rebuild.QuickHelp'); }); });

Define Ctrl+[ as a synonym for Esc (for leaving insert mode to normal mode, and leaving normal mode to Jupyter mode)

This synonym is a useful and popular way to reduce how far your hands must go from home row (see here and here). It is set up by default in most terminals, and for gVim, a mapping was set up specifically to reproduce the terminal behavior.

require([ 'nbextensions/vim_binding/vim_binding', 'base/js/namespace', ], function(vim_binding, ns) { // Add post callback vim_binding.on_ready_callbacks.push(function(){ var km = ns.keyboard_manager; // Indicate the key combination to run the commands km.edit_shortcuts.add_shortcut('ctrl-[', CodeMirror.prototype.leaveInsertMode, true); km.edit_shortcuts.add_shortcut('shift-ctrl-[', CodeMirror.prototype.leaveNormalMode, true); // Update help km.edit_shortcuts.events.trigger('rebuild.QuickHelp'); }); });

Powerful resources