##// END OF EJS Templates
Added saving and loading of output of all types.
Brian E. Granger -
Show More
@@ -1,333 +1,374 b''
1
1
2 //============================================================================
2 //============================================================================
3 // CodeCell
3 // CodeCell
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var CodeCell = function (notebook) {
10 var CodeCell = function (notebook) {
11 this.code_mirror = null;
11 this.code_mirror = null;
12 this.input_prompt_number = ' ';
12 this.input_prompt_number = ' ';
13 this.is_completing = false;
13 this.is_completing = false;
14 this.completion_cursor = null;
14 this.completion_cursor = null;
15 this.outputs = [];
15 IPython.Cell.apply(this, arguments);
16 IPython.Cell.apply(this, arguments);
16 };
17 };
17
18
18
19
19 CodeCell.prototype = new IPython.Cell();
20 CodeCell.prototype = new IPython.Cell();
20
21
21
22
22 CodeCell.prototype.create_element = function () {
23 CodeCell.prototype.create_element = function () {
23 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
24 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
24 var input = $('<div></div>').addClass('input hbox');
25 var input = $('<div></div>').addClass('input hbox');
25 input.append($('<div/>').addClass('prompt input_prompt'));
26 input.append($('<div/>').addClass('prompt input_prompt'));
26 var input_area = $('<div/>').addClass('input_area box-flex1');
27 var input_area = $('<div/>').addClass('input_area box-flex1');
27 this.code_mirror = CodeMirror(input_area.get(0), {
28 this.code_mirror = CodeMirror(input_area.get(0), {
28 indentUnit : 4,
29 indentUnit : 4,
29 enterMode : 'flat',
30 enterMode : 'flat',
30 tabMode: 'shift',
31 tabMode: 'shift',
31 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
32 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
32 });
33 });
33 input.append(input_area);
34 input.append(input_area);
34 var output = $('<div></div>').addClass('output vbox');
35 var output = $('<div></div>').addClass('output vbox');
35 cell.append(input).append(output);
36 cell.append(input).append(output);
36 this.element = cell;
37 this.element = cell;
37 this.collapse()
38 this.collapse()
38 };
39 };
39
40
40
41
41 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
42 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
42 // This method gets called in CodeMirror's onKeyDown/onKeyPress handlers and
43 // This method gets called in CodeMirror's onKeyDown/onKeyPress handlers and
43 // is used to provide custom key handling. Its return value is used to determine
44 // is used to provide custom key handling. Its return value is used to determine
44 // if CodeMirror should ignore the event: true = ignore, false = don't ignore.
45 // if CodeMirror should ignore the event: true = ignore, false = don't ignore.
45 if (event.keyCode === 13 && event.shiftKey) {
46 if (event.keyCode === 13 && event.shiftKey) {
46 // Always ignore shift-enter in CodeMirror as we handle it.
47 // Always ignore shift-enter in CodeMirror as we handle it.
47 return true;
48 return true;
48 // } else if (event.keyCode == 32 && (event.ctrlKey || event.metaKey) && !event.altKey) {
49 // } else if (event.keyCode == 32 && (event.ctrlKey || event.metaKey) && !event.altKey) {
49 } else if (event.keyCode == 9) {
50 } else if (event.keyCode == 9) {
50 var cur = editor.getCursor();
51 var cur = editor.getCursor();
51 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur).trim();
52 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur).trim();
52 if (pre_cursor === "") {
53 if (pre_cursor === "") {
53 // Don't autocomplete if the part of the line before the cursor is empty.
54 // Don't autocomplete if the part of the line before the cursor is empty.
54 // In this case, let CodeMirror handle indentation.
55 // In this case, let CodeMirror handle indentation.
55 return false;
56 return false;
56 } else {
57 } else {
57 // Autocomplete the current line.
58 // Autocomplete the current line.
58 event.stop();
59 event.stop();
59 var line = editor.getLine(cur.line);
60 var line = editor.getLine(cur.line);
60 this.is_completing = true;
61 this.is_completing = true;
61 this.completion_cursor = cur;
62 this.completion_cursor = cur;
62 IPython.notebook.complete_cell(this, line, cur.ch);
63 IPython.notebook.complete_cell(this, line, cur.ch);
63 return true;
64 return true;
64 }
65 }
65 } else {
66 } else {
66 if (this.is_completing && this.completion_cursor !== editor.getCursor()) {
67 if (this.is_completing && this.completion_cursor !== editor.getCursor()) {
67 this.is_completing = false;
68 this.is_completing = false;
68 this.completion_cursor = null;
69 this.completion_cursor = null;
69 }
70 }
70 return false;
71 return false;
71 };
72 };
72 };
73 };
73
74
74
75
75 CodeCell.prototype.finish_completing = function (matched_text, matches) {
76 CodeCell.prototype.finish_completing = function (matched_text, matches) {
76 if (!this.is_completing || matches.length === 0) {return;}
77 if (!this.is_completing || matches.length === 0) {return;}
77 // console.log("Got matches", matched_text, matches);
78 // console.log("Got matches", matched_text, matches);
78
79
79 var that = this;
80 var that = this;
80 var cur = this.completion_cursor;
81 var cur = this.completion_cursor;
81 var complete = $('<div/>').addClass('completions');
82 var complete = $('<div/>').addClass('completions');
82 var select = $('<select/>').attr('multiple','true');
83 var select = $('<select/>').attr('multiple','true');
83 for (var i=0; i<matches.length; ++i) {
84 for (var i=0; i<matches.length; ++i) {
84 select.append($('<option/>').text(matches[i]));
85 select.append($('<option/>').text(matches[i]));
85 }
86 }
86 select.children().first().attr('selected','true');
87 select.children().first().attr('selected','true');
87 select.attr('size',Math.min(10,matches.length));
88 select.attr('size',Math.min(10,matches.length));
88 var pos = this.code_mirror.cursorCoords();
89 var pos = this.code_mirror.cursorCoords();
89 complete.css('left',pos.x+'px');
90 complete.css('left',pos.x+'px');
90 complete.css('top',pos.yBot+'px');
91 complete.css('top',pos.yBot+'px');
91 complete.append(select);
92 complete.append(select);
92
93
93 $('body').append(complete);
94 $('body').append(complete);
94 var done = false;
95 var done = false;
95
96
96 var insert = function (selected_text) {
97 var insert = function (selected_text) {
97 that.code_mirror.replaceRange(
98 that.code_mirror.replaceRange(
98 selected_text,
99 selected_text,
99 {line: cur.line, ch: (cur.ch-matched_text.length)},
100 {line: cur.line, ch: (cur.ch-matched_text.length)},
100 {line: cur.line, ch: cur.ch}
101 {line: cur.line, ch: cur.ch}
101 );
102 );
102 };
103 };
103
104
104 var close = function () {
105 var close = function () {
105 if (done) return;
106 if (done) return;
106 done = true;
107 done = true;
107 complete.remove();
108 complete.remove();
108 that.is_completing = false;
109 that.is_completing = false;
109 that.completion_cursor = null;
110 that.completion_cursor = null;
110 };
111 };
111
112
112 var pick = function () {
113 var pick = function () {
113 insert(select.val()[0]);
114 insert(select.val()[0]);
114 close();
115 close();
115 setTimeout(function(){that.code_mirror.focus();}, 50);
116 setTimeout(function(){that.code_mirror.focus();}, 50);
116 };
117 };
117
118
118 select.blur(close);
119 select.blur(close);
119 select.keydown(function (event) {
120 select.keydown(function (event) {
120 var code = event.which;
121 var code = event.which;
121 if (code === 13 || code === 32) {
122 if (code === 13 || code === 32) {
122 // Pressing SPACE or ENTER will cause a pick
123 // Pressing SPACE or ENTER will cause a pick
123 event.stopPropagation();
124 event.stopPropagation();
124 event.preventDefault();
125 event.preventDefault();
125 pick();
126 pick();
126 } else if (code === 38 || code === 40) {
127 } else if (code === 38 || code === 40) {
127 // We don't want the document keydown handler to handle UP/DOWN,
128 // We don't want the document keydown handler to handle UP/DOWN,
128 // but we want the default action.
129 // but we want the default action.
129 event.stopPropagation();
130 event.stopPropagation();
130 } else {
131 } else {
131 // All other key presses simple exit completion.
132 // All other key presses simple exit completion.
132 event.stopPropagation();
133 event.stopPropagation();
133 event.preventDefault();
134 event.preventDefault();
134 close();
135 close();
135 that.code_mirror.focus();
136 that.code_mirror.focus();
136 }
137 }
137 });
138 });
138 // Double click also causes a pick.
139 // Double click also causes a pick.
139 select.dblclick(pick);
140 select.dblclick(pick);
140 select.focus();
141 select.focus();
141 };
142 };
142
143
143
144
144 CodeCell.prototype.select = function () {
145 CodeCell.prototype.select = function () {
145 IPython.Cell.prototype.select.apply(this);
146 IPython.Cell.prototype.select.apply(this);
146 this.code_mirror.focus();
147 this.code_mirror.focus();
147 };
148 };
148
149
149
150
150 CodeCell.prototype.append_pyout = function (data, n) {
151 CodeCell.prototype.append_output = function (json) {
152 this.expand();
153 if (json.output_type === 'pyout') {
154 this.append_pyout(json);
155 } else if (json.output_type === 'pyerr') {
156 this.append_pyerr(json);
157 } else if (json.output_type === 'display_data') {
158 this.append_display_data(json);
159 } else if (json.output_type === 'stream') {
160 this.append_stream(json);
161 };
162 this.outputs.push(json);
163 };
164
165
166 CodeCell.prototype.append_pyout = function (json) {
167 n = json.prompt_number || ' ';
151 var toinsert = $("<div/>").addClass("output_area output_pyout hbox");
168 var toinsert = $("<div/>").addClass("output_area output_pyout hbox");
152 toinsert.append($('<div/>').
169 toinsert.append($('<div/>').
153 addClass('prompt output_prompt').
170 addClass('prompt output_prompt').
154 html('Out[' + n + ']:')
171 html('Out[' + n + ']:')
155 );
172 );
156 this.append_display_data(data, toinsert);
173 this.append_mime_type(json, toinsert);
157 toinsert.children().last().addClass("box_flex1");
174 toinsert.children().last().addClass("box_flex1");
158 this.element.find("div.output").append(toinsert);
175 this.element.find("div.output").append(toinsert);
159 // If we just output latex, typeset it.
176 // If we just output latex, typeset it.
160 if (data["text/latex"] !== undefined) {
177 if (json.latex !== undefined) {
161 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
178 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
162 };
179 };
163 };
180 };
164
181
165
182
166 CodeCell.prototype.append_pyerr = function (ename, evalue, tb) {
183 CodeCell.prototype.append_pyerr = function (json) {
184 var tb = json.traceback;
167 var s = '';
185 var s = '';
168 var len = tb.length;
186 var len = tb.length;
169 for (var i=0; i<len; i++) {
187 for (var i=0; i<len; i++) {
170 s = s + tb[i] + '\n';
188 s = s + tb[i] + '\n';
171 }
189 }
172 s = s + '\n';
190 s = s + '\n';
173 this.append_stream(s);
191 this.append_text(s);
192 };
193
194
195 CodeCell.prototype.append_stream = function (json) {
196 this.append_text(json.text);
174 };
197 };
175
198
176
199
177 CodeCell.prototype.append_display_data = function (data, element) {
200 CodeCell.prototype.append_display_data = function (json) {
178 if (data["text/html"] !== undefined) {
201 this.append_mime_type(json);
179 this.append_html(data["text/html"], element);
202 };
180 } else if (data["text/latex"] !== undefined) {
203
181 this.append_latex(data["text/latex"], element);
204
205 CodeCell.prototype.append_mime_type = function (json, element) {
206 if (json.html !== undefined) {
207 this.append_html(json.html, element);
208 } else if (json.latex !== undefined) {
209 this.append_latex(json.latex, element);
182 // If it is undefined, then we just appended to div.output, which
210 // If it is undefined, then we just appended to div.output, which
183 // makes the latex visible and we can typeset it. The typesetting
211 // makes the latex visible and we can typeset it. The typesetting
184 // has to be done after the latex is on the page.
212 // has to be done after the latex is on the page.
185 if (element === undefined) {
213 if (element === undefined) {
186 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
214 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
187 };
215 };
188 } else if (data["image/svg+xml"] !== undefined) {
216 } else if (json.svg !== undefined) {
189 this.append_svg(data["image/svg+xml"], element);
217 this.append_svg(json.svg, element);
190 } else if (data["image/png"] !== undefined) {
218 } else if (json.png !== undefined) {
191 this.append_png(data["image/png"], element);
219 this.append_png(json.png, element);
192 } else if (data["text/plain"] !== undefined) {
220 } else if (json.text !== undefined) {
193 this.append_stream(data["text/plain"], element);
221 this.append_text(json.text, element);
194 };
222 };
195 return element;
223 return element;
196 };
224 };
197
225
198
226
199 CodeCell.prototype.append_html = function (html, element) {
227 CodeCell.prototype.append_html = function (html, element) {
200 element = element || this.element.find("div.output");
228 element = element || this.element.find("div.output");
201 var toinsert = $("<div/>").addClass("output_area output_html");
229 var toinsert = $("<div/>").addClass("output_area output_html");
202 toinsert.append(html);
230 toinsert.append(html);
203 element.append(toinsert);
231 element.append(toinsert);
204 return element;
232 return element;
205 }
233 }
206
234
207
235
208 CodeCell.prototype.append_stream = function (data, element) {
236 CodeCell.prototype.append_text = function (data, element) {
209 element = element || this.element.find("div.output");
237 element = element || this.element.find("div.output");
210 var toinsert = $("<div/>").addClass("output_area output_stream");
238 var toinsert = $("<div/>").addClass("output_area output_stream");
211 toinsert.append($("<pre/>").html(utils.fixConsole(data)));
239 toinsert.append($("<pre/>").html(utils.fixConsole(data)));
212 element.append(toinsert);
240 element.append(toinsert);
213 return element;
241 return element;
214 };
242 };
215
243
216
244
217 CodeCell.prototype.append_svg = function (svg, element) {
245 CodeCell.prototype.append_svg = function (svg, element) {
218 element = element || this.element.find("div.output");
246 element = element || this.element.find("div.output");
219 var toinsert = $("<div/>").addClass("output_area output_svg");
247 var toinsert = $("<div/>").addClass("output_area output_svg");
220 toinsert.append(svg);
248 toinsert.append(svg);
221 element.append(toinsert);
249 element.append(toinsert);
222 return element;
250 return element;
223 };
251 };
224
252
225
253
226 CodeCell.prototype.append_png = function (png, element) {
254 CodeCell.prototype.append_png = function (png, element) {
227 element = element || this.element.find("div.output");
255 element = element || this.element.find("div.output");
228 var toinsert = $("<div/>").addClass("output_area output_png");
256 var toinsert = $("<div/>").addClass("output_area output_png");
229 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
257 toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
230 element.append(toinsert);
258 element.append(toinsert);
231 return element;
259 return element;
232 };
260 };
233
261
234
262
235 CodeCell.prototype.append_latex = function (latex, element) {
263 CodeCell.prototype.append_latex = function (latex, element) {
236 // This method cannot do the typesetting because the latex first has to
264 // This method cannot do the typesetting because the latex first has to
237 // be on the page.
265 // be on the page.
238 element = element || this.element.find("div.output");
266 element = element || this.element.find("div.output");
239 var toinsert = $("<div/>").addClass("output_area output_latex");
267 var toinsert = $("<div/>").addClass("output_area output_latex");
240 toinsert.append(latex);
268 toinsert.append(latex);
241 element.append(toinsert);
269 element.append(toinsert);
242 return element;
270 return element;
243 }
271 }
244
272
245
273
246 CodeCell.prototype.clear_output = function () {
274 CodeCell.prototype.clear_output = function () {
247 this.element.find("div.output").html("");
275 this.element.find("div.output").html("");
276 this.outputs = [];
248 };
277 };
249
278
250
279
251 CodeCell.prototype.clear_input = function () {
280 CodeCell.prototype.clear_input = function () {
252 this.code_mirror.setValue('');
281 this.code_mirror.setValue('');
253 };
282 };
254
283
255
284
256 CodeCell.prototype.collapse = function () {
285 CodeCell.prototype.collapse = function () {
257 this.element.find('div.output').hide();
286 this.element.find('div.output').hide();
258 };
287 };
259
288
260
289
261 CodeCell.prototype.expand = function () {
290 CodeCell.prototype.expand = function () {
262 this.element.find('div.output').show();
291 this.element.find('div.output').show();
263 };
292 };
264
293
265
294
266 CodeCell.prototype.set_input_prompt = function (number) {
295 CodeCell.prototype.set_input_prompt = function (number) {
267 var n = number || ' ';
296 var n = number || ' ';
268 this.input_prompt_number = n
297 this.input_prompt_number = n
269 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
298 this.element.find('div.input_prompt').html('In&nbsp;[' + n + ']:');
270 };
299 };
271
300
272
301
273 CodeCell.prototype.get_code = function () {
302 CodeCell.prototype.get_code = function () {
274 return this.code_mirror.getValue();
303 return this.code_mirror.getValue();
275 };
304 };
276
305
277
306
278 CodeCell.prototype.set_code = function (code) {
307 CodeCell.prototype.set_code = function (code) {
279 return this.code_mirror.setValue(code);
308 return this.code_mirror.setValue(code);
280 };
309 };
281
310
282
311
283 CodeCell.prototype.at_top = function () {
312 CodeCell.prototype.at_top = function () {
284 var cursor = this.code_mirror.getCursor();
313 var cursor = this.code_mirror.getCursor();
285 if (cursor.line === 0) {
314 if (cursor.line === 0) {
286 return true;
315 return true;
287 } else {
316 } else {
288 return false;
317 return false;
289 }
318 }
290 };
319 };
291
320
292
321
293 CodeCell.prototype.at_bottom = function () {
322 CodeCell.prototype.at_bottom = function () {
294 var cursor = this.code_mirror.getCursor();
323 var cursor = this.code_mirror.getCursor();
295 if (cursor.line === (this.code_mirror.lineCount()-1)) {
324 if (cursor.line === (this.code_mirror.lineCount()-1)) {
296 return true;
325 return true;
297 } else {
326 } else {
298 return false;
327 return false;
299 }
328 }
300 };
329 };
301
330
302
331
303 CodeCell.prototype.fromJSON = function (data) {
332 CodeCell.prototype.fromJSON = function (data) {
333 // console.log('Import from JSON:', data);
304 if (data.cell_type === 'code') {
334 if (data.cell_type === 'code') {
305 if (data.input !== undefined) {
335 if (data.input !== undefined) {
306 this.set_code(data.input);
336 this.set_code(data.input);
307 }
337 }
308 if (data.prompt_number !== undefined) {
338 if (data.prompt_number !== undefined) {
309 this.set_input_prompt(data.prompt_number);
339 this.set_input_prompt(data.prompt_number);
310 } else {
340 } else {
311 this.set_input_prompt();
341 this.set_input_prompt();
312 };
342 };
343 var len = data.outputs.length;
344 for (var i=0; i<len; i++) {
345 this.append_output(data.outputs[i]);
346 };
313 };
347 };
314 };
348 };
315
349
316
350
317 CodeCell.prototype.toJSON = function () {
351 CodeCell.prototype.toJSON = function () {
318 var data = {}
352 var data = {};
319 data.input = this.get_code();
353 data.input = this.get_code();
320 data.cell_type = 'code';
354 data.cell_type = 'code';
321 if (this.input_prompt_number !== ' ') {
355 if (this.input_prompt_number !== ' ') {
322 data.prompt_number = this.input_prompt_number
356 data.prompt_number = this.input_prompt_number
323 };
357 };
324 data.outputs = [];
358 var outputs = [];
359 var len = this.outputs.length;
360 for (var i=0; i<len; i++) {
361 outputs[i] = this.outputs[i];
362 };
363 data.outputs = outputs;
325 data.language = 'python';
364 data.language = 'python';
365 // console.log('Export to JSON:',data);
326 return data;
366 return data;
327 };
367 };
328
368
369
329 IPython.CodeCell = CodeCell;
370 IPython.CodeCell = CodeCell;
330
371
331 return IPython;
372 return IPython;
332 }(IPython));
373 }(IPython));
333
374
@@ -1,623 +1,658 b''
1
1
2 //============================================================================
2 //============================================================================
3 // Notebook
3 // Notebook
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var Notebook = function (selector) {
10 var Notebook = function (selector) {
11 this.element = $(selector);
11 this.element = $(selector);
12 this.element.scroll();
12 this.element.scroll();
13 this.element.data("notebook", this);
13 this.element.data("notebook", this);
14 this.next_prompt_number = 1;
14 this.next_prompt_number = 1;
15 this.kernel = null;
15 this.kernel = null;
16 this.msg_cell_map = {};
16 this.msg_cell_map = {};
17 this.style();
17 this.style();
18 this.create_elements();
18 this.create_elements();
19 this.bind_events();
19 this.bind_events();
20 };
20 };
21
21
22
22
23 Notebook.prototype.style = function () {
23 Notebook.prototype.style = function () {
24 $('div#notebook').addClass('border-box-sizing');
24 $('div#notebook').addClass('border-box-sizing');
25 };
25 };
26
26
27
27
28 Notebook.prototype.create_elements = function () {
28 Notebook.prototype.create_elements = function () {
29 // We add this end_space div to the end of the notebook div to:
29 // We add this end_space div to the end of the notebook div to:
30 // i) provide a margin between the last cell and the end of the notebook
30 // i) provide a margin between the last cell and the end of the notebook
31 // ii) to prevent the div from scrolling up when the last cell is being
31 // ii) to prevent the div from scrolling up when the last cell is being
32 // edited, but is too low on the page, which browsers will do automatically.
32 // edited, but is too low on the page, which browsers will do automatically.
33 this.element.append($('<div class="end_space"></div>').height(50));
33 this.element.append($('<div class="end_space"></div>').height(50));
34 $('div#notebook').addClass('border-box-sizing');
34 $('div#notebook').addClass('border-box-sizing');
35 };
35 };
36
36
37
37
38 Notebook.prototype.bind_events = function () {
38 Notebook.prototype.bind_events = function () {
39 var that = this;
39 var that = this;
40 $(document).keydown(function (event) {
40 $(document).keydown(function (event) {
41 // console.log(event);
41 // console.log(event);
42 if (event.which === 38) {
42 if (event.which === 38) {
43 var cell = that.selected_cell();
43 var cell = that.selected_cell();
44 if (cell.at_top()) {
44 if (cell.at_top()) {
45 event.preventDefault();
45 event.preventDefault();
46 that.select_prev();
46 that.select_prev();
47 };
47 };
48 } else if (event.which === 40) {
48 } else if (event.which === 40) {
49 var cell = that.selected_cell();
49 var cell = that.selected_cell();
50 if (cell.at_bottom()) {
50 if (cell.at_bottom()) {
51 event.preventDefault();
51 event.preventDefault();
52 that.select_next();
52 that.select_next();
53 };
53 };
54 } else if (event.which === 13 && event.shiftKey) {
54 } else if (event.which === 13 && event.shiftKey) {
55 that.execute_selected_cell();
55 that.execute_selected_cell();
56 return false;
56 return false;
57 } else if (event.which === 13 && event.ctrlKey) {
57 } else if (event.which === 13 && event.ctrlKey) {
58 that.execute_selected_cell({terminal:true});
58 that.execute_selected_cell({terminal:true});
59 return false;
59 return false;
60 };
60 };
61 });
61 });
62
62
63 this.element.bind('collapse_pager', function () {
63 this.element.bind('collapse_pager', function () {
64 var app_height = $('div#main_app').height(); // content height
64 var app_height = $('div#main_app').height(); // content height
65 var splitter_height = $('div#pager_splitter').outerHeight(true);
65 var splitter_height = $('div#pager_splitter').outerHeight(true);
66 var new_height = app_height - splitter_height;
66 var new_height = app_height - splitter_height;
67 that.element.animate({height : new_height + 'px'}, 'fast');
67 that.element.animate({height : new_height + 'px'}, 'fast');
68 });
68 });
69
69
70 this.element.bind('expand_pager', function () {
70 this.element.bind('expand_pager', function () {
71 var app_height = $('div#main_app').height(); // content height
71 var app_height = $('div#main_app').height(); // content height
72 var splitter_height = $('div#pager_splitter').outerHeight(true);
72 var splitter_height = $('div#pager_splitter').outerHeight(true);
73 var pager_height = $('div#pager').outerHeight(true);
73 var pager_height = $('div#pager').outerHeight(true);
74 var new_height = app_height - pager_height - splitter_height;
74 var new_height = app_height - pager_height - splitter_height;
75 that.element.animate({height : new_height + 'px'}, 'fast');
75 that.element.animate({height : new_height + 'px'}, 'fast');
76 });
76 });
77
77
78 this.element.bind('collapse_left_panel', function () {
78 this.element.bind('collapse_left_panel', function () {
79 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
79 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
80 var new_margin = splitter_width;
80 var new_margin = splitter_width;
81 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
81 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
82 });
82 });
83
83
84 this.element.bind('expand_left_panel', function () {
84 this.element.bind('expand_left_panel', function () {
85 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
85 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
86 var left_panel_width = IPython.left_panel.width;
86 var left_panel_width = IPython.left_panel.width;
87 var new_margin = splitter_width + left_panel_width;
87 var new_margin = splitter_width + left_panel_width;
88 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
88 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
89 });
89 });
90 };
90 };
91
91
92
92
93 Notebook.prototype.scroll_to_bottom = function () {
93 Notebook.prototype.scroll_to_bottom = function () {
94 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
94 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
95 };
95 };
96
96
97
97
98 Notebook.prototype.scroll_to_top = function () {
98 Notebook.prototype.scroll_to_top = function () {
99 this.element.animate({scrollTop:0}, 0);
99 this.element.animate({scrollTop:0}, 0);
100 };
100 };
101
101
102
102
103 // Cell indexing, retrieval, etc.
103 // Cell indexing, retrieval, etc.
104
104
105
105
106 Notebook.prototype.cell_elements = function () {
106 Notebook.prototype.cell_elements = function () {
107 return this.element.children("div.cell");
107 return this.element.children("div.cell");
108 }
108 }
109
109
110
110
111 Notebook.prototype.ncells = function (cell) {
111 Notebook.prototype.ncells = function (cell) {
112 return this.cell_elements().length;
112 return this.cell_elements().length;
113 }
113 }
114
114
115
115
116 // TODO: we are often calling cells as cells()[i], which we should optimize
116 // TODO: we are often calling cells as cells()[i], which we should optimize
117 // to cells(i) or a new method.
117 // to cells(i) or a new method.
118 Notebook.prototype.cells = function () {
118 Notebook.prototype.cells = function () {
119 return this.cell_elements().toArray().map(function (e) {
119 return this.cell_elements().toArray().map(function (e) {
120 return $(e).data("cell");
120 return $(e).data("cell");
121 });
121 });
122 }
122 }
123
123
124
124
125 Notebook.prototype.find_cell_index = function (cell) {
125 Notebook.prototype.find_cell_index = function (cell) {
126 var result = null;
126 var result = null;
127 this.cell_elements().filter(function (index) {
127 this.cell_elements().filter(function (index) {
128 if ($(this).data("cell") === cell) {
128 if ($(this).data("cell") === cell) {
129 result = index;
129 result = index;
130 };
130 };
131 });
131 });
132 return result;
132 return result;
133 };
133 };
134
134
135
135
136 Notebook.prototype.index_or_selected = function (index) {
136 Notebook.prototype.index_or_selected = function (index) {
137 return index || this.selected_index() || 0;
137 return index || this.selected_index() || 0;
138 }
138 }
139
139
140
140
141 Notebook.prototype.select = function (index) {
141 Notebook.prototype.select = function (index) {
142 if (index !== undefined && index >= 0 && index < this.ncells()) {
142 if (index !== undefined && index >= 0 && index < this.ncells()) {
143 if (this.selected_index() !== null) {
143 if (this.selected_index() !== null) {
144 this.selected_cell().unselect();
144 this.selected_cell().unselect();
145 };
145 };
146 this.cells()[index].select();
146 this.cells()[index].select();
147 if (index === (this.ncells()-1)) {
147 if (index === (this.ncells()-1)) {
148 this.scroll_to_bottom();
148 this.scroll_to_bottom();
149 };
149 };
150 };
150 };
151 return this;
151 return this;
152 };
152 };
153
153
154
154
155 Notebook.prototype.select_next = function () {
155 Notebook.prototype.select_next = function () {
156 var index = this.selected_index();
156 var index = this.selected_index();
157 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
157 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
158 this.select(index+1);
158 this.select(index+1);
159 };
159 };
160 return this;
160 return this;
161 };
161 };
162
162
163
163
164 Notebook.prototype.select_prev = function () {
164 Notebook.prototype.select_prev = function () {
165 var index = this.selected_index();
165 var index = this.selected_index();
166 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
166 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
167 this.select(index-1);
167 this.select(index-1);
168 };
168 };
169 return this;
169 return this;
170 };
170 };
171
171
172
172
173 Notebook.prototype.selected_index = function () {
173 Notebook.prototype.selected_index = function () {
174 var result = null;
174 var result = null;
175 this.cell_elements().filter(function (index) {
175 this.cell_elements().filter(function (index) {
176 if ($(this).data("cell").selected === true) {
176 if ($(this).data("cell").selected === true) {
177 result = index;
177 result = index;
178 };
178 };
179 });
179 });
180 return result;
180 return result;
181 };
181 };
182
182
183
183
184 Notebook.prototype.cell_for_msg = function (msg_id) {
184 Notebook.prototype.cell_for_msg = function (msg_id) {
185 var cell_id = this.msg_cell_map[msg_id];
185 var cell_id = this.msg_cell_map[msg_id];
186 var result = null;
186 var result = null;
187 this.cell_elements().filter(function (index) {
187 this.cell_elements().filter(function (index) {
188 cell = $(this).data("cell");
188 cell = $(this).data("cell");
189 if (cell.cell_id === cell_id) {
189 if (cell.cell_id === cell_id) {
190 result = cell;
190 result = cell;
191 };
191 };
192 });
192 });
193 return result;
193 return result;
194 };
194 };
195
195
196
196
197 Notebook.prototype.selected_cell = function () {
197 Notebook.prototype.selected_cell = function () {
198 return this.cell_elements().eq(this.selected_index()).data("cell");
198 return this.cell_elements().eq(this.selected_index()).data("cell");
199 }
199 }
200
200
201
201
202 // Cell insertion, deletion and moving.
202 // Cell insertion, deletion and moving.
203
203
204
204
205 Notebook.prototype.delete_cell = function (index) {
205 Notebook.prototype.delete_cell = function (index) {
206 var i = index || this.selected_index();
206 var i = index || this.selected_index();
207 if (i !== null && i >= 0 && i < this.ncells()) {
207 if (i !== null && i >= 0 && i < this.ncells()) {
208 this.cell_elements().eq(i).remove();
208 this.cell_elements().eq(i).remove();
209 if (i === (this.ncells())) {
209 if (i === (this.ncells())) {
210 this.select(i-1);
210 this.select(i-1);
211 } else {
211 } else {
212 this.select(i);
212 this.select(i);
213 };
213 };
214 };
214 };
215 return this;
215 return this;
216 };
216 };
217
217
218
218
219 Notebook.prototype.append_cell = function (cell) {
219 Notebook.prototype.append_cell = function (cell) {
220 this.element.find('div.end_space').before(cell.element);
220 this.element.find('div.end_space').before(cell.element);
221 return this;
221 return this;
222 };
222 };
223
223
224
224
225 Notebook.prototype.insert_cell_after = function (cell, index) {
225 Notebook.prototype.insert_cell_after = function (cell, index) {
226 var ncells = this.ncells();
226 var ncells = this.ncells();
227 if (ncells === 0) {
227 if (ncells === 0) {
228 this.append_cell(cell);
228 this.append_cell(cell);
229 return this;
229 return this;
230 };
230 };
231 if (index >= 0 && index < ncells) {
231 if (index >= 0 && index < ncells) {
232 this.cell_elements().eq(index).after(cell.element);
232 this.cell_elements().eq(index).after(cell.element);
233 };
233 };
234 return this
234 return this
235 };
235 };
236
236
237
237
238 Notebook.prototype.insert_cell_before = function (cell, index) {
238 Notebook.prototype.insert_cell_before = function (cell, index) {
239 var ncells = this.ncells();
239 var ncells = this.ncells();
240 if (ncells === 0) {
240 if (ncells === 0) {
241 this.append_cell(cell);
241 this.append_cell(cell);
242 return this;
242 return this;
243 };
243 };
244 if (index >= 0 && index < ncells) {
244 if (index >= 0 && index < ncells) {
245 this.cell_elements().eq(index).before(cell.element);
245 this.cell_elements().eq(index).before(cell.element);
246 };
246 };
247 return this;
247 return this;
248 };
248 };
249
249
250
250
251 Notebook.prototype.move_cell_up = function (index) {
251 Notebook.prototype.move_cell_up = function (index) {
252 var i = index || this.selected_index();
252 var i = index || this.selected_index();
253 if (i !== null && i < this.ncells() && i > 0) {
253 if (i !== null && i < this.ncells() && i > 0) {
254 var pivot = this.cell_elements().eq(i-1);
254 var pivot = this.cell_elements().eq(i-1);
255 var tomove = this.cell_elements().eq(i);
255 var tomove = this.cell_elements().eq(i);
256 if (pivot !== null && tomove !== null) {
256 if (pivot !== null && tomove !== null) {
257 tomove.detach();
257 tomove.detach();
258 pivot.before(tomove);
258 pivot.before(tomove);
259 this.select(i-1);
259 this.select(i-1);
260 };
260 };
261 };
261 };
262 return this;
262 return this;
263 }
263 }
264
264
265
265
266 Notebook.prototype.move_cell_down = function (index) {
266 Notebook.prototype.move_cell_down = function (index) {
267 var i = index || this.selected_index();
267 var i = index || this.selected_index();
268 if (i !== null && i < (this.ncells()-1) && i >= 0) {
268 if (i !== null && i < (this.ncells()-1) && i >= 0) {
269 var pivot = this.cell_elements().eq(i+1)
269 var pivot = this.cell_elements().eq(i+1)
270 var tomove = this.cell_elements().eq(i)
270 var tomove = this.cell_elements().eq(i)
271 if (pivot !== null && tomove !== null) {
271 if (pivot !== null && tomove !== null) {
272 tomove.detach();
272 tomove.detach();
273 pivot.after(tomove);
273 pivot.after(tomove);
274 this.select(i+1);
274 this.select(i+1);
275 };
275 };
276 };
276 };
277 return this;
277 return this;
278 }
278 }
279
279
280
280
281 Notebook.prototype.sort_cells = function () {
281 Notebook.prototype.sort_cells = function () {
282 var ncells = this.ncells();
282 var ncells = this.ncells();
283 var sindex = this.selected_index();
283 var sindex = this.selected_index();
284 var swapped;
284 var swapped;
285 do {
285 do {
286 swapped = false
286 swapped = false
287 for (var i=1; i<ncells; i++) {
287 for (var i=1; i<ncells; i++) {
288 current = this.cell_elements().eq(i).data("cell");
288 current = this.cell_elements().eq(i).data("cell");
289 previous = this.cell_elements().eq(i-1).data("cell");
289 previous = this.cell_elements().eq(i-1).data("cell");
290 if (previous.input_prompt_number > current.input_prompt_number) {
290 if (previous.input_prompt_number > current.input_prompt_number) {
291 this.move_cell_up(i);
291 this.move_cell_up(i);
292 swapped = true;
292 swapped = true;
293 };
293 };
294 };
294 };
295 } while (swapped);
295 } while (swapped);
296 this.select(sindex);
296 this.select(sindex);
297 return this;
297 return this;
298 };
298 };
299
299
300
300
301 Notebook.prototype.insert_code_cell_before = function (index) {
301 Notebook.prototype.insert_code_cell_before = function (index) {
302 // TODO: Bounds check for i
302 // TODO: Bounds check for i
303 var i = this.index_or_selected(index);
303 var i = this.index_or_selected(index);
304 var cell = new IPython.CodeCell(this);
304 var cell = new IPython.CodeCell(this);
305 cell.set_input_prompt();
305 cell.set_input_prompt();
306 this.insert_cell_before(cell, i);
306 this.insert_cell_before(cell, i);
307 this.select(this.find_cell_index(cell));
307 this.select(this.find_cell_index(cell));
308 return cell;
308 return cell;
309 }
309 }
310
310
311
311
312 Notebook.prototype.insert_code_cell_after = function (index) {
312 Notebook.prototype.insert_code_cell_after = function (index) {
313 // TODO: Bounds check for i
313 // TODO: Bounds check for i
314 var i = this.index_or_selected(index);
314 var i = this.index_or_selected(index);
315 var cell = new IPython.CodeCell(this);
315 var cell = new IPython.CodeCell(this);
316 cell.set_input_prompt();
316 cell.set_input_prompt();
317 this.insert_cell_after(cell, i);
317 this.insert_cell_after(cell, i);
318 this.select(this.find_cell_index(cell));
318 this.select(this.find_cell_index(cell));
319 return cell;
319 return cell;
320 }
320 }
321
321
322
322
323 Notebook.prototype.insert_text_cell_before = function (index) {
323 Notebook.prototype.insert_text_cell_before = function (index) {
324 // TODO: Bounds check for i
324 // TODO: Bounds check for i
325 var i = this.index_or_selected(index);
325 var i = this.index_or_selected(index);
326 var cell = new IPython.TextCell(this);
326 var cell = new IPython.TextCell(this);
327 cell.config_mathjax();
327 cell.config_mathjax();
328 this.insert_cell_before(cell, i);
328 this.insert_cell_before(cell, i);
329 this.select(this.find_cell_index(cell));
329 this.select(this.find_cell_index(cell));
330 return cell;
330 return cell;
331 }
331 }
332
332
333
333
334 Notebook.prototype.insert_text_cell_after = function (index) {
334 Notebook.prototype.insert_text_cell_after = function (index) {
335 // TODO: Bounds check for i
335 // TODO: Bounds check for i
336 var i = this.index_or_selected(index);
336 var i = this.index_or_selected(index);
337 var cell = new IPython.TextCell(this);
337 var cell = new IPython.TextCell(this);
338 cell.config_mathjax();
338 cell.config_mathjax();
339 this.insert_cell_after(cell, i);
339 this.insert_cell_after(cell, i);
340 this.select(this.find_cell_index(cell));
340 this.select(this.find_cell_index(cell));
341 return cell;
341 return cell;
342 }
342 }
343
343
344
344
345 Notebook.prototype.text_to_code = function (index) {
345 Notebook.prototype.text_to_code = function (index) {
346 // TODO: Bounds check for i
346 // TODO: Bounds check for i
347 var i = this.index_or_selected(index);
347 var i = this.index_or_selected(index);
348 var source_element = this.cell_elements().eq(i);
348 var source_element = this.cell_elements().eq(i);
349 var source_cell = source_element.data("cell");
349 var source_cell = source_element.data("cell");
350 if (source_cell instanceof IPython.TextCell) {
350 if (source_cell instanceof IPython.TextCell) {
351 this.insert_code_cell_after(i);
351 this.insert_code_cell_after(i);
352 var target_cell = this.cells()[i+1];
352 var target_cell = this.cells()[i+1];
353 target_cell.set_code(source_cell.get_text());
353 target_cell.set_code(source_cell.get_text());
354 source_element.remove();
354 source_element.remove();
355 };
355 };
356 };
356 };
357
357
358
358
359 Notebook.prototype.code_to_text = function (index) {
359 Notebook.prototype.code_to_text = function (index) {
360 // TODO: Bounds check for i
360 // TODO: Bounds check for i
361 var i = this.index_or_selected(index);
361 var i = this.index_or_selected(index);
362 var source_element = this.cell_elements().eq(i);
362 var source_element = this.cell_elements().eq(i);
363 var source_cell = source_element.data("cell");
363 var source_cell = source_element.data("cell");
364 if (source_cell instanceof IPython.CodeCell) {
364 if (source_cell instanceof IPython.CodeCell) {
365 this.insert_text_cell_after(i);
365 this.insert_text_cell_after(i);
366 var target_cell = this.cells()[i+1];
366 var target_cell = this.cells()[i+1];
367 var text = source_cell.get_code();
367 var text = source_cell.get_code();
368 if (text === "") {text = target_cell.placeholder;};
368 if (text === "") {text = target_cell.placeholder;};
369 target_cell.set_text(text);
369 target_cell.set_text(text);
370 source_element.remove();
370 source_element.remove();
371 target_cell.edit();
371 target_cell.edit();
372 };
372 };
373 };
373 };
374
374
375
375
376 // Cell collapsing
376 // Cell collapsing
377
377
378 Notebook.prototype.collapse = function (index) {
378 Notebook.prototype.collapse = function (index) {
379 var i = this.index_or_selected(index);
379 var i = this.index_or_selected(index);
380 this.cells()[i].collapse();
380 this.cells()[i].collapse();
381 };
381 };
382
382
383
383
384 Notebook.prototype.expand = function (index) {
384 Notebook.prototype.expand = function (index) {
385 var i = this.index_or_selected(index);
385 var i = this.index_or_selected(index);
386 this.cells()[i].expand();
386 this.cells()[i].expand();
387 };
387 };
388
388
389
389
390 // Kernel related things
390 // Kernel related things
391
391
392 Notebook.prototype.start_kernel = function () {
392 Notebook.prototype.start_kernel = function () {
393 this.kernel = new IPython.Kernel();
393 this.kernel = new IPython.Kernel();
394 var notebook_id = IPython.save_widget.get_notebook_id();
394 var notebook_id = IPython.save_widget.get_notebook_id();
395 this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this));
395 this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this));
396 };
396 };
397
397
398
398
399 Notebook.prototype.handle_shell_reply = function (e) {
399 Notebook.prototype.handle_shell_reply = function (e) {
400 reply = $.parseJSON(e.data);
400 reply = $.parseJSON(e.data);
401 var header = reply.header;
401 var header = reply.header;
402 var content = reply.content;
402 var content = reply.content;
403 var msg_type = header.msg_type;
403 var msg_type = header.msg_type;
404 // console.log(reply);
404 // console.log(reply);
405 var cell = this.cell_for_msg(reply.parent_header.msg_id);
405 var cell = this.cell_for_msg(reply.parent_header.msg_id);
406 if (msg_type === "execute_reply") {
406 if (msg_type === "execute_reply") {
407 cell.set_input_prompt(content.execution_count);
407 cell.set_input_prompt(content.execution_count);
408 } else if (msg_type === "complete_reply") {
408 } else if (msg_type === "complete_reply") {
409 cell.finish_completing(content.matched_text, content.matches);
409 cell.finish_completing(content.matched_text, content.matches);
410 };
410 };
411 var payload = content.payload || [];
411 var payload = content.payload || [];
412 this.handle_payload(payload);
412 this.handle_payload(payload);
413 };
413 };
414
414
415
415
416 Notebook.prototype.handle_payload = function (payload) {
416 Notebook.prototype.handle_payload = function (payload) {
417 var l = payload.length;
417 var l = payload.length;
418 if (l > 0) {
418 if (l > 0) {
419 IPython.pager.clear();
419 IPython.pager.clear();
420 IPython.pager.expand();
420 IPython.pager.expand();
421 };
421 };
422 for (var i=0; i<l; i++) {
422 for (var i=0; i<l; i++) {
423 IPython.pager.append_text(payload[i].text);
423 IPython.pager.append_text(payload[i].text);
424 };
424 };
425 };
425 };
426
426
427
427
428 Notebook.prototype.handle_iopub_reply = function (e) {
428 Notebook.prototype.handle_iopub_reply = function (e) {
429 reply = $.parseJSON(e.data);
429 reply = $.parseJSON(e.data);
430 var content = reply.content;
430 var content = reply.content;
431 // console.log(reply);
431 // console.log(reply);
432 var msg_type = reply.header.msg_type;
432 var msg_type = reply.header.msg_type;
433 var cell = this.cell_for_msg(reply.parent_header.msg_id);
433 var cell = this.cell_for_msg(reply.parent_header.msg_id);
434 if (msg_type === "stream") {
434 var output_types = ['stream','display_data','pyout','pyerr'];
435 cell.expand();
435 if (output_types.indexOf(msg_type) >= 0) {
436 cell.append_stream(content.data + "\n");
436 this.handle_output(cell, msg_type, content);
437 } else if (msg_type === "display_data") {
438 cell.expand();
439 cell.append_display_data(content.data);
440 } else if (msg_type === "pyout") {
441 cell.expand();
442 cell.append_pyout(content.data, content.execution_count)
443 } else if (msg_type === "pyerr") {
444 cell.expand();
445 cell.append_pyerr(content.ename, content.evalue, content.traceback);
446 } else if (msg_type === "status") {
437 } else if (msg_type === "status") {
447 if (content.execution_state === "busy") {
438 if (content.execution_state === "busy") {
448 IPython.kernel_status_widget.status_busy();
439 IPython.kernel_status_widget.status_busy();
449 } else if (content.execution_state === "idle") {
440 } else if (content.execution_state === "idle") {
450 IPython.kernel_status_widget.status_idle();
441 IPython.kernel_status_widget.status_idle();
451 };
442 };
452 }
443 }
453 };
444 };
454
445
455
446
447 Notebook.prototype.handle_output = function (cell, msg_type, content) {
448 var json = {};
449 json.output_type = msg_type;
450 if (msg_type === "stream") {
451 json.text = content.data + '\n';
452 } else if (msg_type === "display_data") {
453 json = this.convert_mime_types(json, content.data);
454 } else if (msg_type === "pyout") {
455 json.prompt_number = content.execution_count;
456 json = this.convert_mime_types(json, content.data);
457 } else if (msg_type === "pyerr") {
458 json.ename = content.ename;
459 json.evalue = content.evalue;
460 json.traceback = content.traceback;
461 };
462 cell.append_output(json);
463 };
464
465
466 Notebook.prototype.convert_mime_types = function (json, data) {
467 if (data['text/plain'] !== undefined) {
468 json.text = data['text/plain'];
469 };
470 if (data['text/html'] !== undefined) {
471 json.html = data['text/html'];
472 };
473 if (data['image/svg+xml'] !== undefined) {
474 json.svg = data['image/svg+xml'];
475 };
476 if (data['image/png'] !== undefined) {
477 json.png = data['image/png'];
478 };
479 if (data['text/latex'] !== undefined) {
480 json.latex = data['text/latex'];
481 };
482 if (data['application/json'] !== undefined) {
483 json.json = data['application/json'];
484 };
485 if (data['application/javascript'] !== undefined) {
486 json.javascript = data['application/javascript'];
487 }
488 return json;
489 };
490
456 Notebook.prototype.kernel_started = function () {
491 Notebook.prototype.kernel_started = function () {
457 console.log("Kernel started: ", this.kernel.kernel_id);
492 console.log("Kernel started: ", this.kernel.kernel_id);
458 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
493 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
459 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
494 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
460 };
495 };
461
496
462
497
463 Notebook.prototype.execute_selected_cell = function (options) {
498 Notebook.prototype.execute_selected_cell = function (options) {
464 // add_new: should a new cell be added if we are at the end of the nb
499 // add_new: should a new cell be added if we are at the end of the nb
465 // terminal: execute in terminal mode, which stays in the current cell
500 // terminal: execute in terminal mode, which stays in the current cell
466 default_options = {terminal: false, add_new: true}
501 default_options = {terminal: false, add_new: true}
467 $.extend(default_options, options)
502 $.extend(default_options, options)
468 var that = this;
503 var that = this;
469 var cell = that.selected_cell();
504 var cell = that.selected_cell();
470 var cell_index = that.find_cell_index(cell);
505 var cell_index = that.find_cell_index(cell);
471 if (cell instanceof IPython.CodeCell) {
506 if (cell instanceof IPython.CodeCell) {
472 cell.clear_output();
507 cell.clear_output();
473 var code = cell.get_code();
508 var code = cell.get_code();
474 var msg_id = that.kernel.execute(cell.get_code());
509 var msg_id = that.kernel.execute(cell.get_code());
475 that.msg_cell_map[msg_id] = cell.cell_id;
510 that.msg_cell_map[msg_id] = cell.cell_id;
476 } else if (cell instanceof IPython.TextCell) {
511 } else if (cell instanceof IPython.TextCell) {
477 cell.render();
512 cell.render();
478 }
513 }
479 if (default_options.terminal) {
514 if (default_options.terminal) {
480 cell.clear_input();
515 cell.clear_input();
481 } else {
516 } else {
482 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
517 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
483 that.insert_code_cell_after();
518 that.insert_code_cell_after();
484 // If we are adding a new cell at the end, scroll down to show it.
519 // If we are adding a new cell at the end, scroll down to show it.
485 that.scroll_to_bottom();
520 that.scroll_to_bottom();
486 } else {
521 } else {
487 that.select(cell_index+1);
522 that.select(cell_index+1);
488 };
523 };
489 };
524 };
490 };
525 };
491
526
492
527
493 Notebook.prototype.execute_all_cells = function () {
528 Notebook.prototype.execute_all_cells = function () {
494 var ncells = this.ncells();
529 var ncells = this.ncells();
495 for (var i=0; i<ncells; i++) {
530 for (var i=0; i<ncells; i++) {
496 this.select(i);
531 this.select(i);
497 this.execute_selected_cell({add_new:false});
532 this.execute_selected_cell({add_new:false});
498 };
533 };
499 this.scroll_to_bottom();
534 this.scroll_to_bottom();
500 };
535 };
501
536
502
537
503 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
538 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
504 var msg_id = this.kernel.complete(line, cursor_pos);
539 var msg_id = this.kernel.complete(line, cursor_pos);
505 this.msg_cell_map[msg_id] = cell.cell_id;
540 this.msg_cell_map[msg_id] = cell.cell_id;
506 };
541 };
507
542
508 // Persistance and loading
543 // Persistance and loading
509
544
510
545
511 Notebook.prototype.fromJSON = function (data) {
546 Notebook.prototype.fromJSON = function (data) {
512 var ncells = this.ncells();
547 var ncells = this.ncells();
513 for (var i=0; i<ncells; i++) {
548 for (var i=0; i<ncells; i++) {
514 // Always delete cell 0 as they get renumbered as they are deleted.
549 // Always delete cell 0 as they get renumbered as they are deleted.
515 this.delete_cell(0);
550 this.delete_cell(0);
516 };
551 };
517 // Only handle 1 worksheet for now.
552 // Only handle 1 worksheet for now.
518 var worksheet = data.worksheets[0];
553 var worksheet = data.worksheets[0];
519 if (worksheet !== undefined) {
554 if (worksheet !== undefined) {
520 var new_cells = worksheet.cells;
555 var new_cells = worksheet.cells;
521 ncells = new_cells.length;
556 ncells = new_cells.length;
522 var cell_data = null;
557 var cell_data = null;
523 var new_cell = null;
558 var new_cell = null;
524 for (var i=0; i<ncells; i++) {
559 for (var i=0; i<ncells; i++) {
525 cell_data = new_cells[i];
560 cell_data = new_cells[i];
526 if (cell_data.cell_type == 'code') {
561 if (cell_data.cell_type == 'code') {
527 new_cell = this.insert_code_cell_after();
562 new_cell = this.insert_code_cell_after();
528 new_cell.fromJSON(cell_data);
563 new_cell.fromJSON(cell_data);
529 } else if (cell_data.cell_type === 'text') {
564 } else if (cell_data.cell_type === 'text') {
530 new_cell = this.insert_text_cell_after();
565 new_cell = this.insert_text_cell_after();
531 new_cell.fromJSON(cell_data);
566 new_cell.fromJSON(cell_data);
532 };
567 };
533 };
568 };
534 };
569 };
535 };
570 };
536
571
537
572
538 Notebook.prototype.toJSON = function () {
573 Notebook.prototype.toJSON = function () {
539 var cells = this.cells();
574 var cells = this.cells();
540 var ncells = cells.length;
575 var ncells = cells.length;
541 cell_array = new Array(ncells);
576 cell_array = new Array(ncells);
542 for (var i=0; i<ncells; i++) {
577 for (var i=0; i<ncells; i++) {
543 cell_array[i] = cells[i].toJSON();
578 cell_array[i] = cells[i].toJSON();
544 };
579 };
545 data = {
580 data = {
546 // Only handle 1 worksheet for now.
581 // Only handle 1 worksheet for now.
547 worksheets : [{cells:cell_array}]
582 worksheets : [{cells:cell_array}]
548 }
583 }
549 return data
584 return data
550 };
585 };
551
586
552 Notebook.prototype.save_notebook = function () {
587 Notebook.prototype.save_notebook = function () {
553 if (IPython.save_widget.test_notebook_name()) {
588 if (IPython.save_widget.test_notebook_name()) {
554 var notebook_id = IPython.save_widget.get_notebook_id();
589 var notebook_id = IPython.save_widget.get_notebook_id();
555 var nbname = IPython.save_widget.get_notebook_name();
590 var nbname = IPython.save_widget.get_notebook_name();
556 // We may want to move the name/id/nbformat logic inside toJSON?
591 // We may want to move the name/id/nbformat logic inside toJSON?
557 var data = this.toJSON();
592 var data = this.toJSON();
558 data.name = nbname;
593 data.name = nbname;
559 data.nbformat = 2;
594 data.nbformat = 2;
560 data.id = notebook_id
595 data.id = notebook_id
561 // We do the call with settings so we can set cache to false.
596 // We do the call with settings so we can set cache to false.
562 var settings = {
597 var settings = {
563 processData : false,
598 processData : false,
564 cache : false,
599 cache : false,
565 type : "PUT",
600 type : "PUT",
566 data : JSON.stringify(data),
601 data : JSON.stringify(data),
567 headers : {'Content-Type': 'application/json'},
602 headers : {'Content-Type': 'application/json'},
568 success : $.proxy(this.notebook_saved,this)
603 success : $.proxy(this.notebook_saved,this)
569 };
604 };
570 IPython.save_widget.status_saving();
605 IPython.save_widget.status_saving();
571 $.ajax("/notebooks/" + notebook_id, settings);
606 $.ajax("/notebooks/" + notebook_id, settings);
572 };
607 };
573 };
608 };
574
609
575
610
576 Notebook.prototype.notebook_saved = function (data, status, xhr) {
611 Notebook.prototype.notebook_saved = function (data, status, xhr) {
577 IPython.save_widget.status_save();
612 IPython.save_widget.status_save();
578 }
613 }
579
614
580
615
581 Notebook.prototype.load_notebook = function (callback) {
616 Notebook.prototype.load_notebook = function (callback) {
582 var that = this;
617 var that = this;
583 var notebook_id = IPython.save_widget.get_notebook_id();
618 var notebook_id = IPython.save_widget.get_notebook_id();
584 // We do the call with settings so we can set cache to false.
619 // We do the call with settings so we can set cache to false.
585 var settings = {
620 var settings = {
586 processData : false,
621 processData : false,
587 cache : false,
622 cache : false,
588 type : "GET",
623 type : "GET",
589 dataType : "json",
624 dataType : "json",
590 success : function (data, status, xhr) {
625 success : function (data, status, xhr) {
591 that.notebook_loaded(data, status, xhr);
626 that.notebook_loaded(data, status, xhr);
592 if (callback !== undefined) {
627 if (callback !== undefined) {
593 callback();
628 callback();
594 };
629 };
595 }
630 }
596 };
631 };
597 IPython.save_widget.status_loading();
632 IPython.save_widget.status_loading();
598 $.ajax("/notebooks/" + notebook_id, settings);
633 $.ajax("/notebooks/" + notebook_id, settings);
599 }
634 }
600
635
601
636
602 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
637 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
603 this.fromJSON(data);
638 this.fromJSON(data);
604 if (this.ncells() === 0) {
639 if (this.ncells() === 0) {
605 this.insert_code_cell_after();
640 this.insert_code_cell_after();
606 };
641 };
607 IPython.save_widget.status_save();
642 IPython.save_widget.status_save();
608 IPython.save_widget.set_notebook_name(data.name);
643 IPython.save_widget.set_notebook_name(data.name);
609 this.start_kernel();
644 this.start_kernel();
610 // fromJSON always selects the last cell inserted. We need to wait
645 // fromJSON always selects the last cell inserted. We need to wait
611 // until that is done before scrolling to the top.
646 // until that is done before scrolling to the top.
612 setTimeout(function () {
647 setTimeout(function () {
613 IPython.notebook.select(0);
648 IPython.notebook.select(0);
614 IPython.notebook.scroll_to_top();
649 IPython.notebook.scroll_to_top();
615 }, 50);
650 }, 50);
616 };
651 };
617
652
618 IPython.Notebook = Notebook;
653 IPython.Notebook = Notebook;
619
654
620 return IPython;
655 return IPython;
621
656
622 }(IPython));
657 }(IPython));
623
658
@@ -1,103 +1,104 b''
1 """The basic dict based notebook format."""
1 """The basic dict based notebook format."""
2
2
3 import pprint
3 import pprint
4 import uuid
4 import uuid
5
5
6 from IPython.utils.ipstruct import Struct
6 from IPython.utils.ipstruct import Struct
7
7
8
8
9 class NotebookNode(Struct):
9 class NotebookNode(Struct):
10 pass
10 pass
11
11
12
12
13 def from_dict(d):
13 def from_dict(d):
14 if isinstance(d, dict):
14 if isinstance(d, dict):
15 newd = NotebookNode()
15 newd = NotebookNode()
16 for k,v in d.items():
16 for k,v in d.items():
17 newd[k] = from_dict(v)
17 newd[k] = from_dict(v)
18 return newd
18 return newd
19 elif isinstance(d, (tuple, list)):
19 elif isinstance(d, (tuple, list)):
20 return [from_dict(i) for i in d]
20 return [from_dict(i) for i in d]
21 else:
21 else:
22 return d
22 return d
23
23
24
24
25 def new_output(output_type=None, output_text=None, output_png=None,
25 def new_output(output_type=None, output_text=None, output_png=None,
26 output_html=None, output_svg=None, output_latex=None, output_json=None,
26 output_html=None, output_svg=None, output_latex=None, output_json=None,
27 output_javascript=None):
27 output_javascript=None, prompt_number=None):
28 """Create a new code cell with input and output"""
28 """Create a new code cell with input and output"""
29 output = NotebookNode()
29 output = NotebookNode()
30 if output_type is not None:
30 if output_type is not None:
31 output.output_type = unicode(output_type)
31 output.output_type = unicode(output_type)
32 if output_text is not None:
32 if output_text is not None:
33 output.text = unicode(output_text)
33 output.text = unicode(output_text)
34 if output_png is not None:
34 if output_png is not None:
35 output.png = bytes(output_png)
35 output.png = bytes(output_png)
36 if output_html is not None:
36 if output_html is not None:
37 output.html = unicode(output_html)
37 output.html = unicode(output_html)
38 if output_svg is not None:
38 if output_svg is not None:
39 output.svg = unicode(output_svg)
39 output.svg = unicode(output_svg)
40 if output_latex is not None:
40 if output_latex is not None:
41 output.latex = unicode(output_latex)
41 output.latex = unicode(output_latex)
42 if output_json is not None:
42 if output_json is not None:
43 output.json = unicode(output_json)
43 output.json = unicode(output_json)
44 if output_javascript is not None:
44 if output_javascript is not None:
45 output.javascript = unicode(output_javascript)
45 output.javascript = unicode(output_javascript)
46
46 if prompt_number is not None:
47 output.prompt_number = int(prompt_number)
47 return output
48 return output
48
49
49
50
50 def new_code_cell(input=None, prompt_number=None, outputs=None, language=u'python'):
51 def new_code_cell(input=None, prompt_number=None, outputs=None, language=u'python'):
51 """Create a new code cell with input and output"""
52 """Create a new code cell with input and output"""
52 cell = NotebookNode()
53 cell = NotebookNode()
53 cell.cell_type = u'code'
54 cell.cell_type = u'code'
54 if language is not None:
55 if language is not None:
55 cell.language = unicode(language)
56 cell.language = unicode(language)
56 if input is not None:
57 if input is not None:
57 cell.input = unicode(input)
58 cell.input = unicode(input)
58 if prompt_number is not None:
59 if prompt_number is not None:
59 cell.prompt_number = int(prompt_number)
60 cell.prompt_number = int(prompt_number)
60 if outputs is None:
61 if outputs is None:
61 cell.outputs = []
62 cell.outputs = []
62 else:
63 else:
63 cell.outputs = outputs
64 cell.outputs = outputs
64
65
65 return cell
66 return cell
66
67
67 def new_text_cell(text=None):
68 def new_text_cell(text=None):
68 """Create a new text cell."""
69 """Create a new text cell."""
69 cell = NotebookNode()
70 cell = NotebookNode()
70 if text is not None:
71 if text is not None:
71 cell.text = unicode(text)
72 cell.text = unicode(text)
72 cell.cell_type = u'text'
73 cell.cell_type = u'text'
73 return cell
74 return cell
74
75
75
76
76 def new_worksheet(name=None, cells=None):
77 def new_worksheet(name=None, cells=None):
77 """Create a worksheet by name with with a list of cells."""
78 """Create a worksheet by name with with a list of cells."""
78 ws = NotebookNode()
79 ws = NotebookNode()
79 if name is not None:
80 if name is not None:
80 ws.name = unicode(name)
81 ws.name = unicode(name)
81 if cells is None:
82 if cells is None:
82 ws.cells = []
83 ws.cells = []
83 else:
84 else:
84 ws.cells = list(cells)
85 ws.cells = list(cells)
85 return ws
86 return ws
86
87
87
88
88 def new_notebook(name=None, id=None, worksheets=None):
89 def new_notebook(name=None, id=None, worksheets=None):
89 """Create a notebook by name, id and a list of worksheets."""
90 """Create a notebook by name, id and a list of worksheets."""
90 nb = NotebookNode()
91 nb = NotebookNode()
91 nb.nbformat = 2
92 nb.nbformat = 2
92 if name is not None:
93 if name is not None:
93 nb.name = unicode(name)
94 nb.name = unicode(name)
94 if id is None:
95 if id is None:
95 nb.id = unicode(uuid.uuid4())
96 nb.id = unicode(uuid.uuid4())
96 else:
97 else:
97 nb.id = unicode(id)
98 nb.id = unicode(id)
98 if worksheets is None:
99 if worksheets is None:
99 nb.worksheets = []
100 nb.worksheets = []
100 else:
101 else:
101 nb.worksheets = list(worksheets)
102 nb.worksheets = list(worksheets)
102 return nb
103 return nb
103
104
@@ -1,165 +1,168 b''
1 """Read and write notebook files as XML."""
1 """Read and write notebook files as XML."""
2
2
3 from base64 import encodestring, decodestring
3 from base64 import encodestring, decodestring
4 from xml.etree import ElementTree as ET
4 from xml.etree import ElementTree as ET
5
5
6 from .rwbase import NotebookReader, NotebookWriter
6 from .rwbase import NotebookReader, NotebookWriter
7 from .nbbase import (
7 from .nbbase import (
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
9 )
9 )
10
10
11 def indent(elem, level=0):
11 def indent(elem, level=0):
12 i = "\n" + level*" "
12 i = "\n" + level*" "
13 if len(elem):
13 if len(elem):
14 if not elem.text or not elem.text.strip():
14 if not elem.text or not elem.text.strip():
15 elem.text = i + " "
15 elem.text = i + " "
16 if not elem.tail or not elem.tail.strip():
16 if not elem.tail or not elem.tail.strip():
17 elem.tail = i
17 elem.tail = i
18 for elem in elem:
18 for elem in elem:
19 indent(elem, level+1)
19 indent(elem, level+1)
20 if not elem.tail or not elem.tail.strip():
20 if not elem.tail or not elem.tail.strip():
21 elem.tail = i
21 elem.tail = i
22 else:
22 else:
23 if level and (not elem.tail or not elem.tail.strip()):
23 if level and (not elem.tail or not elem.tail.strip()):
24 elem.tail = i
24 elem.tail = i
25
25
26
26
27 def _get_text(e, tag):
27 def _get_text(e, tag):
28 sub_e = e.find(tag)
28 sub_e = e.find(tag)
29 if sub_e is None:
29 if sub_e is None:
30 return None
30 return None
31 else:
31 else:
32 return sub_e.text
32 return sub_e.text
33
33
34
34
35 def _set_text(nbnode, attr, parent, tag):
35 def _set_text(nbnode, attr, parent, tag):
36 if attr in nbnode:
36 if attr in nbnode:
37 e = ET.SubElement(parent, tag)
37 e = ET.SubElement(parent, tag)
38 e.text = nbnode[attr]
38 e.text = nbnode[attr]
39
39
40
40
41 def _get_int(e, tag):
41 def _get_int(e, tag):
42 sub_e = e.find(tag)
42 sub_e = e.find(tag)
43 if sub_e is None:
43 if sub_e is None:
44 return None
44 return None
45 else:
45 else:
46 return int(sub_e.text)
46 return int(sub_e.text)
47
47
48
48
49 def _set_int(nbnode, attr, parent, tag):
49 def _set_int(nbnode, attr, parent, tag):
50 if attr in nbnode:
50 if attr in nbnode:
51 e = ET.SubElement(parent, tag)
51 e = ET.SubElement(parent, tag)
52 e.text = unicode(nbnode[attr])
52 e.text = unicode(nbnode[attr])
53
53
54
54
55 def _get_binary(e, tag):
55 def _get_binary(e, tag):
56 sub_e = e.find(tag)
56 sub_e = e.find(tag)
57 if sub_e is None:
57 if sub_e is None:
58 return None
58 return None
59 else:
59 else:
60 return decodestring(sub_e.text)
60 return decodestring(sub_e.text)
61
61
62
62
63 def _set_binary(nbnode, attr, parent, tag):
63 def _set_binary(nbnode, attr, parent, tag):
64 if attr in nbnode:
64 if attr in nbnode:
65 e = ET.SubElement(parent, tag)
65 e = ET.SubElement(parent, tag)
66 e.text = encodestring(nbnode[attr])
66 e.text = encodestring(nbnode[attr])
67
67
68
68
69 class XMLReader(NotebookReader):
69 class XMLReader(NotebookReader):
70
70
71 def reads(self, s, **kwargs):
71 def reads(self, s, **kwargs):
72 root = ET.fromstring(s)
72 root = ET.fromstring(s)
73 return self.to_notebook(root, **kwargs)
73 return self.to_notebook(root, **kwargs)
74
74
75 def to_notebook(self, root, **kwargs):
75 def to_notebook(self, root, **kwargs):
76 nbname = _get_text(root,'name')
76 nbname = _get_text(root,'name')
77 nbid = _get_text(root,'id')
77 nbid = _get_text(root,'id')
78
78
79 worksheets = []
79 worksheets = []
80 for ws_e in root.find('worksheets').getiterator('worksheet'):
80 for ws_e in root.find('worksheets').getiterator('worksheet'):
81 wsname = _get_text(ws_e,'name')
81 wsname = _get_text(ws_e,'name')
82 cells = []
82 cells = []
83 for cell_e in ws_e.find('cells').getiterator():
83 for cell_e in ws_e.find('cells').getiterator():
84 if cell_e.tag == 'codecell':
84 if cell_e.tag == 'codecell':
85 input = _get_text(cell_e,'input')
85 input = _get_text(cell_e,'input')
86 prompt_number = _get_int(cell_e,'prompt_number')
86 prompt_number = _get_int(cell_e,'prompt_number')
87 language = _get_text(cell_e,'language')
87 language = _get_text(cell_e,'language')
88 outputs = []
88 outputs = []
89 for output_e in cell_e.find('outputs').getiterator('output'):
89 for output_e in cell_e.find('outputs').getiterator('output'):
90 prompt_number = _get_int(output_e,'prompt_number')
90 output_type = _get_text(output_e,'output_type')
91 output_type = _get_text(output_e,'output_type')
91 output_text = _get_text(output_e,'text')
92 output_text = _get_text(output_e,'text')
92 output_png = _get_binary(output_e,'png')
93 output_png = _get_binary(output_e,'png')
93 output_svg = _get_text(output_e,'svg')
94 output_svg = _get_text(output_e,'svg')
94 output_html = _get_text(output_e,'html')
95 output_html = _get_text(output_e,'html')
95 output_latex = _get_text(output_e,'latex')
96 output_latex = _get_text(output_e,'latex')
96 output_json = _get_text(output_e,'json')
97 output_json = _get_text(output_e,'json')
97 output_javascript = _get_text(output_e,'javascript')
98 output_javascript = _get_text(output_e,'javascript')
98 output = new_output(output_type=output_type,output_png=output_png,
99 output = new_output(output_type=output_type,output_png=output_png,
99 output_text=output_text,output_svg=output_svg,
100 output_text=output_text,output_svg=output_svg,
100 output_html=output_html,output_latex=output_latex,
101 output_html=output_html,output_latex=output_latex,
101 output_json=output_json,output_javascript=output_javascript
102 output_json=output_json,output_javascript=output_javascript,
103 prompt_number=prompt_number
102 )
104 )
103 outputs.append(output)
105 outputs.append(output)
104 cc = new_code_cell(input=input,prompt_number=prompt_number,
106 cc = new_code_cell(input=input,prompt_number=prompt_number,
105 language=language,outputs=outputs)
107 language=language,outputs=outputs)
106 cells.append(cc)
108 cells.append(cc)
107 if cell_e.tag == 'textcell':
109 if cell_e.tag == 'textcell':
108 text = _get_text(cell_e,'text')
110 text = _get_text(cell_e,'text')
109 cells.append(new_text_cell(text=text))
111 cells.append(new_text_cell(text=text))
110 ws = new_worksheet(name=wsname,cells=cells)
112 ws = new_worksheet(name=wsname,cells=cells)
111 worksheets.append(ws)
113 worksheets.append(ws)
112
114
113 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
115 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
114 return nb
116 return nb
115
117
116
118
117 class XMLWriter(NotebookWriter):
119 class XMLWriter(NotebookWriter):
118
120
119 def writes(self, nb, **kwargs):
121 def writes(self, nb, **kwargs):
120 nb_e = ET.Element('notebook')
122 nb_e = ET.Element('notebook')
121 _set_text(nb,'name',nb_e,'name')
123 _set_text(nb,'name',nb_e,'name')
122 _set_text(nb,'id',nb_e,'id')
124 _set_text(nb,'id',nb_e,'id')
123 _set_int(nb,'nbformat',nb_e,'nbformat')
125 _set_int(nb,'nbformat',nb_e,'nbformat')
124 wss_e = ET.SubElement(nb_e,'worksheets')
126 wss_e = ET.SubElement(nb_e,'worksheets')
125 for ws in nb.worksheets:
127 for ws in nb.worksheets:
126 ws_e = ET.SubElement(wss_e, 'worksheet')
128 ws_e = ET.SubElement(wss_e, 'worksheet')
127 _set_text(ws,'name',ws_e,'name')
129 _set_text(ws,'name',ws_e,'name')
128 cells_e = ET.SubElement(ws_e,'cells')
130 cells_e = ET.SubElement(ws_e,'cells')
129 for cell in ws.cells:
131 for cell in ws.cells:
130 cell_type = cell.cell_type
132 cell_type = cell.cell_type
131 if cell_type == 'code':
133 if cell_type == 'code':
132 cell_e = ET.SubElement(cells_e, 'codecell')
134 cell_e = ET.SubElement(cells_e, 'codecell')
133 _set_text(cell,'input',cell_e,'input')
135 _set_text(cell,'input',cell_e,'input')
134 _set_text(cell,'language',cell_e,'language')
136 _set_text(cell,'language',cell_e,'language')
135 _set_int(cell,'prompt_number',cell_e,'prompt_number')
137 _set_int(cell,'prompt_number',cell_e,'prompt_number')
136 outputs_e = ET.SubElement(cell_e, 'outputs')
138 outputs_e = ET.SubElement(cell_e, 'outputs')
137 for output in cell.outputs:
139 for output in cell.outputs:
138 output_e = ET.SubElement(outputs_e, 'output')
140 output_e = ET.SubElement(outputs_e, 'output')
141 _set_int(cell,'prompt_number',output_e,'prompt_number')
139 _set_text(output,'output_type',output_e,'output_type')
142 _set_text(output,'output_type',output_e,'output_type')
140 _set_text(output,'text',output_e,'text')
143 _set_text(output,'text',output_e,'text')
141 _set_binary(output,'png',output_e,'png')
144 _set_binary(output,'png',output_e,'png')
142 _set_text(output,'html',output_e,'html')
145 _set_text(output,'html',output_e,'html')
143 _set_text(output,'svg',output_e,'svg')
146 _set_text(output,'svg',output_e,'svg')
144 _set_text(output,'latex',output_e,'latex')
147 _set_text(output,'latex',output_e,'latex')
145 _set_text(output,'json',output_e,'json')
148 _set_text(output,'json',output_e,'json')
146 _set_text(output,'javascript',output_e,'javascript')
149 _set_text(output,'javascript',output_e,'javascript')
147 elif cell_type == 'text':
150 elif cell_type == 'text':
148 cell_e = ET.SubElement(cells_e, 'textcell')
151 cell_e = ET.SubElement(cells_e, 'textcell')
149 _set_text(cell,'text',cell_e,'text')
152 _set_text(cell,'text',cell_e,'text')
150
153
151 indent(nb_e)
154 indent(nb_e)
152 txt = ET.tostring(nb_e, encoding="utf-8")
155 txt = ET.tostring(nb_e, encoding="utf-8")
153 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
156 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
154 return txt
157 return txt
155
158
156
159
157 _reader = XMLReader()
160 _reader = XMLReader()
158 _writer = XMLWriter()
161 _writer = XMLWriter()
159
162
160 reads = _reader.reads
163 reads = _reader.reads
161 read = _reader.read
164 read = _reader.read
162 to_notebook = _reader.to_notebook
165 to_notebook = _reader.to_notebook
163 write = _writer.write
166 write = _writer.write
164 writes = _writer.writes
167 writes = _writer.writes
165
168
General Comments 0
You need to be logged in to leave comments. Login now