autochange highlight with cell magics

also detect diff in raw cells

mode is détected on enter keypress, notebook load, cell and focus out
This commit is contained in:
Matthias BUSSONNIER 2012-07-28 17:39:36 +02:00
parent 99ccdf15d9
commit d88f7d4c72
5 changed files with 105 additions and 2 deletions

View File

@ -20,19 +20,21 @@ var IPython = (function (IPython) {
this.selected = false;
this.element = null;
this.metadata = {};
// load this from metadata later ?
this.user_highlight == 'auto';
this.create_element();
if (this.element !== null) {
this.element.data("cell", this);
this.bind_events();
}
this.cell_id = utils.uuid();
};
// Subclasses must implement create_element.
Cell.prototype.create_element = function () {};
Cell.prototype.bind_events = function () {
var that = this;
// We trigger events so that Cell doesn't have to depend on Notebook.
@ -154,6 +156,61 @@ var IPython = (function (IPython) {
this.code_mirror.refresh();
};
Cell.prototype.force_highlight = function(mode) {
this.user_highlight = mode;
this.auto_highlight();
};
Cell.prototype._auto_highlight = function (modes) {
//Here we handle manually selected modes
if( this.user_highlight != undefined && this.user_highlight != 'auto' )
{
var mode = this.user_highlight;
CodeMirror.autoLoadMode(this.code_mirror, mode);
this.code_mirror.setOption('mode', mode);
return;
}
var first_line = this.code_mirror.getLine(0);
// loop on every pairs
for( var mode in modes) {
var regs = modes[mode]['reg'];
// only one key every time but regexp can't be keys...
for(var reg in regs ) {
// here we handle non magic_modes
if(first_line.match(regs[reg]) != null) {
if (mode.search('magic_') != 0) {
this.code_mirror.setOption('mode',mode);
CodeMirror.autoLoadMode(this.code_mirror, mode);
return;
}
var open = modes[mode]['open']|| "%%";
var close = modes[mode]['close']|| "%%end";
var mmode = mode;
mode = mmode.substr(6);
CodeMirror.autoLoadMode(this.code_mirror, mode);
// create on the fly a mode that swhitch between
// plain/text and smth else otherwise `%%` is
// source of some highlight issues.
// we use patchedGetMode to circumvent a bug in CM
CodeMirror.defineMode(mmode , function(config) {
return CodeMirror.multiplexingMode(
CodeMirror.patchedGetMode(config, 'text/plain'),
// always set someting on close
{open: open, close: close,
mode: CodeMirror.patchedGetMode(config, mode),
delimStyle: "delimit"
}
);
});
this.code_mirror.setOption('mode', mmode);
return;
}
}
}
// fallback on default (python)
var default_mode = this.default_mode || 'text/plain';
this.code_mirror.setOption('mode', default_mode);
};
IPython.Cell = Cell;

View File

@ -14,6 +14,7 @@ var IPython = (function (IPython) {
var utils = IPython.utils;
var key = IPython.utils.keycodes;
CodeMirror.modeURL = "/static/codemirror/mode/%N/%N.js";
var CodeCell = function (kernel) {
// The kernel doesn't have to be set at creation time, in that case
@ -23,13 +24,23 @@ var IPython = (function (IPython) {
this.input_prompt_number = null;
this.tooltip_on_tab = true;
this.collapsed = false;
this.default_mode = 'python';
IPython.Cell.apply(this, arguments);
var that = this;
this.element.focusout(
function() { that.auto_highlight(); }
);
};
CodeCell.prototype = new IPython.Cell();
CodeCell.prototype.auto_highlight = function () {
this._auto_highlight(IPython.config.cell_magic_highlight)
};
CodeCell.prototype.create_element = function () {
var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
cell.attr('tabindex','2');
@ -76,6 +87,9 @@ var IPython = (function (IPython) {
};
var cur = editor.getCursor();
if (event.keyCode === key.ENTER){
this.auto_highlight();
}
if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
// Always ignore shift-enter in CodeMirror as we handle it.
@ -172,6 +186,7 @@ var IPython = (function (IPython) {
IPython.Cell.prototype.select.apply(this);
this.code_mirror.refresh();
this.code_mirror.focus();
this.auto_highlight();
// We used to need an additional refresh() after the focus, but
// it appears that this has been fixed in CM. This bug would show
// up on FF when a newly loaded markdown cell was edited.
@ -267,6 +282,7 @@ var IPython = (function (IPython) {
// make this value the starting point, so that we can only undo
// to this state, instead of a blank cell
this.code_mirror.clearHistory();
this.auto_highlight();
}
if (data.prompt_number !== undefined) {
this.set_input_prompt(data.prompt_number);

View File

@ -1,5 +1,5 @@
//----------------------------------------------------------------------------
// Copyright (C) 2008-2011 The IPython Development Team
// Copyright (C) 2011 The IPython Development Team
//
// Distributed under the terms of the BSD License. The full license is in
// the file COPYING, distributed as part of this software.
@ -12,6 +12,25 @@
$(document).ready(function () {
// monkey patch CM to be able to syntax highlight cell magics
// bug reported upstream,
// see https://github.com/marijnh/CodeMirror2/issues/670
if(CodeMirror.getMode(1,'text/plain').indent == undefined ){
console.log('patching CM for undefined indent');
CodeMirror.modes.null = function() { return {token: function(stream) {stream.skipToEnd();},indent : function(){return 0}}}
}
CodeMirror.patchedGetMode = function(config, mode){
var cmmode = CodeMirror.getMode(config, mode);
if(cmmode.indent == null)
{
console.log('patch mode "' , mode, '" on the fly');
cmmode.indent = function(){return 0};
}
return cmmode;
}
// end monkey patching CodeMirror
IPython.init_mathjax();
IPython.read_only = $('body').data('readOnly') === 'True';

View File

@ -257,11 +257,19 @@ var IPython = (function (IPython) {
this.code_mirror_mode = 'rst';
IPython.TextCell.apply(this, arguments);
this.cell_type = 'raw';
var that = this
this.element.focusout(
function() { that.auto_highlight(); }
);
};
RawCell.prototype = new TextCell();
RawCell.prototype.auto_highlight = function () {
this._auto_highlight(IPython.config.raw_cell_highlight);
};
RawCell.prototype.render = function () {
this.rendered = true;

View File

@ -212,6 +212,8 @@ data-notebook-id={{notebook_id}}
{% block script %}
<script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/lib/util/loadmode.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/lib/util/multiplex.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
@ -243,6 +245,7 @@ data-notebook-id={{notebook_id}}
<script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notificationwidget.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/tooltip.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/config.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/contexthint.js") }}" charset="utf-8"></script>