diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js index 7559641..a63a497 100644 --- a/IPython/html/static/notebook/js/codecell.js +++ b/IPython/html/static/notebook/js/codecell.js @@ -14,6 +14,7 @@ define([ 'jquery', 'base/js/utils', 'base/js/keyboard', + 'services/config', 'notebook/js/cell', 'notebook/js/outputarea', 'notebook/js/completer', @@ -21,7 +22,19 @@ define([ 'codemirror/lib/codemirror', 'codemirror/mode/python/python', 'notebook/js/codemirror-ipython' -], function(IPython, $, utils, keyboard, cell, outputarea, completer, celltoolbar, CodeMirror, cmpython, cmip) { +], function(IPython, + $, + utils, + keyboard, + configmod, + cell, + outputarea, + completer, + celltoolbar, + CodeMirror, + cmpython, + cmip + ) { "use strict"; var Cell = cell.Cell; @@ -76,6 +89,8 @@ define([ this.events = options.events; this.tooltip = options.tooltip; this.config = options.config; + this.class_config = new configmod.ConfigWithDefaults(this.config, + CodeCell.config_defaults, 'CodeCell'); // create all attributed in constructor function // even if null for V8 VM optimisation @@ -103,9 +118,8 @@ define([ this.completer = null; this.widget_views = []; - var config = utils.mergeopt(CodeCell, this.config); Cell.apply(this,[{ - config: config, + config: $.extend({}, CodeCell.options_default), keyboard_manager: options.keyboard_manager, events: this.events}]); @@ -131,6 +145,18 @@ define([ } }; + CodeCell.config_defaults = { + cell_magic_highlight : { + 'magic_javascript' :{'reg':[/^%%javascript/]}, + 'magic_perl' :{'reg':[/^%%perl/]}, + 'magic_ruby' :{'reg':[/^%%ruby/]}, + 'magic_python' :{'reg':[/^%%python3?/]}, + 'magic_shell' :{'reg':[/^%%bash/]}, + 'magic_r' :{'reg':[/^%%R/]}, + 'magic_text/x-cython' :{'reg':[/^%%cython/]}, + }, + }; + CodeCell.msg_cells = {}; CodeCell.prototype = Object.create(Cell.prototype); @@ -156,7 +182,7 @@ define([ * @method auto_highlight */ CodeCell.prototype.auto_highlight = function () { - this._auto_highlight(this.config.cell_magic_highlight); + this._auto_highlight(this.class_config.get_sync('cell_magic_highlight')); }; /** @method create_element */ diff --git a/IPython/html/static/notebook/js/config.js b/IPython/html/static/notebook/js/config.js deleted file mode 100644 index 1c60b6f..0000000 --- a/IPython/html/static/notebook/js/config.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) IPython Development Team. -// Distributed under the terms of the Modified BSD License. - -/** - * - * - * @module config - * @namespace config - * @class Config - */ - - -define([], function() { - "use strict"; - - var default_config = { - /** - * Dictionary of object to autodetect highlight mode for code cell. - * Item of the dictionnary should take the form : - * - * key : {'reg':[list_of_regexp]} - * - * where `key` will be the code mirror mode name - * and `list_of_regexp` should be a list of regext that should match - * the first line of the cell to trigger this mode. - * - * if `key` is prefixed by the `magic_` prefix the codemirror `mode` - * will be applied only at the end of the first line - * - * @attribute cell_magic_highlight - * @example - * This would trigger javascript mode - * from the second line if first line start with `%%javascript` or `%%jsmagic` - * - * cell_magic_highlight['magic_javascript'] = {'reg':[/^%%javascript/,/^%%jsmagic/]} - * @example - * This would trigger javascript mode - * from the second line if first line start with `var` - * - * cell_magic_highlight['javascript'] = {'reg':[/^var/]} - */ - cell_magic_highlight : { - 'magic_javascript' :{'reg':[/^%%javascript/]}, - 'magic_perl' :{'reg':[/^%%perl/]}, - 'magic_ruby' :{'reg':[/^%%ruby/]}, - 'magic_python' :{'reg':[/^%%python3?/]}, - 'magic_shell' :{'reg':[/^%%bash/]}, - 'magic_r' :{'reg':[/^%%R/]}, - 'magic_text/x-cython' :{'reg':[/^%%cython/]}, - }, - - /** - * same as `cell_magic_highlight` but for raw cells - * @attribute raw_cell_highlight - */ - raw_cell_highlight : { - 'diff' :{'reg':[/^diff/]} - }, - }; - - return { - 'default_config': default_config, - }; -}); diff --git a/IPython/html/static/notebook/js/main.js b/IPython/html/static/notebook/js/main.js index a6c8264..50d0de5 100644 --- a/IPython/html/static/notebook/js/main.js +++ b/IPython/html/static/notebook/js/main.js @@ -19,7 +19,6 @@ require([ 'notebook/js/savewidget', 'notebook/js/actions', 'notebook/js/keyboardmanager', - 'notebook/js/config', 'notebook/js/kernelselector', 'codemirror/lib/codemirror', 'notebook/js/about', @@ -43,7 +42,6 @@ require([ savewidget, actions, keyboardmanager, - config, kernelselector, CodeMirror, about, @@ -62,7 +60,6 @@ require([ notebook_name : utils.get_body_data('notebookName') }; - var user_config = $.extend({}, config.default_config); var page = new page.Page(); var pager = new pager.Pager('div#pager', { events: events}); @@ -84,7 +81,7 @@ require([ keyboard_manager: keyboard_manager, save_widget: save_widget, contents: contents, - config: user_config}, + config: config_section}, common_options)); var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options); var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', { @@ -150,7 +147,6 @@ require([ IPython.notification_area = notification_area; IPython.keyboard_manager = keyboard_manager; IPython.save_widget = save_widget; - IPython.config = user_config; IPython.tooltip = notebook.tooltip; events.trigger('app_initialized.NotebookApp'); diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index 940a3f3..e41cb4e 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -12,6 +12,7 @@ define([ 'notebook/js/cell', 'notebook/js/textcell', 'notebook/js/codecell', + 'services/config', 'services/sessions/session', 'notebook/js/celltoolbar', 'components/marked/lib/marked', @@ -32,6 +33,7 @@ define([ cellmod, textcell, codecell, + configmod, session, celltoolbar, marked, @@ -63,7 +65,9 @@ define([ * @param {string} options.notebook_name */ var Notebook = function (selector, options) { - this.config = utils.mergeopt(Notebook, options.config); + this.config = options.config; + this.class_config = new configmod.ConfigWithDefaults(this.config, + Notebook.options_default, 'Notebook'); this.base_url = options.base_url; this.notebook_path = options.notebook_path; this.notebook_name = options.notebook_name; @@ -74,7 +78,6 @@ define([ this.tooltip = new tooltip.Tooltip(this.events); this.ws_url = options.ws_url; this._session_starting = false; - this.default_cell_type = this.config.default_cell_type || 'code'; // Create default scroll manager. this.scroll_manager = new scrollmanager.ScrollManager(this); @@ -172,9 +175,7 @@ define([ Notebook.options_default = { // can be any cell type, or the special values of // 'above', 'below', or 'selected' to get the value from another cell. - Notebook: { - default_cell_type: 'code' - } + default_cell_type: 'code' }; /** @@ -861,7 +862,7 @@ define([ index = Math.min(index, ncells); index = Math.max(index, 0); var cell = null; - type = type || this.default_cell_type; + type = type || this.class_config.get_sync('default_cell_type'); if (type === 'above') { if (index > 0) { type = this.get_cell(index-1).cell_type; diff --git a/IPython/html/static/notebook/js/textcell.js b/IPython/html/static/notebook/js/textcell.js index cf3feed..2a7cf4b 100644 --- a/IPython/html/static/notebook/js/textcell.js +++ b/IPython/html/static/notebook/js/textcell.js @@ -7,13 +7,26 @@ define([ 'jquery', 'notebook/js/cell', 'base/js/security', + 'services/config', 'notebook/js/mathjaxutils', 'notebook/js/celltoolbar', 'components/marked/lib/marked', 'codemirror/lib/codemirror', 'codemirror/mode/gfm/gfm', 'notebook/js/codemirror-ipythongfm' -], function(IPython,utils , $, cell, security, mathjaxutils, celltoolbar, marked, CodeMirror, gfm, ipgfm) { +], function(IPython, + utils, + $, + cell, + security, + configmod, + mathjaxutils, + celltoolbar, + marked, + CodeMirror, + gfm, + ipgfm + ) { "use strict"; var Cell = cell.Cell; @@ -204,14 +217,16 @@ define([ * options: dictionary * Dictionary of keyword arguments. * events: $(Events) instance - * config: dictionary + * config: ConfigSection instance * keyboard_manager: KeyboardManager instance * notebook: Notebook instance */ options = options || {}; - var config = utils.mergeopt(MarkdownCell, options.config); + var config = utils.mergeopt(MarkdownCell, {}); TextCell.apply(this, [$.extend({}, options, {config: config})]); + this.class_config = new configmod.ConfigWithDefaults(options.config, + {}, 'MarkdownCell'); this.cell_type = 'markdown'; }; @@ -287,14 +302,16 @@ define([ * options: dictionary * Dictionary of keyword arguments. * events: $(Events) instance - * config: dictionary + * config: ConfigSection instance * keyboard_manager: KeyboardManager instance * notebook: Notebook instance */ options = options || {}; - var config = utils.mergeopt(RawCell, options.config); + var config = utils.mergeopt(RawCell, {}); TextCell.apply(this, [$.extend({}, options, {config: config})]); + this.class_config = new configmod.ConfigWithDefaults(options.config, + RawCell.config_defaults, 'RawCell'); this.cell_type = 'raw'; }; @@ -303,6 +320,12 @@ define([ "It will not be rendered in the notebook. " + "When passing through nbconvert, a Raw Cell's content is added to the output unmodified." }; + + RawCell.config_defaults = { + highlight_modes : { + 'diff' :{'reg':[/^diff/]} + }, + }; RawCell.prototype = Object.create(TextCell.prototype); @@ -323,7 +346,7 @@ define([ * @method auto_highlight */ RawCell.prototype.auto_highlight = function () { - this._auto_highlight(this.config.raw_cell_highlight); + this._auto_highlight(this.class_config.get_sync('highlight_modes')); }; /** @method render **/ diff --git a/IPython/html/static/services/config.js b/IPython/html/static/services/config.js index 139a02a..0d2a9f9 100644 --- a/IPython/html/static/services/config.js +++ b/IPython/html/static/services/config.js @@ -48,7 +48,14 @@ function($, utils) { }); }; + /** + * Modify the config values stored. Update the local data immediately, + * send the change to the server, and use the updated data from the server + * when the reply comes. + */ ConfigSection.prototype.update = function(newdata) { + $.extend(true, this.data, newdata); // true -> recursive update + var that = this; return utils.promising_ajax(this.api_url(), { processData: false, @@ -63,6 +70,60 @@ function($, utils) { }); }; - return {ConfigSection: ConfigSection}; + + var ConfigWithDefaults = function(section, defaults, classname) { + this.section = section; + this.defaults = defaults; + this.classname = classname; + }; + + ConfigWithDefaults.prototype._class_data = function() { + if (this.classname) { + return this.section.data[this.classname] || {}; + } else { + return this.section.data + } + }; + + /** + * Wait for config to have loaded, then get a value or the default. + * Returns a promise. + */ + ConfigWithDefaults.prototype.get = function(key) { + var that = this; + return this.section.loaded.then(function() { + return this._class_data()[key] || this.defaults[key] + }); + }; + + /** + * Return a config value. If config is not yet loaded, return the default + * instead of waiting for it to load. + */ + ConfigWithDefaults.prototype.get_sync = function(key) { + return this._class_data()[key] || this.defaults[key]; + }; + + /** + * Set a config value. Send the update to the server, and change our + * local copy of the data immediately. + * Returns a promise which is fulfilled when the server replies to the + * change. + */ + ConfigWithDefaults.prototype.set = function(key, value) { + var d = {}; + d[key] = value; + if (this.classname) { + var d2 = {}; + d2[this.classname] = d; + return this.section.update(d2); + } else { + return this.section.update(d); + } + }; + + return {ConfigSection: ConfigSection, + ConfigWithDefaults: ConfigWithDefaults, + }; }); diff --git a/IPython/html/tests/notebook/dualmode_cellinsert.js b/IPython/html/tests/notebook/dualmode_cellinsert.js index 1764042..093f5b6 100644 --- a/IPython/html/tests/notebook/dualmode_cellinsert.js +++ b/IPython/html/tests/notebook/dualmode_cellinsert.js @@ -33,7 +33,7 @@ casper.notebook_test(function () { }); this.thenEvaluate(function() { - IPython.notebook.default_cell_type = 'selected'; + IPython.notebook.class_config.set('default_cell_type', 'selected'); }); this.then(function () { @@ -47,7 +47,7 @@ casper.notebook_test(function () { }); this.thenEvaluate(function() { - IPython.notebook.default_cell_type = 'above'; + IPython.notebook.class_config.set('default_cell_type', 'above'); }); this.then(function () { @@ -61,7 +61,7 @@ casper.notebook_test(function () { }); this.thenEvaluate(function() { - IPython.notebook.default_cell_type = 'below'; + IPython.notebook.class_config.set('default_cell_type', 'below'); }); this.then(function () {