Merge pull request #1351 from Carreau/es6

ES6 and prerequisite to shortcut editor
This commit is contained in:
Min RK 2016-04-18 11:37:32 +02:00
commit f75e591bd6
7 changed files with 122 additions and 19 deletions

View File

@ -26,10 +26,12 @@ before_install:
- nvm install 5.6
- nvm use 5.6
- npm upgrade -g npm
- npm install
- 'if [[ $GROUP == js* ]]; then npm install -g casperjs@1.1.0-beta5; fi'
- git clone --quiet --depth 1 https://github.com/minrk/travis-wheels travis-wheels
install:
- npm run build
- pip install -f travis-wheels/wheelhouse file://$PWD#egg=notebook[test]
script:

View File

@ -168,20 +168,27 @@ define([
// Shortcut manager class
var ShortcutManager = function (delay, events, actions, env) {
var ShortcutManager = function (delay, events, actions, env, config, mode) {
/**
* A class to deal with keyboard event and shortcut
*
* @class ShortcutManager
* @constructor
*
* :config: configobjet on which to call `update(....)` to persist the config.
* :mode: mode of this shortcut manager where to persist config.
*/
mode = mode || 'command';
this._shortcuts = {};
this._defaults_bindings = [];
this.delay = delay || 800; // delay in milliseconds
this.events = events;
this.actions = actions;
this.actions.extend_env(env);
this._queue = [];
this._cleartimeout = null;
this._config = config;
this._mode = mode;
Object.seal(this);
};
@ -334,8 +341,30 @@ define([
}
};
ShortcutManager.prototype.is_available_shortcut = function(shortcut){
var shortcut_array = shortcut.split(',');
return this._is_available_shortcut(shortcut_array, this._shortcuts);
};
ShortcutManager.prototype._is_available_shortcut = function(shortcut_array, tree){
var current_node = tree[shortcut_array[0]];
if(!shortcut_array[0]){
return false;
}
if(current_node === undefined){
return true;
} else {
if (typeof(current_node) == 'string'){
return false;
} else { // assume is a sub-shortcut tree
return this._is_available_shortcut(shortcut_array.slice(1), current_node);
}
}
};
ShortcutManager.prototype._set_leaf = function(shortcut_array, action_name, tree){
var current_node = tree[shortcut_array[0]];
if(shortcut_array.length === 1){
if(current_node !== undefined && typeof(current_node) !== 'string'){
console.warn('[warning], you are overriting a long shortcut with a shorter one');
@ -356,6 +385,50 @@ define([
}
};
ShortcutManager.prototype._persist_shortcut = function(shortcut, data) {
/**
* add a shortcut to this manager and persist it to the config file.
**/
shortcut = shortcut.toLowerCase();
this.add_shortcut(shortcut, data);
var patch = {keys:{}};
var b = {bind:{}};
patch.keys[this._mode] = {bind:{}};
patch.keys[this._mode].bind[shortcut] = data;
this._config.update(patch);
};
ShortcutManager.prototype._persist_remove_shortcut = function(shortcut){
/**
* Remove a shortcut from this manager and persist its removal.
*/
shortcut = shortcut.toLowerCase();
this.remove_shortcut(shortcut);
var patch = {keys:{}};
var b = {bind:{}};
patch.keys[this._mode] = {bind:{}};
patch.keys[this._mode].bind[shortcut] = null;
this._config.update(patch);
// if the shortcut we unbind is a default one, we add it to the list of
// things to unbind at startup
if(this._defaults_bindings.indexOf(shortcut) !== -1){
var cnf = (this._config.data.keys||{})[this._mode];
var unbind_array = cnf.unbind||[];
// unless it's already there (like if we have remapped a default
// shortcut to another command, and unbind it)
if(unbind_array.indexOf(shortcut) !== -1){
unbind_array.concat(shortcut);
var unbind_patch = {keys:{unbind:unbind_array}};
this._config._update(unbind_patch);
}
}
};
ShortcutManager.prototype.add_shortcut = function (shortcut, data, suppress_help_update) {
/**
* Add a action to be handled by shortcut manager.
@ -369,8 +442,8 @@ define([
if (! action_name){
throw new Error('does not know how to deal with : ' + data);
}
shortcut = normalize_shortcut(shortcut);
this.set_shortcut(shortcut, action_name);
var _shortcut = normalize_shortcut(shortcut);
this.set_shortcut(_shortcut, action_name);
if (!suppress_help_update) {
// update the keyboard shortcuts notebook help
@ -391,6 +464,16 @@ define([
this.events.trigger('rebuild.QuickHelp');
};
ShortcutManager.prototype._add_default_shortcuts = function (data) {
/**
* same as add_shortcuts, but register them as "default" that if persistently unbound, with
* persist_remove_shortcut, need to be on the "unbind" list.
**/
this._defaults_bindings = this._defaults_bindings.concat(Object.keys(data));
this.add_shortcuts(data);
};
ShortcutManager.prototype.remove_shortcut = function (shortcut, suppress_help_update) {
/**
* Remove the binding of shortcut `sortcut` with its action.
@ -415,7 +498,7 @@ define([
this.events.trigger('rebuild.QuickHelp');
}
} catch (ex) {
throw new Error('trying to remove a non-existent shortcut', shortcut);
throw new Error('trying to remove a non-existent shortcut', shortcut, typeof shortcut);
}
};

View File

@ -36,12 +36,12 @@ define([
this.bind_events();
this.env = {pager:this.pager};
this.actions = options.actions;
this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env );
this.command_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
this.command_shortcuts.add_shortcuts(this.get_default_command_shortcuts());
this.command_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env, options.config, 'command');
this.command_shortcuts._add_default_shortcuts(this.get_default_common_shortcuts());
this.command_shortcuts._add_default_shortcuts(this.get_default_command_shortcuts());
this.edit_shortcuts = new keyboard.ShortcutManager(undefined, options.events, this.actions, this.env);
this.edit_shortcuts.add_shortcuts(this.get_default_common_shortcuts());
this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts());
this.edit_shortcuts._add_default_shortcuts(this.get_default_common_shortcuts());
this.edit_shortcuts._add_default_shortcuts(this.get_default_edit_shortcuts());
this.config = options.config;
@ -106,7 +106,7 @@ define([
'ctrl-enter' : 'jupyter-notebook:run-cell',
'alt-enter' : 'jupyter-notebook:run-cell-and-insert-below',
// cmd on mac, ctrl otherwise
'cmdtrl-s' : 'jupyter-notebook:save-notebook',
'cmdtrl-s' : 'jupyter-notebook:save-notebook'
};
};

View File

@ -153,13 +153,22 @@ define([
return hum;
}
function humanize_shortcut(shortcut){
function _humanize_sequence(sequence){
var joinchar = ',';
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), _humanize_shortcut).join(joinchar);
return hum;
}
function _humanize_shortcut(shortcut){
var joinchar = '-';
if (platform === 'MacOS'){
joinchar = '';
}
var sh = _.map(shortcut.split('-'), humanize_key ).join(joinchar);
return '<kbd>'+sh+'</kbd>';
return _.map(shortcut.split('-'), humanize_key ).join(joinchar);
}
function humanize_shortcut(shortcut){
return '<kbd>'+_humanize_shortcut(shortcut)+'</kbd>';
}
@ -301,6 +310,7 @@ define([
return {'QuickHelp': QuickHelp,
humanize_shortcut: humanize_shortcut,
humanize_sequence: humanize_sequence
humanize_sequence: humanize_sequence,
_humanize_sequence: _humanize_sequence,
};
});

View File

@ -71,21 +71,25 @@ casper.notebook_test(function () {
that.msgs = [];
that.on('remote.message', function(msg) {
that.msgs.push(msg);
})
});
that.evaluate(function (obj) {
for(var k in obj){
IPython.keyboard_manager.command_shortcuts.add_shortcut(k, function(){console.log(obj[k])});
if ({}.hasOwnProperty.call(obj, k)) {
IPython.keyboard_manager.command_shortcuts.add_shortcut(k, function(){console.log(obj[k]);});
}
}
}, shortcuts_test);
var longer_first = false;
var longer_last = false;
for(var m in that.msgs){
longer_first = longer_first||(that.msgs[m].match(/you are overriting/)!= null);
longer_last = longer_last ||(that.msgs[m].match(/will be shadowed/) != null);
if ({}.hasOwnProperty.call(that.msgs, m)) {
longer_first = longer_first||(that.msgs[m].match(/you are overriting/)!= null);
longer_last = longer_last ||(that.msgs[m].match(/will be shadowed/) != null);
}
}
this.test.assert(longer_first, 'no warning if registering shorter shortut');
this.test.assert(longer_last , 'no warning if registering longer shortut');
})
});
});

View File

@ -18,6 +18,9 @@
"build:js:watch": "npm run build:js -- --watch"
},
"devDependencies": {
"babel-core": "^6.7.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"bower": "*",
"concurrently": "^1.0.0",
"less": "~2",

View File

@ -14,6 +14,7 @@ var commonConfig = {
},
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules|\/notebook\/static\/component/, loader: "babel-loader"},
{ test: /\.css$/, loader: "style-loader!css-loader" },
{ test: /\.json$/, loader: "json-loader" },
// jquery-ui loads some images