diff --git a/IPython/html/static/base/js/dialog.js b/IPython/html/static/base/js/dialog.js index 0bc41cf..3597443 100644 --- a/IPython/html/static/base/js/dialog.js +++ b/IPython/html/static/base/js/dialog.js @@ -4,7 +4,8 @@ define([ 'base/js/namespace', 'jquery', -], function(IPython, $) { + 'codemirror/lib/codemirror', +], function(IPython, $, CodeMirror) { "use strict"; var modal = function (options) { diff --git a/IPython/html/static/base/js/keyboard.js b/IPython/html/static/base/js/keyboard.js index 211ce2a..c8aa919 100644 --- a/IPython/html/static/base/js/keyboard.js +++ b/IPython/html/static/base/js/keyboard.js @@ -1,5 +1,12 @@ // Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. +/** + * + * + * @module keyboard + * @namespace keyboard + * @class ShortcutManager + */ define([ 'base/js/namespace', @@ -126,6 +133,12 @@ define([ // Shortcut manager class var ShortcutManager = function (delay, events) { + /** + * A class to deal with keyboard event and shortcut + * + * @class ShortcutManager + * @constructor + */ this._shortcuts = {}; this._counts = {}; this._timers = {}; @@ -201,6 +214,16 @@ define([ }; ShortcutManager.prototype.count_handler = function (shortcut, event, data) { + /** + * Seem to allow to call an handler only after several key press. + * like, I suppose `dd` that delete the current cell only after + * `d` has been pressed twice.. + * @method count_handler + * @return {Boolean} `true|false`, whether or not the event has been handled. + * @param shortcut {shortcut} + * @param event {event} + * @param data {data} + */ var that = this; var c = this._counts; var t = this._timers; @@ -221,6 +244,12 @@ define([ }; ShortcutManager.prototype.call_handler = function (event) { + /** + * Call the corresponding shortcut handler for a keyboard event + * @method call_handler + * @return {Boolean} `true|false`, `false` if no handler was found, otherwise the value return by the handler. + * @param event {event} + */ var shortcut = event_to_shortcut(event); var data = this._shortcuts[shortcut]; if (data) { @@ -252,7 +281,7 @@ define([ event_to_shortcut : event_to_shortcut }; - // For backwards compatability. + // For backwards compatibility. IPython.keyboard = keyboard; return keyboard; diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js index cde25f3..e63d510 100644 --- a/IPython/html/static/base/js/utils.js +++ b/IPython/html/static/base/js/utils.js @@ -4,7 +4,8 @@ define([ 'base/js/namespace', 'jquery', -], function(IPython, $){ + 'codemirror/lib/codemirror', +], function(IPython, $, CodeMirror){ "use strict"; IPython.load_extensions = function () { diff --git a/IPython/html/static/components b/IPython/html/static/components index b3909af..1760cce 160000 --- a/IPython/html/static/components +++ b/IPython/html/static/components @@ -1 +1 @@ -Subproject commit b3909af1b61ca7a412481759fdb441ecdfb3ab66 +Subproject commit 1760cce3697b0535efb598fbd609abd6caebf920 diff --git a/IPython/html/static/notebook/js/cell.js b/IPython/html/static/notebook/js/cell.js index e53a4e8..4533d14 100644 --- a/IPython/html/static/notebook/js/cell.js +++ b/IPython/html/static/notebook/js/cell.js @@ -1,11 +1,24 @@ // Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. +/** + * + * + * @module cell + * @namespace cell + * @class Cell + */ + + define([ 'base/js/namespace', 'jquery', 'base/js/utils', -], function(IPython, $, utils) { + 'codemirror/lib/codemirror', + 'codemirror/addon/edit/matchbrackets', + 'codemirror/addon/edit/closebrackets', + 'codemirror/addon/comment/comment' +], function(IPython, $, utils, CodeMirror, cm_match, cm_closeb, cm_comment) { // TODO: remove IPython dependency here "use strict"; @@ -29,16 +42,17 @@ define([ // end monkey patching CodeMirror var Cell = function (options) { - // Constructor - // - // The Base `Cell` class from which to inherit. - // - // Parameters: - // options: dictionary - // Dictionary of keyword arguments. - // events: $(Events) instance - // config: dictionary - // keyboard_manager: KeyboardManager instance + /* Constructor + * + * The Base `Cell` class from which to inherit. + * @constructor + * @param: + * options: dictionary + * Dictionary of keyword arguments. + * events: $(Events) instance + * config: dictionary + * keyboard_manager: KeyboardManager instance + */ options = options || {}; this.keyboard_manager = options.keyboard_manager; this.events = options.events; @@ -278,8 +292,6 @@ define([ */ Cell.prototype.handle_keyevent = function (editor, event) { - // console.log('CM', this.mode, event.which, event.type) - if (this.mode === 'command') { return true; } else if (this.mode === 'edit') { diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js index d1a68d8..d23d56c 100644 --- a/IPython/html/static/notebook/js/codecell.js +++ b/IPython/html/static/notebook/js/codecell.js @@ -1,5 +1,13 @@ // Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. +/** + * + * + * @module codecell + * @namespace codecell + * @class CodeCell + */ + define([ 'base/js/namespace', @@ -10,7 +18,10 @@ define([ 'notebook/js/outputarea', 'notebook/js/completer', 'notebook/js/celltoolbar', -], function(IPython, $, utils, keyboard, cell, outputarea, completer, celltoolbar) { + 'codemirror/lib/codemirror', + 'codemirror/mode/python/python', + 'notebook/js/codemirror-ipython' +], function(IPython, $, utils, keyboard, cell, outputarea, completer, celltoolbar, CodeMirror, cmpython, cmip) { "use strict"; var Cell = cell.Cell; @@ -102,9 +113,7 @@ define([ }, mode: 'ipython', theme: 'ipython', - matchBrackets: true, - // don't auto-close strings because of CodeMirror #2385 - autoCloseBrackets: "()[]{}" + matchBrackets: true } }; @@ -135,6 +144,7 @@ define([ inner_cell.append(this.celltoolbar.element); var input_area = $('
').addClass('input_area'); this.code_mirror = new CodeMirror(input_area.get(0), this.cm_config); + this.code_mirror.on('keydown', $.proxy(this.handle_codemirror_keyevent,this)) $(this.code_mirror.getInputField()).attr("spellcheck", "false"); inner_cell.append(input_area); input.append(prompt).append(inner_cell); @@ -220,7 +230,8 @@ define([ } // If we closed the tooltip, don't let CM or the global handlers // handle this event. - event.stop(); + event.codemirrorIgnore = true; + event.preventDefault(); return true; } else if (event.keyCode === keycodes.tab && event.type === 'keydown' && event.shiftKey) { if (editor.somethingSelected()){ @@ -231,7 +242,8 @@ define([ } } this.tooltip.request(that); - event.stop(); + event.codemirrorIgnore = true; + event.preventDefault(); return true; } else if (event.keyCode === keycodes.tab && event.type == 'keydown') { // Tab completion. @@ -245,7 +257,8 @@ define([ // is empty. In this case, let CodeMirror handle indentation. return false; } else { - event.stop(); + event.codemirrorIgnore = true; + event.preventDefault(); this.completer.startCompletion(); return true; } diff --git a/IPython/html/static/notebook/js/codemirror-ipython.js b/IPython/html/static/notebook/js/codemirror-ipython.js index d01abe9..7b9efdb 100644 --- a/IPython/html/static/notebook/js/codemirror-ipython.js +++ b/IPython/html/static/notebook/js/codemirror-ipython.js @@ -3,9 +3,20 @@ // callback to auto-load python mode, which is more likely not the best things // to do, but at least the simple one for now. -CodeMirror.requireMode('python',function(){ +(function(mod) { + if (typeof exports == "object" && typeof module == "object"){ // CommonJS + mod(require("codemirror/lib/codemirror"), + require("codemirror/mode/python/python") + ); + } else if (typeof define == "function" && define.amd){ // AMD + define(["codemirror/lib/codemirror", + "codemirror/mode/python/python"], mod); + } else {// Plain browser env + mod(CodeMirror); + } +})(function(CodeMirror) { "use strict"; - + CodeMirror.defineMode("ipython", function(conf, parserConf) { var pythonConf = {}; for (var prop in parserConf) { @@ -25,3 +36,4 @@ CodeMirror.requireMode('python',function(){ CodeMirror.defineMIME("text/x-ipython", "ipython"); }) + diff --git a/IPython/html/static/notebook/js/codemirror-ipythongfm.js b/IPython/html/static/notebook/js/codemirror-ipythongfm.js index 68b61b3..5493caf 100644 --- a/IPython/html/static/notebook/js/codemirror-ipythongfm.js +++ b/IPython/html/static/notebook/js/codemirror-ipythongfm.js @@ -6,39 +6,59 @@ // But was later removed in // https://github.com/codemirror/CodeMirror/commit/d9c9f1b1ffe984aee41307f3e927f80d1f23590c -CodeMirror.requireMode('gfm', function(){ - CodeMirror.requireMode('stex', function(){ - CodeMirror.defineMode("ipythongfm", function(config, parserConfig) { - - var gfm_mode = CodeMirror.getMode(config, "gfm"); - var tex_mode = CodeMirror.getMode(config, "stex"); - - return CodeMirror.multiplexingMode( - gfm_mode, - { - open: "$", close: "$", - mode: tex_mode, - delimStyle: "delimit" - }, - { - open: "$$", close: "$$", - mode: tex_mode, - delimStyle: "delimit" - }, - { - open: "\\(", close: "\\)", - mode: tex_mode, - delimStyle: "delimit" - }, - { - open: "\\[", close: "\\]", - mode: tex_mode, - delimStyle: "delimit" - } - // .. more multiplexed styles can follow here - ); - }, 'gfm'); + +(function(mod) { + if (typeof exports == "object" && typeof module == "object"){ // CommonJS + mod(require("codemirror/lib/codemirror") + ,require("codemirror/addon/mode/multiplex") + ,require("codemirror/mode/gfm/gfm") + ,require("codemirror/mode/stex/stex") + ); + } else if (typeof define == "function" && define.amd){ // AMD + define(["codemirror/lib/codemirror" + ,"codemirror/addon/mode/multiplex" + ,"codemirror/mode/python/python" + ,"codemirror/mode/stex/stex" + ], mod); + } else {// Plain browser env + mod(CodeMirror); + } +})( function(CodeMirror){ + "use strict"; + + CodeMirror.defineMode("ipythongfm", function(config, parserConfig) { + + var gfm_mode = CodeMirror.getMode(config, "gfm"); + var tex_mode = CodeMirror.getMode(config, "stex"); - CodeMirror.defineMIME("text/x-ipythongfm", "ipythongfm"); - }); -}); + return CodeMirror.multiplexingMode( + gfm_mode, + { + open: "$", close: "$", + mode: tex_mode, + delimStyle: "delimit" + }, + { + // not sure this works as $$ is interpreted at (opening $, closing $, as defined just above) + open: "$$", close: "$$", + mode: tex_mode, + delimStyle: "delimit" + }, + { + open: "\\(", close: "\\)", + mode: tex_mode, + delimStyle: "delimit" + }, + { + open: "\\[", close: "\\]", + mode: tex_mode, + delimStyle: "delimit" + } + // .. more multiplexed styles can follow here + ); + }, 'gfm'); + + CodeMirror.defineMIME("text/x-ipythongfm", "ipythongfm"); + + +}) diff --git a/IPython/html/static/notebook/js/completer.js b/IPython/html/static/notebook/js/completer.js index 951fb78..576885c 100644 --- a/IPython/html/static/notebook/js/completer.js +++ b/IPython/html/static/notebook/js/completer.js @@ -7,7 +7,8 @@ define([ 'base/js/utils', 'base/js/keyboard', 'notebook/js/contexthint', -], function(IPython, $, utils, keyboard) { + 'codemirror/lib/codemirror', +], function(IPython, $, utils, keyboard, CodeMirror) { "use strict"; // easier key mapping @@ -316,11 +317,13 @@ define([ // Enter if (code == keycodes.enter) { - CodeMirror.e_stop(event); + event.codemirrorIgnore = true; + event.preventDefault(); this.pick(); // Escape or backspace } else if (code == keycodes.esc || code == keycodes.backspace) { - CodeMirror.e_stop(event); + event.codemirrorIgnore = true; + event.preventDefault(); this.close(); } else if (code == keycodes.tab) { //all the fastforwarding operation, @@ -339,7 +342,8 @@ define([ } else if (code == keycodes.up || code == keycodes.down) { // need to do that to be able to move the arrow // when on the first or last line ofo a code cell - CodeMirror.e_stop(event); + event.codemirrorIgnore = true; + event.preventDefault(); var options = this.sel.find('option'); var index = this.sel[0].selectedIndex; diff --git a/IPython/html/static/notebook/js/config.js b/IPython/html/static/notebook/js/config.js index 8db7d18..1c60b6f 100644 --- a/IPython/html/static/notebook/js/config.js +++ b/IPython/html/static/notebook/js/config.js @@ -1,6 +1,15 @@ // Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. +/** + * + * + * @module config + * @namespace config + * @class Config + */ + + define([], function() { "use strict"; diff --git a/IPython/html/static/notebook/js/contexthint.js b/IPython/html/static/notebook/js/contexthint.js index c64b67b..30b7cd7 100644 --- a/IPython/html/static/notebook/js/contexthint.js +++ b/IPython/html/static/notebook/js/contexthint.js @@ -2,7 +2,7 @@ // Distributed under the terms of the Modified BSD License. // highly adapted for codemiror jshint -define([], function() { +define(['codemirror/lib/codemirror'], function(CodeMirror) { "use strict"; var forEach = function(arr, f) { diff --git a/IPython/html/static/notebook/js/keyboardmanager.js b/IPython/html/static/notebook/js/keyboardmanager.js index 3ff69ba..c315b4e 100644 --- a/IPython/html/static/notebook/js/keyboardmanager.js +++ b/IPython/html/static/notebook/js/keyboardmanager.js @@ -1,5 +1,12 @@ // Copyright (c) IPython Development Team. // Distributed under the terms of the Modified BSD License. +/** + * + * + * @module keyboardmanager + * @namespace keyboardmanager + * @class KeyboardManager + */ define([ 'base/js/namespace', @@ -16,13 +23,15 @@ define([ var keycodes = keyboard.keycodes; var KeyboardManager = function (options) { - // Constructor - // - // Parameters: - // options: dictionary - // Dictionary of keyword arguments. - // events: $(Events) instance - // pager: Pager instance + /** + * A class to deal with keyboard event and shortcut + * + * @class KeyboardManager + * @constructor + * @param options {dict} Dictionary of keyword arguments : + * @param options.events {$(Events)} instance + * @param options.pager: {Pager} pager instance + */ this.mode = 'command'; this.enabled = true; this.pager = options.pager; @@ -37,6 +46,22 @@ define([ this.edit_shortcuts.add_shortcuts(this.get_default_edit_shortcuts()); }; + /** + * Return a dict of common shortcut + * @method get_default_common_shortcuts + * + * @example Example of returned shortcut + * ``` + * 'shortcut-key': // a string representing the shortcut as dash separated value. + * // e.g. 'shift' , 'shift-enter', 'cmd-t' + * { + * help: String // user facing help string + * help_index: String // string used internally to order the shortcut on the quickhelp + * handler: function(event){return true|false} // function that takes an even as first and only parameter + * // and return a boolean indicating whether or not the event should been handled further. + * } + *``` + */ KeyboardManager.prototype.get_default_common_shortcuts = function() { var that = this; var shortcuts = { @@ -125,19 +150,17 @@ define([ handler : function (event) { var index = that.notebook.get_selected_index(); var cell = that.notebook.get_cell(index); - if (cell && cell.at_top() && index !== 0) { + var cm = that.notebook.get_selected_cell().code_mirror; + var cur = cm.getCursor() + if (cell && cell.at_top() && index !== 0 && cur.ch === 0) { event.preventDefault(); that.notebook.command_mode(); that.notebook.select_prev(); that.notebook.edit_mode(); var cm = that.notebook.get_selected_cell().code_mirror; cm.setCursor(cm.lastLine(), 0); - return false; - } else if (cell) { - var cm = cell.code_mirror; - cm.execCommand('goLineUp'); - return false; } + return false; } }, 'down' : { @@ -154,11 +177,8 @@ define([ var cm = that.notebook.get_selected_cell().code_mirror; cm.setCursor(0, 0); return false; - } else { - var cm = cell.code_mirror; - cm.execCommand('goLineDown'); - return false; } + return false; } }, 'ctrl-shift--' : { diff --git a/IPython/html/static/notebook/js/main.js b/IPython/html/static/notebook/js/main.js index 4ddee4b..f6352da 100644 --- a/IPython/html/static/notebook/js/main.js +++ b/IPython/html/static/notebook/js/main.js @@ -19,8 +19,10 @@ require([ 'notebook/js/keyboardmanager', 'notebook/js/config', 'notebook/js/kernelselector', - // only loaded, not used: - 'custom/custom', + 'codemirror/lib/codemirror', + 'codemirror/addon/mode/loadmode', + // only loaded, not used, please keep sure this is loaded last + 'custom/custom' ], function( IPython, $, @@ -38,10 +40,18 @@ require([ savewidget, keyboardmanager, config, - kernelselector + kernelselector, + CodeMirror, + cm_loadmode, + // please keep sure that even if not used, this is loaded last + custom ) { "use strict"; + window.CodeMirror = CodeMirror; + $('#ipython-main-app').addClass('border-box-sizing'); + $('div#notebook_panel').addClass('border-box-sizing'); + var common_options = { base_url : utils.get_body_data("baseUrl"), ws_url : IPython.utils.get_body_data("wsUrl"), diff --git a/IPython/html/static/notebook/js/textcell.js b/IPython/html/static/notebook/js/textcell.js index 51e8c18..f4668c9 100644 --- a/IPython/html/static/notebook/js/textcell.js +++ b/IPython/html/static/notebook/js/textcell.js @@ -10,7 +10,10 @@ define([ 'notebook/js/mathjaxutils', 'notebook/js/celltoolbar', 'components/marked/lib/marked', -], function(IPython, utils, $, cell, security, mathjaxutils, celltoolbar, marked) { + 'codemirror/lib/codemirror', + 'codemirror/mode/gfm/gfm', + 'notebook/js/codemirror-ipythongfm' +], function(IPython,utils , $, cell, security, mathjaxutils, celltoolbar, marked, CodeMirror, gfm, ipgfm) { "use strict"; var Cell = cell.Cell; diff --git a/IPython/html/templates/notebook.html b/IPython/html/templates/notebook.html index d4c65f8..a4c1aa8 100644 --- a/IPython/html/templates/notebook.html +++ b/IPython/html/templates/notebook.html @@ -311,25 +311,17 @@ class="notebook_app" {% block script %} {{super()}} - + - - - - - - - - - - - - - - - diff --git a/IPython/html/templates/page.html b/IPython/html/templates/page.html index 9d6bf4e..cc8adb1 100644 --- a/IPython/html/templates/page.html +++ b/IPython/html/templates/page.html @@ -28,6 +28,7 @@ jqueryui: 'components/jquery-ui/ui/minified/jquery-ui.min', highlight: 'components/highlight.js/build/highlight.pack', moment: "components/moment/moment", + codemirror: 'components/codemirror', }, shim: { underscore: {