Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1e68350

Browse files
committed
alright, enough messing around, vimception!
in all of its ugly glory
0 parents  commit 1e68350

1 file changed

Lines changed: 323 additions & 0 deletions

File tree

vimception.js

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
2+
var cmd = IPython.keyboard_manager.command_shortcuts;
3+
var edit = IPython.keyboard_manager.edit_shortcuts;
4+
var def_cmd = IPython.default_command_shortcuts;
5+
var def_edit = IPython.default_edit_shortcuts;
6+
7+
// get the code mirror editor of a curently selected cell
8+
function C() { return IPython.notebook.get_selected_cell().code_mirror; };
9+
10+
// change the mode of all current and future CodeMirror instances
11+
function to(mode) {
12+
var mode = mode || 'vim'
13+
// first let's apply vim mode to all current cells
14+
function to_mode(c) { return c.code_mirror.setOption('keyMap', mode);};
15+
IPython.notebook.get_cells().map(to_mode);
16+
// apply the mode to future cells created
17+
IPython.Cell.options_default.cm_config.keyMap = mode;
18+
}
19+
20+
function getCSS(path) {
21+
$('<link/>', {
22+
rel: 'stylesheet',
23+
type: 'text/css',
24+
href: path,
25+
}).appendTo('head');
26+
}
27+
28+
29+
var p = "/static/components/codemirror/addon/";
30+
// Grab the CodeMirror vim keymap
31+
$.getScript("/static/components/codemirror/keymap/vim.js");
32+
33+
// also make search work
34+
$.getScript(p + "search/search.js");
35+
$.getScript(p + "search/searchcursor.js");
36+
// TODO: hook-up gq to perform a harwrap
37+
$.getScript(p + "wrap/hardwrap.js");
38+
$.getScript(p + "selection/active-line.js");
39+
//$.getScript("/static/components/codemirror/addon/
40+
// WARNING
41+
42+
$.getScript(p + "display/fullscreen.js");
43+
getCSS(p + "display/fullscreen.css");
44+
45+
getCSS(p + "dialog/dialog.css");
46+
$.getScript("static/components/codemirror/addon/dialog/dialog.js");
47+
48+
//$.getScript("/static/components/codemirror/addon/
49+
$.getScript(p + "fold/indent-fold.js");
50+
$.getScript(p + "fold/foldcode.js");
51+
$.getScript(p + "fold/foldgutter.js");
52+
53+
IPython.CodeCell.options_default.cm_config.foldGutter = true;
54+
IPython.CodeCell.options_default.cm_config.gutters = ["CodeMirror-linenumbers", "CodeMirror-foldgutter"];
55+
getCSS(p + "fold/foldgutter.css");
56+
57+
var p = "/static/components/codemirror/";
58+
//themes
59+
getCSS(p + "theme/tomorrow-night-eighties.css");
60+
getCSS(p + "theme/twilight.css");
61+
getCSS(p + "theme/vibrant-ink.css");
62+
63+
// on all code mirror instances on this page, apply the function f
64+
function all_cm(f) {
65+
// apply f to every code mirror instance. f takes one parameter
66+
IPython.notebook.get_cells().map(function (c) { f(c.code_mirror); } );
67+
}
68+
69+
70+
to('vim');
71+
function vim_up(event) {
72+
var cell = IPython.notebook.get_selected_cell();
73+
console.log('IPython "k" handler invoked')
74+
if (cell && cell.at_top() && cell.code_mirror.options.keyMap === 'vim') {
75+
console.log('inside the business logic k');
76+
event.preventDefault();
77+
IPython.notebook.command_mode()
78+
IPython.notebook.select_prev();
79+
IPython.notebook.edit_mode();
80+
return false;
81+
};
82+
}
83+
84+
function vim_down(event) {
85+
var cell = IPython.notebook.get_selected_cell();
86+
if (cell && cell.at_bottom() && cell.code_mirror.options.keyMap === 'vim') {
87+
event.preventDefault();
88+
IPython.notebook.command_mode()
89+
IPython.notebook.select_next();
90+
IPython.notebook.edit_mode();
91+
return false;
92+
};
93+
}
94+
95+
var m = '(vim) '
96+
var shortcuts = {
97+
'k' : {
98+
help : m + 'up a line, even across cells',
99+
help_index : 'AA',
100+
handler : vim_up
101+
},
102+
'j' : {
103+
help : m + 'down a line, even across cells',
104+
help_index : 'AA',
105+
handler : vim_down
106+
},
107+
};
108+
edit.add_shortcuts(shortcuts);
109+
//edit.add_shortcuts('k', def_edit['up'].handler);
110+
//edit.add_shortcut('j', def_edit['down'].handler);
111+
112+
// N.B. This code looks fairly simple, but it took me forever to
113+
// figure out how to do this,
114+
//
115+
// there's a problem here, Ctrl-[ is already handled by CodeMirror by the time we
116+
// (IPython.keyboard_manager) get it CodeMirror issues signals on mode change,
117+
// so we have to hook into that to get Ctrl-[
118+
edit.remove_shortcut('Ctrl+[');
119+
120+
CodeMirror.commands.leaveInsertOrEdit = function (cm) {
121+
if ( cm.state.vim.insertMode ) {
122+
// do magic here to get out of insert mode
123+
CodeMirror.keyMap['vim-insert']['Esc'](cm);
124+
} else {
125+
IPython.notebook.command_mode();
126+
IPython.notebook.focus_cell();
127+
}
128+
};
129+
130+
//C().options.extraKeys['Ctrl-['] = 'leaveInsertOrEdit';
131+
all_cm( function (cm) {
132+
cm.options.extraKeys['Ctrl-['] = 'leaveInsertOrEdit';
133+
if ( CodeMirror.defaults.extraKeys === null ) {
134+
CodeMirror.defaults.extraKeys = {};
135+
}
136+
// TODO: make this change permanent
137+
// this part seems to be ignore when adding a new cell
138+
// - alternative solution would be to listen for NewCell events and rerun the CM function on it
139+
// - it could also be the case that when we instatiate CodeMirror, we somehow leave out CM.defaults.extraKeys
140+
IPython.CodeCell.options_default.cm_config.extraKeys['Ctrl-['] = 'leaveInsertOrEdit';
141+
IPython.TextCell.options_default.cm_config.extraKeys['Ctrl-['] = 'leaveInsertOrEdit';
142+
})
143+
144+
// On blur, make sure we go back to command mode for CodeMirror (in case user clicked away)
145+
// TODO: Make this permanent - how to get CodeMirror to do this for new cells created after
146+
all_cm( function (cm) {
147+
cm.on('blur', function(cm) {
148+
// TODO: I wish I understood a better way to do this, but fake pressing Escape work
149+
CodeMirror.keyMap['vim-insert']['Esc'](cm);
150+
CodeMirror.keyMap['vim']['Esc'](cm);
151+
cm.setOption('styleActiveLine', false);
152+
});
153+
cm.on('focus', function(cm) {
154+
cm.setOption('styleActiveLine', true);
155+
});
156+
});
157+
158+
// 'i' by default interrupts the kernel (what Ctrl-C does at the terminal)
159+
cmd.remove_shortcut('i');
160+
cmd.add_shortcut('i', def_cmd.enter);
161+
162+
// not quite what we want - 'i' requires a double-tap
163+
// add documentation for this.
164+
cmd.add_shortcut('ctrl+c', function(e) { IPython.notebook.kernel.interrupt(); return false});
165+
166+
167+
function focus_last(e) {
168+
var cells = IPython.notebook.get_cells();
169+
cells[cells.length-1].focus_cell();
170+
};
171+
172+
function focus_first(e) {
173+
console.log('focus first called');
174+
var cells = IPython.notebook.get_cells();
175+
cells[0].focus_cell();
176+
};
177+
178+
function combo_tap(combo, action) {
179+
var that = this;
180+
function f() {
181+
console.log('f called once');
182+
183+
// redo this so that when an action is performed, we restore the original combo
184+
cmd.add_shortcut(combo[1], action);
185+
setTimeout(function () {
186+
console.log('resetting f');
187+
reset();
188+
//cmd.add_shortcut(combo[0], reset)
189+
}, 800);
190+
}
191+
function reset(e) {
192+
console.log('reset called');
193+
//that(combo, action);
194+
cmd.add_shortcut(combo[0], f);
195+
}
196+
197+
reset();
198+
};
199+
cmd.add_shortcut('shift+g', focus_last);
200+
combo_tap('gg', focus_first);
201+
202+
// cut
203+
combo_tap('dd', def_cmd['x']);
204+
205+
// copy
206+
combo_tap('yy', def_cmd['c']);
207+
208+
// paste
209+
cmd.add_shortcut('p', def_cmd['v']);
210+
211+
// undo
212+
cmd.add_shortcut('u', def_cmd['z']);
213+
214+
// Join (merge down with cell below)
215+
cmd.add_shortcut('shift+j', def_cmd['shift+m'])
216+
217+
//edit.add_shortcut('k', def_edit['up'].handler);
218+
//[edit.add_shortcut('j', def_edit['down'].handler);
219+
edit.remove_shortcut('ctrl+[');
220+
221+
CodeMirror.prototype.save = function() {
222+
IPython.notebook.save_checkpoint()
223+
}
224+
225+
function focus_last(e) {
226+
var cells = IPython.notebook.get_cells();
227+
cells[cells.length-1].focus_cell();
228+
};
229+
230+
function focus_first(e) {
231+
console.log('focus first called');
232+
var cells = IPython.notebook.get_cells();
233+
cells[0].focus_cell();
234+
};
235+
236+
function combo_tap(combo, action) {
237+
var that = this;
238+
function f() {
239+
console.log('f called once');
240+
setTimeout(function () {
241+
console.log('resetting f');
242+
// this wasn't a double tap, so maybe do the default action for the single key, if there was one
243+
def_cmd[combo[0]].handler();
244+
reset();
245+
//cmd.add_shortcut(combo[0], reset)
246+
}, 800);
247+
cmd.add_shortcut(combo[1], action);
248+
}
249+
function reset(e) {
250+
console.log('reset called');
251+
//that(combo, action);
252+
cmd.add_shortcut(combo[0], f);
253+
}
254+
255+
reset();
256+
};
257+
258+
cmd.add_shortcut('shift+g', focus_last);
259+
combo_tap('gg', focus_first);
260+
261+
// get rid of the default Ctrl-W binding
262+
// this only works for Firefox
263+
$(document).ready(function() {
264+
$(this).bind('keypress', function(e) {
265+
var key = (e.keyCode ? e.keyCode : e.charCode);
266+
if (key == '119' && e.ctrlKey) {
267+
return false;
268+
}
269+
});
270+
});
271+
272+
window.addEventListener("beforeunload", function( event ) {
273+
var press = jQuery.Event("keypress");
274+
press.ctrlKey = false;
275+
press.which = 27; // escape
276+
$(document).trigger(press);
277+
event.returnValue = "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
278+
event.returnValue +="\nX Chrome sucks at captruring Ctrl-W, sorry X";
279+
event.returnValue += "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
280+
});
281+
282+
// update the keyboard shortcuts
283+
IPython.quick_help = new IPython.QuickHelp();
284+
285+
//IPython.CodeCell.options_default.cm_config.styleActiveLine = true;
286+
287+
all_cm( function (cm) {
288+
cm.setOption('foldGutter', true);
289+
cm.setOption('gutters', ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]);
290+
cm.options.extraKeys["Ctrl-F"] = function(cm){ cm.foldCode(cm.getCursor()); },
291+
cm.options.extraKeys["Ctrl-F"] = function(cm) { cm.setOption("fullScreen", !cm.getOption("fullScreen"))};
292+
IPython.CodeCell.options_default.cm_config.extraKeys['Ctrl-F'] = function(cm){ cm.foldCode(cm.getCursor()); };
293+
IPython.TextCell.options_default.cm_config.extraKeys['Ctrl-F'] = function(cm){ cm.foldCode(cm.getCursor()); };
294+
295+
// todo - do this for new cells as well
296+
cm.setOption('theme', "tomorrow-night-eighties");
297+
// support this a :only? turn off full screen on blur
298+
cm.options.extraKeys["F11"] = function(cm) { cm.setOption("fullScreen", !cm.getOption("fullScreen"))};
299+
cm.options.extraKeys["Esc"] = function(cm) {
300+
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
301+
};
302+
cm.options.extraKeys["Ctrl-A"] = function(cm) {
303+
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
304+
};
305+
//all_cm( function (cm) {
306+
cm.on('blur',function(cm) {
307+
if (cm.getOption("fullScreen")) {
308+
cm.setOption('fullScreen', false);
309+
// fullScreen the newly selected code mirror (doesn't work)
310+
//setTimeout(100, function() {
311+
// console.log(IPython.notebook.get_selected_cell().code_mirror);
312+
// IPython.notebook.get_selected_cell().code_mirror.setOption('fullScreen', true);
313+
//});
314+
}
315+
});
316+
});
317+
318+
setTimeout(200, function() {IPython.notebook.get_selected_cell().set_input_prompt('vim');})
319+
320+
$("#ipython_notebook").append('<img src="http://www.vim.org/images/vim_on_fire.gif" style="'
321+
+ 'position: absolute; left: 51px; top: -10px; height: initial;">');
322+
323+

0 commit comments

Comments
 (0)