Skip to content

Commit 1096410

Browse files
committed
Try es6 and add a few features for shortcut editor.
1 parent ac70e49 commit 1096410

File tree

7 files changed

+117
-17
lines changed

7 files changed

+117
-17
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ before_install:
2626
- nvm install 5.6
2727
- nvm use 5.6
2828
- npm upgrade -g npm
29+
- npm install
2930
- 'if [[ $GROUP == js* ]]; then npm install -g [email protected]; fi'
3031
- git clone --quiet --depth 1 https://github.com/minrk/travis-wheels travis-wheels
3132

3233
install:
34+
- npm run build
3335
- pip install -f travis-wheels/wheelhouse file://$PWD#egg=notebook[test]
3436

3537
script:

notebook/static/base/js/keyboard.js

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,20 +168,27 @@ define([
168168

169169
// Shortcut manager class
170170

171-
var ShortcutManager = function (delay, events, actions, env) {
171+
var ShortcutManager = function (delay, events, actions, env, config, mode) {
172172
/**
173173
* A class to deal with keyboard event and shortcut
174174
*
175175
* @class ShortcutManager
176176
* @constructor
177+
*
178+
* :config: configobjet on which to call `update(....)` to persist the config.
179+
* :mode: mode of this shortcut manager where to persist config.
177180
*/
181+
mode = mode || 'command';
178182
this._shortcuts = {};
183+
this._defaults_bindings = [];
179184
this.delay = delay || 800; // delay in milliseconds
180185
this.events = events;
181186
this.actions = actions;
182187
this.actions.extend_env(env);
183188
this._queue = [];
184189
this._cleartimeout = null;
190+
this._config = config;
191+
this._mode = mode;
185192
Object.seal(this);
186193
};
187194

@@ -334,8 +341,30 @@ define([
334341
}
335342
};
336343

344+
ShortcutManager.prototype.is_available_shortcut = function(shortcut){
345+
var shortcut_array = shortcut.split(',');
346+
return this._is_available_shortcut(shortcut_array, this._shortcuts);
347+
};
348+
349+
ShortcutManager.prototype._is_available_shortcut = function(shortcut_array, tree){
350+
var current_node = tree[shortcut_array[0]];
351+
if(!shortcut_array[0]){
352+
return false;
353+
}
354+
if(current_node === undefined){
355+
return true;
356+
} else {
357+
if (typeof(current_node) == 'string'){
358+
return false;
359+
} else { // assume is a sub-shortcut tree
360+
return this._is_available_shortcut(shortcut_array.slice(1), current_node);
361+
}
362+
}
363+
};
364+
337365
ShortcutManager.prototype._set_leaf = function(shortcut_array, action_name, tree){
338366
var current_node = tree[shortcut_array[0]];
367+
339368
if(shortcut_array.length === 1){
340369
if(current_node !== undefined && typeof(current_node) !== 'string'){
341370
console.warn('[warning], you are overriting a long shortcut with a shorter one');
@@ -356,6 +385,51 @@ define([
356385
}
357386
};
358387

388+
ShortcutManager.prototype._persist_shortcut = function(shortcut, data) {
389+
/**
390+
* add a shortcut to this manager and persist it to the config file.
391+
**/
392+
shortcut = shortcut.toLowerCase();
393+
this.add_shortcut(shortcut, data);
394+
var patch = {keys:{}};
395+
var b = {bind:{}};
396+
patch.keys[this._mode] = {bind:{}};
397+
patch.keys[this._mode].bind[shortcut] = data;
398+
this._config.update(patch);
399+
};
400+
401+
ShortcutManager.prototype._persist_remove_shortcut = function(shortcut){
402+
/**
403+
* Remove a shortcut from this manager and persist its removal.
404+
*/
405+
406+
shortcut = shortcut.toLowerCase();
407+
this.remove_shortcut(shortcut);
408+
var patch = {keys:{}};
409+
var b = {bind:{}};
410+
patch.keys[this._mode] = {bind:{}};
411+
patch.keys[this._mode].bind[shortcut] = null;
412+
this._config.update(patch);
413+
console.info(patch);
414+
415+
// if the shortcut we unbind is a default one, we add it to the list of
416+
// things to unbind at startup
417+
418+
if(this._defaults_bindings.indexOf(shortcut) !== -1){
419+
var cnf = (this._config.data.keys||{})[this._mode];
420+
var unbind_array = cnf.unbind||[];
421+
422+
// unless it's already there (like if we have remapped a default
423+
// shortcut to another command, and unbind it)
424+
if(unbind_array.indexOf(shortcut) !== -1){
425+
unbind_array.concat(shortcut);
426+
var unbind_patch = {keys:{unbind:unbind_array}};
427+
this._config._update(unbind_patch);
428+
}
429+
}
430+
};
431+
432+
359433
ShortcutManager.prototype.add_shortcut = function (shortcut, data, suppress_help_update) {
360434
/**
361435
* Add a action to be handled by shortcut manager.
@@ -369,8 +443,8 @@ define([
369443
if (! action_name){
370444
throw new Error('does not know how to deal with : ' + data);
371445
}
372-
shortcut = normalize_shortcut(shortcut);
373-
this.set_shortcut(shortcut, action_name);
446+
var _shortcut = normalize_shortcut(shortcut);
447+
this.set_shortcut(_shortcut, action_name);
374448

375449
if (!suppress_help_update) {
376450
// update the keyboard shortcuts notebook help
@@ -391,6 +465,16 @@ define([
391465
this.events.trigger('rebuild.QuickHelp');
392466
};
393467

468+
ShortcutManager.prototype._add_default_shortcuts = function (data) {
469+
/**
470+
* same as add_shortcuts, but register them as "default" that if persistently unbound, with
471+
* persist_remove_shortcut, need to be on the "unbind" list.
472+
**/
473+
this._defaults_bindings = this._defaults_bindings.concat(Object.keys(data));
474+
this.add_shortcuts(data);
475+
476+
};
477+
394478
ShortcutManager.prototype.remove_shortcut = function (shortcut, suppress_help_update) {
395479
/**
396480
* Remove the binding of shortcut `sortcut` with its action.
@@ -415,7 +499,7 @@ define([
415499
this.events.trigger('rebuild.QuickHelp');
416500
}
417501
} catch (ex) {
418-
throw new Error('trying to remove a non-existent shortcut', shortcut);
502+
throw new Error('trying to remove a non-existent shortcut', shortcut, typeof shortcut);
419503
}
420504
};
421505

notebook/static/notebook/js/keyboardmanager.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ define([
3636
this.bind_events();
3737
this.env = {pager:this.pager};
3838
this.actions = options.actions;
39-
this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env );
40-
this.command_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
41-
this.command_shortcuts.add_shortcuts(this.get_default_command_shortcuts());
39+
this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env, options.config, 'command');
40+
this.command_shortcuts._add_default_shortcuts(this.get_default_common_shortcuts());
41+
this.command_shortcuts._add_default_shortcuts(this.get_default_command_shortcuts());
4242
this.edit_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env);
43-
this.edit_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
44-
this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts());
43+
this.edit_shortcuts._add_default_shortcuts(this.get_default_common_shortcuts());
44+
this.edit_shortcuts._add_default_shortcuts(this.get_default_edit_shortcuts());
4545

4646

4747
this.config = options.config;
@@ -106,7 +106,7 @@ define([
106106
'ctrl-enter' : 'jupyter-notebook:run-cell',
107107
'alt-enter' : 'jupyter-notebook:run-cell-and-insert-below',
108108
// cmd on mac, ctrl otherwise
109-
'cmdtrl-s' : 'jupyter-notebook:save-notebook',
109+
'cmdtrl-s' : 'jupyter-notebook:save-notebook'
110110
};
111111
};
112112

notebook/static/notebook/js/quickhelp.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,22 @@ define([
153153
return hum;
154154
}
155155

156-
function humanize_shortcut(shortcut){
156+
function _humanize_sequence(sequence){
157+
var joinchar = ',';
158+
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), _humanize_shortcut).join(joinchar);
159+
return hum;
160+
}
161+
162+
function _humanize_shortcut(shortcut){
157163
var joinchar = '-';
158164
if (platform === 'MacOS'){
159165
joinchar = '';
160166
}
161-
var sh = _.map(shortcut.split('-'), humanize_key ).join(joinchar);
162-
return '<kbd>'+sh+'</kbd>';
167+
return _.map(shortcut.split('-'), humanize_key ).join(joinchar);
168+
}
169+
170+
function humanize_shortcut(shortcut){
171+
return '<kbd>'+_humanize_shortcut(shortcut)+'</kbd>';
163172
}
164173

165174

@@ -301,6 +310,7 @@ define([
301310

302311
return {'QuickHelp': QuickHelp,
303312
humanize_shortcut: humanize_shortcut,
304-
humanize_sequence: humanize_sequence
313+
humanize_sequence: humanize_sequence,
314+
_humanize_sequence: _humanize_sequence,
305315
};
306316
});

notebook/tests/base/keyboard.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ casper.notebook_test(function () {
7171
that.msgs = [];
7272
that.on('remote.message', function(msg) {
7373
that.msgs.push(msg);
74-
})
74+
});
7575
that.evaluate(function (obj) {
7676
for(var k in obj){
77-
IPython.keyboard_manager.command_shortcuts.add_shortcut(k, function(){console.log(obj[k])});
77+
IPython.keyboard_manager.command_shortcuts.add_shortcut(k, function(){console.log(obj[k]);});
7878
}
7979
}, shortcuts_test);
8080

@@ -86,6 +86,6 @@ casper.notebook_test(function () {
8686
}
8787
this.test.assert(longer_first, 'no warning if registering shorter shortut');
8888
this.test.assert(longer_last , 'no warning if registering longer shortut');
89-
})
89+
});
9090

9191
});

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
"build:js:watch": "npm run build:js -- --watch"
1919
},
2020
"devDependencies": {
21+
"babel-core": "^6.7.4",
22+
"babel-loader": "^6.2.4",
23+
"babel-preset-es2015": "^6.6.0",
2124
"bower": "*",
2225
"concurrently": "^1.0.0",
2326
"less": "~2",

webpack.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var commonConfig = {
1414
},
1515
module: {
1616
loaders: [
17+
{ test: /\.js$/, exclude: /node_modules|\/notebook\/static\/component/, loader: "babel-loader"},
1718
{ test: /\.css$/, loader: "style-loader!css-loader" },
1819
{ test: /\.json$/, loader: "json-loader" },
1920
// jquery-ui loads some images

0 commit comments

Comments
 (0)