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

Commit c2cfd73

Browse files
committed
Add quickhelp for jupyter-vim-binding
1 parent 4c280f6 commit c2cfd73

File tree

2 files changed

+300
-0
lines changed

2 files changed

+300
-0
lines changed

lib/jupyter/quickhelp.js

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
define([
2+
'base/js/utils',
3+
'base/js/dialog',
4+
'underscore',
5+
'notebook/js/quickhelp'
6+
], function(utils, dialog, _, quickhelp) {
7+
"use strict";
8+
var exports = {};
9+
exports.attach = function attach() {
10+
// Copyright (c) Jupyter Development Team.
11+
// Distributed under the terms of the Modified BSD License.
12+
var platform = utils.platform;
13+
14+
// Override Jupyter's QuickHelp class
15+
var cmd_ctrl = 'Ctrl-';
16+
var platform_specific;
17+
18+
if (platform === 'MacOS') {
19+
// Mac OS X specific
20+
cmd_ctrl = 'Cmd-';
21+
platform_specific = [
22+
{ shortcut: "Cmd-Up", help:"go to cell start" },
23+
{ shortcut: "Cmd-Down", help:"go to cell end" },
24+
{ shortcut: "Alt-Left", help:"go one word left" },
25+
{ shortcut: "Alt-Right", help:"go one word right" },
26+
{ shortcut: "Alt-Backspace", help:"delete word before" },
27+
{ shortcut: "Alt-Delete", help:"delete word after" },
28+
];
29+
} else {
30+
// PC specific
31+
platform_specific = [
32+
{ shortcut: "Ctrl-Home", help:"go to cell start" },
33+
{ shortcut: "Ctrl-Up", help:"go to cell start" },
34+
{ shortcut: "Ctrl-End", help:"go to cell end" },
35+
{ shortcut: "Ctrl-Down", help:"go to cell end" },
36+
{ shortcut: "Ctrl-Left", help:"go one word left" },
37+
{ shortcut: "Ctrl-Right", help:"go one word right" },
38+
{ shortcut: "Ctrl-Backspace", help:"delete word before" },
39+
{ shortcut: "Ctrl-Delete", help:"delete word after" },
40+
];
41+
}
42+
43+
var cm_shortcuts = [
44+
{ shortcut: "Ctrl-n", help:"code completion forward" },
45+
{ shortcut: "Ctrl-p", help:"code completion backward" },
46+
{ shortcut: "Ctrl-g", help:"tooltip" },
47+
{ shortcut: ">>", help:"indent" },
48+
{ shortcut: "<<", help:"dedent" },
49+
{ shortcut: "ggVG", help:"select all" },
50+
{ shortcut: "u", help:"undo" },
51+
{ shortcut: "Ctrl-R", help:"redo" },
52+
].concat( platform_specific );
53+
54+
var mac_humanize_map = {
55+
// all these are unicode, will probably display badly on anything except macs.
56+
// these are the standard symbol that are used in MacOS native menus
57+
// cf http://apple.stackexchange.com/questions/55727/
58+
// for htmlentities and/or unicode value
59+
'cmd':'⌘',
60+
'shift':'⇧',
61+
'alt':'⌥',
62+
'up':'↑',
63+
'down':'↓',
64+
'left':'←',
65+
'right':'→',
66+
'eject':'⏏',
67+
'tab':'⇥',
68+
'backtab':'⇤',
69+
'capslock':'⇪',
70+
'esc':'esc',
71+
'ctrl':'⌃',
72+
'enter':'↩',
73+
'pageup':'⇞',
74+
'pagedown':'⇟',
75+
'home':'↖',
76+
'end':'↘',
77+
'altenter':'⌤',
78+
'space':'␣',
79+
'delete':'⌦',
80+
'backspace':'⌫',
81+
'apple':'',
82+
};
83+
84+
var default_humanize_map = {
85+
'shift':'Shift',
86+
'alt':'Alt',
87+
'up':'Up',
88+
'down':'Down',
89+
'left':'Left',
90+
'right':'Right',
91+
'tab':'Tab',
92+
'capslock':'Caps Lock',
93+
'esc':'Esc',
94+
'ctrl':'Ctrl',
95+
'enter':'Enter',
96+
'pageup':'Page Up',
97+
'pagedown':'Page Down',
98+
'home':'Home',
99+
'end':'End',
100+
'space':'Space',
101+
'backspace':'Backspace',
102+
'-':'Minus'
103+
};
104+
105+
var humanize_map;
106+
107+
if (platform === 'MacOS'){
108+
humanize_map = mac_humanize_map;
109+
} else {
110+
humanize_map = default_humanize_map;
111+
}
112+
113+
var special_case = { pageup: "PageUp", pagedown: "Page Down" };
114+
115+
function humanize_key(key){
116+
if (key.length === 1){
117+
return key.toUpperCase();
118+
}
119+
120+
key = humanize_map[key.toLowerCase()]||key;
121+
122+
if (key.indexOf(',') === -1){
123+
return ( special_case[key] ? special_case[key] : key.charAt(0).toUpperCase() + key.slice(1) );
124+
}
125+
}
126+
127+
// return an **html** string of the keyboard shortcut
128+
// for human eyes consumption.
129+
// the sequence is a string, comma sepparated linkt of shortcut,
130+
// where the shortcut is a list of dash-joined keys.
131+
// Each shortcut will be wrapped in <kbd> tag, and joined by comma is in a
132+
// sequence.
133+
//
134+
// Depending on the platform each shortcut will be normalized, with or without dashes.
135+
// and replace with the corresponding unicode symbol for modifier if necessary.
136+
function humanize_sequence(sequence){
137+
var joinchar = ',';
138+
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), humanize_shortcut).join(joinchar);
139+
return hum;
140+
}
141+
142+
function _humanize_sequence(sequence){
143+
var joinchar = ',';
144+
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), _humanize_shortcut).join(joinchar);
145+
return hum;
146+
}
147+
148+
function _humanize_shortcut(shortcut){
149+
var joinchar = '-';
150+
if (platform === 'MacOS'){
151+
joinchar = '';
152+
}
153+
return _.map(shortcut.split('-'), humanize_key ).join(joinchar);
154+
}
155+
156+
function humanize_shortcut(shortcut){
157+
return '<kbd>'+_humanize_shortcut(shortcut)+'</kbd>';
158+
}
159+
160+
161+
quickhelp.QuickHelp.prototype.show_keyboard_shortcuts = function () {
162+
/**
163+
* toggles display of keyboard shortcut dialog
164+
*/
165+
var that = this;
166+
if ( this.force_rebuild ) {
167+
this.shortcut_dialog.remove();
168+
delete(this.shortcut_dialog);
169+
this.force_rebuild = false;
170+
}
171+
if ( this.shortcut_dialog ){
172+
// if dialog is already shown, close it
173+
$(this.shortcut_dialog).modal("toggle");
174+
return;
175+
}
176+
var command_shortcuts = this.keyboard_manager.command_shortcuts.help();
177+
var edit_shortcuts = this.keyboard_manager.edit_shortcuts.help();
178+
var help, shortcut;
179+
var i, half, n;
180+
var element = $('<div/>');
181+
182+
// The documentation
183+
var doc = $('<div/>').addClass('alert alert-info');
184+
doc.append(
185+
'The Jupyter Notebook with jupyter-vim-binding has two different keyboard input modes.' +
186+
'<b>Jupyter mode</b> binds the keyboard to notebook level commands and is indicated by a grey cell border with a blue left margin.' +
187+
'<b>Vim command mode</b> allows you to type code/text into a cell and is indicated by a green cell border.'
188+
);
189+
element.append(doc);
190+
if (platform === 'MacOS') {
191+
doc = $('<div/>').addClass('alert alert-info');
192+
var key_div = this.build_key_names();
193+
doc.append(key_div);
194+
element.append(doc);
195+
}
196+
197+
// Command mode
198+
var cmd_div = this.build_command_help();
199+
element.append(cmd_div);
200+
201+
// Edit mode
202+
var edit_div = this.build_edit_help(cm_shortcuts);
203+
element.append(edit_div);
204+
205+
this.shortcut_dialog = dialog.modal({
206+
title : "Keyboard shortcuts",
207+
body : element,
208+
destroy : false,
209+
buttons : {
210+
Close : {}
211+
},
212+
notebook: this.notebook,
213+
keyboard_manager: this.keyboard_manager,
214+
});
215+
this.shortcut_dialog.addClass("modal_stretch");
216+
217+
this.events.on('rebuild.QuickHelp', function() { that.force_rebuild = true;});
218+
};
219+
220+
quickhelp.QuickHelp.prototype.build_key_names = function () {
221+
var key_names_mac = [
222+
{ shortcut:"⌘", help:"Command" },
223+
{ shortcut:"⌃", help:"Control" },
224+
{ shortcut:"⌥", help:"Option" },
225+
{ shortcut:"⇧", help:"Shift" },
226+
{ shortcut:"↩", help:"Return" },
227+
{ shortcut:"␣", help:"Space" },
228+
{ shortcut:"⇥", help:"Tab" }];
229+
var i, half, n;
230+
var div = $('<div/>').append('Mac OS X modifier keys:');
231+
var sub_div = $('<div/>').addClass('container-fluid');
232+
var col1 = $('<div/>').addClass('col-md-6');
233+
var col2 = $('<div/>').addClass('col-md-6');
234+
n = key_names_mac.length;
235+
half = ~~(n/2);
236+
for (i=0; i<half; i++) { col1.append(
237+
build_one(key_names_mac[i])
238+
); }
239+
for (i=half; i<n; i++) { col2.append(
240+
build_one(key_names_mac[i])
241+
); }
242+
sub_div.append(col1).append(col2);
243+
div.append(sub_div);
244+
return div;
245+
};
246+
247+
248+
quickhelp.QuickHelp.prototype.build_command_help = function () {
249+
var command_shortcuts = this.keyboard_manager.command_shortcuts.help();
250+
return build_div('<h4>Jupyter Mode (press <kbd>Shift-Esc</kbd> to enable)</h4>', command_shortcuts);
251+
};
252+
253+
254+
quickhelp.QuickHelp.prototype.build_edit_help = function (cm_shortcuts) {
255+
var edit_shortcuts = this.keyboard_manager.edit_shortcuts.help();
256+
edit_shortcuts = jQuery.merge(jQuery.merge([], cm_shortcuts), edit_shortcuts);
257+
return build_div('<h4>Vim Command Mode (press <kbd>i</kbd> to enable)</h4>', edit_shortcuts);
258+
};
259+
260+
var build_one = function (s) {
261+
var help = s.help;
262+
var shortcut = '';
263+
if(s.shortcut){
264+
shortcut = humanize_sequence(s.shortcut);
265+
}
266+
return $('<div>').addClass('quickhelp').
267+
append($('<span/>').addClass('shortcut_key').append($(shortcut))).
268+
append($('<span/>').addClass('shortcut_descr').text(' : ' + help));
269+
270+
};
271+
272+
var build_div = function (title, shortcuts) {
273+
274+
// Remove jupyter-notebook:ignore shortcuts.
275+
shortcuts = shortcuts.filter(function(shortcut) {
276+
if (shortcut.help === 'ignore') {
277+
return false;
278+
} else {
279+
return true;
280+
}
281+
});
282+
283+
var i, half, n;
284+
var div = $('<div/>').append($(title));
285+
var sub_div = $('<div/>').addClass('container-fluid');
286+
var col1 = $('<div/>').addClass('col-md-6');
287+
var col2 = $('<div/>').addClass('col-md-6');
288+
n = shortcuts.length;
289+
half = ~~(n/2); // Truncate :)
290+
for (i=0; i<half; i++) { col1.append( build_one(shortcuts[i]) ); }
291+
for (i=half; i<n; i++) { col2.append( build_one(shortcuts[i]) ); }
292+
sub_div.append(col1).append(col2);
293+
div.append(sub_div);
294+
return div;
295+
};
296+
};
297+
298+
return exports;
299+
});

vim_binding.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ define([
2929
'./lib/jupyter/keyboard',
3030
'./lib/jupyter/notebook',
3131
'./lib/jupyter/shortcuts',
32+
'./lib/jupyter/quickhelp',
3233
], function(require, $, config, ns, utils, cell) {
3334
"use strict";
3435
var undefined;

0 commit comments

Comments
 (0)