From 1af4bfb3ce1eea0fc95ff68c23432da7986dd6fc Mon Sep 17 00:00:00 2001 From: "Brian E. Granger" Date: Mon, 27 Jan 2014 15:00:19 -0800 Subject: [PATCH 1/4] Misc work on shortcuts: * shift+v for paste above. * ii for interrupt * 00 for restart * All shortcuts can have a count field for multiple press. --- .../static/notebook/js/keyboardmanager.js | 72 +++++++++++++------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/IPython/html/static/notebook/js/keyboardmanager.js b/IPython/html/static/notebook/js/keyboardmanager.js index f2a1b3916..b6e09f9c1 100644 --- a/IPython/html/static/notebook/js/keyboardmanager.js +++ b/IPython/html/static/notebook/js/keyboardmanager.js @@ -276,9 +276,17 @@ var IPython = (function (IPython) { return false; } }, + 'shift+v' : { + help : 'paste cell above', + help_index : 'eg', + handler : function (event) { + IPython.notebook.paste_cell_above(); + return false; + } + }, 'v' : { help : 'paste cell below', - help_index : 'eg', + help_index : 'eh', handler : function (event) { IPython.notebook.paste_cell_below(); return false; @@ -286,18 +294,10 @@ var IPython = (function (IPython) { }, 'd' : { help : 'delete cell (press twice)', - help_index : 'ei', + help_index : 'ej', + count: 2, handler : function (event) { - var dc = IPython.keyboard_manager._delete_count; - if (dc === 0) { - IPython.keyboard_manager._delete_count = 1; - setTimeout(function () { - IPython.keyboard_manager._delete_count = 0; - }, 800); - } else if (dc === 1) { - IPython.notebook.delete_cell(); - IPython.keyboard_manager._delete_count = 0; - } + IPython.notebook.delete_cell(); return false; } }, @@ -337,7 +337,7 @@ var IPython = (function (IPython) { return false; } }, - 't' : { + 'r' : { help : 'to raw', help_index : 'cc', handler : function (event) { @@ -442,16 +442,18 @@ var IPython = (function (IPython) { } }, 'i' : { - help : 'interrupt kernel', + help : 'interrupt kernel (press twice)', help_index : 'ha', + count: 2, handler : function (event) { IPython.notebook.kernel.interrupt(); return false; } }, - '.' : { - help : 'restart kernel', + '0' : { + help : 'restart kernel (press twice)', help_index : 'hb', + count: 2, handler : function (event) { IPython.notebook.restart_kernel(); return false; @@ -467,7 +469,7 @@ var IPython = (function (IPython) { }, 'z' : { help : 'undo last delete', - help_index : 'eh', + help_index : 'ei', handler : function (event) { IPython.notebook.undelete_cell(); return false; @@ -475,7 +477,7 @@ var IPython = (function (IPython) { }, 'shift+=' : { help : 'merge cell below', - help_index : 'ej', + help_index : 'ek', handler : function (event) { IPython.notebook.merge_cell_below(); return false; @@ -486,8 +488,10 @@ var IPython = (function (IPython) { // Shortcut manager class - var ShortcutManager = function () { + var ShortcutManager = function (delay) { this._shortcuts = {} + this._counts = {} + this.delay = delay || 800; // delay in milliseconds } ShortcutManager.prototype.help = function () { @@ -552,10 +556,12 @@ var IPython = (function (IPython) { } data.help_index = data.help_index || ''; data.help = data.help || ''; + data.count = data.count || 1; if (data.help_index === '') { data.help_index = 'zz'; } shortcut = this.normalize_shortcut(shortcut); + this._counts[shortcut] = 0; this._shortcuts[shortcut] = data; } @@ -567,16 +573,37 @@ var IPython = (function (IPython) { ShortcutManager.prototype.remove_shortcut = function (shortcut) { shortcut = this.normalize_shortcut(shortcut); + delete this._counts[shortcut]; delete this._shortcuts[shortcut]; } + ShortcutManager.prototype.count_handler = function (shortcut, event, handler) { + var that = this; + var c = this._counts; + if (c[shortcut] === 0) { + c[shortcut] = 1; + setTimeout(function () { + c[shortcut] = 0; + }, that.delay); + } else if (c[shortcut] === 1) { + c[shortcut] = 0; + return handler(event); + } + return false; + + } + ShortcutManager.prototype.call_handler = function (event) { var shortcut = this.event_to_shortcut(event); var data = this._shortcuts[shortcut]; - if (data !== undefined) { + if (data) { var handler = data['handler']; - if (handler !== undefined) { - return handler(event); + if (handler) { + if (data.count === 1) { + return handler(event); + } else if (data.count > 1) { + return this.count_handler(shortcut, event, handler); + } } } return true; @@ -589,7 +616,6 @@ var IPython = (function (IPython) { var KeyboardManager = function () { this.mode = 'command'; this.enabled = true; - this._delete_count = 0; this.bind_events(); this.command_shortcuts = new ShortcutManager(); this.command_shortcuts.add_shortcuts(default_common_shortcuts); From 0af185787afc5e0137b2dea8b2baebe30678d639 Mon Sep 17 00:00:00 2001 From: "Brian E. Granger" Date: Mon, 27 Jan 2014 16:27:25 -0800 Subject: [PATCH 2/4] Added platform dep. logic. --- IPython/html/static/base/js/utils.js | 11 +++ .../static/notebook/js/keyboardmanager.js | 99 +++++++++++++++---- .../static/notebook/js/notificationarea.js | 2 +- 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js index 90eca6e08..723f90add 100644 --- a/IPython/html/static/base/js/utils.js +++ b/IPython/html/static/base/js/utils.js @@ -459,6 +459,16 @@ IPython.utils = (function (IPython) { return M; })(); + // http://stackoverflow.com/questions/11219582/how-to-detect-my-browser-version-and-operating-system-using-javascript + var platform = (function () { + var OSName="Unknown OS"; + if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows"; + if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS"; + if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX"; + if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux"; + return OSName + })(); + var is_or_has = function (a, b) { // Is b a child of a or a itself? return a.has(b).length !==0 || a.is(b); @@ -500,6 +510,7 @@ IPython.utils = (function (IPython) { splitext : splitext, always_new : always_new, browser : browser, + platform: platform, is_or_has : is_or_has, is_focused : is_focused }; diff --git a/IPython/html/static/notebook/js/keyboardmanager.js b/IPython/html/static/notebook/js/keyboardmanager.js index b6e09f9c1..8fe5be236 100644 --- a/IPython/html/static/notebook/js/keyboardmanager.js +++ b/IPython/html/static/notebook/js/keyboardmanager.js @@ -50,6 +50,7 @@ var IPython = (function (IPython) { } var browser = IPython.utils.browser[0]; + var platform = IPython.utils.platform; if (browser === 'Firefox' || browser === 'Opera') { $.extend(_keycodes, _mozilla_keycodes); @@ -78,24 +79,6 @@ var IPython = (function (IPython) { // Default keyboard shortcuts var default_common_shortcuts = { - 'meta+s' : { - help : 'save notebook', - help_index : 'fb', - handler : function (event) { - IPython.notebook.save_checkpoint(); - event.preventDefault(); - return false; - } - }, - 'ctrl+s' : { - help : 'save notebook', - help_index : 'fc', - handler : function (event) { - IPython.notebook.save_checkpoint(); - event.preventDefault(); - return false; - } - }, 'shift' : { help : '', help_index : '', @@ -130,6 +113,30 @@ var IPython = (function (IPython) { } } + if (platform === 'MacOS') { + default_common_shortcuts['cmd+s'] = + { + help : 'save notebook', + help_index : 'fb', + handler : function (event) { + IPython.notebook.save_checkpoint(); + event.preventDefault(); + return false; + } + }; + } else { + default_common_shortcuts['ctrl+s'] = + { + help : 'save notebook', + help_index : 'fb', + handler : function (event) { + IPython.notebook.save_checkpoint(); + event.preventDefault(); + return false; + } + }; + } + // Edit mode defaults var default_edit_shortcuts = { @@ -195,6 +202,48 @@ var IPython = (function (IPython) { return false; } }, + 'tab' : { + help : 'indent or complete', + help_index : 'ec', + }, + 'shift+tab' : { + help : 'tooltip', + help_index : 'ed', + }, + } + + if (platform === 'MacOS') { + default_edit_shortcuts['cmd+/'] = + { + help : 'toggle comment', + help_index : 'ee' + }; + default_edit_shortcuts['cmd+]'] = + { + help : 'indent', + help_index : 'ef' + }; + default_edit_shortcuts['cmd+['] = + { + help : 'dedent', + help_index : 'eg' + }; + } else { + default_edit_shortcuts['ctrl+/'] = + { + help : 'toggle comment', + help_index : 'ee' + }; + default_edit_shortcuts['ctrl+]'] = + { + help : 'indent', + help_index : 'ef' + }; + default_edit_shortcuts['ctrl+['] = + { + help : 'dedent', + help_index : 'eg' + }; } // Command mode defaults @@ -402,7 +451,7 @@ var IPython = (function (IPython) { } }, 'shift+o' : { - help : 'toggle output', + help : 'toggle output scroll', help_index : 'gc', handler : function (event) { IPython.notebook.toggle_output_scroll(); @@ -483,6 +532,14 @@ var IPython = (function (IPython) { return false; } }, + 'shift+m' : { + help : 'merge cell below', + help_index : 'ek', + handler : function (event) { + IPython.notebook.merge_cell_below(); + return false; + } + }, } @@ -500,6 +557,9 @@ var IPython = (function (IPython) { var help_string = this._shortcuts[shortcut]['help']; var help_index = this._shortcuts[shortcut]['help_index']; if (help_string) { + if (platform === 'MacOS') { + shortcut = shortcut.replace('meta', 'cmd'); + } help.push({ shortcut: shortcut, help: help_string, @@ -523,6 +583,7 @@ var IPython = (function (IPython) { ShortcutManager.prototype.normalize_shortcut = function (shortcut) { // Sort a sequence of + separated modifiers into the order alt+ctrl+meta+shift + shortcut = shortcut.replace('cmd', 'meta').toLowerCase(); var values = shortcut.split("+"); if (values.length === 1) { return this.normalize_key(values[0]) diff --git a/IPython/html/static/notebook/js/notificationarea.js b/IPython/html/static/notebook/js/notificationarea.js index 0f52b7e98..1f1830efa 100644 --- a/IPython/html/static/notebook/js/notificationarea.js +++ b/IPython/html/static/notebook/js/notificationarea.js @@ -88,7 +88,7 @@ var IPython = (function (IPython) { }); $([IPython.events]).on('status_interrupting.Kernel',function () { - knw.set_message("Interrupting kernel"); + knw.set_message("Interrupting kernel", 2000); }); $([IPython.events]).on('status_dead.Kernel',function () { From fd07bb54b64e8c38e41d140f7fad93ea6468b8b9 Mon Sep 17 00:00:00 2001 From: "Brian E. Granger" Date: Tue, 28 Jan 2014 10:17:34 -0800 Subject: [PATCH 3/4] Fixing shortcut counts to work for n>2. --- IPython/html/static/notebook/js/keyboardmanager.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/IPython/html/static/notebook/js/keyboardmanager.js b/IPython/html/static/notebook/js/keyboardmanager.js index 8fe5be236..42db5eb06 100644 --- a/IPython/html/static/notebook/js/keyboardmanager.js +++ b/IPython/html/static/notebook/js/keyboardmanager.js @@ -638,17 +638,17 @@ var IPython = (function (IPython) { delete this._shortcuts[shortcut]; } - ShortcutManager.prototype.count_handler = function (shortcut, event, handler) { + ShortcutManager.prototype.count_handler = function (shortcut, event, data) { var that = this; var c = this._counts; - if (c[shortcut] === 0) { - c[shortcut] = 1; + if (c[shortcut] === data.count-1) { + c[shortcut] = 0; + return data.handler(event); + } else { + c[shortcut] = c[shortcut] + 1; setTimeout(function () { c[shortcut] = 0; }, that.delay); - } else if (c[shortcut] === 1) { - c[shortcut] = 0; - return handler(event); } return false; @@ -663,7 +663,7 @@ var IPython = (function (IPython) { if (data.count === 1) { return handler(event); } else if (data.count > 1) { - return this.count_handler(shortcut, event, handler); + return this.count_handler(shortcut, event, data); } } } From 5137961bf2bed3ea6ae6742288bd2c867cba3322 Mon Sep 17 00:00:00 2001 From: "Brian E. Granger" Date: Tue, 28 Jan 2014 10:19:44 -0800 Subject: [PATCH 4/4] Protect against navigator undefined in platform. --- IPython/html/static/base/js/utils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js index 723f90add..0e6c9fb3d 100644 --- a/IPython/html/static/base/js/utils.js +++ b/IPython/html/static/base/js/utils.js @@ -461,7 +461,11 @@ IPython.utils = (function (IPython) { // http://stackoverflow.com/questions/11219582/how-to-detect-my-browser-version-and-operating-system-using-javascript var platform = (function () { - var OSName="Unknown OS"; + if (typeof navigator === 'undefined') { + // navigator undefined in node + return 'None'; + } + var OSName="None"; if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows"; if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS"; if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";