##// END OF EJS Templates
Adding j/k for select next/prev. Faster than up/down.
Brian E. Granger -
Show More
@@ -1,582 +1,605
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2011 The IPython Development Team
2 // Copyright (C) 2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // Keyboard management
9 // Keyboard management
10 //============================================================================
10 //============================================================================
11
11
12 var IPython = (function (IPython) {
12 var IPython = (function (IPython) {
13 "use strict";
13 "use strict";
14
14
15 // Setup global keycodes and inverse keycodes.
15 // Setup global keycodes and inverse keycodes.
16
16
17 // See http://unixpapa.com/js/key.html for a complete description. The short of
17 // See http://unixpapa.com/js/key.html for a complete description. The short of
18 // it is that there are different keycode sets. Firefox uses the "Mozilla keycodes"
18 // it is that there are different keycode sets. Firefox uses the "Mozilla keycodes"
19 // and Webkit/IE use the "IE keycodes". These keycode sets are mostly the same
19 // and Webkit/IE use the "IE keycodes". These keycode sets are mostly the same
20 // but have minor differences.
20 // but have minor differences.
21
21
22 // These apply to Firefox, (Webkit and IE)
22 // These apply to Firefox, (Webkit and IE)
23 var _keycodes = {
23 var _keycodes = {
24 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73,
24 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73,
25 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82,
25 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82,
26 's': 83, 't': 84, 'u': 85, 'v': 86, 'w': 87, 'x': 88, 'y': 89, 'z': 90,
26 's': 83, 't': 84, 'u': 85, 'v': 86, 'w': 87, 'x': 88, 'y': 89, 'z': 90,
27 '1 !': 49, '2 @': 50, '3 #': 51, '4 $': 52, '5 %': 53, '6 ^': 54,
27 '1 !': 49, '2 @': 50, '3 #': 51, '4 $': 52, '5 %': 53, '6 ^': 54,
28 '7 &': 55, '8 *': 56, '9 (': 57, '0 )': 48,
28 '7 &': 55, '8 *': 56, '9 (': 57, '0 )': 48,
29 '[ {': 219, '] }': 221, '` ~': 192, ', <': 188, '. >': 190, '/ ?': 191,
29 '[ {': 219, '] }': 221, '` ~': 192, ', <': 188, '. >': 190, '/ ?': 191,
30 '\\ |': 220, '\' "': 222,
30 '\\ |': 220, '\' "': 222,
31 'numpad0': 96, 'numpad1': 97, 'numpad2': 98, 'numpad3': 99, 'numpad4': 100,
31 'numpad0': 96, 'numpad1': 97, 'numpad2': 98, 'numpad3': 99, 'numpad4': 100,
32 'numpad5': 101, 'numpad6': 102, 'numpad7': 103, 'numpad8': 104, 'numpad9': 105,
32 'numpad5': 101, 'numpad6': 102, 'numpad7': 103, 'numpad8': 104, 'numpad9': 105,
33 'multiply': 106, 'add': 107, 'subtract': 109, 'decimal': 110, 'divide': 111,
33 'multiply': 106, 'add': 107, 'subtract': 109, 'decimal': 110, 'divide': 111,
34 'f1': 112, 'f2': 113, 'f3': 114, 'f4': 115, 'f5': 116, 'f6': 117, 'f7': 118,
34 'f1': 112, 'f2': 113, 'f3': 114, 'f4': 115, 'f5': 116, 'f6': 117, 'f7': 118,
35 'f8': 119, 'f9': 120, 'f11': 122, 'f12': 123, 'f13': 124, 'f14': 125, 'f15': 126,
35 'f8': 119, 'f9': 120, 'f11': 122, 'f12': 123, 'f13': 124, 'f14': 125, 'f15': 126,
36 'backspace': 8, 'tab': 9, 'enter': 13, 'shift': 16, 'ctrl': 17, 'alt': 18,
36 'backspace': 8, 'tab': 9, 'enter': 13, 'shift': 16, 'ctrl': 17, 'alt': 18,
37 'meta': 91, 'capslock': 20, 'esc': 27, 'space': 32, 'pageup': 33, 'pagedown': 34,
37 'meta': 91, 'capslock': 20, 'esc': 27, 'space': 32, 'pageup': 33, 'pagedown': 34,
38 'end': 35, 'home': 36, 'left': 37, 'up': 38, 'right': 39, 'down': 40,
38 'end': 35, 'home': 36, 'left': 37, 'up': 38, 'right': 39, 'down': 40,
39 'insert': 45, 'delete': 46, 'numlock': 144,
39 'insert': 45, 'delete': 46, 'numlock': 144,
40 };
40 };
41
41
42 // These apply to Firefox and Opera
42 // These apply to Firefox and Opera
43 var _mozilla_keycodes = {
43 var _mozilla_keycodes = {
44 '; :': 59, '= +': 61, '- _': 109,
44 '; :': 59, '= +': 61, '- _': 109,
45 }
45 }
46
46
47 // This apply to Webkit and IE
47 // This apply to Webkit and IE
48 var _ie_keycodes = {
48 var _ie_keycodes = {
49 '; :': 186, '= +': 187, '- _': 189,
49 '; :': 186, '= +': 187, '- _': 189,
50 }
50 }
51
51
52 var browser = IPython.utils.browser[0];
52 var browser = IPython.utils.browser[0];
53
53
54 if (browser === 'Firefox' || browser === 'Opera') {
54 if (browser === 'Firefox' || browser === 'Opera') {
55 $.extend(_keycodes, _mozilla_keycodes);
55 $.extend(_keycodes, _mozilla_keycodes);
56 } else if (browser === 'Safari' || browser === 'Chrome' || browser === 'MSIE') {
56 } else if (browser === 'Safari' || browser === 'Chrome' || browser === 'MSIE') {
57 $.extend(_keycodes, _ie_keycodes);
57 $.extend(_keycodes, _ie_keycodes);
58 }
58 }
59
59
60 var keycodes = {};
60 var keycodes = {};
61 var inv_keycodes = {};
61 var inv_keycodes = {};
62 for (var name in _keycodes) {
62 for (var name in _keycodes) {
63 var names = name.split(' ');
63 var names = name.split(' ');
64 if (names.length === 1) {
64 if (names.length === 1) {
65 var n = names[0]
65 var n = names[0]
66 keycodes[n] = _keycodes[n]
66 keycodes[n] = _keycodes[n]
67 inv_keycodes[_keycodes[n]] = n
67 inv_keycodes[_keycodes[n]] = n
68 } else {
68 } else {
69 var primary = names[0];
69 var primary = names[0];
70 var secondary = names[1];
70 var secondary = names[1];
71 keycodes[primary] = _keycodes[name]
71 keycodes[primary] = _keycodes[name]
72 keycodes[secondary] = _keycodes[name]
72 keycodes[secondary] = _keycodes[name]
73 inv_keycodes[_keycodes[name]] = primary
73 inv_keycodes[_keycodes[name]] = primary
74 }
74 }
75 }
75 }
76
76
77
77
78 // Default keyboard shortcuts
78 // Default keyboard shortcuts
79
79
80 var default_common_shortcuts = {
80 var default_common_shortcuts = {
81 'meta+s' : {
81 'meta+s' : {
82 help : 'save notebook',
82 help : 'save notebook',
83 handler : function (event) {
83 handler : function (event) {
84 IPython.notebook.save_checkpoint();
84 IPython.notebook.save_checkpoint();
85 event.preventDefault();
85 event.preventDefault();
86 return false;
86 return false;
87 }
87 }
88 },
88 },
89 'ctrl+s' : {
89 'ctrl+s' : {
90 help : 'save notebook',
90 help : 'save notebook',
91 handler : function (event) {
91 handler : function (event) {
92 IPython.notebook.save_checkpoint();
92 IPython.notebook.save_checkpoint();
93 event.preventDefault();
93 event.preventDefault();
94 return false;
94 return false;
95 }
95 }
96 },
96 },
97 'shift' : {
97 'shift' : {
98 help : '',
98 help : '',
99 handler : function (event) {
99 handler : function (event) {
100 // ignore shift keydown
100 // ignore shift keydown
101 return true;
101 return true;
102 }
102 }
103 },
103 },
104 'shift+enter' : {
104 'shift+enter' : {
105 help : 'run cell',
105 help : 'run cell',
106 handler : function (event) {
106 handler : function (event) {
107 IPython.notebook.execute_selected_cell('shift');
107 IPython.notebook.execute_selected_cell('shift');
108 return false;
108 return false;
109 }
109 }
110 },
110 },
111 'alt+enter' : {
111 'alt+enter' : {
112 help : 'run cell',
112 help : 'run cell',
113 handler : function (event) {
113 handler : function (event) {
114 IPython.notebook.execute_selected_cell('alt');
114 IPython.notebook.execute_selected_cell('alt');
115 return false;
115 return false;
116 }
116 }
117 },
117 },
118 'ctrl+enter' : {
118 'ctrl+enter' : {
119 help : 'run cell',
119 help : 'run cell',
120 handler : function (event) {
120 handler : function (event) {
121 IPython.notebook.execute_selected_cell('ctrl');
121 IPython.notebook.execute_selected_cell('ctrl');
122 return false;
122 return false;
123 }
123 }
124 }
124 }
125 }
125 }
126
126
127 // Edit mode defaults
127 // Edit mode defaults
128
128
129 var default_edit_shortcuts = {
129 var default_edit_shortcuts = {
130 'esc' : {
130 'esc' : {
131 help : 'command mode',
131 help : 'command mode',
132 handler : function (event) {
132 handler : function (event) {
133 IPython.notebook.command_mode();
133 IPython.notebook.command_mode();
134 return false;
134 return false;
135 }
135 }
136 },
136 },
137 'ctrl+m' : {
137 'ctrl+m' : {
138 help : 'command mode',
138 help : 'command mode',
139 handler : function (event) {
139 handler : function (event) {
140 IPython.notebook.command_mode();
140 IPython.notebook.command_mode();
141 return false;
141 return false;
142 }
142 }
143 },
143 },
144 'up' : {
144 'up' : {
145 help : 'select previous cell',
145 help : 'select previous cell',
146 handler : function (event) {
146 handler : function (event) {
147 var cell = IPython.notebook.get_selected_cell();
147 var cell = IPython.notebook.get_selected_cell();
148 if (cell && cell.at_top()) {
148 if (cell && cell.at_top()) {
149 event.preventDefault();
149 event.preventDefault();
150 IPython.notebook.command_mode()
150 IPython.notebook.command_mode()
151 IPython.notebook.select_prev();
151 IPython.notebook.select_prev();
152 IPython.notebook.edit_mode();
152 IPython.notebook.edit_mode();
153 return false;
153 return false;
154 };
154 };
155 }
155 }
156 },
156 },
157 'down' : {
157 'down' : {
158 help : 'select next cell',
158 help : 'select next cell',
159 handler : function (event) {
159 handler : function (event) {
160 var cell = IPython.notebook.get_selected_cell();
160 var cell = IPython.notebook.get_selected_cell();
161 if (cell && cell.at_bottom()) {
161 if (cell && cell.at_bottom()) {
162 event.preventDefault();
162 event.preventDefault();
163 IPython.notebook.command_mode()
163 IPython.notebook.command_mode()
164 IPython.notebook.select_next();
164 IPython.notebook.select_next();
165 IPython.notebook.edit_mode();
165 IPython.notebook.edit_mode();
166 return false;
166 return false;
167 };
167 };
168 }
168 }
169 },
169 },
170
171 }
170 }
172
171
173 // Command mode defaults
172 // Command mode defaults
174
173
175 var default_command_shortcuts = {
174 var default_command_shortcuts = {
176 'enter' : {
175 'enter' : {
177 help : 'edit mode',
176 help : 'edit mode',
178 handler : function (event) {
177 handler : function (event) {
179 IPython.notebook.edit_mode();
178 IPython.notebook.edit_mode();
180 return false;
179 return false;
181 }
180 }
182 },
181 },
183 'up' : {
182 'up' : {
184 help : 'select previous cell',
183 help : 'select previous cell',
185 handler : function (event) {
184 handler : function (event) {
186 var index = IPython.notebook.get_selected_index();
185 var index = IPython.notebook.get_selected_index();
187 if (index !== 0 && index !== null) {
186 if (index !== 0 && index !== null) {
188 IPython.notebook.select_prev();
187 IPython.notebook.select_prev();
189 var cell = IPython.notebook.get_selected_cell();
188 var cell = IPython.notebook.get_selected_cell();
190 cell.focus_cell();
189 cell.focus_cell();
191 };
190 };
192 return false;
191 return false;
193 }
192 }
194 },
193 },
195 'down' : {
194 'down' : {
196 help : 'select next cell',
195 help : 'select next cell',
197 handler : function (event) {
196 handler : function (event) {
198 var index = IPython.notebook.get_selected_index();
197 var index = IPython.notebook.get_selected_index();
199 if (index !== (IPython.notebook.ncells()-1) && index !== null) {
198 if (index !== (IPython.notebook.ncells()-1) && index !== null) {
200 IPython.notebook.select_next();
199 IPython.notebook.select_next();
201 var cell = IPython.notebook.get_selected_cell();
200 var cell = IPython.notebook.get_selected_cell();
202 cell.focus_cell();
201 cell.focus_cell();
203 };
202 };
204 return false;
203 return false;
205 }
204 }
206 },
205 },
206 'k' : {
207 help : 'select previous cell',
208 handler : function (event) {
209 var index = IPython.notebook.get_selected_index();
210 if (index !== 0 && index !== null) {
211 IPython.notebook.select_prev();
212 var cell = IPython.notebook.get_selected_cell();
213 cell.focus_cell();
214 };
215 return false;
216 }
217 },
218 'j' : {
219 help : 'select next cell',
220 handler : function (event) {
221 var index = IPython.notebook.get_selected_index();
222 if (index !== (IPython.notebook.ncells()-1) && index !== null) {
223 IPython.notebook.select_next();
224 var cell = IPython.notebook.get_selected_cell();
225 cell.focus_cell();
226 };
227 return false;
228 }
229 },
207 'x' : {
230 'x' : {
208 help : 'cut cell',
231 help : 'cut cell',
209 handler : function (event) {
232 handler : function (event) {
210 IPython.notebook.cut_cell();
233 IPython.notebook.cut_cell();
211 return false;
234 return false;
212 }
235 }
213 },
236 },
214 'c' : {
237 'c' : {
215 help : 'copy cell',
238 help : 'copy cell',
216 handler : function (event) {
239 handler : function (event) {
217 IPython.notebook.copy_cell();
240 IPython.notebook.copy_cell();
218 return false;
241 return false;
219 }
242 }
220 },
243 },
221 'v' : {
244 'v' : {
222 help : 'paste cell below',
245 help : 'paste cell below',
223 handler : function (event) {
246 handler : function (event) {
224 IPython.notebook.paste_cell_below();
247 IPython.notebook.paste_cell_below();
225 return false;
248 return false;
226 }
249 }
227 },
250 },
228 'd' : {
251 'd' : {
229 help : 'delete cell (press twice)',
252 help : 'delete cell (press twice)',
230 handler : function (event) {
253 handler : function (event) {
231 var dc = IPython.delete_count;
254 var dc = IPython.delete_count;
232 if (dc === undefined) {
255 if (dc === undefined) {
233 IPython.delete_count = 0;
256 IPython.delete_count = 0;
234 } else if (dc === 0) {
257 } else if (dc === 0) {
235 IPython.delete_count = 1;
258 IPython.delete_count = 1;
236 setTimeout(function () {
259 setTimeout(function () {
237 IPython.delete_count = 0;
260 IPython.delete_count = 0;
238 }, 800);
261 }, 800);
239 } else if (dc === 1) {
262 } else if (dc === 1) {
240 IPython.notebook.delete_cell();
263 IPython.notebook.delete_cell();
241 IPython.delete_count = 0;
264 IPython.delete_count = 0;
242 }
265 }
243 return false;
266 return false;
244 }
267 }
245 },
268 },
246 'a' : {
269 'a' : {
247 help : 'insert cell above',
270 help : 'insert cell above',
248 handler : function (event) {
271 handler : function (event) {
249 IPython.notebook.insert_cell_above('code');
272 IPython.notebook.insert_cell_above('code');
250 IPython.notebook.select_prev();
273 IPython.notebook.select_prev();
251 return false;
274 return false;
252 }
275 }
253 },
276 },
254 'b' : {
277 'b' : {
255 help : 'insert cell below',
278 help : 'insert cell below',
256 handler : function (event) {
279 handler : function (event) {
257 IPython.notebook.insert_cell_below('code');
280 IPython.notebook.insert_cell_below('code');
258 IPython.notebook.select_next();
281 IPython.notebook.select_next();
259 return false;
282 return false;
260 }
283 }
261 },
284 },
262 'y' : {
285 'y' : {
263 help : 'to code',
286 help : 'to code',
264 handler : function (event) {
287 handler : function (event) {
265 IPython.notebook.to_code();
288 IPython.notebook.to_code();
266 return false;
289 return false;
267 }
290 }
268 },
291 },
269 'm' : {
292 'm' : {
270 help : 'to markdown',
293 help : 'to markdown',
271 handler : function (event) {
294 handler : function (event) {
272 IPython.notebook.to_markdown();
295 IPython.notebook.to_markdown();
273 return false;
296 return false;
274 }
297 }
275 },
298 },
276 't' : {
299 't' : {
277 help : 'to raw',
300 help : 'to raw',
278 handler : function (event) {
301 handler : function (event) {
279 IPython.notebook.to_raw();
302 IPython.notebook.to_raw();
280 return false;
303 return false;
281 }
304 }
282 },
305 },
283 '1' : {
306 '1' : {
284 help : 'to heading 1',
307 help : 'to heading 1',
285 handler : function (event) {
308 handler : function (event) {
286 IPython.notebook.to_heading(undefined, 1);
309 IPython.notebook.to_heading(undefined, 1);
287 return false;
310 return false;
288 }
311 }
289 },
312 },
290 '2' : {
313 '2' : {
291 help : 'to heading 2',
314 help : 'to heading 2',
292 handler : function (event) {
315 handler : function (event) {
293 IPython.notebook.to_heading(undefined, 2);
316 IPython.notebook.to_heading(undefined, 2);
294 return false;
317 return false;
295 }
318 }
296 },
319 },
297 '3' : {
320 '3' : {
298 help : 'to heading 3',
321 help : 'to heading 3',
299 handler : function (event) {
322 handler : function (event) {
300 IPython.notebook.to_heading(undefined, 3);
323 IPython.notebook.to_heading(undefined, 3);
301 return false;
324 return false;
302 }
325 }
303 },
326 },
304 '4' : {
327 '4' : {
305 help : 'to heading 4',
328 help : 'to heading 4',
306 handler : function (event) {
329 handler : function (event) {
307 IPython.notebook.to_heading(undefined, 4);
330 IPython.notebook.to_heading(undefined, 4);
308 return false;
331 return false;
309 }
332 }
310 },
333 },
311 '5' : {
334 '5' : {
312 help : 'to heading 5',
335 help : 'to heading 5',
313 handler : function (event) {
336 handler : function (event) {
314 IPython.notebook.to_heading(undefined, 5);
337 IPython.notebook.to_heading(undefined, 5);
315 return false;
338 return false;
316 }
339 }
317 },
340 },
318 '6' : {
341 '6' : {
319 help : 'to heading 6',
342 help : 'to heading 6',
320 handler : function (event) {
343 handler : function (event) {
321 IPython.notebook.to_heading(undefined, 6);
344 IPython.notebook.to_heading(undefined, 6);
322 return false;
345 return false;
323 }
346 }
324 },
347 },
325 'o' : {
348 'o' : {
326 help : 'toggle output',
349 help : 'toggle output',
327 handler : function (event) {
350 handler : function (event) {
328 IPython.notebook.toggle_output();
351 IPython.notebook.toggle_output();
329 return false;
352 return false;
330 }
353 }
331 },
354 },
332 'shift+o' : {
355 'shift+o' : {
333 help : 'toggle output',
356 help : 'toggle output',
334 handler : function (event) {
357 handler : function (event) {
335 IPython.notebook.toggle_output_scroll();
358 IPython.notebook.toggle_output_scroll();
336 return false;
359 return false;
337 }
360 }
338 },
361 },
339 's' : {
362 's' : {
340 help : 'save notebook',
363 help : 'save notebook',
341 handler : function (event) {
364 handler : function (event) {
342 IPython.notebook.save_checkpoint();
365 IPython.notebook.save_checkpoint();
343 return false;
366 return false;
344 }
367 }
345 },
368 },
346 'ctrl+j' : {
369 'ctrl+j' : {
347 help : 'move cell down',
370 help : 'move cell down',
348 handler : function (event) {
371 handler : function (event) {
349 IPython.notebook.move_cell_down();
372 IPython.notebook.move_cell_down();
350 return false;
373 return false;
351 }
374 }
352 },
375 },
353 'ctrl+k' : {
376 'ctrl+k' : {
354 help : 'move cell up',
377 help : 'move cell up',
355 handler : function (event) {
378 handler : function (event) {
356 IPython.notebook.move_cell_up();
379 IPython.notebook.move_cell_up();
357 return false;
380 return false;
358 }
381 }
359 },
382 },
360 'l' : {
383 'l' : {
361 help : 'toggle line numbers',
384 help : 'toggle line numbers',
362 handler : function (event) {
385 handler : function (event) {
363 IPython.notebook.cell_toggle_line_numbers();
386 IPython.notebook.cell_toggle_line_numbers();
364 return false;
387 return false;
365 }
388 }
366 },
389 },
367 'i' : {
390 'i' : {
368 help : 'interrupt kernel',
391 help : 'interrupt kernel',
369 handler : function (event) {
392 handler : function (event) {
370 IPython.notebook.kernel.interrupt();
393 IPython.notebook.kernel.interrupt();
371 return false;
394 return false;
372 }
395 }
373 },
396 },
374 '.' : {
397 '.' : {
375 help : 'restart kernel',
398 help : 'restart kernel',
376 handler : function (event) {
399 handler : function (event) {
377 IPython.notebook.restart_kernel();
400 IPython.notebook.restart_kernel();
378 return false;
401 return false;
379 }
402 }
380 },
403 },
381 'h' : {
404 'h' : {
382 help : 'keyboard shortcuts',
405 help : 'keyboard shortcuts',
383 handler : function (event) {
406 handler : function (event) {
384 IPython.quick_help.show_keyboard_shortcuts();
407 IPython.quick_help.show_keyboard_shortcuts();
385 return false;
408 return false;
386 }
409 }
387 },
410 },
388 'z' : {
411 'z' : {
389 help : 'undo last delete',
412 help : 'undo last delete',
390 handler : function (event) {
413 handler : function (event) {
391 IPython.notebook.undelete_cell();
414 IPython.notebook.undelete_cell();
392 return false;
415 return false;
393 }
416 }
394 },
417 },
395 '-' : {
418 '-' : {
396 help : 'split cell',
419 help : 'split cell',
397 handler : function (event) {
420 handler : function (event) {
398 IPython.notebook.split_cell();
421 IPython.notebook.split_cell();
399 return false;
422 return false;
400 }
423 }
401 },
424 },
402 'shift+=' : {
425 'shift+=' : {
403 help : 'merge cell below',
426 help : 'merge cell below',
404 handler : function (event) {
427 handler : function (event) {
405 IPython.notebook.merge_cell_below();
428 IPython.notebook.merge_cell_below();
406 return false;
429 return false;
407 }
430 }
408 },
431 },
409 }
432 }
410
433
411
434
412 // Shortcut manager class
435 // Shortcut manager class
413
436
414 var ShortcutManager = function () {
437 var ShortcutManager = function () {
415 this._shortcuts = {}
438 this._shortcuts = {}
416 }
439 }
417
440
418 ShortcutManager.prototype.help = function () {
441 ShortcutManager.prototype.help = function () {
419 var help = [];
442 var help = [];
420 for (var shortcut in this._shortcuts) {
443 for (var shortcut in this._shortcuts) {
421 help.push({shortcut: shortcut, help: this._shortcuts[shortcut]['help']});
444 help.push({shortcut: shortcut, help: this._shortcuts[shortcut]['help']});
422 }
445 }
423 return help;
446 return help;
424 }
447 }
425
448
426 ShortcutManager.prototype.canonicalize_key = function (key) {
449 ShortcutManager.prototype.canonicalize_key = function (key) {
427 return inv_keycodes[keycodes[key]];
450 return inv_keycodes[keycodes[key]];
428 }
451 }
429
452
430 ShortcutManager.prototype.canonicalize_shortcut = function (shortcut) {
453 ShortcutManager.prototype.canonicalize_shortcut = function (shortcut) {
431 // Sort a sequence of + separated modifiers into the order alt+ctrl+meta+shift
454 // Sort a sequence of + separated modifiers into the order alt+ctrl+meta+shift
432 var values = shortcut.split("+");
455 var values = shortcut.split("+");
433 if (values.length === 1) {
456 if (values.length === 1) {
434 return this.canonicalize_key(values[0])
457 return this.canonicalize_key(values[0])
435 } else {
458 } else {
436 var modifiers = values.slice(0,-1);
459 var modifiers = values.slice(0,-1);
437 var key = this.canonicalize_key(values[values.length-1]);
460 var key = this.canonicalize_key(values[values.length-1]);
438 modifiers.sort();
461 modifiers.sort();
439 return modifiers.join('+') + '+' + key;
462 return modifiers.join('+') + '+' + key;
440 }
463 }
441 }
464 }
442
465
443 ShortcutManager.prototype.event_to_shortcut = function (event) {
466 ShortcutManager.prototype.event_to_shortcut = function (event) {
444 // Convert a jQuery keyboard event to a strong based keyboard shortcut
467 // Convert a jQuery keyboard event to a strong based keyboard shortcut
445 var shortcut = '';
468 var shortcut = '';
446 var key = inv_keycodes[event.which]
469 var key = inv_keycodes[event.which]
447 if (event.altKey && key !== 'alt') {shortcut += 'alt+';}
470 if (event.altKey && key !== 'alt') {shortcut += 'alt+';}
448 if (event.ctrlKey && key !== 'ctrl') {shortcut += 'ctrl+';}
471 if (event.ctrlKey && key !== 'ctrl') {shortcut += 'ctrl+';}
449 if (event.metaKey && key !== 'meta') {shortcut += 'meta+';}
472 if (event.metaKey && key !== 'meta') {shortcut += 'meta+';}
450 if (event.shiftKey && key !== 'shift') {shortcut += 'shift+';}
473 if (event.shiftKey && key !== 'shift') {shortcut += 'shift+';}
451 shortcut += key;
474 shortcut += key;
452 return shortcut
475 return shortcut
453 }
476 }
454
477
455 ShortcutManager.prototype.clear_shortcuts = function () {
478 ShortcutManager.prototype.clear_shortcuts = function () {
456 this._shortcuts = {};
479 this._shortcuts = {};
457 }
480 }
458
481
459 ShortcutManager.prototype.add_shortcut = function (shortcut, data) {
482 ShortcutManager.prototype.add_shortcut = function (shortcut, data) {
460 shortcut = this.canonicalize_shortcut(shortcut);
483 shortcut = this.canonicalize_shortcut(shortcut);
461 this._shortcuts[shortcut] = data;
484 this._shortcuts[shortcut] = data;
462 }
485 }
463
486
464 ShortcutManager.prototype.add_shortcuts = function (data) {
487 ShortcutManager.prototype.add_shortcuts = function (data) {
465 for (var shortcut in data) {
488 for (var shortcut in data) {
466 this.add_shortcut(shortcut, data[shortcut]);
489 this.add_shortcut(shortcut, data[shortcut]);
467 }
490 }
468 }
491 }
469
492
470 ShortcutManager.prototype.remove_shortcut = function (shortcut) {
493 ShortcutManager.prototype.remove_shortcut = function (shortcut) {
471 shortcut = this.canonicalize_shortcut(shortcut);
494 shortcut = this.canonicalize_shortcut(shortcut);
472 delete this._shortcuts[shortcut];
495 delete this._shortcuts[shortcut];
473 }
496 }
474
497
475 ShortcutManager.prototype.call_handler = function (event) {
498 ShortcutManager.prototype.call_handler = function (event) {
476 var shortcut = this.event_to_shortcut(event);
499 var shortcut = this.event_to_shortcut(event);
477 var data = this._shortcuts[shortcut];
500 var data = this._shortcuts[shortcut];
478 if (data !== undefined) {
501 if (data !== undefined) {
479 var handler = data['handler'];
502 var handler = data['handler'];
480 if (handler !== undefined) {
503 if (handler !== undefined) {
481 return handler(event);
504 return handler(event);
482 }
505 }
483 }
506 }
484 return true;
507 return true;
485 }
508 }
486
509
487
510
488
511
489 // Main keyboard manager for the notebook
512 // Main keyboard manager for the notebook
490
513
491 var KeyboardManager = function () {
514 var KeyboardManager = function () {
492 this.mode = 'command';
515 this.mode = 'command';
493 this.enabled = true;
516 this.enabled = true;
494 this.delete_count = 0;
517 this.delete_count = 0;
495 this.bind_events();
518 this.bind_events();
496 this.command_shortcuts = new ShortcutManager();
519 this.command_shortcuts = new ShortcutManager();
497 this.command_shortcuts.add_shortcuts(default_common_shortcuts);
520 this.command_shortcuts.add_shortcuts(default_common_shortcuts);
498 this.command_shortcuts.add_shortcuts(default_command_shortcuts);
521 this.command_shortcuts.add_shortcuts(default_command_shortcuts);
499 this.edit_shortcuts = new ShortcutManager();
522 this.edit_shortcuts = new ShortcutManager();
500 this.edit_shortcuts.add_shortcuts(default_common_shortcuts);
523 this.edit_shortcuts.add_shortcuts(default_common_shortcuts);
501 this.edit_shortcuts.add_shortcuts(default_edit_shortcuts);
524 this.edit_shortcuts.add_shortcuts(default_edit_shortcuts);
502 };
525 };
503
526
504 KeyboardManager.prototype.bind_events = function () {
527 KeyboardManager.prototype.bind_events = function () {
505 var that = this;
528 var that = this;
506 $(document).keydown(function (event) {
529 $(document).keydown(function (event) {
507 return that.handle_keydown(event);
530 return that.handle_keydown(event);
508 });
531 });
509 };
532 };
510
533
511 KeyboardManager.prototype.handle_keydown = function (event) {
534 KeyboardManager.prototype.handle_keydown = function (event) {
512 var notebook = IPython.notebook;
535 var notebook = IPython.notebook;
513
536
514 console.log('keyboard_manager', this.mode, event.keyCode);
537 console.log('keyboard_manager', this.mode, event.keyCode);
515
538
516 if (event.which === keycodes['esc']) {
539 if (event.which === keycodes['esc']) {
517 // Intercept escape at highest level to avoid closing
540 // Intercept escape at highest level to avoid closing
518 // websocket connection with firefox
541 // websocket connection with firefox
519 event.preventDefault();
542 event.preventDefault();
520 }
543 }
521
544
522 if (!this.enabled) {
545 if (!this.enabled) {
523 if (event.which === keycodes['esc']) {
546 if (event.which === keycodes['esc']) {
524 // ESC
547 // ESC
525 notebook.command_mode();
548 notebook.command_mode();
526 return false;
549 return false;
527 }
550 }
528 return true;
551 return true;
529 }
552 }
530
553
531 if (this.mode === 'edit') {
554 if (this.mode === 'edit') {
532 return this.edit_shortcuts.call_handler(event);
555 return this.edit_shortcuts.call_handler(event);
533 } else if (this.mode === 'command') {
556 } else if (this.mode === 'command') {
534 return this.command_shortcuts.call_handler(event);
557 return this.command_shortcuts.call_handler(event);
535 }
558 }
536 return true;
559 return true;
537 }
560 }
538
561
539 KeyboardManager.prototype.edit_mode = function () {
562 KeyboardManager.prototype.edit_mode = function () {
540 console.log('KeyboardManager', 'changing to edit mode');
563 console.log('KeyboardManager', 'changing to edit mode');
541 this.last_mode = this.mode;
564 this.last_mode = this.mode;
542 this.mode = 'edit';
565 this.mode = 'edit';
543 }
566 }
544
567
545 KeyboardManager.prototype.command_mode = function () {
568 KeyboardManager.prototype.command_mode = function () {
546 console.log('KeyboardManager', 'changing to command mode');
569 console.log('KeyboardManager', 'changing to command mode');
547 this.last_mode = this.mode;
570 this.last_mode = this.mode;
548 this.mode = 'command';
571 this.mode = 'command';
549 }
572 }
550
573
551 KeyboardManager.prototype.enable = function () {
574 KeyboardManager.prototype.enable = function () {
552 this.enabled = true;
575 this.enabled = true;
553 }
576 }
554
577
555 KeyboardManager.prototype.disable = function () {
578 KeyboardManager.prototype.disable = function () {
556 this.enabled = false;
579 this.enabled = false;
557 }
580 }
558
581
559 KeyboardManager.prototype.register_events = function (e) {
582 KeyboardManager.prototype.register_events = function (e) {
560 var that = this;
583 var that = this;
561 e.on('focusin', function () {
584 e.on('focusin', function () {
562 that.command_mode();
585 that.command_mode();
563 that.disable();
586 that.disable();
564 });
587 });
565 e.on('focusout', function () {
588 e.on('focusout', function () {
566 that.command_mode();
589 that.command_mode();
567 that.enable();
590 that.enable();
568 })
591 })
569 }
592 }
570
593
571
594
572 IPython.keycodes = keycodes;
595 IPython.keycodes = keycodes;
573 IPython.inv_keycodes = inv_keycodes;
596 IPython.inv_keycodes = inv_keycodes;
574 IPython.default_common_shortcuts = default_common_shortcuts;
597 IPython.default_common_shortcuts = default_common_shortcuts;
575 IPython.default_edit_shortcuts = default_edit_shortcuts;
598 IPython.default_edit_shortcuts = default_edit_shortcuts;
576 IPython.default_command_shortcuts = default_command_shortcuts;
599 IPython.default_command_shortcuts = default_command_shortcuts;
577 IPython.ShortcutManager = ShortcutManager;
600 IPython.ShortcutManager = ShortcutManager;
578 IPython.KeyboardManager = KeyboardManager;
601 IPython.KeyboardManager = KeyboardManager;
579
602
580 return IPython;
603 return IPython;
581
604
582 }(IPython));
605 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now