Show More
This diff has been collapsed as it changes many lines, (503 lines changed) Show them Hide them | |||||
@@ -0,0 +1,503 b'' | |||||
|
1 | // Copyright (c) IPython Development Team. | |||
|
2 | // Distributed under the terms of the Modified BSD License. | |||
|
3 | ||||
|
4 | define(['require' | |||
|
5 | ], function(require) { | |||
|
6 | "use strict"; | |||
|
7 | ||||
|
8 | var ActionHandler = function (env) { | |||
|
9 | this.env = env || {}; | |||
|
10 | Object.seal(this); | |||
|
11 | }; | |||
|
12 | ||||
|
13 | /** | |||
|
14 | * A bunch of predefined `Simple Actions` used by IPython. | |||
|
15 | * `Simple Actions` have the following keys: | |||
|
16 | * help (optional): a short string the describe the action. | |||
|
17 | * will be used in various context, like as menu name, tool tips on buttons, | |||
|
18 | * and short description in help menu. | |||
|
19 | * help_index (optional): a string used to sort action in help menu. | |||
|
20 | * icon (optional): a short string that represent the icon that have to be used with this | |||
|
21 | * action. this should mainly correspond to a Font_awesome class. | |||
|
22 | * handler : a function which is called when the action is activated. It will receive at first parameter | |||
|
23 | * a dictionary containing various handle to element of the notebook. | |||
|
24 | * | |||
|
25 | * action need to be registered with a **name** that can be use to refer to this action. | |||
|
26 | * | |||
|
27 | * | |||
|
28 | * if `help` is not provided it will be derived by replacing any dash by space | |||
|
29 | * in the **name** of the action. It is advised to provide a prefix to action name to | |||
|
30 | * avoid conflict the prefix should be all lowercase and end with a dot `.` | |||
|
31 | * in the absence of a prefix the behavior of the action is undefined. | |||
|
32 | * | |||
|
33 | * All action provided by IPython are prefixed with `ipython.`. | |||
|
34 | * | |||
|
35 | * One can register extra actions or replace an existing action with another one is possible | |||
|
36 | * but is considered undefined behavior. | |||
|
37 | * | |||
|
38 | **/ | |||
|
39 | var _action = { | |||
|
40 | 'run-select-next': { | |||
|
41 | icon: 'fa-play', | |||
|
42 | help : 'run cell, select below', | |||
|
43 | help_index : 'ba', | |||
|
44 | handler : function (env) { | |||
|
45 | env.notebook.execute_cell_and_select_below(); | |||
|
46 | } | |||
|
47 | }, | |||
|
48 | 'execute-in-place':{ | |||
|
49 | help : 'run cell', | |||
|
50 | help_index : 'bb', | |||
|
51 | handler : function (env) { | |||
|
52 | env.notebook.execute_cell(); | |||
|
53 | } | |||
|
54 | }, | |||
|
55 | 'execute-and-insert-after':{ | |||
|
56 | help : 'run cell, insert below', | |||
|
57 | help_index : 'bc', | |||
|
58 | handler : function (env) { | |||
|
59 | env.notebook.execute_cell_and_insert_below(); | |||
|
60 | } | |||
|
61 | }, | |||
|
62 | 'go-to-command-mode': { | |||
|
63 | help : 'command mode', | |||
|
64 | help_index : 'aa', | |||
|
65 | handler : function (env) { | |||
|
66 | env.notebook.command_mode(); | |||
|
67 | } | |||
|
68 | }, | |||
|
69 | 'split-cell-at-cursor': { | |||
|
70 | help : 'split cell', | |||
|
71 | help_index : 'ea', | |||
|
72 | handler : function (env) { | |||
|
73 | env.notebook.split_cell(); | |||
|
74 | } | |||
|
75 | }, | |||
|
76 | 'enter-edit-mode' : { | |||
|
77 | help_index : 'aa', | |||
|
78 | handler : function (env) { | |||
|
79 | env.notebook.edit_mode(); | |||
|
80 | } | |||
|
81 | }, | |||
|
82 | 'select-previous-cell' : { | |||
|
83 | help_index : 'da', | |||
|
84 | handler : function (env) { | |||
|
85 | var index = env.notebook.get_selected_index(); | |||
|
86 | if (index !== 0 && index !== null) { | |||
|
87 | env.notebook.select_prev(); | |||
|
88 | env.notebook.focus_cell(); | |||
|
89 | } | |||
|
90 | } | |||
|
91 | }, | |||
|
92 | 'select-next-cell' : { | |||
|
93 | help_index : 'db', | |||
|
94 | handler : function (env) { | |||
|
95 | var index = env.notebook.get_selected_index(); | |||
|
96 | if (index !== (env.notebook.ncells()-1) && index !== null) { | |||
|
97 | env.notebook.select_next(); | |||
|
98 | env.notebook.focus_cell(); | |||
|
99 | } | |||
|
100 | } | |||
|
101 | }, | |||
|
102 | 'cut-selected-cell' : { | |||
|
103 | icon: 'fa-cut', | |||
|
104 | help_index : 'ee', | |||
|
105 | handler : function (env) { | |||
|
106 | env.notebook.cut_cell(); | |||
|
107 | } | |||
|
108 | }, | |||
|
109 | 'copy-selected-cell' : { | |||
|
110 | icon: 'fa-copy', | |||
|
111 | help_index : 'ef', | |||
|
112 | handler : function (env) { | |||
|
113 | env.notebook.copy_cell(); | |||
|
114 | } | |||
|
115 | }, | |||
|
116 | 'paste-cell-before' : { | |||
|
117 | help_index : 'eg', | |||
|
118 | handler : function (env) { | |||
|
119 | env.notebook.paste_cell_above(); | |||
|
120 | } | |||
|
121 | }, | |||
|
122 | 'paste-cell-after' : { | |||
|
123 | icon: 'fa-paste', | |||
|
124 | help_index : 'eh', | |||
|
125 | handler : function (env) { | |||
|
126 | env.notebook.paste_cell_below(); | |||
|
127 | } | |||
|
128 | }, | |||
|
129 | 'insert-cell-before' : { | |||
|
130 | help_index : 'ec', | |||
|
131 | handler : function (env) { | |||
|
132 | env.notebook.insert_cell_above(); | |||
|
133 | env.notebook.select_prev(); | |||
|
134 | env.notebook.focus_cell(); | |||
|
135 | } | |||
|
136 | }, | |||
|
137 | 'insert-cell-after' : { | |||
|
138 | icon : 'fa-plus', | |||
|
139 | help_index : 'ed', | |||
|
140 | handler : function (env) { | |||
|
141 | env.notebook.insert_cell_below(); | |||
|
142 | env.notebook.select_next(); | |||
|
143 | env.notebook.focus_cell(); | |||
|
144 | } | |||
|
145 | }, | |||
|
146 | 'change-selected-cell-to-code-cell' : { | |||
|
147 | help : 'to code', | |||
|
148 | help_index : 'ca', | |||
|
149 | handler : function (env) { | |||
|
150 | env.notebook.to_code(); | |||
|
151 | } | |||
|
152 | }, | |||
|
153 | 'change-selected-cell-to-markdown-cell' : { | |||
|
154 | help : 'to markdown', | |||
|
155 | help_index : 'cb', | |||
|
156 | handler : function (env) { | |||
|
157 | env.notebook.to_markdown(); | |||
|
158 | } | |||
|
159 | }, | |||
|
160 | 'change-selected-cell-to-raw-cell' : { | |||
|
161 | help : 'to raw', | |||
|
162 | help_index : 'cc', | |||
|
163 | handler : function (env) { | |||
|
164 | env.notebook.to_raw(); | |||
|
165 | } | |||
|
166 | }, | |||
|
167 | 'change-selected-cell-to-heading-1' : { | |||
|
168 | help : 'to heading 1', | |||
|
169 | help_index : 'cd', | |||
|
170 | handler : function (env) { | |||
|
171 | env.notebook.to_heading(undefined, 1); | |||
|
172 | } | |||
|
173 | }, | |||
|
174 | 'change-selected-cell-to-heading-2' : { | |||
|
175 | help : 'to heading 2', | |||
|
176 | help_index : 'ce', | |||
|
177 | handler : function (env) { | |||
|
178 | env.notebook.to_heading(undefined, 2); | |||
|
179 | } | |||
|
180 | }, | |||
|
181 | 'change-selected-cell-to-heading-3' : { | |||
|
182 | help : 'to heading 3', | |||
|
183 | help_index : 'cf', | |||
|
184 | handler : function (env) { | |||
|
185 | env.notebook.to_heading(undefined, 3); | |||
|
186 | } | |||
|
187 | }, | |||
|
188 | 'change-selected-cell-to-heading-4' : { | |||
|
189 | help : 'to heading 4', | |||
|
190 | help_index : 'cg', | |||
|
191 | handler : function (env) { | |||
|
192 | env.notebook.to_heading(undefined, 4); | |||
|
193 | } | |||
|
194 | }, | |||
|
195 | 'change-selected-cell-to-heading-5' : { | |||
|
196 | help : 'to heading 5', | |||
|
197 | help_index : 'ch', | |||
|
198 | handler : function (env) { | |||
|
199 | env.notebook.to_heading(undefined, 5); | |||
|
200 | } | |||
|
201 | }, | |||
|
202 | 'change-selected-cell-to-heading-6' : { | |||
|
203 | help : 'to heading 6', | |||
|
204 | help_index : 'ci', | |||
|
205 | handler : function (env) { | |||
|
206 | env.notebook.to_heading(undefined, 6); | |||
|
207 | } | |||
|
208 | }, | |||
|
209 | 'toggle-output-visibility-selected-cell' : { | |||
|
210 | help : 'toggle output', | |||
|
211 | help_index : 'gb', | |||
|
212 | handler : function (env) { | |||
|
213 | env.notebook.toggle_output(); | |||
|
214 | } | |||
|
215 | }, | |||
|
216 | 'toggle-output-scrolling-selected-cell' : { | |||
|
217 | help : 'toggle output scrolling', | |||
|
218 | help_index : 'gc', | |||
|
219 | handler : function (env) { | |||
|
220 | env.notebook.toggle_output_scroll(); | |||
|
221 | } | |||
|
222 | }, | |||
|
223 | 'move-selected-cell-down' : { | |||
|
224 | icon: 'fa-arrow-down', | |||
|
225 | help_index : 'eb', | |||
|
226 | handler : function (env) { | |||
|
227 | env.notebook.move_cell_down(); | |||
|
228 | } | |||
|
229 | }, | |||
|
230 | 'move-selected-cell-up' : { | |||
|
231 | icon: 'fa-arrow-up', | |||
|
232 | help_index : 'ea', | |||
|
233 | handler : function (env) { | |||
|
234 | env.notebook.move_cell_up(); | |||
|
235 | } | |||
|
236 | }, | |||
|
237 | 'toggle-line-number-selected-cell' : { | |||
|
238 | help : 'toggle line numbers', | |||
|
239 | help_index : 'ga', | |||
|
240 | handler : function (env) { | |||
|
241 | env.notebook.cell_toggle_line_numbers(); | |||
|
242 | } | |||
|
243 | }, | |||
|
244 | 'show-keyboard-shortcut-help-dialog' : { | |||
|
245 | help_index : 'ge', | |||
|
246 | handler : function (env) { | |||
|
247 | env.quick_help.show_keyboard_shortcuts(); | |||
|
248 | } | |||
|
249 | }, | |||
|
250 | 'delete-cell': { | |||
|
251 | help_index : 'ej', | |||
|
252 | handler : function (env) { | |||
|
253 | env.notebook.delete_cell(); | |||
|
254 | } | |||
|
255 | }, | |||
|
256 | 'interrupt-kernel':{ | |||
|
257 | icon: 'fa-stop', | |||
|
258 | help_index : 'ha', | |||
|
259 | handler : function (env) { | |||
|
260 | env.notebook.kernel.interrupt(); | |||
|
261 | } | |||
|
262 | }, | |||
|
263 | 'restart-kernel':{ | |||
|
264 | icon: 'fa-repeat', | |||
|
265 | help_index : 'hb', | |||
|
266 | handler : function (env) { | |||
|
267 | env.notebook.restart_kernel(); | |||
|
268 | } | |||
|
269 | }, | |||
|
270 | 'undo-last-cell-deletion' : { | |||
|
271 | help_index : 'ei', | |||
|
272 | handler : function (env) { | |||
|
273 | env.notebook.undelete_cell(); | |||
|
274 | } | |||
|
275 | }, | |||
|
276 | 'merge-selected-cell-with-cell-after' : { | |||
|
277 | help : 'merge cell below', | |||
|
278 | help_index : 'ek', | |||
|
279 | handler : function (env) { | |||
|
280 | env.notebook.merge_cell_below(); | |||
|
281 | } | |||
|
282 | }, | |||
|
283 | 'close-pager' : { | |||
|
284 | help_index : 'gd', | |||
|
285 | handler : function (env) { | |||
|
286 | env.pager.collapse(); | |||
|
287 | } | |||
|
288 | } | |||
|
289 | ||||
|
290 | }; | |||
|
291 | ||||
|
292 | /** | |||
|
293 | * A bunch of `Advance actions` for IPython. | |||
|
294 | * Cf `Simple Action` plus the following properties. | |||
|
295 | * | |||
|
296 | * handler: first argument of the handler is the event that triggerd the action | |||
|
297 | * (typically keypress). The handler is responsible for any modification of the | |||
|
298 | * event and event propagation. | |||
|
299 | * Is also responsible for returning false if the event have to be further ignored, | |||
|
300 | * true, to tell keyboard manager that it ignored the event. | |||
|
301 | * | |||
|
302 | * the second parameter of the handler is the environemnt passed to Simple Actions | |||
|
303 | * | |||
|
304 | **/ | |||
|
305 | var custom_ignore = { | |||
|
306 | 'ignore':{ | |||
|
307 | handler : function () { | |||
|
308 | return true; | |||
|
309 | } | |||
|
310 | }, | |||
|
311 | 'move-cursor-up-or-previous-cell':{ | |||
|
312 | handler : function (env, event) { | |||
|
313 | var index = env.notebook.get_selected_index(); | |||
|
314 | var cell = env.notebook.get_cell(index); | |||
|
315 | var cm = env.notebook.get_selected_cell().code_mirror; | |||
|
316 | var cur = cm.getCursor(); | |||
|
317 | if (cell && cell.at_top() && index !== 0 && cur.ch === 0) { | |||
|
318 | if(event){ | |||
|
319 | event.preventDefault(); | |||
|
320 | } | |||
|
321 | env.notebook.command_mode(); | |||
|
322 | env.notebook.select_prev(); | |||
|
323 | env.notebook.edit_mode(); | |||
|
324 | cm = env.notebook.get_selected_cell().code_mirror; | |||
|
325 | cm.setCursor(cm.lastLine(), 0); | |||
|
326 | } | |||
|
327 | return false; | |||
|
328 | } | |||
|
329 | }, | |||
|
330 | 'move-cursor-down-or-next-cell':{ | |||
|
331 | handler : function (env, event) { | |||
|
332 | var index = env.notebook.get_selected_index(); | |||
|
333 | var cell = env.notebook.get_cell(index); | |||
|
334 | if (cell.at_bottom() && index !== (env.notebook.ncells()-1)) { | |||
|
335 | if(event){ | |||
|
336 | event.preventDefault(); | |||
|
337 | } | |||
|
338 | env.notebook.command_mode(); | |||
|
339 | env.notebook.select_next(); | |||
|
340 | env.notebook.edit_mode(); | |||
|
341 | var cm = env.notebook.get_selected_cell().code_mirror; | |||
|
342 | cm.setCursor(0, 0); | |||
|
343 | } | |||
|
344 | return false; | |||
|
345 | } | |||
|
346 | }, | |||
|
347 | 'scroll-down': { | |||
|
348 | handler: function(env, event) { | |||
|
349 | if(event){ | |||
|
350 | event.preventDefault(); | |||
|
351 | } | |||
|
352 | return env.notebook.scroll_manager.scroll(1); | |||
|
353 | }, | |||
|
354 | }, | |||
|
355 | 'scroll-up': { | |||
|
356 | handler: function(env, event) { | |||
|
357 | if(event){ | |||
|
358 | event.preventDefault(); | |||
|
359 | } | |||
|
360 | return env.notebook.scroll_manager.scroll(-1); | |||
|
361 | }, | |||
|
362 | }, | |||
|
363 | 'save-notebook':{ | |||
|
364 | help: "Save and Checkpoint", | |||
|
365 | help_index : 'fb', | |||
|
366 | icon: 'fa-save', | |||
|
367 | handler : function (env, event) { | |||
|
368 | env.notebook.save_checkpoint(); | |||
|
369 | if(event){ | |||
|
370 | event.preventDefault(); | |||
|
371 | } | |||
|
372 | return false; | |||
|
373 | } | |||
|
374 | }, | |||
|
375 | }; | |||
|
376 | ||||
|
377 | // private stuff that prepend `.ipython` to actions names | |||
|
378 | // and uniformize/fill in missing pieces in of an action. | |||
|
379 | var _prepare_handler = function(registry, subkey, source){ | |||
|
380 | registry['ipython.'+subkey] = {}; | |||
|
381 | registry['ipython.'+subkey].help = source[subkey].help||subkey.replace(/-/g,' '); | |||
|
382 | registry['ipython.'+subkey].help_index = source[subkey].help_index; | |||
|
383 | registry['ipython.'+subkey].icon = source[subkey].icon; | |||
|
384 | return source[subkey].handler; | |||
|
385 | }; | |||
|
386 | ||||
|
387 | // Will actually generate/register all the IPython actions | |||
|
388 | var fun = function(){ | |||
|
389 | var final_actions = {}; | |||
|
390 | for(var k in _action){ | |||
|
391 | // Js closure are function level not block level need to wrap in a IIFE | |||
|
392 | // and append ipython to event name these things do intercept event so are wrapped | |||
|
393 | // in a function that return false. | |||
|
394 | var handler = _prepare_handler(final_actions, k, _action); | |||
|
395 | (function(key, handler){ | |||
|
396 | final_actions['ipython.'+key].handler = function(env, event){ | |||
|
397 | handler(env); | |||
|
398 | if(event){ | |||
|
399 | event.preventDefault(); | |||
|
400 | } | |||
|
401 | return false; | |||
|
402 | }; | |||
|
403 | })(k, handler); | |||
|
404 | } | |||
|
405 | ||||
|
406 | for(var k in custom_ignore){ | |||
|
407 | // Js closure are function level not block level need to wrap in a IIFE | |||
|
408 | // same as above, but decide for themselves wether or not they intercept events. | |||
|
409 | var handler = _prepare_handler(final_actions, k, custom_ignore); | |||
|
410 | (function(key, handler){ | |||
|
411 | final_actions['ipython.'+key].handler = function(env, event){ | |||
|
412 | return handler(env, event); | |||
|
413 | }; | |||
|
414 | })(k, handler); | |||
|
415 | } | |||
|
416 | ||||
|
417 | return final_actions; | |||
|
418 | }; | |||
|
419 | ActionHandler.prototype._actions = fun(); | |||
|
420 | ||||
|
421 | ||||
|
422 | /** | |||
|
423 | * extend the environment variable that will be pass to handlers | |||
|
424 | **/ | |||
|
425 | ActionHandler.prototype.extend_env = function(env){ | |||
|
426 | for(var k in env){ | |||
|
427 | this.env[k] = env[k]; | |||
|
428 | } | |||
|
429 | }; | |||
|
430 | ||||
|
431 | ActionHandler.prototype.register = function(action, name, prefix){ | |||
|
432 | /** | |||
|
433 | * Register an `action` with an optional name and prefix. | |||
|
434 | * | |||
|
435 | * if name and prefix are not given they will be determined automatically. | |||
|
436 | * if action if just a `function` it will be wrapped in an anonymous action. | |||
|
437 | * | |||
|
438 | * @return the full name to access this action . | |||
|
439 | **/ | |||
|
440 | action = this.normalise(action); | |||
|
441 | if( !name ){ | |||
|
442 | name = 'autogenerated-'+String(action.handler); | |||
|
443 | } | |||
|
444 | prefix = prefix || 'auto'; | |||
|
445 | var full_name = prefix+'.'+name; | |||
|
446 | this._actions[full_name] = action; | |||
|
447 | return full_name; | |||
|
448 | ||||
|
449 | }; | |||
|
450 | ||||
|
451 | ||||
|
452 | ActionHandler.prototype.normalise = function(data){ | |||
|
453 | /** | |||
|
454 | * given an `action` or `function`, return a normalised `action` | |||
|
455 | * by setting all known attributes and removing unknown attributes; | |||
|
456 | **/ | |||
|
457 | if(typeof(data) === 'function'){ | |||
|
458 | data = {handler:data}; | |||
|
459 | } | |||
|
460 | if(typeof(data.handler) !== 'function'){ | |||
|
461 | throw('unknown datatype, cannot register'); | |||
|
462 | } | |||
|
463 | var _data = data; | |||
|
464 | data = {}; | |||
|
465 | data.handler = _data.handler; | |||
|
466 | data.help = data.help || ''; | |||
|
467 | data.icon = data.icon || ''; | |||
|
468 | data.help_index = data.help_index || ''; | |||
|
469 | return data; | |||
|
470 | }; | |||
|
471 | ||||
|
472 | ActionHandler.prototype.get_name = function(name_or_data){ | |||
|
473 | /** | |||
|
474 | * given an `action` or `name` of a action, return the name attached to this action. | |||
|
475 | * if given the name of and corresponding actions does not exist in registry, return `null`. | |||
|
476 | **/ | |||
|
477 | ||||
|
478 | if(typeof(name_or_data) === 'string'){ | |||
|
479 | if(this.exists(name_or_data)){ | |||
|
480 | return name_or_data; | |||
|
481 | } else { | |||
|
482 | return null; | |||
|
483 | } | |||
|
484 | } else { | |||
|
485 | return this.register(name_or_data); | |||
|
486 | } | |||
|
487 | }; | |||
|
488 | ||||
|
489 | ActionHandler.prototype.get = function(name){ | |||
|
490 | return this._actions[name]; | |||
|
491 | }; | |||
|
492 | ||||
|
493 | ActionHandler.prototype.call = function(name, event, env){ | |||
|
494 | return this._actions[name].handler(env|| this.env, event); | |||
|
495 | }; | |||
|
496 | ||||
|
497 | ActionHandler.prototype.exists = function(name){ | |||
|
498 | return (typeof(this._actions[name]) !== 'undefined'); | |||
|
499 | }; | |||
|
500 | ||||
|
501 | return {init:ActionHandler}; | |||
|
502 | ||||
|
503 | }); |
@@ -12,18 +12,22 b' define([' | |||||
12 | 'base/js/namespace', |
|
12 | 'base/js/namespace', | |
13 | 'jquery', |
|
13 | 'jquery', | |
14 | 'base/js/utils', |
|
14 | 'base/js/utils', | |
15 | ], function(IPython, $, utils) { |
|
15 | 'underscore', | |
|
16 | ], function(IPython, $, utils, _) { | |||
16 | "use strict"; |
|
17 | "use strict"; | |
17 |
|
18 | |||
18 |
|
19 | |||
19 | // Setup global keycodes and inverse keycodes. |
|
20 | /** | |
|
21 | * Setup global keycodes and inverse keycodes. | |||
|
22 | * | |||
|
23 | * See http://unixpapa.com/js/key.html for a complete description. The short of | |||
|
24 | * it is that there are different keycode sets. Firefox uses the "Mozilla keycodes" | |||
|
25 | * and Webkit/IE use the "IE keycodes". These keycode sets are mostly the same | |||
|
26 | * but have minor differences. | |||
|
27 | **/ | |||
20 |
|
28 | |||
21 | // See http://unixpapa.com/js/key.html for a complete description. The short of |
|
29 | // These apply to Firefox, (Webkit and IE) | |
22 | // it is that there are different keycode sets. Firefox uses the "Mozilla keycodes" |
|
30 | // This does work **only** on US keyboard. | |
23 | // and Webkit/IE use the "IE keycodes". These keycode sets are mostly the same |
|
|||
24 | // but have minor differences. |
|
|||
25 |
|
||||
26 | // These apply to Firefox, (Webkit and IE) |
|
|||
27 | var _keycodes = { |
|
31 | var _keycodes = { | |
28 | 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73, |
|
32 | 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73, | |
29 | 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82, |
|
33 | 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82, | |
@@ -84,13 +88,32 b' define([' | |||||
84 | }; |
|
88 | }; | |
85 |
|
89 | |||
86 | var normalize_shortcut = function (shortcut) { |
|
90 | var normalize_shortcut = function (shortcut) { | |
87 | // Put a shortcut into normalized form: |
|
91 | /** | |
88 | // 1. Make lowercase |
|
92 | * @function _normalize_shortcut | |
89 | // 2. Replace cmd by meta |
|
93 | * @private | |
90 | // 3. Sort '-' separated modifiers into the order alt-ctrl-meta-shift |
|
94 | * return a dict containing the normalized shortcut and the number of time it should be pressed: | |
91 | // 4. Normalize keys |
|
95 | * | |
|
96 | * Put a shortcut into normalized form: | |||
|
97 | * 1. Make lowercase | |||
|
98 | * 2. Replace cmd by meta | |||
|
99 | * 3. Sort '-' separated modifiers into the order alt-ctrl-meta-shift | |||
|
100 | * 4. Normalize keys | |||
|
101 | **/ | |||
|
102 | if (platform === 'MacOS') { | |||
|
103 | shortcut = shortcut.toLowerCase().replace('cmdtrl-', 'cmd-'); | |||
|
104 | } else { | |||
|
105 | shortcut = shortcut.toLowerCase().replace('cmdtrl-', 'ctrl-'); | |||
|
106 | } | |||
|
107 | ||||
92 | shortcut = shortcut.toLowerCase().replace('cmd', 'meta'); |
|
108 | shortcut = shortcut.toLowerCase().replace('cmd', 'meta'); | |
93 | shortcut = shortcut.replace(/-$/, '_'); // catch shortcuts using '-' key |
|
109 | shortcut = shortcut.replace(/-$/, '_'); // catch shortcuts using '-' key | |
|
110 | shortcut = shortcut.replace(/,$/, 'comma'); // catch shortcuts using '-' key | |||
|
111 | if(shortcut.indexOf(',') !== -1){ | |||
|
112 | var sht = shortcut.split(','); | |||
|
113 | sht = _.map(sht, normalize_shortcut); | |||
|
114 | return shortcut; | |||
|
115 | } | |||
|
116 | shortcut = shortcut.replace(/comma/g, ','); // catch shortcuts using '-' key | |||
94 | var values = shortcut.split("-"); |
|
117 | var values = shortcut.split("-"); | |
95 | if (values.length === 1) { |
|
118 | if (values.length === 1) { | |
96 | return normalize_key(values[0]); |
|
119 | return normalize_key(values[0]); | |
@@ -103,7 +126,9 b' define([' | |||||
103 | }; |
|
126 | }; | |
104 |
|
127 | |||
105 | var shortcut_to_event = function (shortcut, type) { |
|
128 | var shortcut_to_event = function (shortcut, type) { | |
106 | // Convert a shortcut (shift-r) to a jQuery Event object |
|
129 | /** | |
|
130 | * Convert a shortcut (shift-r) to a jQuery Event object | |||
|
131 | **/ | |||
107 | type = type || 'keydown'; |
|
132 | type = type || 'keydown'; | |
108 | shortcut = normalize_shortcut(shortcut); |
|
133 | shortcut = normalize_shortcut(shortcut); | |
109 | shortcut = shortcut.replace(/-$/, '_'); // catch shortcuts using '-' key |
|
134 | shortcut = shortcut.replace(/-$/, '_'); // catch shortcuts using '-' key | |
@@ -118,8 +143,21 b' define([' | |||||
118 | return $.Event(type, opts); |
|
143 | return $.Event(type, opts); | |
119 | }; |
|
144 | }; | |
120 |
|
145 | |||
|
146 | var only_modifier_event = function(event){ | |||
|
147 | /** | |||
|
148 | * Return `true` if the event only contains modifiers keys. | |||
|
149 | * false otherwise | |||
|
150 | **/ | |||
|
151 | var key = inv_keycodes[event.which]; | |||
|
152 | return ((event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) && | |||
|
153 | (key === 'alt'|| key === 'ctrl'|| key === 'meta'|| key === 'shift')); | |||
|
154 | ||||
|
155 | }; | |||
|
156 | ||||
121 | var event_to_shortcut = function (event) { |
|
157 | var event_to_shortcut = function (event) { | |
122 | // Convert a jQuery Event object to a shortcut (shift-r) |
|
158 | /** | |
|
159 | * Convert a jQuery Event object to a normalized shortcut string (shift-r) | |||
|
160 | **/ | |||
123 | var shortcut = ''; |
|
161 | var shortcut = ''; | |
124 | var key = inv_keycodes[event.which]; |
|
162 | var key = inv_keycodes[event.which]; | |
125 | if (event.altKey && key !== 'alt') {shortcut += 'alt-';} |
|
163 | if (event.altKey && key !== 'alt') {shortcut += 'alt-';} | |
@@ -132,7 +170,7 b' define([' | |||||
132 |
|
170 | |||
133 | // Shortcut manager class |
|
171 | // Shortcut manager class | |
134 |
|
172 | |||
135 | var ShortcutManager = function (delay, events) { |
|
173 | var ShortcutManager = function (delay, events, actions, env) { | |
136 | /** |
|
174 | /** | |
137 | * A class to deal with keyboard event and shortcut |
|
175 | * A class to deal with keyboard event and shortcut | |
138 | * |
|
176 | * | |
@@ -140,33 +178,78 b' define([' | |||||
140 | * @constructor |
|
178 | * @constructor | |
141 | */ |
|
179 | */ | |
142 | this._shortcuts = {}; |
|
180 | this._shortcuts = {}; | |
143 | this._counts = {}; |
|
|||
144 | this._timers = {}; |
|
|||
145 | this.delay = delay || 800; // delay in milliseconds |
|
181 | this.delay = delay || 800; // delay in milliseconds | |
146 | this.events = events; |
|
182 | this.events = events; | |
|
183 | this.actions = actions; | |||
|
184 | this.actions.extend_env(env); | |||
|
185 | this._queue = []; | |||
|
186 | this._cleartimeout = null; | |||
|
187 | Object.seal(this); | |||
|
188 | }; | |||
|
189 | ||||
|
190 | ShortcutManager.prototype.clearsoon = function(){ | |||
|
191 | /** | |||
|
192 | * Clear the pending shortcut soon, and cancel previous clearing | |||
|
193 | * that might be registered. | |||
|
194 | **/ | |||
|
195 | var that = this; | |||
|
196 | clearTimeout(this._cleartimeout); | |||
|
197 | this._cleartimeout = setTimeout(function(){that.clearqueue();}, this.delay); | |||
|
198 | }; | |||
|
199 | ||||
|
200 | ||||
|
201 | ShortcutManager.prototype.clearqueue = function(){ | |||
|
202 | /** | |||
|
203 | * clear the pending shortcut sequence now. | |||
|
204 | **/ | |||
|
205 | this._queue = []; | |||
|
206 | clearTimeout(this._cleartimeout); | |||
|
207 | }; | |||
|
208 | ||||
|
209 | ||||
|
210 | var flatten_shorttree = function(tree){ | |||
|
211 | /** | |||
|
212 | * Flatten a tree of shortcut sequences. | |||
|
213 | * use full to iterate over all the key/values of available shortcuts. | |||
|
214 | **/ | |||
|
215 | var dct = {}; | |||
|
216 | for(var key in tree){ | |||
|
217 | var value = tree[key]; | |||
|
218 | if(typeof(value) === 'string'){ | |||
|
219 | dct[key] = value; | |||
|
220 | } else { | |||
|
221 | var ftree=flatten_shorttree(value); | |||
|
222 | for(var subkey in ftree){ | |||
|
223 | dct[key+','+subkey] = ftree[subkey]; | |||
|
224 | } | |||
|
225 | } | |||
|
226 | } | |||
|
227 | return dct; | |||
147 | }; |
|
228 | }; | |
148 |
|
229 | |||
149 | ShortcutManager.prototype.help = function () { |
|
230 | ShortcutManager.prototype.help = function () { | |
150 | var help = []; |
|
231 | var help = []; | |
151 |
|
|
232 | var ftree = flatten_shorttree(this._shortcuts); | |
152 | var help_string = this._shortcuts[shortcut].help; |
|
233 | for (var shortcut in ftree) { | |
153 |
var |
|
234 | var action = this.actions.get(ftree[shortcut]); | |
|
235 | var help_string = action.help||'== no help =='; | |||
|
236 | var help_index = action.help_index; | |||
154 | if (help_string) { |
|
237 | if (help_string) { | |
155 | if (platform === 'MacOS') { |
|
238 | var shortstring = (action.shortstring||shortcut); | |
156 | shortcut = shortcut.replace('meta', 'cmd'); |
|
|||
157 | } |
|
|||
158 | help.push({ |
|
239 | help.push({ | |
159 |
shortcut: short |
|
240 | shortcut: shortstring, | |
160 | help: help_string, |
|
241 | help: help_string, | |
161 | help_index: help_index} |
|
242 | help_index: help_index} | |
162 | ); |
|
243 | ); | |
163 | } |
|
244 | } | |
164 | } |
|
245 | } | |
165 | help.sort(function (a, b) { |
|
246 | help.sort(function (a, b) { | |
166 | if (a.help_index > b.help_index) |
|
247 | if (a.help_index > b.help_index){ | |
167 | return 1; |
|
248 | return 1; | |
168 | if (a.help_index < b.help_index) |
|
249 | } | |
|
250 | if (a.help_index < b.help_index){ | |||
169 | return -1; |
|
251 | return -1; | |
|
252 | } | |||
170 | return 0; |
|
253 | return 0; | |
171 | }); |
|
254 | }); | |
172 | return help; |
|
255 | return help; | |
@@ -176,19 +259,105 b' define([' | |||||
176 | this._shortcuts = {}; |
|
259 | this._shortcuts = {}; | |
177 | }; |
|
260 | }; | |
178 |
|
261 | |||
179 |
ShortcutManager.prototype. |
|
262 | ShortcutManager.prototype.get_shortcut = function (shortcut){ | |
180 | if (typeof(data) === 'function') { |
|
263 | /** | |
181 | data = {help: '', help_index: '', handler: data}; |
|
264 | * return a node of the shortcut tree which an action name (string) if leaf, | |
|
265 | * and an object with `object.subtree===true` | |||
|
266 | **/ | |||
|
267 | if(typeof(shortcut) === 'string'){ | |||
|
268 | shortcut = shortcut.split(','); | |||
|
269 | } | |||
|
270 | ||||
|
271 | return this._get_leaf(shortcut, this._shortcuts); | |||
|
272 | }; | |||
|
273 | ||||
|
274 | ||||
|
275 | ShortcutManager.prototype._get_leaf = function(shortcut_array, tree){ | |||
|
276 | /** | |||
|
277 | * @private | |||
|
278 | * find a leaf/node in a subtree of the keyboard shortcut | |||
|
279 | * | |||
|
280 | **/ | |||
|
281 | if(shortcut_array.length === 1){ | |||
|
282 | return tree[shortcut_array[0]]; | |||
|
283 | } else if( typeof(tree[shortcut_array[0]]) !== 'string'){ | |||
|
284 | return this._get_leaf(shortcut_array.slice(1), tree[shortcut_array[0]]); | |||
|
285 | } | |||
|
286 | return null; | |||
|
287 | }; | |||
|
288 | ||||
|
289 | ShortcutManager.prototype.set_shortcut = function( shortcut, action_name){ | |||
|
290 | if( typeof(action_name) !== 'string'){ throw('action is not a string', action_name);} | |||
|
291 | if( typeof(shortcut) === 'string'){ | |||
|
292 | shortcut = shortcut.split(','); | |||
|
293 | } | |||
|
294 | return this._set_leaf(shortcut, action_name, this._shortcuts); | |||
|
295 | }; | |||
|
296 | ||||
|
297 | ShortcutManager.prototype._is_leaf = function(shortcut_array, tree){ | |||
|
298 | if(shortcut_array.length === 1){ | |||
|
299 | return(typeof(tree[shortcut_array[0]]) === 'string'); | |||
|
300 | } else { | |||
|
301 | var subtree = tree[shortcut_array[0]]; | |||
|
302 | return this._is_leaf(shortcut_array.slice(1), subtree ); | |||
|
303 | } | |||
|
304 | }; | |||
|
305 | ||||
|
306 | ShortcutManager.prototype._remove_leaf = function(shortcut_array, tree, allow_node){ | |||
|
307 | if(shortcut_array.length === 1){ | |||
|
308 | var current_node = tree[shortcut_array[0]]; | |||
|
309 | if(typeof(current_node) === 'string'){ | |||
|
310 | delete tree[shortcut_array[0]]; | |||
|
311 | } else { | |||
|
312 | throw('try to delete non-leaf'); | |||
|
313 | } | |||
|
314 | } else { | |||
|
315 | this._remove_leaf(shortcut_array.slice(1), tree[shortcut_array[0]], allow_node); | |||
|
316 | if(_.keys(tree[shortcut_array[0]]).length === 0){ | |||
|
317 | delete tree[shortcut_array[0]]; | |||
|
318 | } | |||
|
319 | } | |||
|
320 | }; | |||
|
321 | ||||
|
322 | ShortcutManager.prototype._set_leaf = function(shortcut_array, action_name, tree){ | |||
|
323 | var current_node = tree[shortcut_array[0]]; | |||
|
324 | if(shortcut_array.length === 1){ | |||
|
325 | if(current_node !== undefined && typeof(current_node) !== 'string'){ | |||
|
326 | console.warn('[warning], you are overriting a long shortcut with a shorter one'); | |||
|
327 | } | |||
|
328 | tree[shortcut_array[0]] = action_name; | |||
|
329 | return true; | |||
|
330 | } else { | |||
|
331 | if(typeof(current_node) === 'string'){ | |||
|
332 | console.warn('you are trying to set a shortcut that will be shadowed'+ | |||
|
333 | 'by a more specific one. Aborting for :', action_name, 'the follwing '+ | |||
|
334 | 'will take precedence', current_node); | |||
|
335 | return false; | |||
|
336 | } else { | |||
|
337 | tree[shortcut_array[0]] = tree[shortcut_array[0]]||{}; | |||
|
338 | } | |||
|
339 | this._set_leaf(shortcut_array.slice(1), action_name, tree[shortcut_array[0]]); | |||
|
340 | return true; | |||
182 | } |
|
341 | } | |
183 | data.help_index = data.help_index || ''; |
|
342 | }; | |
184 | data.help = data.help || ''; |
|
343 | ||
185 | data.count = data.count || 1; |
|
344 | ShortcutManager.prototype.add_shortcut = function (shortcut, data, suppress_help_update) { | |
186 | if (data.help_index === '') { |
|
345 | /** | |
187 | data.help_index = 'zz'; |
|
346 | * Add a action to be handled by shortcut manager. | |
|
347 | * | |||
|
348 | * - `shortcut` should be a `Shortcut Sequence` of the for `Ctrl-Alt-C,Meta-X`... | |||
|
349 | * - `data` could be an `action name`, an `action` or a `function`. | |||
|
350 | * if a `function` is passed it will be converted to an anonymous `action`. | |||
|
351 | * | |||
|
352 | **/ | |||
|
353 | var action_name = this.actions.get_name(data); | |||
|
354 | if (! action_name){ | |||
|
355 | throw('does nto know how to deal with ', data); | |||
188 | } |
|
356 | } | |
|
357 | ||||
189 | shortcut = normalize_shortcut(shortcut); |
|
358 | shortcut = normalize_shortcut(shortcut); | |
190 | this._counts[shortcut] = 0; |
|
359 | this.set_shortcut(shortcut, action_name); | |
191 | this._shortcuts[shortcut] = data; |
|
360 | ||
192 | if (!suppress_help_update) { |
|
361 | if (!suppress_help_update) { | |
193 | // update the keyboard shortcuts notebook help |
|
362 | // update the keyboard shortcuts notebook help | |
194 | this.events.trigger('rebuild.QuickHelp'); |
|
363 | this.events.trigger('rebuild.QuickHelp'); | |
@@ -196,6 +365,11 b' define([' | |||||
196 | }; |
|
365 | }; | |
197 |
|
366 | |||
198 | ShortcutManager.prototype.add_shortcuts = function (data) { |
|
367 | ShortcutManager.prototype.add_shortcuts = function (data) { | |
|
368 | /** | |||
|
369 | * Convenient methods to call `add_shortcut(key, value)` on several items | |||
|
370 | * | |||
|
371 | * data : Dict of the form {key:value, ...} | |||
|
372 | **/ | |||
199 | for (var shortcut in data) { |
|
373 | for (var shortcut in data) { | |
200 | this.add_shortcut(shortcut, data[shortcut], true); |
|
374 | this.add_shortcut(shortcut, data[shortcut], true); | |
201 | } |
|
375 | } | |
@@ -204,44 +378,22 b' define([' | |||||
204 | }; |
|
378 | }; | |
205 |
|
379 | |||
206 | ShortcutManager.prototype.remove_shortcut = function (shortcut, suppress_help_update) { |
|
380 | ShortcutManager.prototype.remove_shortcut = function (shortcut, suppress_help_update) { | |
|
381 | /** | |||
|
382 | * Remove the binding of shortcut `sortcut` with its action. | |||
|
383 | * throw an error if trying to remove a non-exiting shortcut | |||
|
384 | **/ | |||
207 | shortcut = normalize_shortcut(shortcut); |
|
385 | shortcut = normalize_shortcut(shortcut); | |
208 | delete this._counts[shortcut]; |
|
386 | if( typeof(shortcut) === 'string'){ | |
209 |
|
|
387 | shortcut = shortcut.split(','); | |
|
388 | } | |||
|
389 | this._remove_leaf(shortcut, this._shortcuts); | |||
210 | if (!suppress_help_update) { |
|
390 | if (!suppress_help_update) { | |
211 | // update the keyboard shortcuts notebook help |
|
391 | // update the keyboard shortcuts notebook help | |
212 | this.events.trigger('rebuild.QuickHelp'); |
|
392 | this.events.trigger('rebuild.QuickHelp'); | |
213 | } |
|
393 | } | |
214 | }; |
|
394 | }; | |
215 |
|
395 | |||
216 | ShortcutManager.prototype.count_handler = function (shortcut, event, data) { |
|
396 | ||
217 | /** |
|
|||
218 | * Seem to allow to call an handler only after several key press. |
|
|||
219 | * like, I suppose `dd` that delete the current cell only after |
|
|||
220 | * `d` has been pressed twice.. |
|
|||
221 | * @method count_handler |
|
|||
222 | * @return {Boolean} `true|false`, whether or not the event has been handled. |
|
|||
223 | * @param shortcut {shortcut} |
|
|||
224 | * @param event {event} |
|
|||
225 | * @param data {data} |
|
|||
226 | */ |
|
|||
227 | var that = this; |
|
|||
228 | var c = this._counts; |
|
|||
229 | var t = this._timers; |
|
|||
230 | var timer = null; |
|
|||
231 | if (c[shortcut] === data.count-1) { |
|
|||
232 | c[shortcut] = 0; |
|
|||
233 | timer = t[shortcut]; |
|
|||
234 | if (timer) {clearTimeout(timer); delete t[shortcut];} |
|
|||
235 | return data.handler(event); |
|
|||
236 | } else { |
|
|||
237 | c[shortcut] = c[shortcut] + 1; |
|
|||
238 | timer = setTimeout(function () { |
|
|||
239 | c[shortcut] = 0; |
|
|||
240 | }, that.delay); |
|
|||
241 | t[shortcut] = timer; |
|
|||
242 | } |
|
|||
243 | return false; |
|
|||
244 | }; |
|
|||
245 |
|
397 | |||
246 | ShortcutManager.prototype.call_handler = function (event) { |
|
398 | ShortcutManager.prototype.call_handler = function (event) { | |
247 | /** |
|
399 | /** | |
@@ -249,26 +401,40 b' define([' | |||||
249 | * @method call_handler |
|
401 | * @method call_handler | |
250 | * @return {Boolean} `true|false`, `false` if no handler was found, otherwise the value return by the handler. |
|
402 | * @return {Boolean} `true|false`, `false` if no handler was found, otherwise the value return by the handler. | |
251 | * @param event {event} |
|
403 | * @param event {event} | |
252 |
* |
|
404 | * | |
|
405 | * given an event, call the corresponding shortcut. | |||
|
406 | * return false is event wan handled, true otherwise | |||
|
407 | * in any case returning false stop event propagation | |||
|
408 | **/ | |||
|
409 | ||||
|
410 | ||||
|
411 | this.clearsoon(); | |||
|
412 | if(only_modifier_event(event)){ | |||
|
413 | return true; | |||
|
414 | } | |||
253 | var shortcut = event_to_shortcut(event); |
|
415 | var shortcut = event_to_shortcut(event); | |
254 | var data = this._shortcuts[shortcut]; |
|
416 | this._queue.push(shortcut); | |
255 | if (data) { |
|
417 | var action_name = this.get_shortcut(this._queue); | |
256 | var handler = data.handler; |
|
418 | ||
257 | if (handler) { |
|
419 | if (typeof(action_name) === 'undefined'|| action_name === null){ | |
258 | if (data.count === 1) { |
|
420 | this.clearqueue(); | |
259 |
|
|
421 | return true; | |
260 | } else if (data.count > 1) { |
|
422 | } | |
261 | return this.count_handler(shortcut, event, data); |
|
423 | ||
262 | } |
|
424 | if (this.actions.exists(action_name)) { | |
263 | } |
|
425 | event.preventDefault(); | |
|
426 | this.clearqueue(); | |||
|
427 | return this.actions.call(action_name, event); | |||
264 | } |
|
428 | } | |
265 | return true; |
|
429 | ||
|
430 | return false; | |||
266 | }; |
|
431 | }; | |
267 |
|
432 | |||
|
433 | ||||
268 | ShortcutManager.prototype.handles = function (event) { |
|
434 | ShortcutManager.prototype.handles = function (event) { | |
269 | var shortcut = event_to_shortcut(event); |
|
435 | var shortcut = event_to_shortcut(event); | |
270 |
var |
|
436 | var action_name = this.get_shortcut(this._queue.concat(shortcut)); | |
271 | return !( data === undefined || data.handler === undefined ); |
|
437 | return (typeof(action_name) !== 'undefined'); | |
272 | }; |
|
438 | }; | |
273 |
|
439 | |||
274 | var keyboard = { |
|
440 | var keyboard = { | |
@@ -278,7 +444,7 b' define([' | |||||
278 | normalize_key : normalize_key, |
|
444 | normalize_key : normalize_key, | |
279 | normalize_shortcut : normalize_shortcut, |
|
445 | normalize_shortcut : normalize_shortcut, | |
280 | shortcut_to_event : shortcut_to_event, |
|
446 | shortcut_to_event : shortcut_to_event, | |
281 | event_to_shortcut : event_to_shortcut |
|
447 | event_to_shortcut : event_to_shortcut, | |
282 | }; |
|
448 | }; | |
283 |
|
449 | |||
284 | // For backwards compatibility. |
|
450 | // For backwards compatibility. |
This diff has been collapsed as it changes many lines, (533 lines changed) Show them Hide them | |||||
@@ -16,9 +16,6 b' define([' | |||||
16 | ], function(IPython, $, utils, keyboard) { |
|
16 | ], function(IPython, $, utils, keyboard) { | |
17 | "use strict"; |
|
17 | "use strict"; | |
18 |
|
18 | |||
19 | var browser = utils.browser[0]; |
|
|||
20 | var platform = utils.platform; |
|
|||
21 |
|
||||
22 | // Main keyboard manager for the notebook |
|
19 | // Main keyboard manager for the notebook | |
23 | var keycodes = keyboard.keycodes; |
|
20 | var keycodes = keyboard.keycodes; | |
24 |
|
21 | |||
@@ -37,470 +34,101 b' define([' | |||||
37 | this.pager = options.pager; |
|
34 | this.pager = options.pager; | |
38 | this.quick_help = undefined; |
|
35 | this.quick_help = undefined; | |
39 | this.notebook = undefined; |
|
36 | this.notebook = undefined; | |
|
37 | this.last_mode = undefined; | |||
40 | this.bind_events(); |
|
38 | this.bind_events(); | |
41 | this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events); |
|
39 | this.env = {pager:this.pager}; | |
|
40 | this.actions = options.actions; | |||
|
41 | this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env ); | |||
42 | this.command_shortcuts.add_shortcuts(this.get_default_common_shortcuts()); |
|
42 | this.command_shortcuts.add_shortcuts(this.get_default_common_shortcuts()); | |
43 | this.command_shortcuts.add_shortcuts(this.get_default_command_shortcuts()); |
|
43 | this.command_shortcuts.add_shortcuts(this.get_default_command_shortcuts()); | |
44 | this.edit_shortcuts = new keyboard.ShortcutManager(undefined, options.events); |
|
44 | this.edit_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env); | |
45 | this.edit_shortcuts.add_shortcuts(this.get_default_common_shortcuts()); |
|
45 | this.edit_shortcuts.add_shortcuts(this.get_default_common_shortcuts()); | |
46 | this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts()); |
|
46 | this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts()); | |
|
47 | Object.seal(this); | |||
47 | }; |
|
48 | }; | |
48 |
|
49 | |||
|
50 | ||||
|
51 | ||||
|
52 | ||||
49 | /** |
|
53 | /** | |
50 | * Return a dict of common shortcut |
|
54 | * Return a dict of common shortcut | |
51 | * @method get_default_common_shortcuts |
|
55 | * @method get_default_common_shortcuts | |
52 | * |
|
56 | * | |
53 | * @example Example of returned shortcut |
|
57 | * @example Example of returned shortcut | |
54 | * ``` |
|
58 | * ``` | |
55 | * 'shortcut-key': // a string representing the shortcut as dash separated value. |
|
59 | * 'shortcut-key': 'action-name' | |
56 | * // e.g. 'shift' , 'shift-enter', 'cmd-t' |
|
60 | * // a string representing the shortcut as dash separated value. | |
57 | * { |
|
61 | * // e.g. 'shift' , 'shift-enter', 'cmd-t' | |
58 | * help: String // user facing help string |
|
|||
59 | * help_index: String // string used internally to order the shortcut on the quickhelp |
|
|||
60 | * handler: function(event){return true|false} // function that takes an even as first and only parameter |
|
|||
61 | * // and return a boolean indicating whether or not the event should been handled further. |
|
|||
62 | * } |
|
|||
63 | *``` |
|
62 | *``` | |
64 | */ |
|
63 | */ | |
65 | KeyboardManager.prototype.get_default_common_shortcuts = function() { |
|
64 | KeyboardManager.prototype.get_default_common_shortcuts = function() { | |
66 | var that = this; |
|
65 | return { | |
67 | var shortcuts = { |
|
66 | 'shift' : 'ipython.ignore', | |
68 | 'shift' : { |
|
67 | 'shift-enter' : 'ipython.run-select-next', | |
69 | help : '', |
|
68 | 'ctrl-enter' : 'ipython.execute-in-place', | |
70 | help_index : '', |
|
69 | 'alt-enter' : 'ipython.execute-and-insert-after', | |
71 | handler : function (event) { |
|
70 | // cmd on mac, ctrl otherwise | |
72 | // ignore shift keydown |
|
71 | 'cmdtrl-s' : 'ipython.save-notebook', | |
73 | return true; |
|
|||
74 | } |
|
|||
75 | }, |
|
|||
76 | 'shift-enter' : { |
|
|||
77 | help : 'run cell, select below', |
|
|||
78 | help_index : 'ba', |
|
|||
79 | handler : function (event) { |
|
|||
80 | that.notebook.execute_cell_and_select_below(); |
|
|||
81 | return false; |
|
|||
82 | } |
|
|||
83 | }, |
|
|||
84 | 'ctrl-enter' : { |
|
|||
85 | help : 'run cell', |
|
|||
86 | help_index : 'bb', |
|
|||
87 | handler : function (event) { |
|
|||
88 | that.notebook.execute_cell(); |
|
|||
89 | return false; |
|
|||
90 | } |
|
|||
91 | }, |
|
|||
92 | 'alt-enter' : { |
|
|||
93 | help : 'run cell, insert below', |
|
|||
94 | help_index : 'bc', |
|
|||
95 | handler : function (event) { |
|
|||
96 | that.notebook.execute_cell_and_insert_below(); |
|
|||
97 | return false; |
|
|||
98 | } |
|
|||
99 | } |
|
|||
100 | }; |
|
72 | }; | |
101 |
|
||||
102 | if (platform === 'MacOS') { |
|
|||
103 | shortcuts['cmd-s'] = |
|
|||
104 | { |
|
|||
105 | help : 'save notebook', |
|
|||
106 | help_index : 'fb', |
|
|||
107 | handler : function (event) { |
|
|||
108 | that.notebook.save_checkpoint(); |
|
|||
109 | event.preventDefault(); |
|
|||
110 | return false; |
|
|||
111 | } |
|
|||
112 | }; |
|
|||
113 | } else { |
|
|||
114 | shortcuts['ctrl-s'] = |
|
|||
115 | { |
|
|||
116 | help : 'save notebook', |
|
|||
117 | help_index : 'fb', |
|
|||
118 | handler : function (event) { |
|
|||
119 | that.notebook.save_checkpoint(); |
|
|||
120 | event.preventDefault(); |
|
|||
121 | return false; |
|
|||
122 | } |
|
|||
123 | }; |
|
|||
124 | } |
|
|||
125 | return shortcuts; |
|
|||
126 | }; |
|
73 | }; | |
127 |
|
74 | |||
128 | KeyboardManager.prototype.get_default_edit_shortcuts = function() { |
|
75 | KeyboardManager.prototype.get_default_edit_shortcuts = function() { | |
129 | var that = this; |
|
|||
130 | return { |
|
76 | return { | |
131 | 'esc' : { |
|
77 | 'esc' : 'ipython.go-to-command-mode', | |
132 | help : 'command mode', |
|
78 | 'ctrl-m' : 'ipython.go-to-command-mode', | |
133 | help_index : 'aa', |
|
79 | 'up' : 'ipython.move-cursor-up-or-previous-cell', | |
134 | handler : function (event) { |
|
80 | 'down' : 'ipython.move-cursor-down-or-next-cell', | |
135 | that.notebook.command_mode(); |
|
81 | 'ctrl-shift--' : 'ipython.split-cell-at-cursor', | |
136 | return false; |
|
82 | 'ctrl-shift-subtract' : 'ipython.split-cell-at-cursor' | |
137 | } |
|
|||
138 | }, |
|
|||
139 | 'ctrl-m' : { |
|
|||
140 | help : 'command mode', |
|
|||
141 | help_index : 'ab', |
|
|||
142 | handler : function (event) { |
|
|||
143 | that.notebook.command_mode(); |
|
|||
144 | return false; |
|
|||
145 | } |
|
|||
146 | }, |
|
|||
147 | 'up' : { |
|
|||
148 | help : '', |
|
|||
149 | help_index : '', |
|
|||
150 | handler : function (event) { |
|
|||
151 | var index = that.notebook.get_selected_index(); |
|
|||
152 | var cell = that.notebook.get_cell(index); |
|
|||
153 | var cm = that.notebook.get_selected_cell().code_mirror; |
|
|||
154 | var cur = cm.getCursor() |
|
|||
155 | if (cell && cell.at_top() && index !== 0 && cur.ch === 0) { |
|
|||
156 | event.preventDefault(); |
|
|||
157 | that.notebook.command_mode(); |
|
|||
158 | that.notebook.select_prev(); |
|
|||
159 | that.notebook.edit_mode(); |
|
|||
160 | var cm = that.notebook.get_selected_cell().code_mirror; |
|
|||
161 | cm.setCursor(cm.lastLine(), 0); |
|
|||
162 | } |
|
|||
163 | return false; |
|
|||
164 | } |
|
|||
165 | }, |
|
|||
166 | 'down' : { |
|
|||
167 | help : '', |
|
|||
168 | help_index : '', |
|
|||
169 | handler : function (event) { |
|
|||
170 | var index = that.notebook.get_selected_index(); |
|
|||
171 | var cell = that.notebook.get_cell(index); |
|
|||
172 | if (cell.at_bottom() && index !== (that.notebook.ncells()-1)) { |
|
|||
173 | event.preventDefault(); |
|
|||
174 | that.notebook.command_mode(); |
|
|||
175 | that.notebook.select_next(); |
|
|||
176 | that.notebook.edit_mode(); |
|
|||
177 | var cm = that.notebook.get_selected_cell().code_mirror; |
|
|||
178 | cm.setCursor(0, 0); |
|
|||
179 | return false; |
|
|||
180 | } |
|
|||
181 | return false; |
|
|||
182 | } |
|
|||
183 | }, |
|
|||
184 | 'ctrl-shift--' : { |
|
|||
185 | help : 'split cell', |
|
|||
186 | help_index : 'ea', |
|
|||
187 | handler : function (event) { |
|
|||
188 | that.notebook.split_cell(); |
|
|||
189 | return false; |
|
|||
190 | } |
|
|||
191 | }, |
|
|||
192 | 'ctrl-shift-subtract' : { |
|
|||
193 | help : '', |
|
|||
194 | help_index : 'eb', |
|
|||
195 | handler : function (event) { |
|
|||
196 | that.notebook.split_cell(); |
|
|||
197 | return false; |
|
|||
198 | } |
|
|||
199 | }, |
|
|||
200 | }; |
|
83 | }; | |
201 | }; |
|
84 | }; | |
202 |
|
85 | |||
203 | KeyboardManager.prototype.get_default_command_shortcuts = function() { |
|
86 | KeyboardManager.prototype.get_default_command_shortcuts = function() { | |
204 | var that = this; |
|
|||
205 | return { |
|
87 | return { | |
206 |
'space': |
|
88 | 'shift-space': 'ipython.scroll-up', | |
207 | help: "Scroll down", |
|
89 | 'shift-v' : 'ipython.paste-cell-before', | |
208 | handler: function(event) { |
|
90 | 'shift-m' : 'ipython.merge-selected-cell-with-cell-after', | |
209 | return that.notebook.scroll_manager.scroll(1); |
|
91 | 'shift-o' : 'ipython.toggle-output-scrolling-selected-cell', | |
210 | }, |
|
92 | 'ctrl-j' : 'ipython.move-selected-cell-down', | |
211 | }, |
|
93 | 'ctrl-k' : 'ipython.move-selected-cell-up', | |
212 | 'shift-space': { |
|
94 | 'enter' : 'ipython.enter-edit-mode', | |
213 | help: "Scroll up", |
|
95 | 'space' : 'ipython.scroll-down', | |
214 | handler: function(event) { |
|
96 | 'down' : 'ipython.select-next-cell', | |
215 | return that.notebook.scroll_manager.scroll(-1); |
|
97 | 'i,i' : 'ipython.interrupt-kernel', | |
216 | }, |
|
98 | '0,0' : 'ipython.restart-kernel', | |
217 | }, |
|
99 | 'd,d' : 'ipython.delete-cell', | |
218 | 'enter' : { |
|
100 | 'up' : 'ipython.select-previous-cell', | |
219 | help : 'edit mode', |
|
101 | 'k' : 'ipython.select-previous-cell', | |
220 | help_index : 'aa', |
|
102 | 'j' : 'ipython.select-next-cell', | |
221 | handler : function (event) { |
|
103 | 'x' : 'ipython.cut-selected-cell', | |
222 | that.notebook.edit_mode(); |
|
104 | 'c' : 'ipython.copy-selected-cell', | |
223 | return false; |
|
105 | 'v' : 'ipython.paste-cell-after', | |
224 | } |
|
106 | 'a' : 'ipython.insert-cell-before', | |
225 | }, |
|
107 | 'b' : 'ipython.insert-cell-after', | |
226 | 'up' : { |
|
108 | 'y' : 'ipython.change-selected-cell-to-code-cell', | |
227 | help : 'select previous cell', |
|
109 | 'm' : 'ipython.change-selected-cell-to-markdown-cell', | |
228 | help_index : 'da', |
|
110 | 'r' : 'ipython.change-selected-cell-to-raw-cell', | |
229 | handler : function (event) { |
|
111 | '1' : 'ipython.change-selected-cell-to-heading-1', | |
230 | var index = that.notebook.get_selected_index(); |
|
112 | '2' : 'ipython.change-selected-cell-to-heading-2', | |
231 | if (index !== 0 && index !== null) { |
|
113 | '3' : 'ipython.change-selected-cell-to-heading-3', | |
232 | that.notebook.select_prev(); |
|
114 | '4' : 'ipython.change-selected-cell-to-heading-4', | |
233 | that.notebook.focus_cell(); |
|
115 | '5' : 'ipython.change-selected-cell-to-heading-5', | |
234 | } |
|
116 | '6' : 'ipython.change-selected-cell-to-heading-6', | |
235 | return false; |
|
117 | 'o' : 'ipython.toggle-output-visibility-selected-cell', | |
236 | } |
|
118 | 's' : 'ipython.save-notebook', | |
237 | }, |
|
119 | 'l' : 'ipython.toggle-line-number-selected-cell', | |
238 | 'down' : { |
|
120 | 'h' : 'ipython.show-keyboard-shortcut-help-dialog', | |
239 | help : 'select next cell', |
|
121 | 'z' : 'ipython.undo-last-cell-deletion', | |
240 | help_index : 'db', |
|
122 | 'q' : 'ipython.close-pager', | |
241 | handler : function (event) { |
|
123 | 'i,e,e,e,e,e' : function(){console.log('[[===>>> 5E <<<===]]');}, | |
242 | var index = that.notebook.get_selected_index(); |
|
124 | 'i,d,d,q,d' : function(){console.log('[[===>>> Trigger god mode <<<===]]');}, | |
243 | if (index !== (that.notebook.ncells()-1) && index !== null) { |
|
125 | 'i,d,d' : function(){console.log('[[===>>> should warn at registration <<<===]]');}, | |
244 | that.notebook.select_next(); |
|
126 | 'i,d,k' : function(){console.log('[[===>>> Trigger shadow mode <<<===]]');}, | |
245 | that.notebook.focus_cell(); |
|
127 | 'i,d,k,r,q' : function(){console.log('[[===>>> Trigger invisibility mode <<<===]]');}, | |
246 | } |
|
128 | ';,up,down,up,down,left,right,left,right,b,a' : function(){console.log('[[===>>> Konami <<<===]]');}, | |
247 | return false; |
|
129 | 'ctrl-x,meta-c,meta-b,u,t,t,e,r,f,l,y' : function(){ | |
248 | } |
|
130 | console.log('[[Are you a real Programmer ?]]'); | |
249 | }, |
|
131 | window.open('http://xkcd.com/378/','_blank'); | |
250 | 'k' : { |
|
|||
251 | help : 'select previous cell', |
|
|||
252 | help_index : 'dc', |
|
|||
253 | handler : function (event) { |
|
|||
254 | var index = that.notebook.get_selected_index(); |
|
|||
255 | if (index !== 0 && index !== null) { |
|
|||
256 | that.notebook.select_prev(); |
|
|||
257 | that.notebook.focus_cell(); |
|
|||
258 | } |
|
|||
259 | return false; |
|
|||
260 | } |
|
|||
261 | }, |
|
|||
262 | 'j' : { |
|
|||
263 | help : 'select next cell', |
|
|||
264 | help_index : 'dd', |
|
|||
265 | handler : function (event) { |
|
|||
266 | var index = that.notebook.get_selected_index(); |
|
|||
267 | if (index !== (that.notebook.ncells()-1) && index !== null) { |
|
|||
268 | that.notebook.select_next(); |
|
|||
269 | that.notebook.focus_cell(); |
|
|||
270 | } |
|
|||
271 | return false; |
|
|||
272 | } |
|
|||
273 | }, |
|
|||
274 | 'x' : { |
|
|||
275 | help : 'cut cell', |
|
|||
276 | help_index : 'ee', |
|
|||
277 | handler : function (event) { |
|
|||
278 | that.notebook.cut_cell(); |
|
|||
279 | return false; |
|
|||
280 | } |
|
|||
281 | }, |
|
|||
282 | 'c' : { |
|
|||
283 | help : 'copy cell', |
|
|||
284 | help_index : 'ef', |
|
|||
285 | handler : function (event) { |
|
|||
286 | that.notebook.copy_cell(); |
|
|||
287 | return false; |
|
|||
288 | } |
|
|||
289 | }, |
|
|||
290 | 'shift-v' : { |
|
|||
291 | help : 'paste cell above', |
|
|||
292 | help_index : 'eg', |
|
|||
293 | handler : function (event) { |
|
|||
294 | that.notebook.paste_cell_above(); |
|
|||
295 | return false; |
|
|||
296 | } |
|
|||
297 | }, |
|
|||
298 | 'v' : { |
|
|||
299 | help : 'paste cell below', |
|
|||
300 | help_index : 'eh', |
|
|||
301 | handler : function (event) { |
|
|||
302 | that.notebook.paste_cell_below(); |
|
|||
303 | return false; |
|
|||
304 | } |
|
|||
305 | }, |
|
|||
306 | 'd' : { |
|
|||
307 | help : 'delete cell (press twice)', |
|
|||
308 | help_index : 'ej', |
|
|||
309 | count: 2, |
|
|||
310 | handler : function (event) { |
|
|||
311 | that.notebook.delete_cell(); |
|
|||
312 | return false; |
|
|||
313 | } |
|
|||
314 | }, |
|
|||
315 | 'a' : { |
|
|||
316 | help : 'insert cell above', |
|
|||
317 | help_index : 'ec', |
|
|||
318 | handler : function (event) { |
|
|||
319 | that.notebook.insert_cell_above(); |
|
|||
320 | that.notebook.select_prev(); |
|
|||
321 | that.notebook.focus_cell(); |
|
|||
322 | return false; |
|
|||
323 | } |
|
|||
324 | }, |
|
|||
325 | 'b' : { |
|
|||
326 | help : 'insert cell below', |
|
|||
327 | help_index : 'ed', |
|
|||
328 | handler : function (event) { |
|
|||
329 | that.notebook.insert_cell_below(); |
|
|||
330 | that.notebook.select_next(); |
|
|||
331 | that.notebook.focus_cell(); |
|
|||
332 | return false; |
|
|||
333 | } |
|
|||
334 | }, |
|
|||
335 | 'y' : { |
|
|||
336 | help : 'to code', |
|
|||
337 | help_index : 'ca', |
|
|||
338 | handler : function (event) { |
|
|||
339 | that.notebook.to_code(); |
|
|||
340 | return false; |
|
|||
341 | } |
|
|||
342 | }, |
|
|||
343 | 'm' : { |
|
|||
344 | help : 'to markdown', |
|
|||
345 | help_index : 'cb', |
|
|||
346 | handler : function (event) { |
|
|||
347 | that.notebook.to_markdown(); |
|
|||
348 | return false; |
|
|||
349 | } |
|
|||
350 | }, |
|
|||
351 | 'r' : { |
|
|||
352 | help : 'to raw', |
|
|||
353 | help_index : 'cc', |
|
|||
354 | handler : function (event) { |
|
|||
355 | that.notebook.to_raw(); |
|
|||
356 | return false; |
|
|||
357 | } |
|
|||
358 | }, |
|
|||
359 | '1' : { |
|
|||
360 | help : 'to heading 1', |
|
|||
361 | help_index : 'cd', |
|
|||
362 | handler : function (event) { |
|
|||
363 | that.notebook.to_heading(undefined, 1); |
|
|||
364 | return false; |
|
|||
365 | } |
|
|||
366 | }, |
|
|||
367 | '2' : { |
|
|||
368 | help : 'to heading 2', |
|
|||
369 | help_index : 'ce', |
|
|||
370 | handler : function (event) { |
|
|||
371 | that.notebook.to_heading(undefined, 2); |
|
|||
372 | return false; |
|
|||
373 | } |
|
|||
374 | }, |
|
|||
375 | '3' : { |
|
|||
376 | help : 'to heading 3', |
|
|||
377 | help_index : 'cf', |
|
|||
378 | handler : function (event) { |
|
|||
379 | that.notebook.to_heading(undefined, 3); |
|
|||
380 | return false; |
|
|||
381 | } |
|
|||
382 | }, |
|
|||
383 | '4' : { |
|
|||
384 | help : 'to heading 4', |
|
|||
385 | help_index : 'cg', |
|
|||
386 | handler : function (event) { |
|
|||
387 | that.notebook.to_heading(undefined, 4); |
|
|||
388 | return false; |
|
|||
389 | } |
|
|||
390 | }, |
|
|||
391 | '5' : { |
|
|||
392 | help : 'to heading 5', |
|
|||
393 | help_index : 'ch', |
|
|||
394 | handler : function (event) { |
|
|||
395 | that.notebook.to_heading(undefined, 5); |
|
|||
396 | return false; |
|
|||
397 | } |
|
|||
398 | }, |
|
|||
399 | '6' : { |
|
|||
400 | help : 'to heading 6', |
|
|||
401 | help_index : 'ci', |
|
|||
402 | handler : function (event) { |
|
|||
403 | that.notebook.to_heading(undefined, 6); |
|
|||
404 | return false; |
|
|||
405 | } |
|
|||
406 | }, |
|
|||
407 | 'o' : { |
|
|||
408 | help : 'toggle output', |
|
|||
409 | help_index : 'gb', |
|
|||
410 | handler : function (event) { |
|
|||
411 | that.notebook.toggle_output(); |
|
|||
412 | return false; |
|
|||
413 | } |
|
|||
414 | }, |
|
|||
415 | 'shift-o' : { |
|
|||
416 | help : 'toggle output scrolling', |
|
|||
417 | help_index : 'gc', |
|
|||
418 | handler : function (event) { |
|
|||
419 | that.notebook.toggle_output_scroll(); |
|
|||
420 | return false; |
|
|||
421 | } |
|
|||
422 | }, |
|
|||
423 | 's' : { |
|
|||
424 | help : 'save notebook', |
|
|||
425 | help_index : 'fa', |
|
|||
426 | handler : function (event) { |
|
|||
427 | that.notebook.save_checkpoint(); |
|
|||
428 | return false; |
|
|||
429 | } |
|
|||
430 | }, |
|
|||
431 | 'ctrl-j' : { |
|
|||
432 | help : 'move cell down', |
|
|||
433 | help_index : 'eb', |
|
|||
434 | handler : function (event) { |
|
|||
435 | that.notebook.move_cell_down(); |
|
|||
436 | return false; |
|
|||
437 | } |
|
|||
438 | }, |
|
|||
439 | 'ctrl-k' : { |
|
|||
440 | help : 'move cell up', |
|
|||
441 | help_index : 'ea', |
|
|||
442 | handler : function (event) { |
|
|||
443 | that.notebook.move_cell_up(); |
|
|||
444 | return false; |
|
|||
445 | } |
|
|||
446 | }, |
|
|||
447 | 'l' : { |
|
|||
448 | help : 'toggle line numbers', |
|
|||
449 | help_index : 'ga', |
|
|||
450 | handler : function (event) { |
|
|||
451 | that.notebook.cell_toggle_line_numbers(); |
|
|||
452 | return false; |
|
|||
453 | } |
|
|||
454 | }, |
|
|||
455 | 'i' : { |
|
|||
456 | help : 'interrupt kernel (press twice)', |
|
|||
457 | help_index : 'ha', |
|
|||
458 | count: 2, |
|
|||
459 | handler : function (event) { |
|
|||
460 | that.notebook.kernel.interrupt(); |
|
|||
461 | return false; |
|
|||
462 | } |
|
|||
463 | }, |
|
|||
464 | '0' : { |
|
|||
465 | help : 'restart kernel (press twice)', |
|
|||
466 | help_index : 'hb', |
|
|||
467 | count: 2, |
|
|||
468 | handler : function (event) { |
|
|||
469 | that.notebook.restart_kernel(); |
|
|||
470 | return false; |
|
|||
471 | } |
|
|||
472 | }, |
|
|||
473 | 'h' : { |
|
|||
474 | help : 'keyboard shortcuts', |
|
|||
475 | help_index : 'ge', |
|
|||
476 | handler : function (event) { |
|
|||
477 | that.quick_help.show_keyboard_shortcuts(); |
|
|||
478 | return false; |
|
|||
479 | } |
|
|||
480 | }, |
|
|||
481 | 'z' : { |
|
|||
482 | help : 'undo last delete', |
|
|||
483 | help_index : 'ei', |
|
|||
484 | handler : function (event) { |
|
|||
485 | that.notebook.undelete_cell(); |
|
|||
486 | return false; |
|
|||
487 | } |
|
|||
488 | }, |
|
|||
489 | 'shift-m' : { |
|
|||
490 | help : 'merge cell below', |
|
|||
491 | help_index : 'ek', |
|
|||
492 | handler : function (event) { |
|
|||
493 | that.notebook.merge_cell_below(); |
|
|||
494 | return false; |
|
|||
495 | } |
|
|||
496 | }, |
|
|||
497 | 'q' : { |
|
|||
498 | help : 'close pager', |
|
|||
499 | help_index : 'gd', |
|
|||
500 | handler : function (event) { |
|
|||
501 | that.pager.collapse(); |
|
|||
502 | return false; |
|
|||
503 | } |
|
|||
504 | }, |
|
132 | }, | |
505 | }; |
|
133 | }; | |
506 | }; |
|
134 | }; | |
@@ -508,16 +136,27 b' define([' | |||||
508 | KeyboardManager.prototype.bind_events = function () { |
|
136 | KeyboardManager.prototype.bind_events = function () { | |
509 | var that = this; |
|
137 | var that = this; | |
510 | $(document).keydown(function (event) { |
|
138 | $(document).keydown(function (event) { | |
511 |
|
139 | if(event._ipkmIgnore===true||(event.originalEvent||{})._ipkmIgnore===true){ | ||
512 | if(event._ipkmIgnore==true||(event.originalEvent||{})._ipkmIgnore==true){ |
|
|||
513 | return false; |
|
140 | return false; | |
514 | } |
|
141 | } | |
515 | return that.handle_keydown(event); |
|
142 | return that.handle_keydown(event); | |
516 | }); |
|
143 | }); | |
517 | }; |
|
144 | }; | |
518 |
|
145 | |||
|
146 | KeyboardManager.prototype.set_notebook = function (notebook) { | |||
|
147 | this.notebook = notebook; | |||
|
148 | this.actions.extend_env({notebook:notebook}); | |||
|
149 | }; | |||
|
150 | ||||
|
151 | KeyboardManager.prototype.set_quickhelp = function (notebook) { | |||
|
152 | this.actions.extend_env({quick_help:notebook}); | |||
|
153 | }; | |||
|
154 | ||||
|
155 | ||||
519 | KeyboardManager.prototype.handle_keydown = function (event) { |
|
156 | KeyboardManager.prototype.handle_keydown = function (event) { | |
520 | var notebook = this.notebook; |
|
157 | /** | |
|
158 | * returning false from this will stop event propagation | |||
|
159 | **/ | |||
521 |
|
160 | |||
522 | if (event.which === keycodes.esc) { |
|
161 | if (event.which === keycodes.esc) { | |
523 | // Intercept escape at highest level to avoid closing |
|
162 | // Intercept escape at highest level to avoid closing | |
@@ -527,8 +166,7 b' define([' | |||||
527 |
|
166 | |||
528 | if (!this.enabled) { |
|
167 | if (!this.enabled) { | |
529 | if (event.which === keycodes.esc) { |
|
168 | if (event.which === keycodes.esc) { | |
530 | // ESC |
|
169 | this.notebook.command_mode(); | |
531 | notebook.command_mode(); |
|
|||
532 | return false; |
|
170 | return false; | |
533 | } |
|
171 | } | |
534 | return true; |
|
172 | return true; | |
@@ -595,7 +233,8 b' define([' | |||||
595 | }); |
|
233 | }); | |
596 | }; |
|
234 | }; | |
597 |
|
235 | |||
598 | // For backwards compatability. |
|
236 | ||
|
237 | // For backwards compatibility. | |||
599 | IPython.KeyboardManager = KeyboardManager; |
|
238 | IPython.KeyboardManager = KeyboardManager; | |
600 |
|
239 | |||
601 | return {'KeyboardManager': KeyboardManager}; |
|
240 | return {'KeyboardManager': KeyboardManager}; |
@@ -16,6 +16,7 b' require([' | |||||
16 | 'notebook/js/menubar', |
|
16 | 'notebook/js/menubar', | |
17 | 'notebook/js/notificationarea', |
|
17 | 'notebook/js/notificationarea', | |
18 | 'notebook/js/savewidget', |
|
18 | 'notebook/js/savewidget', | |
|
19 | 'notebook/js/actions', | |||
19 | 'notebook/js/keyboardmanager', |
|
20 | 'notebook/js/keyboardmanager', | |
20 | 'notebook/js/config', |
|
21 | 'notebook/js/config', | |
21 | 'notebook/js/kernelselector', |
|
22 | 'notebook/js/kernelselector', | |
@@ -36,7 +37,8 b' require([' | |||||
36 | quickhelp, |
|
37 | quickhelp, | |
37 | menubar, |
|
38 | menubar, | |
38 | notificationarea, |
|
39 | notificationarea, | |
39 |
savewidget, |
|
40 | savewidget, | |
|
41 | actions, | |||
40 | keyboardmanager, |
|
42 | keyboardmanager, | |
41 | config, |
|
43 | config, | |
42 | kernelselector, |
|
44 | kernelselector, | |
@@ -62,9 +64,11 b' require([' | |||||
62 | var pager = new pager.Pager('div#pager', 'div#pager_splitter', { |
|
64 | var pager = new pager.Pager('div#pager', 'div#pager_splitter', { | |
63 | layout_manager: layout_manager, |
|
65 | layout_manager: layout_manager, | |
64 | events: events}); |
|
66 | events: events}); | |
|
67 | var acts = new actions.init(); | |||
65 | var keyboard_manager = new keyboardmanager.KeyboardManager({ |
|
68 | var keyboard_manager = new keyboardmanager.KeyboardManager({ | |
66 | pager: pager, |
|
69 | pager: pager, | |
67 |
events: events |
|
70 | events: events, | |
|
71 | actions: acts }); | |||
68 | var save_widget = new savewidget.SaveWidget('span#save_widget', { |
|
72 | var save_widget = new savewidget.SaveWidget('span#save_widget', { | |
69 | events: events, |
|
73 | events: events, | |
70 | keyboard_manager: keyboard_manager}); |
|
74 | keyboard_manager: keyboard_manager}); | |
@@ -77,11 +81,14 b' require([' | |||||
77 | var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options); |
|
81 | var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options); | |
78 | var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', { |
|
82 | var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', { | |
79 | notebook: notebook, |
|
83 | notebook: notebook, | |
80 |
events: events |
|
84 | events: events, | |
|
85 | actions: acts}); | |||
81 | var quick_help = new quickhelp.QuickHelp({ |
|
86 | var quick_help = new quickhelp.QuickHelp({ | |
82 | keyboard_manager: keyboard_manager, |
|
87 | keyboard_manager: keyboard_manager, | |
83 | events: events, |
|
88 | events: events, | |
84 | notebook: notebook}); |
|
89 | notebook: notebook}); | |
|
90 | keyboard_manager.set_notebook(notebook); | |||
|
91 | keyboard_manager.set_quickhelp(quick_help); | |||
85 | var menubar = new menubar.MenuBar('#menubar', $.extend({ |
|
92 | var menubar = new menubar.MenuBar('#menubar', $.extend({ | |
86 | notebook: notebook, |
|
93 | notebook: notebook, | |
87 | layout_manager: layout_manager, |
|
94 | layout_manager: layout_manager, |
@@ -34,10 +34,10 b' define([' | |||||
34 | platform_specific = [ |
|
34 | platform_specific = [ | |
35 | { shortcut: "Cmd-Up", help:"go to cell start" }, |
|
35 | { shortcut: "Cmd-Up", help:"go to cell start" }, | |
36 | { shortcut: "Cmd-Down", help:"go to cell end" }, |
|
36 | { shortcut: "Cmd-Down", help:"go to cell end" }, | |
37 |
{ shortcut: " |
|
37 | { shortcut: "Alt-Left", help:"go one word left" }, | |
38 |
{ shortcut: " |
|
38 | { shortcut: "Alt-Right", help:"go one word right" }, | |
39 |
{ shortcut: " |
|
39 | { shortcut: "Alt-Backspace", help:"del word before" }, | |
40 |
{ shortcut: " |
|
40 | { shortcut: "Alt-Delete", help:"del word after" }, | |
41 | ]; |
|
41 | ]; | |
42 | } else { |
|
42 | } else { | |
43 | // PC specific |
|
43 | // PC specific | |
@@ -65,10 +65,6 b' define([' | |||||
65 | ].concat( platform_specific ); |
|
65 | ].concat( platform_specific ); | |
66 |
|
66 | |||
67 |
|
67 | |||
68 |
|
||||
69 |
|
||||
70 |
|
||||
71 |
|
||||
72 | QuickHelp.prototype.show_keyboard_shortcuts = function () { |
|
68 | QuickHelp.prototype.show_keyboard_shortcuts = function () { | |
73 | // toggles display of keyboard shortcut dialog |
|
69 | // toggles display of keyboard shortcut dialog | |
74 | var that = this; |
|
70 | var that = this; | |
@@ -139,7 +135,9 b' define([' | |||||
139 | keys[i] = "<code><strong>" + k + "</strong></code>"; |
|
135 | keys[i] = "<code><strong>" + k + "</strong></code>"; | |
140 | continue; // leave individual keys lower-cased |
|
136 | continue; // leave individual keys lower-cased | |
141 | } |
|
137 | } | |
142 | keys[i] = ( special_case[k] ? special_case[k] : k.charAt(0).toUpperCase() + k.slice(1) ); |
|
138 | if (k.indexOf(',') === -1){ | |
|
139 | keys[i] = ( special_case[k] ? special_case[k] : k.charAt(0).toUpperCase() + k.slice(1) ); | |||
|
140 | } | |||
143 | keys[i] = "<code><strong>" + keys[i] + "</strong></code>"; |
|
141 | keys[i] = "<code><strong>" + keys[i] + "</strong></code>"; | |
144 | } |
|
142 | } | |
145 | return keys.join('-'); |
|
143 | return keys.join('-'); | |
@@ -155,7 +153,12 b' define([' | |||||
155 |
|
153 | |||
156 | var build_one = function (s) { |
|
154 | var build_one = function (s) { | |
157 | var help = s.help; |
|
155 | var help = s.help; | |
158 |
var shortcut = |
|
156 | var shortcut = ''; | |
|
157 | if(s.shortcut){ | |||
|
158 | shortcut = prettify(s.shortcut); | |||
|
159 | } else { | |||
|
160 | console.error('[debug] - nothing for', s) | |||
|
161 | } | |||
159 | return $('<div>').addClass('quickhelp'). |
|
162 | return $('<div>').addClass('quickhelp'). | |
160 | append($('<span/>').addClass('shortcut_key').append($(shortcut))). |
|
163 | append($('<span/>').addClass('shortcut_key').append($(shortcut))). | |
161 | append($('<span/>').addClass('shortcut_descr').text(' : ' + help)); |
|
164 | append($('<span/>').addClass('shortcut_descr').text(' : ' + help)); |
@@ -11,7 +11,7 b' define([' | |||||
11 | * A generic toolbar on which one can add button |
|
11 | * A generic toolbar on which one can add button | |
12 | * @class ToolBar |
|
12 | * @class ToolBar | |
13 | * @constructor |
|
13 | * @constructor | |
14 |
* @param {Dom |
|
14 | * @param {Dom object} selector | |
15 | */ |
|
15 | */ | |
16 | var ToolBar = function (selector, layout_manager) { |
|
16 | var ToolBar = function (selector, layout_manager) { | |
17 | this.selector = selector; |
|
17 | this.selector = selector; |
General Comments 0
You need to be logged in to leave comments.
Login now