From a2f6a8c3bbdfd6fb0800730032efb2ed6f0f6306 Mon Sep 17 00:00:00 2001 From: Min RK Date: Tue, 18 Apr 2017 11:02:42 +0200 Subject: [PATCH] editor: remember user language choices per file extension When the language is selected manually, record the file extension and choice in config so that future files opened with the same extension use the same mode. This allows users to teach the editor about file extensions CodeMirror doesn't know about. --- notebook/static/edit/js/editor.js | 74 ++++++++++++++++++++++++------ notebook/static/edit/js/menubar.js | 2 + 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/notebook/static/edit/js/editor.js b/notebook/static/edit/js/editor.js index 71a582dcc..06fa5b66a 100644 --- a/notebook/static/edit/js/editor.js +++ b/notebook/static/edit/js/editor.js @@ -32,6 +32,8 @@ function( this.base_url = options.base_url; this.file_path = options.file_path; this.config = options.config; + this.file_extension_modes = options.file_extension_modes || {}; + this.codemirror = new CodeMirror($(this.selector)[0]); this.codemirror.on('changes', function(cm, changes){ that._clean_state(); @@ -54,6 +56,14 @@ function( ); that._set_codemirror_options(cmopts); that.events.trigger('config_changed.Editor', {config: that.config}); + if (cfg.file_extension_modes) { + // check for file extension in user preferences + var modename = cfg.file_extension_modes[that._get_file_extension()]; + if (modename) { + var modeinfo = CodeMirror.findModeByName(modename); + that.set_codemirror_mode(modeinfo); + } + } that._clean_state(); }); this.clean_sel = $('
'); @@ -99,7 +109,7 @@ function( } ); }; - + Editor.prototype._set_mode_for_model = function (model) { /** Set the CodeMirror mode based on the file model */ @@ -107,20 +117,28 @@ function( // first by mime-type, then by file extension var modeinfo; - // mimetype is unset on file rename - if (model.mimetype) { - modeinfo = CodeMirror.findModeByMIME(model.mimetype); + var ext = this._get_file_extension(); + if (ext) { + // check if a mode has been remembered for this extension + var modename = this.file_extension_modes[ext]; + if (modename) { + modeinfo = CodeMirror.findModeByName(modename); + } } + // prioritize CodeMirror's filename identification if (!modeinfo || modeinfo.mode === "null") { - // find by mime failed, use find by ext - var ext_idx = model.name.lastIndexOf('.'); - - if (ext_idx > 0) { - // CodeMirror.findModeByExtension wants extension without '.' - modeinfo = CodeMirror.findModeByExtension( - model.name.slice(ext_idx + 1).toLowerCase()); + modeinfo = CodeMirror.findModeByFileName(model.name); + // codemirror's filename identification is case-sensitive. + // try once more with lowercase extension + if (!modeinfo && ext) { + // CodeMirror wants lowercase ext without leading '.' + modeinfo = CodeMirror.findModeByExtension(ext.slice(1).toLowerCase()); } } + if (model.mimetype && (!modeinfo || modeinfo.mode === "null")) { + // mimetype is not set on file rename + modeinfo = CodeMirror.findModeByMIME(model.mimetype); + } if (modeinfo) { this.set_codemirror_mode(modeinfo); } @@ -134,11 +152,41 @@ function( that.events.trigger("mode_changed.Editor", modeinfo); }); }; - + + Editor.prototype.save_codemirror_mode = function (modeinfo) { + /** save the selected codemirror mode for the current extension in config */ + var update_mode_map = {}; + var ext = this._get_file_extension(); + // no extension, nothing to save + // TODO: allow remembering no-extension things like Makefile? + if (!ext) return; + + update_mode_map[ext] = modeinfo.name; + return this.config.update({ + Editor: { + file_extension_modes: update_mode_map, + } + }) + }; + Editor.prototype.get_filename = function () { return utils.url_path_split(this.file_path)[1]; }; + Editor.prototype._get_file_extension = function () { + /** return file extension *including* . + + Returns undefined if no extension is found. + */ + var filename = this.get_filename(); + var ext_idx = filename.lastIndexOf('.'); + if (ext_idx < 0) { + return; + } else { + return filename.slice(ext_idx); + } + }; + Editor.prototype.rename = function (new_name) { /** rename the file */ var that = this; @@ -203,7 +251,7 @@ function( }); var that = this; }; - + Editor.prototype.update_codemirror_options = function (options) { /** update codemirror options locally and save changes in config */ var that = this; diff --git a/notebook/static/edit/js/menubar.js b/notebook/static/edit/js/menubar.js index 992e58590..d7fa05577 100644 --- a/notebook/static/edit/js/menubar.js +++ b/notebook/static/edit/js/menubar.js @@ -146,6 +146,8 @@ define([ function make_set_mode(info) { return function () { editor.set_codemirror_mode(info); + // save codemirror mode for extension when explicitly selected + editor.save_codemirror_mode(info); }; } for (var i = 0; i < CodeMirror.modeInfo.length; i++) {