##// END OF EJS Templates
Backport PR #6706: Correctly display prompt numbers that are 'None'...
Min RK -
Show More
@@ -0,0 +1,36 b''
1
2 // Test
3 casper.notebook_test(function () {
4
5 var that = this;
6 var set_prompt = function (i, val) {
7 that.evaluate(function (i, val) {
8 var cell = IPython.notebook.get_cell(i);
9 cell.set_input_prompt(val);
10 }, [i, val]);
11 };
12
13 var get_prompt = function (i) {
14 return that.evaluate(function (i) {
15 var elem = IPython.notebook.get_cell(i).element;
16 return elem.find('div.input_prompt').html();
17 }, [i]);
18 };
19
20 this.then(function () {
21 var a = 'print("a")';
22 var index = this.append_cell(a);
23
24 this.test.assertEquals(get_prompt(index), "In [ ]:", "prompt number is   by default");
25 set_prompt(index, 2);
26 this.test.assertEquals(get_prompt(index), "In [2]:", "prompt number is 2");
27 set_prompt(index, 0);
28 this.test.assertEquals(get_prompt(index), "In [0]:", "prompt number is 0");
29 set_prompt(index, "*");
30 this.test.assertEquals(get_prompt(index), "In [*]:", "prompt number is *");
31 set_prompt(index, undefined);
32 this.test.assertEquals(get_prompt(index), "In [ ]:", "prompt number is  ");
33 set_prompt(index, null);
34 this.test.assertEquals(get_prompt(index), "In [ ]:", "prompt number is  ");
35 });
36 });
@@ -0,0 +1,81 b''
1 {
2 "metadata": {
3 "name": "notebook2"
4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
7 "worksheets": [
8 {
9 "cells": [
10 {
11 "cell_type": "code",
12 "collapsed": false,
13 "input": [
14 "import numpy as np"
15 ],
16 "language": "python",
17 "metadata": {},
18 "outputs": [],
19 "prompt_number": 2
20 },
21 {
22 "cell_type": "code",
23 "collapsed": false,
24 "input": [
25 "evs = np.zeros(100)",
26 "evs.shape"
27 ],
28 "language": "python",
29 "metadata": {},
30 "outputs": [
31 {
32 "metadata": {},
33 "output_type": "pyout",
34 "prompt_number": 10,
35 "text": [
36 "(100,)"
37 ]
38 }
39 ],
40 "prompt_number": 10
41 },
42 {
43 "cell_type": "code",
44 "collapsed": false,
45 "input": [],
46 "language": "python",
47 "metadata": {},
48 "outputs": []
49 },
50 {
51 "cell_type": "code",
52 "collapsed": false,
53 "input": [],
54 "language": "python",
55 "metadata": {},
56 "outputs": [],
57 "prompt_number": null
58 },
59 {
60 "cell_type": "code",
61 "collapsed": false,
62 "input": [],
63 "language": "python",
64 "metadata": {},
65 "outputs": [],
66 "prompt_number": "*"
67 },
68 {
69 "cell_type": "code",
70 "collapsed": false,
71 "input": [],
72 "language": "python",
73 "metadata": {},
74 "outputs": [],
75 "prompt_number": 0
76 }
77 ],
78 "metadata": {}
79 }
80 ]
81 } No newline at end of file
@@ -1,517 +1,517 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008-2011 The IPython Development Team
2 // Copyright (C) 2008-2011 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // CodeCell
9 // CodeCell
10 //============================================================================
10 //============================================================================
11 /**
11 /**
12 * An extendable module that provide base functionnality to create cell for notebook.
12 * An extendable module that provide base functionnality to create cell for notebook.
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule CodeCell
15 * @submodule CodeCell
16 */
16 */
17
17
18
18
19 /* local util for codemirror */
19 /* local util for codemirror */
20 var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;};
20 var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;};
21
21
22 /**
22 /**
23 *
23 *
24 * function to delete until previous non blanking space character
24 * function to delete until previous non blanking space character
25 * or first multiple of 4 tabstop.
25 * or first multiple of 4 tabstop.
26 * @private
26 * @private
27 */
27 */
28 CodeMirror.commands.delSpaceToPrevTabStop = function(cm){
28 CodeMirror.commands.delSpaceToPrevTabStop = function(cm){
29 var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
29 var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
30 if (!posEq(from, to)) { cm.replaceRange("", from, to); return; }
30 if (!posEq(from, to)) { cm.replaceRange("", from, to); return; }
31 var cur = cm.getCursor(), line = cm.getLine(cur.line);
31 var cur = cm.getCursor(), line = cm.getLine(cur.line);
32 var tabsize = cm.getOption('tabSize');
32 var tabsize = cm.getOption('tabSize');
33 var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize;
33 var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize;
34 from = {ch:cur.ch-chToPrevTabStop,line:cur.line};
34 from = {ch:cur.ch-chToPrevTabStop,line:cur.line};
35 var select = cm.getRange(from,cur);
35 var select = cm.getRange(from,cur);
36 if( select.match(/^\ +$/) !== null){
36 if( select.match(/^\ +$/) !== null){
37 cm.replaceRange("",from,cur);
37 cm.replaceRange("",from,cur);
38 } else {
38 } else {
39 cm.deleteH(-1,"char");
39 cm.deleteH(-1,"char");
40 }
40 }
41 };
41 };
42
42
43
43
44 var IPython = (function (IPython) {
44 var IPython = (function (IPython) {
45 "use strict";
45 "use strict";
46
46
47 var utils = IPython.utils;
47 var utils = IPython.utils;
48 var keycodes = IPython.keyboard.keycodes;
48 var keycodes = IPython.keyboard.keycodes;
49
49
50 /**
50 /**
51 * A Cell conceived to write code.
51 * A Cell conceived to write code.
52 *
52 *
53 * The kernel doesn't have to be set at creation time, in that case
53 * The kernel doesn't have to be set at creation time, in that case
54 * it will be null and set_kernel has to be called later.
54 * it will be null and set_kernel has to be called later.
55 * @class CodeCell
55 * @class CodeCell
56 * @extends IPython.Cell
56 * @extends IPython.Cell
57 *
57 *
58 * @constructor
58 * @constructor
59 * @param {Object|null} kernel
59 * @param {Object|null} kernel
60 * @param {object|undefined} [options]
60 * @param {object|undefined} [options]
61 * @param [options.cm_config] {object} config to pass to CodeMirror
61 * @param [options.cm_config] {object} config to pass to CodeMirror
62 */
62 */
63 var CodeCell = function (kernel, options) {
63 var CodeCell = function (kernel, options) {
64 this.kernel = kernel || null;
64 this.kernel = kernel || null;
65 this.collapsed = false;
65 this.collapsed = false;
66
66
67 // create all attributed in constructor function
67 // create all attributed in constructor function
68 // even if null for V8 VM optimisation
68 // even if null for V8 VM optimisation
69 this.input_prompt_number = null;
69 this.input_prompt_number = null;
70 this.celltoolbar = null;
70 this.celltoolbar = null;
71 this.output_area = null;
71 this.output_area = null;
72 this.last_msg_id = null;
72 this.last_msg_id = null;
73 this.completer = null;
73 this.completer = null;
74
74
75
75
76 var cm_overwrite_options = {
76 var cm_overwrite_options = {
77 onKeyEvent: $.proxy(this.handle_keyevent,this)
77 onKeyEvent: $.proxy(this.handle_keyevent,this)
78 };
78 };
79
79
80 options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options});
80 options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options});
81
81
82 IPython.Cell.apply(this,[options]);
82 IPython.Cell.apply(this,[options]);
83
83
84 // Attributes we want to override in this subclass.
84 // Attributes we want to override in this subclass.
85 this.cell_type = "code";
85 this.cell_type = "code";
86
86
87 var that = this;
87 var that = this;
88 this.element.focusout(
88 this.element.focusout(
89 function() { that.auto_highlight(); }
89 function() { that.auto_highlight(); }
90 );
90 );
91 };
91 };
92
92
93 CodeCell.options_default = {
93 CodeCell.options_default = {
94 cm_config : {
94 cm_config : {
95 extraKeys: {
95 extraKeys: {
96 "Tab" : "indentMore",
96 "Tab" : "indentMore",
97 "Shift-Tab" : "indentLess",
97 "Shift-Tab" : "indentLess",
98 "Backspace" : "delSpaceToPrevTabStop",
98 "Backspace" : "delSpaceToPrevTabStop",
99 "Cmd-/" : "toggleComment",
99 "Cmd-/" : "toggleComment",
100 "Ctrl-/" : "toggleComment"
100 "Ctrl-/" : "toggleComment"
101 },
101 },
102 mode: 'ipython',
102 mode: 'ipython',
103 theme: 'ipython',
103 theme: 'ipython',
104 matchBrackets: true,
104 matchBrackets: true,
105 // don't auto-close strings because of CodeMirror #2385
105 // don't auto-close strings because of CodeMirror #2385
106 autoCloseBrackets: "()[]{}"
106 autoCloseBrackets: "()[]{}"
107 }
107 }
108 };
108 };
109
109
110 CodeCell.msg_cells = {};
110 CodeCell.msg_cells = {};
111
111
112 CodeCell.prototype = new IPython.Cell();
112 CodeCell.prototype = new IPython.Cell();
113
113
114 /**
114 /**
115 * @method auto_highlight
115 * @method auto_highlight
116 */
116 */
117 CodeCell.prototype.auto_highlight = function () {
117 CodeCell.prototype.auto_highlight = function () {
118 this._auto_highlight(IPython.config.cell_magic_highlight);
118 this._auto_highlight(IPython.config.cell_magic_highlight);
119 };
119 };
120
120
121 /** @method create_element */
121 /** @method create_element */
122 CodeCell.prototype.create_element = function () {
122 CodeCell.prototype.create_element = function () {
123 IPython.Cell.prototype.create_element.apply(this, arguments);
123 IPython.Cell.prototype.create_element.apply(this, arguments);
124
124
125 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell');
125 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell');
126 cell.attr('tabindex','2');
126 cell.attr('tabindex','2');
127
127
128 var input = $('<div></div>').addClass('input');
128 var input = $('<div></div>').addClass('input');
129 var prompt = $('<div/>').addClass('prompt input_prompt');
129 var prompt = $('<div/>').addClass('prompt input_prompt');
130 var inner_cell = $('<div/>').addClass('inner_cell');
130 var inner_cell = $('<div/>').addClass('inner_cell');
131 this.celltoolbar = new IPython.CellToolbar(this);
131 this.celltoolbar = new IPython.CellToolbar(this);
132 inner_cell.append(this.celltoolbar.element);
132 inner_cell.append(this.celltoolbar.element);
133 var input_area = $('<div/>').addClass('input_area');
133 var input_area = $('<div/>').addClass('input_area');
134 this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);
134 this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);
135 $(this.code_mirror.getInputField()).attr("spellcheck", "false");
135 $(this.code_mirror.getInputField()).attr("spellcheck", "false");
136 inner_cell.append(input_area);
136 inner_cell.append(input_area);
137 input.append(prompt).append(inner_cell);
137 input.append(prompt).append(inner_cell);
138
138
139 var widget_area = $('<div/>')
139 var widget_area = $('<div/>')
140 .addClass('widget-area')
140 .addClass('widget-area')
141 .hide();
141 .hide();
142 this.widget_area = widget_area;
142 this.widget_area = widget_area;
143 var widget_prompt = $('<div/>')
143 var widget_prompt = $('<div/>')
144 .addClass('prompt')
144 .addClass('prompt')
145 .appendTo(widget_area);
145 .appendTo(widget_area);
146 var widget_subarea = $('<div/>')
146 var widget_subarea = $('<div/>')
147 .addClass('widget-subarea')
147 .addClass('widget-subarea')
148 .appendTo(widget_area);
148 .appendTo(widget_area);
149 this.widget_subarea = widget_subarea;
149 this.widget_subarea = widget_subarea;
150 var widget_clear_buton = $('<button />')
150 var widget_clear_buton = $('<button />')
151 .addClass('close')
151 .addClass('close')
152 .html('&times;')
152 .html('&times;')
153 .click(function() {
153 .click(function() {
154 widget_area.slideUp('', function(){ widget_subarea.html(''); });
154 widget_area.slideUp('', function(){ widget_subarea.html(''); });
155 })
155 })
156 .appendTo(widget_prompt);
156 .appendTo(widget_prompt);
157
157
158 var output = $('<div></div>');
158 var output = $('<div></div>');
159 cell.append(input).append(widget_area).append(output);
159 cell.append(input).append(widget_area).append(output);
160 this.element = cell;
160 this.element = cell;
161 this.output_area = new IPython.OutputArea(output, true);
161 this.output_area = new IPython.OutputArea(output, true);
162 this.completer = new IPython.Completer(this);
162 this.completer = new IPython.Completer(this);
163 };
163 };
164
164
165 /** @method bind_events */
165 /** @method bind_events */
166 CodeCell.prototype.bind_events = function () {
166 CodeCell.prototype.bind_events = function () {
167 IPython.Cell.prototype.bind_events.apply(this);
167 IPython.Cell.prototype.bind_events.apply(this);
168 var that = this;
168 var that = this;
169
169
170 this.element.focusout(
170 this.element.focusout(
171 function() { that.auto_highlight(); }
171 function() { that.auto_highlight(); }
172 );
172 );
173 };
173 };
174
174
175
175
176 /**
176 /**
177 * This method gets called in CodeMirror's onKeyDown/onKeyPress
177 * This method gets called in CodeMirror's onKeyDown/onKeyPress
178 * handlers and is used to provide custom key handling. Its return
178 * handlers and is used to provide custom key handling. Its return
179 * value is used to determine if CodeMirror should ignore the event:
179 * value is used to determine if CodeMirror should ignore the event:
180 * true = ignore, false = don't ignore.
180 * true = ignore, false = don't ignore.
181 * @method handle_codemirror_keyevent
181 * @method handle_codemirror_keyevent
182 */
182 */
183 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
183 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
184
184
185 var that = this;
185 var that = this;
186 // whatever key is pressed, first, cancel the tooltip request before
186 // whatever key is pressed, first, cancel the tooltip request before
187 // they are sent, and remove tooltip if any, except for tab again
187 // they are sent, and remove tooltip if any, except for tab again
188 var tooltip_closed = null;
188 var tooltip_closed = null;
189 if (event.type === 'keydown' && event.which != keycodes.tab ) {
189 if (event.type === 'keydown' && event.which != keycodes.tab ) {
190 tooltip_closed = IPython.tooltip.remove_and_cancel_tooltip();
190 tooltip_closed = IPython.tooltip.remove_and_cancel_tooltip();
191 }
191 }
192
192
193 var cur = editor.getCursor();
193 var cur = editor.getCursor();
194 if (event.keyCode === keycodes.enter){
194 if (event.keyCode === keycodes.enter){
195 this.auto_highlight();
195 this.auto_highlight();
196 }
196 }
197
197
198 if (event.which === keycodes.down && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
198 if (event.which === keycodes.down && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
199 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
199 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
200 // browser and keyboard layout !
200 // browser and keyboard layout !
201 // Pressing '(' , request tooltip, don't forget to reappend it
201 // Pressing '(' , request tooltip, don't forget to reappend it
202 // The second argument says to hide the tooltip if the docstring
202 // The second argument says to hide the tooltip if the docstring
203 // is actually empty
203 // is actually empty
204 IPython.tooltip.pending(that, true);
204 IPython.tooltip.pending(that, true);
205 } else if ( tooltip_closed && event.which === keycodes.esc && event.type === 'keydown') {
205 } else if ( tooltip_closed && event.which === keycodes.esc && event.type === 'keydown') {
206 // If tooltip is active, cancel it. The call to
206 // If tooltip is active, cancel it. The call to
207 // remove_and_cancel_tooltip above doesn't pass, force=true.
207 // remove_and_cancel_tooltip above doesn't pass, force=true.
208 // Because of this it won't actually close the tooltip
208 // Because of this it won't actually close the tooltip
209 // if it is in sticky mode. Thus, we have to check again if it is open
209 // if it is in sticky mode. Thus, we have to check again if it is open
210 // and close it with force=true.
210 // and close it with force=true.
211 if (!IPython.tooltip._hidden) {
211 if (!IPython.tooltip._hidden) {
212 IPython.tooltip.remove_and_cancel_tooltip(true);
212 IPython.tooltip.remove_and_cancel_tooltip(true);
213 }
213 }
214 // If we closed the tooltip, don't let CM or the global handlers
214 // If we closed the tooltip, don't let CM or the global handlers
215 // handle this event.
215 // handle this event.
216 event.stop();
216 event.stop();
217 return true;
217 return true;
218 } else if (event.keyCode === keycodes.tab && event.type === 'keydown' && event.shiftKey) {
218 } else if (event.keyCode === keycodes.tab && event.type === 'keydown' && event.shiftKey) {
219 if (editor.somethingSelected()){
219 if (editor.somethingSelected()){
220 var anchor = editor.getCursor("anchor");
220 var anchor = editor.getCursor("anchor");
221 var head = editor.getCursor("head");
221 var head = editor.getCursor("head");
222 if( anchor.line != head.line){
222 if( anchor.line != head.line){
223 return false;
223 return false;
224 }
224 }
225 }
225 }
226 IPython.tooltip.request(that);
226 IPython.tooltip.request(that);
227 event.stop();
227 event.stop();
228 return true;
228 return true;
229 } else if (event.keyCode === keycodes.tab && event.type == 'keydown') {
229 } else if (event.keyCode === keycodes.tab && event.type == 'keydown') {
230 // Tab completion.
230 // Tab completion.
231 IPython.tooltip.remove_and_cancel_tooltip();
231 IPython.tooltip.remove_and_cancel_tooltip();
232 if (editor.somethingSelected()) {
232 if (editor.somethingSelected()) {
233 return false;
233 return false;
234 }
234 }
235 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
235 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
236 if (pre_cursor.trim() === "") {
236 if (pre_cursor.trim() === "") {
237 // Don't autocomplete if the part of the line before the cursor
237 // Don't autocomplete if the part of the line before the cursor
238 // is empty. In this case, let CodeMirror handle indentation.
238 // is empty. In this case, let CodeMirror handle indentation.
239 return false;
239 return false;
240 } else {
240 } else {
241 event.stop();
241 event.stop();
242 this.completer.startCompletion();
242 this.completer.startCompletion();
243 return true;
243 return true;
244 }
244 }
245 }
245 }
246
246
247 // keyboard event wasn't one of those unique to code cells, let's see
247 // keyboard event wasn't one of those unique to code cells, let's see
248 // if it's one of the generic ones (i.e. check edit mode shortcuts)
248 // if it's one of the generic ones (i.e. check edit mode shortcuts)
249 return IPython.Cell.prototype.handle_codemirror_keyevent.apply(this, [editor, event]);
249 return IPython.Cell.prototype.handle_codemirror_keyevent.apply(this, [editor, event]);
250 };
250 };
251
251
252 // Kernel related calls.
252 // Kernel related calls.
253
253
254 CodeCell.prototype.set_kernel = function (kernel) {
254 CodeCell.prototype.set_kernel = function (kernel) {
255 this.kernel = kernel;
255 this.kernel = kernel;
256 };
256 };
257
257
258 /**
258 /**
259 * Execute current code cell to the kernel
259 * Execute current code cell to the kernel
260 * @method execute
260 * @method execute
261 */
261 */
262 CodeCell.prototype.execute = function () {
262 CodeCell.prototype.execute = function () {
263 this.output_area.clear_output();
263 this.output_area.clear_output();
264
264
265 // Clear widget area
265 // Clear widget area
266 this.widget_subarea.html('');
266 this.widget_subarea.html('');
267 this.widget_subarea.height('');
267 this.widget_subarea.height('');
268 this.widget_area.height('');
268 this.widget_area.height('');
269 this.widget_area.hide();
269 this.widget_area.hide();
270
270
271 this.set_input_prompt('*');
271 this.set_input_prompt('*');
272 this.element.addClass("running");
272 this.element.addClass("running");
273 if (this.last_msg_id) {
273 if (this.last_msg_id) {
274 this.kernel.clear_callbacks_for_msg(this.last_msg_id);
274 this.kernel.clear_callbacks_for_msg(this.last_msg_id);
275 }
275 }
276 var callbacks = this.get_callbacks();
276 var callbacks = this.get_callbacks();
277
277
278 var old_msg_id = this.last_msg_id;
278 var old_msg_id = this.last_msg_id;
279 this.last_msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false, store_history: true});
279 this.last_msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false, store_history: true});
280 if (old_msg_id) {
280 if (old_msg_id) {
281 delete CodeCell.msg_cells[old_msg_id];
281 delete CodeCell.msg_cells[old_msg_id];
282 }
282 }
283 CodeCell.msg_cells[this.last_msg_id] = this;
283 CodeCell.msg_cells[this.last_msg_id] = this;
284 };
284 };
285
285
286 /**
286 /**
287 * Construct the default callbacks for
287 * Construct the default callbacks for
288 * @method get_callbacks
288 * @method get_callbacks
289 */
289 */
290 CodeCell.prototype.get_callbacks = function () {
290 CodeCell.prototype.get_callbacks = function () {
291 return {
291 return {
292 shell : {
292 shell : {
293 reply : $.proxy(this._handle_execute_reply, this),
293 reply : $.proxy(this._handle_execute_reply, this),
294 payload : {
294 payload : {
295 set_next_input : $.proxy(this._handle_set_next_input, this),
295 set_next_input : $.proxy(this._handle_set_next_input, this),
296 page : $.proxy(this._open_with_pager, this)
296 page : $.proxy(this._open_with_pager, this)
297 }
297 }
298 },
298 },
299 iopub : {
299 iopub : {
300 output : $.proxy(this.output_area.handle_output, this.output_area),
300 output : $.proxy(this.output_area.handle_output, this.output_area),
301 clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area),
301 clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area),
302 },
302 },
303 input : $.proxy(this._handle_input_request, this)
303 input : $.proxy(this._handle_input_request, this)
304 };
304 };
305 };
305 };
306
306
307 CodeCell.prototype._open_with_pager = function (payload) {
307 CodeCell.prototype._open_with_pager = function (payload) {
308 $([IPython.events]).trigger('open_with_text.Pager', payload);
308 $([IPython.events]).trigger('open_with_text.Pager', payload);
309 };
309 };
310
310
311 /**
311 /**
312 * @method _handle_execute_reply
312 * @method _handle_execute_reply
313 * @private
313 * @private
314 */
314 */
315 CodeCell.prototype._handle_execute_reply = function (msg) {
315 CodeCell.prototype._handle_execute_reply = function (msg) {
316 this.set_input_prompt(msg.content.execution_count);
316 this.set_input_prompt(msg.content.execution_count);
317 this.element.removeClass("running");
317 this.element.removeClass("running");
318 $([IPython.events]).trigger('set_dirty.Notebook', {value: true});
318 $([IPython.events]).trigger('set_dirty.Notebook', {value: true});
319 };
319 };
320
320
321 /**
321 /**
322 * @method _handle_set_next_input
322 * @method _handle_set_next_input
323 * @private
323 * @private
324 */
324 */
325 CodeCell.prototype._handle_set_next_input = function (payload) {
325 CodeCell.prototype._handle_set_next_input = function (payload) {
326 var data = {'cell': this, 'text': payload.text};
326 var data = {'cell': this, 'text': payload.text};
327 $([IPython.events]).trigger('set_next_input.Notebook', data);
327 $([IPython.events]).trigger('set_next_input.Notebook', data);
328 };
328 };
329
329
330 /**
330 /**
331 * @method _handle_input_request
331 * @method _handle_input_request
332 * @private
332 * @private
333 */
333 */
334 CodeCell.prototype._handle_input_request = function (msg) {
334 CodeCell.prototype._handle_input_request = function (msg) {
335 this.output_area.append_raw_input(msg);
335 this.output_area.append_raw_input(msg);
336 };
336 };
337
337
338
338
339 // Basic cell manipulation.
339 // Basic cell manipulation.
340
340
341 CodeCell.prototype.select = function () {
341 CodeCell.prototype.select = function () {
342 var cont = IPython.Cell.prototype.select.apply(this);
342 var cont = IPython.Cell.prototype.select.apply(this);
343 if (cont) {
343 if (cont) {
344 this.code_mirror.refresh();
344 this.code_mirror.refresh();
345 this.auto_highlight();
345 this.auto_highlight();
346 }
346 }
347 return cont;
347 return cont;
348 };
348 };
349
349
350 CodeCell.prototype.render = function () {
350 CodeCell.prototype.render = function () {
351 var cont = IPython.Cell.prototype.render.apply(this);
351 var cont = IPython.Cell.prototype.render.apply(this);
352 // Always execute, even if we are already in the rendered state
352 // Always execute, even if we are already in the rendered state
353 return cont;
353 return cont;
354 };
354 };
355
355
356 CodeCell.prototype.unrender = function () {
356 CodeCell.prototype.unrender = function () {
357 // CodeCell is always rendered
357 // CodeCell is always rendered
358 return false;
358 return false;
359 };
359 };
360
360
361 CodeCell.prototype.select_all = function () {
361 CodeCell.prototype.select_all = function () {
362 var start = {line: 0, ch: 0};
362 var start = {line: 0, ch: 0};
363 var nlines = this.code_mirror.lineCount();
363 var nlines = this.code_mirror.lineCount();
364 var last_line = this.code_mirror.getLine(nlines-1);
364 var last_line = this.code_mirror.getLine(nlines-1);
365 var end = {line: nlines-1, ch: last_line.length};
365 var end = {line: nlines-1, ch: last_line.length};
366 this.code_mirror.setSelection(start, end);
366 this.code_mirror.setSelection(start, end);
367 };
367 };
368
368
369
369
370 CodeCell.prototype.collapse_output = function () {
370 CodeCell.prototype.collapse_output = function () {
371 this.collapsed = true;
371 this.collapsed = true;
372 this.output_area.collapse();
372 this.output_area.collapse();
373 };
373 };
374
374
375
375
376 CodeCell.prototype.expand_output = function () {
376 CodeCell.prototype.expand_output = function () {
377 this.collapsed = false;
377 this.collapsed = false;
378 this.output_area.expand();
378 this.output_area.expand();
379 this.output_area.unscroll_area();
379 this.output_area.unscroll_area();
380 };
380 };
381
381
382 CodeCell.prototype.scroll_output = function () {
382 CodeCell.prototype.scroll_output = function () {
383 this.output_area.expand();
383 this.output_area.expand();
384 this.output_area.scroll_if_long();
384 this.output_area.scroll_if_long();
385 };
385 };
386
386
387 CodeCell.prototype.toggle_output = function () {
387 CodeCell.prototype.toggle_output = function () {
388 this.collapsed = Boolean(1 - this.collapsed);
388 this.collapsed = Boolean(1 - this.collapsed);
389 this.output_area.toggle_output();
389 this.output_area.toggle_output();
390 };
390 };
391
391
392 CodeCell.prototype.toggle_output_scroll = function () {
392 CodeCell.prototype.toggle_output_scroll = function () {
393 this.output_area.toggle_scroll();
393 this.output_area.toggle_scroll();
394 };
394 };
395
395
396
396
397 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
397 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
398 var ns;
398 var ns;
399 if (prompt_value === undefined) {
399 if (prompt_value === undefined || prompt_value === null) {
400 ns = "&nbsp;";
400 ns = "&nbsp;";
401 } else {
401 } else {
402 ns = encodeURIComponent(prompt_value);
402 ns = encodeURIComponent(prompt_value);
403 }
403 }
404 return 'In&nbsp;[' + ns + ']:';
404 return 'In&nbsp;[' + ns + ']:';
405 };
405 };
406
406
407 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
407 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
408 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
408 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
409 for(var i=1; i < lines_number; i++) {
409 for(var i=1; i < lines_number; i++) {
410 html.push(['...:']);
410 html.push(['...:']);
411 }
411 }
412 return html.join('<br/>');
412 return html.join('<br/>');
413 };
413 };
414
414
415 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
415 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
416
416
417
417
418 CodeCell.prototype.set_input_prompt = function (number) {
418 CodeCell.prototype.set_input_prompt = function (number) {
419 var nline = 1;
419 var nline = 1;
420 if (this.code_mirror !== undefined) {
420 if (this.code_mirror !== undefined) {
421 nline = this.code_mirror.lineCount();
421 nline = this.code_mirror.lineCount();
422 }
422 }
423 this.input_prompt_number = number;
423 this.input_prompt_number = number;
424 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
424 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
425 // This HTML call is okay because the user contents are escaped.
425 // This HTML call is okay because the user contents are escaped.
426 this.element.find('div.input_prompt').html(prompt_html);
426 this.element.find('div.input_prompt').html(prompt_html);
427 };
427 };
428
428
429
429
430 CodeCell.prototype.clear_input = function () {
430 CodeCell.prototype.clear_input = function () {
431 this.code_mirror.setValue('');
431 this.code_mirror.setValue('');
432 };
432 };
433
433
434
434
435 CodeCell.prototype.get_text = function () {
435 CodeCell.prototype.get_text = function () {
436 return this.code_mirror.getValue();
436 return this.code_mirror.getValue();
437 };
437 };
438
438
439
439
440 CodeCell.prototype.set_text = function (code) {
440 CodeCell.prototype.set_text = function (code) {
441 return this.code_mirror.setValue(code);
441 return this.code_mirror.setValue(code);
442 };
442 };
443
443
444
444
445 CodeCell.prototype.clear_output = function (wait) {
445 CodeCell.prototype.clear_output = function (wait) {
446 this.output_area.clear_output(wait);
446 this.output_area.clear_output(wait);
447 this.set_input_prompt();
447 this.set_input_prompt();
448 };
448 };
449
449
450
450
451 // JSON serialization
451 // JSON serialization
452
452
453 CodeCell.prototype.fromJSON = function (data) {
453 CodeCell.prototype.fromJSON = function (data) {
454 IPython.Cell.prototype.fromJSON.apply(this, arguments);
454 IPython.Cell.prototype.fromJSON.apply(this, arguments);
455 if (data.cell_type === 'code') {
455 if (data.cell_type === 'code') {
456 if (data.input !== undefined) {
456 if (data.input !== undefined) {
457 this.set_text(data.input);
457 this.set_text(data.input);
458 // make this value the starting point, so that we can only undo
458 // make this value the starting point, so that we can only undo
459 // to this state, instead of a blank cell
459 // to this state, instead of a blank cell
460 this.code_mirror.clearHistory();
460 this.code_mirror.clearHistory();
461 this.auto_highlight();
461 this.auto_highlight();
462 }
462 }
463 if (data.prompt_number !== undefined) {
463 if (data.prompt_number !== undefined) {
464 this.set_input_prompt(data.prompt_number);
464 this.set_input_prompt(data.prompt_number);
465 } else {
465 } else {
466 this.set_input_prompt();
466 this.set_input_prompt();
467 }
467 }
468 this.output_area.trusted = data.trusted || false;
468 this.output_area.trusted = data.trusted || false;
469 this.output_area.fromJSON(data.outputs);
469 this.output_area.fromJSON(data.outputs);
470 if (data.collapsed !== undefined) {
470 if (data.collapsed !== undefined) {
471 if (data.collapsed) {
471 if (data.collapsed) {
472 this.collapse_output();
472 this.collapse_output();
473 } else {
473 } else {
474 this.expand_output();
474 this.expand_output();
475 }
475 }
476 }
476 }
477 }
477 }
478 };
478 };
479
479
480
480
481 CodeCell.prototype.toJSON = function () {
481 CodeCell.prototype.toJSON = function () {
482 var data = IPython.Cell.prototype.toJSON.apply(this);
482 var data = IPython.Cell.prototype.toJSON.apply(this);
483 data.input = this.get_text();
483 data.input = this.get_text();
484 // is finite protect against undefined and '*' value
484 // is finite protect against undefined and '*' value
485 if (isFinite(this.input_prompt_number)) {
485 if (isFinite(this.input_prompt_number)) {
486 data.prompt_number = this.input_prompt_number;
486 data.prompt_number = this.input_prompt_number;
487 }
487 }
488 var outputs = this.output_area.toJSON();
488 var outputs = this.output_area.toJSON();
489 data.outputs = outputs;
489 data.outputs = outputs;
490 data.language = 'python';
490 data.language = 'python';
491 data.trusted = this.output_area.trusted;
491 data.trusted = this.output_area.trusted;
492 data.collapsed = this.collapsed;
492 data.collapsed = this.collapsed;
493 return data;
493 return data;
494 };
494 };
495
495
496 /**
496 /**
497 * handle cell level logic when a cell is unselected
497 * handle cell level logic when a cell is unselected
498 * @method unselect
498 * @method unselect
499 * @return is the action being taken
499 * @return is the action being taken
500 */
500 */
501 CodeCell.prototype.unselect = function () {
501 CodeCell.prototype.unselect = function () {
502 var cont = IPython.Cell.prototype.unselect.apply(this);
502 var cont = IPython.Cell.prototype.unselect.apply(this);
503 if (cont) {
503 if (cont) {
504 // When a code cell is usnelected, make sure that the corresponding
504 // When a code cell is usnelected, make sure that the corresponding
505 // tooltip and completer to that cell is closed.
505 // tooltip and completer to that cell is closed.
506 IPython.tooltip.remove_and_cancel_tooltip(true);
506 IPython.tooltip.remove_and_cancel_tooltip(true);
507 if (this.completer !== null) {
507 if (this.completer !== null) {
508 this.completer.close();
508 this.completer.close();
509 }
509 }
510 }
510 }
511 return cont;
511 return cont;
512 };
512 };
513
513
514 IPython.CodeCell = CodeCell;
514 IPython.CodeCell = CodeCell;
515
515
516 return IPython;
516 return IPython;
517 }(IPython));
517 }(IPython));
@@ -1,61 +1,77 b''
1 """Tests for HTMLExporter"""
1 """Tests for HTMLExporter"""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
4 # Copyright (c) 2013, the IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from .base import ExportersTestsBase
15 from .base import ExportersTestsBase
16 from ..html import HTMLExporter
16 from ..html import HTMLExporter
17 from IPython.testing.decorators import onlyif_any_cmd_exists
17 from IPython.testing.decorators import onlyif_any_cmd_exists
18 import re
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Class
21 # Class
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22
23
23 class TestHTMLExporter(ExportersTestsBase):
24 class TestHTMLExporter(ExportersTestsBase):
24 """Tests for HTMLExporter"""
25 """Tests for HTMLExporter"""
25
26
26 exporter_class = HTMLExporter
27 exporter_class = HTMLExporter
27 should_include_raw = ['html']
28 should_include_raw = ['html']
28
29
29 def test_constructor(self):
30 def test_constructor(self):
30 """
31 """
31 Can a HTMLExporter be constructed?
32 Can a HTMLExporter be constructed?
32 """
33 """
33 HTMLExporter()
34 HTMLExporter()
34
35
35
36
36 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
37 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
37 def test_export(self):
38 def test_export(self):
38 """
39 """
39 Can a HTMLExporter export something?
40 Can a HTMLExporter export something?
40 """
41 """
41 (output, resources) = HTMLExporter().from_filename(self._get_notebook())
42 (output, resources) = HTMLExporter().from_filename(self._get_notebook())
42 assert len(output) > 0
43 assert len(output) > 0
43
44
44
45
45 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
46 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
46 def test_export_basic(self):
47 def test_export_basic(self):
47 """
48 """
48 Can a HTMLExporter export using the 'basic' template?
49 Can a HTMLExporter export using the 'basic' template?
49 """
50 """
50 (output, resources) = HTMLExporter(template_file='basic').from_filename(self._get_notebook())
51 (output, resources) = HTMLExporter(template_file='basic').from_filename(self._get_notebook())
51 assert len(output) > 0
52 assert len(output) > 0
52
53
53
54
54 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
55 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
55 def test_export_full(self):
56 def test_export_full(self):
56 """
57 """
57 Can a HTMLExporter export using the 'full' template?
58 Can a HTMLExporter export using the 'full' template?
58 """
59 """
59 (output, resources) = HTMLExporter(template_file='full').from_filename(self._get_notebook())
60 (output, resources) = HTMLExporter(template_file='full').from_filename(self._get_notebook())
60 assert len(output) > 0
61 assert len(output) > 0
61
62
63 @onlyif_any_cmd_exists('nodejs', 'node', 'pandoc')
64 def test_prompt_number(self):
65 """
66 Does HTMLExporter properly format input and output prompts?
67 """
68 (output, resources) = HTMLExporter(template_file='full').from_filename(
69 self._get_notebook(nb_name="prompt_numbers.ipynb"))
70 in_regex = r"In&nbsp;\[(.*)\]:"
71 out_regex = r"Out\[(.*)\]:"
72
73 ins = ["2", "10", "&nbsp;", "&nbsp;", "*", "0"]
74 outs = ["10"]
75
76 assert re.findall(in_regex, output) == ins
77 assert re.findall(out_regex, output) == outs
@@ -1,193 +1,201 b''
1 {%- extends 'display_priority.tpl' -%}
1 {%- extends 'display_priority.tpl' -%}
2
2
3
3
4 {% block codecell %}
4 {% block codecell %}
5 <div class="cell border-box-sizing code_cell rendered">
5 <div class="cell border-box-sizing code_cell rendered">
6 {{ super() }}
6 {{ super() }}
7 </div>
7 </div>
8 {%- endblock codecell %}
8 {%- endblock codecell %}
9
9
10 {% block input_group -%}
10 {% block input_group -%}
11 <div class="input">
11 <div class="input">
12 {{ super() }}
12 {{ super() }}
13 </div>
13 </div>
14 {% endblock input_group %}
14 {% endblock input_group %}
15
15
16 {% block output_group %}
16 {% block output_group %}
17 <div class="output_wrapper">
17 <div class="output_wrapper">
18 <div class="output">
18 <div class="output">
19 {{ super() }}
19 {{ super() }}
20 </div>
20 </div>
21 </div>
21 </div>
22 {% endblock output_group %}
22 {% endblock output_group %}
23
23
24 {% block in_prompt -%}
24 {% block in_prompt -%}
25 <div class="prompt input_prompt">
25 <div class="prompt input_prompt">
26 In&nbsp;[{{ cell.prompt_number }}]:
26 {%- if cell.prompt_number is defined -%}
27 In&nbsp;[{{ cell.prompt_number|replace(None, "&nbsp;") }}]:
28 {%- else -%}
29 In&nbsp;[&nbsp;]:
30 {%- endif -%}
27 </div>
31 </div>
28 {%- endblock in_prompt %}
32 {%- endblock in_prompt %}
29
33
30 {% block empty_in_prompt -%}
34 {% block empty_in_prompt -%}
31 <div class="prompt input_prompt">
35 <div class="prompt input_prompt">
32 </div>
36 </div>
33 {%- endblock empty_in_prompt %}
37 {%- endblock empty_in_prompt %}
34
38
35 {#
39 {#
36 output_prompt doesn't do anything in HTML,
40 output_prompt doesn't do anything in HTML,
37 because there is a prompt div in each output area (see output block)
41 because there is a prompt div in each output area (see output block)
38 #}
42 #}
39 {% block output_prompt %}
43 {% block output_prompt %}
40 {% endblock output_prompt %}
44 {% endblock output_prompt %}
41
45
42 {% block input %}
46 {% block input %}
43 <div class="inner_cell">
47 <div class="inner_cell">
44 <div class="input_area">
48 <div class="input_area">
45 {{ cell.input | highlight2html(language=resources.get('language'), metadata=cell.metadata) }}
49 {{ cell.input | highlight2html(language=resources.get('language'), metadata=cell.metadata) }}
46 </div>
50 </div>
47 </div>
51 </div>
48 {%- endblock input %}
52 {%- endblock input %}
49
53
50 {% block output %}
54 {% block output %}
51 <div class="output_area">
55 <div class="output_area">
52 {%- if output.output_type == 'pyout' -%}
56 {%- if output.output_type == 'pyout' -%}
53 <div class="prompt output_prompt">
57 <div class="prompt output_prompt">
54 Out[{{ cell.prompt_number }}]:
58 {%- if cell.prompt_number is defined -%}
59 Out[{{ cell.prompt_number|replace(None, "&nbsp;") }}]:
60 {%- else -%}
61 Out[&nbsp;]:
62 {%- endif -%}
55 {%- else -%}
63 {%- else -%}
56 <div class="prompt">
64 <div class="prompt">
57 {%- endif -%}
65 {%- endif -%}
58 </div>
66 </div>
59 {{ super() }}
67 {{ super() }}
60 </div>
68 </div>
61 {% endblock output %}
69 {% endblock output %}
62
70
63 {% block markdowncell scoped %}
71 {% block markdowncell scoped %}
64 <div class="cell border-box-sizing text_cell rendered">
72 <div class="cell border-box-sizing text_cell rendered">
65 {{ self.empty_in_prompt() }}
73 {{ self.empty_in_prompt() }}
66 <div class="inner_cell">
74 <div class="inner_cell">
67 <div class="text_cell_render border-box-sizing rendered_html">
75 <div class="text_cell_render border-box-sizing rendered_html">
68 {{ cell.source | markdown2html | strip_files_prefix }}
76 {{ cell.source | markdown2html | strip_files_prefix }}
69 </div>
77 </div>
70 </div>
78 </div>
71 </div>
79 </div>
72 {%- endblock markdowncell %}
80 {%- endblock markdowncell %}
73
81
74 {% block headingcell scoped %}
82 {% block headingcell scoped %}
75 <div class="cell border-box-sizing text_cell rendered">
83 <div class="cell border-box-sizing text_cell rendered">
76 {{ self.empty_in_prompt() }}
84 {{ self.empty_in_prompt() }}
77 <div class="inner_cell">
85 <div class="inner_cell">
78 <div class="text_cell_render border-box-sizing rendered_html">
86 <div class="text_cell_render border-box-sizing rendered_html">
79 {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2html | strip_files_prefix | add_anchor }}
87 {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2html | strip_files_prefix | add_anchor }}
80 </div>
88 </div>
81 </div>
89 </div>
82 </div>
90 </div>
83 {% endblock headingcell %}
91 {% endblock headingcell %}
84
92
85 {% block unknowncell scoped %}
93 {% block unknowncell scoped %}
86 unknown type {{ cell.type }}
94 unknown type {{ cell.type }}
87 {% endblock unknowncell %}
95 {% endblock unknowncell %}
88
96
89 {% block pyout -%}
97 {% block pyout -%}
90 {%- set extra_class="output_pyout" -%}
98 {%- set extra_class="output_pyout" -%}
91 {% block data_priority scoped %}
99 {% block data_priority scoped %}
92 {{ super() }}
100 {{ super() }}
93 {% endblock %}
101 {% endblock %}
94 {%- set extra_class="" -%}
102 {%- set extra_class="" -%}
95 {%- endblock pyout %}
103 {%- endblock pyout %}
96
104
97 {% block stream_stdout -%}
105 {% block stream_stdout -%}
98 <div class="output_subarea output_stream output_stdout output_text">
106 <div class="output_subarea output_stream output_stdout output_text">
99 <pre>
107 <pre>
100 {{ output.text | ansi2html }}
108 {{ output.text | ansi2html }}
101 </pre>
109 </pre>
102 </div>
110 </div>
103 {%- endblock stream_stdout %}
111 {%- endblock stream_stdout %}
104
112
105 {% block stream_stderr -%}
113 {% block stream_stderr -%}
106 <div class="output_subarea output_stream output_stderr output_text">
114 <div class="output_subarea output_stream output_stderr output_text">
107 <pre>
115 <pre>
108 {{ output.text | ansi2html }}
116 {{ output.text | ansi2html }}
109 </pre>
117 </pre>
110 </div>
118 </div>
111 {%- endblock stream_stderr %}
119 {%- endblock stream_stderr %}
112
120
113 {% block data_svg scoped -%}
121 {% block data_svg scoped -%}
114 <div class="output_svg output_subarea {{extra_class}}">
122 <div class="output_svg output_subarea {{extra_class}}">
115 {%- if output.svg_filename %}
123 {%- if output.svg_filename %}
116 <img src="{{output.svg_filename | posix_path}}"
124 <img src="{{output.svg_filename | posix_path}}"
117 {%- else %}
125 {%- else %}
118 {{ output.svg }}
126 {{ output.svg }}
119 {%- endif %}
127 {%- endif %}
120 </div>
128 </div>
121 {%- endblock data_svg %}
129 {%- endblock data_svg %}
122
130
123 {% block data_html scoped -%}
131 {% block data_html scoped -%}
124 <div class="output_html rendered_html output_subarea {{extra_class}}">
132 <div class="output_html rendered_html output_subarea {{extra_class}}">
125 {{ output.html }}
133 {{ output.html }}
126 </div>
134 </div>
127 {%- endblock data_html %}
135 {%- endblock data_html %}
128
136
129 {% block data_png scoped %}
137 {% block data_png scoped %}
130 <div class="output_png output_subarea {{extra_class}}">
138 <div class="output_png output_subarea {{extra_class}}">
131 {%- if output.png_filename %}
139 {%- if output.png_filename %}
132 <img src="{{output.png_filename | posix_path}}"
140 <img src="{{output.png_filename | posix_path}}"
133 {%- else %}
141 {%- else %}
134 <img src="data:image/png;base64,{{ output.png }}"
142 <img src="data:image/png;base64,{{ output.png }}"
135 {%- endif %}
143 {%- endif %}
136 {%- if 'metadata' in output and 'width' in output.metadata.get('png', {}) %}
144 {%- if 'metadata' in output and 'width' in output.metadata.get('png', {}) %}
137 width={{output.metadata['png']['width']}}
145 width={{output.metadata['png']['width']}}
138 {%- endif %}
146 {%- endif %}
139 {%- if 'metadata' in output and 'height' in output.metadata.get('png', {}) %}
147 {%- if 'metadata' in output and 'height' in output.metadata.get('png', {}) %}
140 height={{output.metadata['png']['height']}}
148 height={{output.metadata['png']['height']}}
141 {%- endif %}
149 {%- endif %}
142 >
150 >
143 </div>
151 </div>
144 {%- endblock data_png %}
152 {%- endblock data_png %}
145
153
146 {% block data_jpg scoped %}
154 {% block data_jpg scoped %}
147 <div class="output_jpeg output_subarea {{extra_class}}">
155 <div class="output_jpeg output_subarea {{extra_class}}">
148 {%- if output.jpeg_filename %}
156 {%- if output.jpeg_filename %}
149 <img src="{{output.jpeg_filename | posix_path}}"
157 <img src="{{output.jpeg_filename | posix_path}}"
150 {%- else %}
158 {%- else %}
151 <img src="data:image/jpeg;base64,{{ output.jpeg }}"
159 <img src="data:image/jpeg;base64,{{ output.jpeg }}"
152 {%- endif %}
160 {%- endif %}
153 {%- if 'metadata' in output and 'width' in output.metadata.get('jpeg', {}) %}
161 {%- if 'metadata' in output and 'width' in output.metadata.get('jpeg', {}) %}
154 width={{output.metadata['jpeg']['width']}}
162 width={{output.metadata['jpeg']['width']}}
155 {%- endif %}
163 {%- endif %}
156 {%- if 'metadata' in output and 'height' in output.metadata.get('jpeg', {}) %}
164 {%- if 'metadata' in output and 'height' in output.metadata.get('jpeg', {}) %}
157 height={{output.metadata['jpeg']['height']}}
165 height={{output.metadata['jpeg']['height']}}
158 {%- endif %}
166 {%- endif %}
159 >
167 >
160 </div>
168 </div>
161 {%- endblock data_jpg %}
169 {%- endblock data_jpg %}
162
170
163 {% block data_latex scoped %}
171 {% block data_latex scoped %}
164 <div class="output_latex output_subarea {{extra_class}}">
172 <div class="output_latex output_subarea {{extra_class}}">
165 {{ output.latex }}
173 {{ output.latex }}
166 </div>
174 </div>
167 {%- endblock data_latex %}
175 {%- endblock data_latex %}
168
176
169 {% block pyerr -%}
177 {% block pyerr -%}
170 <div class="output_subarea output_text output_pyerr">
178 <div class="output_subarea output_text output_pyerr">
171 <pre>{{ super() }}</pre>
179 <pre>{{ super() }}</pre>
172 </div>
180 </div>
173 {%- endblock pyerr %}
181 {%- endblock pyerr %}
174
182
175 {%- block traceback_line %}
183 {%- block traceback_line %}
176 {{ line | ansi2html }}
184 {{ line | ansi2html }}
177 {%- endblock traceback_line %}
185 {%- endblock traceback_line %}
178
186
179 {%- block data_text scoped %}
187 {%- block data_text scoped %}
180 <div class="output_text output_subarea {{extra_class}}">
188 <div class="output_text output_subarea {{extra_class}}">
181 <pre>
189 <pre>
182 {{ output.text | ansi2html }}
190 {{ output.text | ansi2html }}
183 </pre>
191 </pre>
184 </div>
192 </div>
185 {%- endblock -%}
193 {%- endblock -%}
186
194
187 {%- block data_javascript scoped %}
195 {%- block data_javascript scoped %}
188 <div class="output_subarea output_javascript {{extra_class}}">
196 <div class="output_subarea output_javascript {{extra_class}}">
189 <script type="text/javascript">
197 <script type="text/javascript">
190 {{ output.javascript }}
198 {{ output.javascript }}
191 </script>
199 </script>
192 </div>
200 </div>
193 {%- endblock -%}
201 {%- endblock -%}
@@ -1,41 +1,45 b''
1 ((= Black&white ipython input/output style =))
1 ((= Black&white ipython input/output style =))
2
2
3 ((*- extends 'base.tplx' -*))
3 ((*- extends 'base.tplx' -*))
4
4
5 %===============================================================================
5 %===============================================================================
6 % Input
6 % Input
7 %===============================================================================
7 %===============================================================================
8
8
9 ((* block input scoped *))
9 ((* block input scoped *))
10 ((( add_prompt(cell.input, cell, 'In ') )))
10 ((( add_prompt(cell.input, cell, 'In ') )))
11 ((* endblock input *))
11 ((* endblock input *))
12
12
13
13
14 %===============================================================================
14 %===============================================================================
15 % Output
15 % Output
16 %===============================================================================
16 %===============================================================================
17
17
18 ((* block pyout scoped *))
18 ((* block pyout scoped *))
19 ((*- for type in output | filter_data_type -*))
19 ((*- for type in output | filter_data_type -*))
20 ((*- if type in ['text']*))
20 ((*- if type in ['text']*))
21 ((( add_prompt(output.text, cell, 'Out') )))
21 ((( add_prompt(output.text, cell, 'Out') )))
22 ((*- else -*))
22 ((*- else -*))
23 \verb+Out[((( cell.prompt_number )))]:+((( super() )))
23 \verb+Out[((( cell.prompt_number )))]:+((( super() )))
24 ((*- endif -*))
24 ((*- endif -*))
25 ((*- endfor -*))
25 ((*- endfor -*))
26 ((* endblock pyout *))
26 ((* endblock pyout *))
27
27
28
28
29 %==============================================================================
29 %==============================================================================
30 % Support Macros
30 % Support Macros
31 %==============================================================================
31 %==============================================================================
32
32
33 % Name: draw_prompt
33 % Name: draw_prompt
34 % Purpose: Renders an output/input prompt
34 % Purpose: Renders an output/input prompt
35 ((* macro add_prompt(text, cell, prompt) -*))
35 ((* macro add_prompt(text, cell, prompt) -*))
36 ((*- set prompt_number = "" ~ cell.prompt_number -*))
36 ((*- if cell.prompt_number is defined -*))
37 ((*- set prompt_number = "" ~ (cell.prompt_number | replace(None, " ")) -*))
38 ((*- else -*))
39 ((*- set prompt_number = " " -*))
40 ((*- endif -*))
37 ((*- set indentation = " " * (prompt_number | length + 7) -*))
41 ((*- set indentation = " " * (prompt_number | length + 7) -*))
38 \begin{verbatim}
42 \begin{verbatim}
39 (((- text | add_prompts(first=prompt ~ '[' ~ prompt_number ~ ']: ', cont=indentation) -)))
43 (((- text | add_prompts(first=prompt ~ '[' ~ prompt_number ~ ']: ', cont=indentation) -)))
40 \end{verbatim}
44 \end{verbatim}
41 ((*- endmacro *))
45 ((*- endmacro *))
@@ -1,54 +1,58 b''
1 ((= IPython input/output style =))
1 ((= IPython input/output style =))
2
2
3 ((*- extends 'base.tplx' -*))
3 ((*- extends 'base.tplx' -*))
4
4
5 % Custom definitions
5 % Custom definitions
6 ((* block definitions *))
6 ((* block definitions *))
7 ((( super() )))
7 ((( super() )))
8
8
9 % Pygments definitions
9 % Pygments definitions
10 ((( resources.latex.pygments_definitions )))
10 ((( resources.latex.pygments_definitions )))
11
11
12 % Exact colors from NB
12 % Exact colors from NB
13 \definecolor{incolor}{rgb}{0.0, 0.0, 0.5}
13 \definecolor{incolor}{rgb}{0.0, 0.0, 0.5}
14 \definecolor{outcolor}{rgb}{0.545, 0.0, 0.0}
14 \definecolor{outcolor}{rgb}{0.545, 0.0, 0.0}
15
15
16 ((* endblock definitions *))
16 ((* endblock definitions *))
17
17
18 %===============================================================================
18 %===============================================================================
19 % Input
19 % Input
20 %===============================================================================
20 %===============================================================================
21
21
22 ((* block input scoped *))
22 ((* block input scoped *))
23 ((( add_prompt(cell.input | highlight2latex(strip_verbatim=True), cell, 'In ', 'incolor') )))
23 ((( add_prompt(cell.input | highlight2latex(strip_verbatim=True), cell, 'In ', 'incolor') )))
24 ((* endblock input *))
24 ((* endblock input *))
25
25
26
26
27 %===============================================================================
27 %===============================================================================
28 % Output
28 % Output
29 %===============================================================================
29 %===============================================================================
30
30
31 ((* block pyout scoped *))
31 ((* block pyout scoped *))
32 ((*- for type in output | filter_data_type -*))
32 ((*- for type in output | filter_data_type -*))
33 ((*- if type in ['text']*))
33 ((*- if type in ['text']*))
34 ((( add_prompt(output.text | escape_latex, cell, 'Out', 'outcolor') )))
34 ((( add_prompt(output.text | escape_latex, cell, 'Out', 'outcolor') )))
35 ((* else -*))
35 ((* else -*))
36 \texttt{\color{outcolor}Out[{\color{outcolor}((( cell.prompt_number )))}]:}((( super() )))
36 \texttt{\color{outcolor}Out[{\color{outcolor}((( cell.prompt_number )))}]:}((( super() )))
37 ((*- endif -*))
37 ((*- endif -*))
38 ((*- endfor -*))
38 ((*- endfor -*))
39 ((* endblock pyout *))
39 ((* endblock pyout *))
40
40
41
41
42 %==============================================================================
42 %==============================================================================
43 % Support Macros
43 % Support Macros
44 %==============================================================================
44 %==============================================================================
45
45
46 % Name: draw_prompt
46 % Name: draw_prompt
47 % Purpose: Renders an output/input prompt
47 % Purpose: Renders an output/input prompt
48 ((* macro add_prompt(text, cell, prompt, prompt_color) -*))
48 ((* macro add_prompt(text, cell, prompt, prompt_color) -*))
49 ((*- set prompt_number = "" ~ cell.prompt_number -*))
49 ((*- if cell.prompt_number is defined -*))
50 ((*- set prompt_number = "" ~ (cell.prompt_number | replace(None, " ")) -*))
51 ((*- else -*))
52 ((*- set prompt_number = " " -*))
53 ((*- endif -*))
50 ((*- set indention = " " * (prompt_number | length + 7) -*))
54 ((*- set indention = " " * (prompt_number | length + 7) -*))
51 \begin{Verbatim}[commandchars=\\\{\}]
55 \begin{Verbatim}[commandchars=\\\{\}]
52 ((( text | add_prompts(first='{\color{' ~ prompt_color ~ '}' ~ prompt ~ '[{\\color{' ~ prompt_color ~ '}' ~ prompt_number ~ '}]:} ', cont=indention) )))
56 ((( text | add_prompts(first='{\color{' ~ prompt_color ~ '}' ~ prompt ~ '[{\\color{' ~ prompt_color ~ '}' ~ prompt_number ~ '}]:} ', cont=indention) )))
53 \end{Verbatim}
57 \end{Verbatim}
54 ((*- endmacro *))
58 ((*- endmacro *))
General Comments 0
You need to be logged in to leave comments. Login now