##// END OF EJS Templates
BUG: Fix broken codemirror highlighting on file rename....
Scott Sanderson -
Show More
@@ -1,190 +1,193 b''
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'jquery',
6 6 'base/js/utils',
7 7 'codemirror/lib/codemirror',
8 8 'codemirror/mode/meta',
9 9 'codemirror/addon/comment/comment',
10 10 'codemirror/addon/dialog/dialog',
11 11 'codemirror/addon/edit/closebrackets',
12 12 'codemirror/addon/edit/matchbrackets',
13 13 'codemirror/addon/search/searchcursor',
14 14 'codemirror/addon/search/search',
15 15 'codemirror/keymap/emacs',
16 16 'codemirror/keymap/sublime',
17 17 'codemirror/keymap/vim',
18 18 ],
19 19 function($,
20 20 utils,
21 21 CodeMirror
22 22 ) {
23 23 "use strict";
24 24
25 25 var Editor = function(selector, options) {
26 26 var that = this;
27 27 this.selector = selector;
28 28 this.contents = options.contents;
29 29 this.events = options.events;
30 30 this.base_url = options.base_url;
31 31 this.file_path = options.file_path;
32 32 this.config = options.config;
33 33 this.codemirror = new CodeMirror($(this.selector)[0]);
34 34 this.generation = -1;
35 35
36 36 // It appears we have to set commands on the CodeMirror class, not the
37 37 // instance. I'd like to be wrong, but since there should only be one CM
38 38 // instance on the page, this is good enough for now.
39 39 CodeMirror.commands.save = $.proxy(this.save, this);
40 40
41 41 this.save_enabled = false;
42 42
43 43 this.config.loaded.then(function () {
44 44 // load codemirror config
45 45 var cfg = that.config.data.Editor || {};
46 46 var cmopts = $.extend(true, {}, // true = recursive copy
47 47 Editor.default_codemirror_options,
48 48 cfg.codemirror_options || {}
49 49 );
50 50 that._set_codemirror_options(cmopts);
51 51 that.events.trigger('config_changed.Editor', {config: that.config});
52 52 });
53 53 };
54 54
55 55 // default CodeMirror options
56 56 Editor.default_codemirror_options = {
57 57 extraKeys: {
58 58 "Tab" : "indentMore",
59 59 },
60 60 indentUnit: 4,
61 61 theme: "ipython",
62 62 lineNumbers: true,
63 63 lineWrapping: true,
64 64 };
65 65
66 66 Editor.prototype.load = function() {
67 67 /** load the file */
68 68 var that = this;
69 69 var cm = this.codemirror;
70 70 return this.contents.get(this.file_path, {type: 'file', format: 'text'})
71 71 .then(function(model) {
72 72 cm.setValue(model.content);
73 73
74 74 // Setting the file's initial value creates a history entry,
75 75 // which we don't want.
76 76 cm.clearHistory();
77 77 that._set_mode_for_model(model);
78 78 that.save_enabled = true;
79 79 that.generation = cm.changeGeneration();
80 80 that.events.trigger("file_loaded.Editor", model);
81 81 },
82 82 function(error) {
83 83 that.events.trigger("file_load_failed.Editor", error);
84 84 if (error.xhr.responseJSON.reason === 'bad format') {
85 85 window.location = utils.url_path_join(
86 86 that.base_url,
87 87 'files',
88 88 that.file_path
89 89 );
90 90 }
91 91 cm.setValue("Error! " + error.message +
92 92 "\nSaving disabled.");
93 93 that.save_enabled = false;
94 94 }
95 95 );
96 96 };
97 97
98 98 Editor.prototype._set_mode_for_model = function (model) {
99 99 /** Set the CodeMirror mode based on the file model */
100 100
101 101 // Find and load the highlighting mode,
102 102 // first by mime-type, then by file extension
103 var modeinfo = CodeMirror.findModeByMIME(model.mimetype);
104 if (modeinfo.mode === "null") {
103 var modeinfo;
104 if (model.mimetype) {
105 modeinfo = CodeMirror.findModeByMIME(model.mimetype);
106 }
107 if (!modeinfo || modeinfo.mode === "null") {
105 108 // find by mime failed, use find by ext
106 109 var ext_idx = model.name.lastIndexOf('.');
107 110
108 111 if (ext_idx > 0) {
109 112 // CodeMirror.findModeByExtension wants extension without '.'
110 113 modeinfo = CodeMirror.findModeByExtension(model.name.slice(ext_idx + 1));
111 114 }
112 115 }
113 116 if (modeinfo) {
114 117 this.set_codemirror_mode(modeinfo);
115 118 }
116 119 };
117 120
118 121 Editor.prototype.set_codemirror_mode = function (modeinfo) {
119 122 /** set the codemirror mode from a modeinfo struct */
120 123 var that = this;
121 124 utils.requireCodeMirrorMode(modeinfo, function () {
122 125 that.codemirror.setOption('mode', modeinfo.mode);
123 126 that.events.trigger("mode_changed.Editor", modeinfo);
124 127 });
125 128 };
126 129
127 130 Editor.prototype.get_filename = function () {
128 131 return utils.url_path_split(this.file_path)[1];
129 132 };
130 133
131 134 Editor.prototype.rename = function (new_name) {
132 135 /** rename the file */
133 136 var that = this;
134 137 var parent = utils.url_path_split(this.file_path)[0];
135 138 var new_path = utils.url_path_join(parent, new_name);
136 139 return this.contents.rename(this.file_path, new_path).then(
137 140 function (model) {
138 141 that.file_path = model.path;
139 142 that.events.trigger('file_renamed.Editor', model);
140 143 that._set_mode_for_model(model);
141 144 }
142 145 );
143 146 };
144 147
145 148 Editor.prototype.save = function () {
146 149 /** save the file */
147 150 if (!this.save_enabled) {
148 151 console.log("Not saving, save disabled");
149 152 return;
150 153 }
151 154 var model = {
152 155 path: this.file_path,
153 156 type: 'file',
154 157 format: 'text',
155 158 content: this.codemirror.getValue(),
156 159 };
157 160 var that = this;
158 161 // record change generation for isClean
159 162 this.generation = this.codemirror.changeGeneration();
160 163 return this.contents.save(this.file_path, model).then(function(data) {
161 164 that.events.trigger("file_saved.Editor", data);
162 165 });
163 166 };
164 167
165 168 Editor.prototype._set_codemirror_options = function (options) {
166 169 // update codemirror options from a dict
167 170 var codemirror = this.codemirror;
168 171 $.map(options, function (value, opt) {
169 172 if (value === null) {
170 173 value = CodeMirror.defaults[opt];
171 174 }
172 175 codemirror.setOption(opt, value);
173 176 });
174 177 };
175 178
176 179 Editor.prototype.update_codemirror_options = function (options) {
177 180 /** update codemirror options locally and save changes in config */
178 181 var that = this;
179 182 this._set_codemirror_options(options);
180 183 return this.config.update({
181 184 Editor: {
182 185 codemirror_options: options
183 186 }
184 187 }).then(
185 188 that.events.trigger('config_changed.Editor', {config: that.config})
186 189 );
187 190 };
188 191
189 192 return {Editor: Editor};
190 193 });
General Comments 0
You need to be logged in to leave comments. Login now