##// END OF EJS Templates
Merge pull request #7811 from abalkin/patch-2...
Kyle Kelley -
r20468:32414b78 merge
parent child Browse files
Show More
@@ -1,518 +1,520 b''
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define(function(require){
5 5 "use strict";
6 6
7 7 var ActionHandler = function (env) {
8 8 this.env = env || {};
9 9 Object.seal(this);
10 10 };
11 11
12 12 /**
13 13 * A bunch of predefined `Simple Actions` used by IPython.
14 14 * `Simple Actions` have the following keys:
15 15 * help (optional): a short string the describe the action.
16 16 * will be used in various context, like as menu name, tool tips on buttons,
17 17 * and short description in help menu.
18 18 * help_index (optional): a string used to sort action in help menu.
19 19 * icon (optional): a short string that represent the icon that have to be used with this
20 20 * action. this should mainly correspond to a Font_awesome class.
21 21 * handler : a function which is called when the action is activated. It will receive at first parameter
22 22 * a dictionary containing various handle to element of the notebook.
23 23 *
24 24 * action need to be registered with a **name** that can be use to refer to this action.
25 25 *
26 26 *
27 27 * if `help` is not provided it will be derived by replacing any dash by space
28 28 * in the **name** of the action. It is advised to provide a prefix to action name to
29 29 * avoid conflict the prefix should be all lowercase and end with a dot `.`
30 30 * in the absence of a prefix the behavior of the action is undefined.
31 31 *
32 32 * All action provided by IPython are prefixed with `ipython.`.
33 33 *
34 34 * One can register extra actions or replace an existing action with another one is possible
35 35 * but is considered undefined behavior.
36 36 *
37 37 **/
38 38 var _actions = {
39 39 'run-select-next': {
40 40 icon: 'fa-play',
41 41 help : 'run cell, select below',
42 42 help_index : 'ba',
43 43 handler : function (env) {
44 44 env.notebook.execute_cell_and_select_below();
45 45 }
46 46 },
47 47 'execute-in-place':{
48 48 help : 'run cell',
49 49 help_index : 'bb',
50 50 handler : function (env) {
51 51 env.notebook.execute_cell();
52 52 }
53 53 },
54 54 'execute-and-insert-after':{
55 55 help : 'run cell, insert below',
56 56 help_index : 'bc',
57 57 handler : function (env) {
58 58 env.notebook.execute_cell_and_insert_below();
59 59 }
60 60 },
61 61 'go-to-command-mode': {
62 62 help : 'command mode',
63 63 help_index : 'aa',
64 64 handler : function (env) {
65 65 env.notebook.command_mode();
66 66 }
67 67 },
68 68 'split-cell-at-cursor': {
69 69 help : 'split cell',
70 70 help_index : 'ea',
71 71 handler : function (env) {
72 72 env.notebook.split_cell();
73 73 }
74 74 },
75 75 'enter-edit-mode' : {
76 76 help_index : 'aa',
77 77 handler : function (env) {
78 78 env.notebook.edit_mode();
79 79 }
80 80 },
81 81 'select-previous-cell' : {
82 help: 'select cell above',
82 83 help_index : 'da',
83 84 handler : function (env) {
84 85 var index = env.notebook.get_selected_index();
85 86 if (index !== 0 && index !== null) {
86 87 env.notebook.select_prev();
87 88 env.notebook.focus_cell();
88 89 }
89 90 }
90 91 },
91 92 'select-next-cell' : {
93 help: 'select cell below',
92 94 help_index : 'db',
93 95 handler : function (env) {
94 96 var index = env.notebook.get_selected_index();
95 97 if (index !== (env.notebook.ncells()-1) && index !== null) {
96 98 env.notebook.select_next();
97 99 env.notebook.focus_cell();
98 100 }
99 101 }
100 102 },
101 103 'cut-selected-cell' : {
102 104 icon: 'fa-cut',
103 105 help_index : 'ee',
104 106 handler : function (env) {
105 107 var index = env.notebook.get_selected_index();
106 108 env.notebook.cut_cell();
107 109 env.notebook.select(index);
108 110 env.notebook.focus_cell();
109 111 }
110 112 },
111 113 'copy-selected-cell' : {
112 114 icon: 'fa-copy',
113 115 help_index : 'ef',
114 116 handler : function (env) {
115 117 env.notebook.copy_cell();
116 118 env.notebook.focus_cell();
117 119 }
118 120 },
119 121 'paste-cell-before' : {
120 122 help: 'paste cell above',
121 123 help_index : 'eg',
122 124 handler : function (env) {
123 125 env.notebook.paste_cell_above();
124 126 }
125 127 },
126 128 'paste-cell-after' : {
127 129 help: 'paste cell below',
128 130 icon: 'fa-paste',
129 131 help_index : 'eh',
130 132 handler : function (env) {
131 133 env.notebook.paste_cell_below();
132 134 }
133 135 },
134 136 'insert-cell-before' : {
135 137 help: 'insert cell above',
136 138 help_index : 'ec',
137 139 handler : function (env) {
138 140 env.notebook.insert_cell_above();
139 141 env.notebook.select_prev();
140 142 env.notebook.focus_cell();
141 143 }
142 144 },
143 145 'insert-cell-after' : {
144 146 help: 'insert cell below',
145 147 icon : 'fa-plus',
146 148 help_index : 'ed',
147 149 handler : function (env) {
148 150 env.notebook.insert_cell_below();
149 151 env.notebook.select_next();
150 152 env.notebook.focus_cell();
151 153 }
152 154 },
153 155 'change-selected-cell-to-code-cell' : {
154 156 help : 'to code',
155 157 help_index : 'ca',
156 158 handler : function (env) {
157 159 env.notebook.to_code();
158 160 }
159 161 },
160 162 'change-selected-cell-to-markdown-cell' : {
161 163 help : 'to markdown',
162 164 help_index : 'cb',
163 165 handler : function (env) {
164 166 env.notebook.to_markdown();
165 167 }
166 168 },
167 169 'change-selected-cell-to-raw-cell' : {
168 170 help : 'to raw',
169 171 help_index : 'cc',
170 172 handler : function (env) {
171 173 env.notebook.to_raw();
172 174 }
173 175 },
174 176 'change-selected-cell-to-heading-1' : {
175 177 help : 'to heading 1',
176 178 help_index : 'cd',
177 179 handler : function (env) {
178 180 env.notebook.to_heading(undefined, 1);
179 181 }
180 182 },
181 183 'change-selected-cell-to-heading-2' : {
182 184 help : 'to heading 2',
183 185 help_index : 'ce',
184 186 handler : function (env) {
185 187 env.notebook.to_heading(undefined, 2);
186 188 }
187 189 },
188 190 'change-selected-cell-to-heading-3' : {
189 191 help : 'to heading 3',
190 192 help_index : 'cf',
191 193 handler : function (env) {
192 194 env.notebook.to_heading(undefined, 3);
193 195 }
194 196 },
195 197 'change-selected-cell-to-heading-4' : {
196 198 help : 'to heading 4',
197 199 help_index : 'cg',
198 200 handler : function (env) {
199 201 env.notebook.to_heading(undefined, 4);
200 202 }
201 203 },
202 204 'change-selected-cell-to-heading-5' : {
203 205 help : 'to heading 5',
204 206 help_index : 'ch',
205 207 handler : function (env) {
206 208 env.notebook.to_heading(undefined, 5);
207 209 }
208 210 },
209 211 'change-selected-cell-to-heading-6' : {
210 212 help : 'to heading 6',
211 213 help_index : 'ci',
212 214 handler : function (env) {
213 215 env.notebook.to_heading(undefined, 6);
214 216 }
215 217 },
216 218 'toggle-output-visibility-selected-cell' : {
217 219 help : 'toggle output',
218 220 help_index : 'gb',
219 221 handler : function (env) {
220 222 env.notebook.toggle_output();
221 223 }
222 224 },
223 225 'toggle-output-scrolling-selected-cell' : {
224 226 help : 'toggle output scrolling',
225 227 help_index : 'gc',
226 228 handler : function (env) {
227 229 env.notebook.toggle_output_scroll();
228 230 }
229 231 },
230 232 'move-selected-cell-down' : {
231 233 icon: 'fa-arrow-down',
232 234 help_index : 'eb',
233 235 handler : function (env) {
234 236 env.notebook.move_cell_down();
235 237 }
236 238 },
237 239 'move-selected-cell-up' : {
238 240 icon: 'fa-arrow-up',
239 241 help_index : 'ea',
240 242 handler : function (env) {
241 243 env.notebook.move_cell_up();
242 244 }
243 245 },
244 246 'toggle-line-number-selected-cell' : {
245 247 help : 'toggle line numbers',
246 248 help_index : 'ga',
247 249 handler : function (env) {
248 250 env.notebook.cell_toggle_line_numbers();
249 251 }
250 252 },
251 253 'show-keyboard-shortcut-help-dialog' : {
252 254 help_index : 'ge',
253 255 handler : function (env) {
254 256 env.quick_help.show_keyboard_shortcuts();
255 257 }
256 258 },
257 259 'delete-cell': {
258 260 help: 'delete selected cell',
259 261 help_index : 'ej',
260 262 handler : function (env) {
261 263 env.notebook.delete_cell();
262 264 }
263 265 },
264 266 'interrupt-kernel':{
265 267 icon: 'fa-stop',
266 268 help_index : 'ha',
267 269 handler : function (env) {
268 270 env.notebook.kernel.interrupt();
269 271 env.notebook.focus_cell();
270 272 }
271 273 },
272 274 'restart-kernel':{
273 275 icon: 'fa-repeat',
274 276 help_index : 'hb',
275 277 handler : function (env) {
276 278 env.notebook.restart_kernel();
277 279 env.notebook.focus_cell();
278 280 }
279 281 },
280 282 'undo-last-cell-deletion' : {
281 283 help_index : 'ei',
282 284 handler : function (env) {
283 285 env.notebook.undelete_cell();
284 286 }
285 287 },
286 288 'merge-selected-cell-with-cell-after' : {
287 289 help : 'merge cell below',
288 290 help_index : 'ek',
289 291 handler : function (env) {
290 292 env.notebook.merge_cell_below();
291 293 }
292 294 },
293 295 'close-pager' : {
294 296 help_index : 'gd',
295 297 handler : function (env) {
296 298 env.pager.collapse();
297 299 }
298 300 }
299 301
300 302 };
301 303
302 304 /**
303 305 * A bunch of `Advance actions` for IPython.
304 306 * Cf `Simple Action` plus the following properties.
305 307 *
306 308 * handler: first argument of the handler is the event that triggerd the action
307 309 * (typically keypress). The handler is responsible for any modification of the
308 310 * event and event propagation.
309 311 * Is also responsible for returning false if the event have to be further ignored,
310 312 * true, to tell keyboard manager that it ignored the event.
311 313 *
312 314 * the second parameter of the handler is the environemnt passed to Simple Actions
313 315 *
314 316 **/
315 317 var custom_ignore = {
316 318 'ignore':{
317 319 handler : function () {
318 320 return true;
319 321 }
320 322 },
321 323 'move-cursor-up-or-previous-cell':{
322 324 handler : function (env, event) {
323 325 var index = env.notebook.get_selected_index();
324 326 var cell = env.notebook.get_cell(index);
325 327 var cm = env.notebook.get_selected_cell().code_mirror;
326 328 var cur = cm.getCursor();
327 329 if (cell && cell.at_top() && index !== 0 && cur.ch === 0) {
328 330 if(event){
329 331 event.preventDefault();
330 332 }
331 333 env.notebook.command_mode();
332 334 env.notebook.select_prev();
333 335 env.notebook.edit_mode();
334 336 cm = env.notebook.get_selected_cell().code_mirror;
335 337 cm.setCursor(cm.lastLine(), 0);
336 338 }
337 339 return false;
338 340 }
339 341 },
340 342 'move-cursor-down-or-next-cell':{
341 343 handler : function (env, event) {
342 344 var index = env.notebook.get_selected_index();
343 345 var cell = env.notebook.get_cell(index);
344 346 if (cell.at_bottom() && index !== (env.notebook.ncells()-1)) {
345 347 if(event){
346 348 event.preventDefault();
347 349 }
348 350 env.notebook.command_mode();
349 351 env.notebook.select_next();
350 352 env.notebook.edit_mode();
351 353 var cm = env.notebook.get_selected_cell().code_mirror;
352 354 cm.setCursor(0, 0);
353 355 }
354 356 return false;
355 357 }
356 358 },
357 359 'scroll-down': {
358 360 handler: function(env, event) {
359 361 if(event){
360 362 event.preventDefault();
361 363 }
362 364 return env.notebook.scroll_manager.scroll(1);
363 365 },
364 366 },
365 367 'scroll-up': {
366 368 handler: function(env, event) {
367 369 if(event){
368 370 event.preventDefault();
369 371 }
370 372 return env.notebook.scroll_manager.scroll(-1);
371 373 },
372 374 },
373 375 'save-notebook':{
374 376 help: "Save and Checkpoint",
375 377 help_index : 'fb',
376 378 icon: 'fa-save',
377 379 handler : function (env, event) {
378 380 env.notebook.save_checkpoint();
379 381 if(event){
380 382 event.preventDefault();
381 383 }
382 384 return false;
383 385 }
384 386 },
385 387 };
386 388
387 389 // private stuff that prepend `.ipython` to actions names
388 390 // and uniformize/fill in missing pieces in of an action.
389 391 var _prepare_handler = function(registry, subkey, source){
390 392 registry['ipython.'+subkey] = {};
391 393 registry['ipython.'+subkey].help = source[subkey].help||subkey.replace(/-/g,' ');
392 394 registry['ipython.'+subkey].help_index = source[subkey].help_index;
393 395 registry['ipython.'+subkey].icon = source[subkey].icon;
394 396 return source[subkey].handler;
395 397 };
396 398
397 399 // Will actually generate/register all the IPython actions
398 400 var fun = function(){
399 401 var final_actions = {};
400 402 var k;
401 403 for(k in _actions){
402 404 if(_actions.hasOwnProperty(k)){
403 405 // Js closure are function level not block level need to wrap in a IIFE
404 406 // and append ipython to event name these things do intercept event so are wrapped
405 407 // in a function that return false.
406 408 var handler = _prepare_handler(final_actions, k, _actions);
407 409 (function(key, handler){
408 410 final_actions['ipython.'+key].handler = function(env, event){
409 411 handler(env);
410 412 if(event){
411 413 event.preventDefault();
412 414 }
413 415 return false;
414 416 };
415 417 })(k, handler);
416 418 }
417 419 }
418 420
419 421 for(k in custom_ignore){
420 422 // Js closure are function level not block level need to wrap in a IIFE
421 423 // same as above, but decide for themselves wether or not they intercept events.
422 424 if(custom_ignore.hasOwnProperty(k)){
423 425 var handler = _prepare_handler(final_actions, k, custom_ignore);
424 426 (function(key, handler){
425 427 final_actions['ipython.'+key].handler = function(env, event){
426 428 return handler(env, event);
427 429 };
428 430 })(k, handler);
429 431 }
430 432 }
431 433
432 434 return final_actions;
433 435 };
434 436 ActionHandler.prototype._actions = fun();
435 437
436 438
437 439 /**
438 440 * extend the environment variable that will be pass to handlers
439 441 **/
440 442 ActionHandler.prototype.extend_env = function(env){
441 443 for(var k in env){
442 444 this.env[k] = env[k];
443 445 }
444 446 };
445 447
446 448 ActionHandler.prototype.register = function(action, name, prefix){
447 449 /**
448 450 * Register an `action` with an optional name and prefix.
449 451 *
450 452 * if name and prefix are not given they will be determined automatically.
451 453 * if action if just a `function` it will be wrapped in an anonymous action.
452 454 *
453 455 * @return the full name to access this action .
454 456 **/
455 457 action = this.normalise(action);
456 458 if( !name ){
457 459 name = 'autogenerated-'+String(action.handler);
458 460 }
459 461 prefix = prefix || 'auto';
460 462 var full_name = prefix+'.'+name;
461 463 this._actions[full_name] = action;
462 464 return full_name;
463 465
464 466 };
465 467
466 468
467 469 ActionHandler.prototype.normalise = function(data){
468 470 /**
469 471 * given an `action` or `function`, return a normalised `action`
470 472 * by setting all known attributes and removing unknown attributes;
471 473 **/
472 474 if(typeof(data) === 'function'){
473 475 data = {handler:data};
474 476 }
475 477 if(typeof(data.handler) !== 'function'){
476 478 throw('unknown datatype, cannot register');
477 479 }
478 480 var _data = data;
479 481 data = {};
480 482 data.handler = _data.handler;
481 483 data.help = _data.help || '';
482 484 data.icon = _data.icon || '';
483 485 data.help_index = _data.help_index || '';
484 486 return data;
485 487 };
486 488
487 489 ActionHandler.prototype.get_name = function(name_or_data){
488 490 /**
489 491 * given an `action` or `name` of a action, return the name attached to this action.
490 492 * if given the name of and corresponding actions does not exist in registry, return `null`.
491 493 **/
492 494
493 495 if(typeof(name_or_data) === 'string'){
494 496 if(this.exists(name_or_data)){
495 497 return name_or_data;
496 498 } else {
497 499 return null;
498 500 }
499 501 } else {
500 502 return this.register(name_or_data);
501 503 }
502 504 };
503 505
504 506 ActionHandler.prototype.get = function(name){
505 507 return this._actions[name];
506 508 };
507 509
508 510 ActionHandler.prototype.call = function(name, event, env){
509 511 return this._actions[name].handler(env|| this.env, event);
510 512 };
511 513
512 514 ActionHandler.prototype.exists = function(name){
513 515 return (typeof(this._actions[name]) !== 'undefined');
514 516 };
515 517
516 518 return {init:ActionHandler};
517 519
518 520 });
General Comments 0
You need to be logged in to leave comments. Login now