Update to codemirror 4

Update to codemirror 4.6 and update most notebook to work wiht it
this include keyevent that where triggerd twice and the re-writing of
ipython-gfm anf ipython mode to work with require.
This commit is contained in:
Matthias BUSSONNIER 2014-07-27 20:09:33 +02:00 committed by Matthias Bussonnier
parent 262bf7d2c9
commit 5b355936df
14 changed files with 221 additions and 103 deletions

View File

@ -4,7 +4,8 @@
define([
'base/js/namespace',
'jquery',
], function(IPython, $) {
'codemirror/lib/codemirror',
], function(IPython, $, CodeMirror) {
"use strict";
var modal = function (options) {

View File

@ -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;

View File

@ -4,7 +4,8 @@
define([
'base/js/namespace',
'jquery',
], function(IPython, $){
'codemirror/lib/codemirror',
], function(IPython, $, CodeMirror){
"use strict";
IPython.load_extensions = function () {

View File

@ -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') {

View File

@ -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 = $('<div/>').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;
}

View File

@ -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");
})

View File

@ -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) {
CodeMirror.defineMIME("text/x-ipythongfm", "ipythongfm");
});
});
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"
},
{
// 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");
})

View File

@ -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;

View File

@ -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) {

View File

@ -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--' : {

View File

@ -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"),

View File

@ -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;

View File

@ -311,25 +311,17 @@ class="notebook_app"
{% block script %}
{{super()}}
<script src="{{ static_url("components/codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
<script type="text/javascript">
CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js", include_version=False) }}";
require(['codemirror/lib/codemirror',
], function(CodeMirror){
CodeMirror.modeURL = "{{ static_url("components/codemirror/mode/%N/%N.js", include_version=False) }}";
// require([
// 'notebook/js/codemirror-ipython',
// 'notebook/js/codemirror-ipythongfm'
//], function(){})
});
</script>
<script src="{{ static_url("components/codemirror/addon/mode/loadmode.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/addon/mode/multiplex.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/addon/mode/overlay.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/addon/edit/matchbrackets.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/addon/edit/closebrackets.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/addon/comment/comment.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/css/css.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
<script src="{{ static_url("components/codemirror/mode/python/python.js") }}" charset="utf-8"></script>
<script src="{{ static_url("notebook/js/codemirror-ipython.js") }}" charset="utf-8"></script>
<script src="{{ static_url("notebook/js/codemirror-ipythongfm.js") }}" charset="utf-8"></script>
<script src="{{ static_url("notebook/js/main.js") }}" charset="utf-8"></script>

View File

@ -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: {