-
-
Notifications
You must be signed in to change notification settings - Fork 136
Customization
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.
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.
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");
});
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");
});
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");
});
require([
'nbextensions/vim_binding/vim_binding',
], function() {
CodeMirror.Vim.map("<C-a>", "ggVG", "normal");
});
require([
'nbextensions/vim_binding/vim_binding',
], function() {
CodeMirror.Vim.map("Y", "yy", "normal");
});
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 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');
});
});
// 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;
}
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"});
});
// 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", {});
});
require(['base/js/namespace'], function(ns) {
ns.keyboard_manager.actions.call('jupyter-notebook:run-cell-and-insert-below');
});
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();
});
});
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');
});
});
Feel free to use this Wiki to share your tips