##// END OF EJS Templates
Merge pull request #4398 from Carreau/no-tooltip-on-tab...
Min RK -
r13484:4134fc9d merge
parent child Browse files
Show More
@@ -0,0 +1,3
1 * In notebook, Showing tooltip on tab has been disables to avoid conflict with
2 completion, Shift-Tab could still be used to invoke tooltip when inside
3 function signature and/or on selection.
@@ -1,466 +1,460
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // CodeCell
10 10 //============================================================================
11 11 /**
12 12 * An extendable module that provide base functionnality to create cell for notebook.
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule CodeCell
16 16 */
17 17
18 18
19 19 /* local util for codemirror */
20 20 var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;};
21 21
22 22 /**
23 23 *
24 24 * function to delete until previous non blanking space character
25 25 * or first multiple of 4 tabstop.
26 26 * @private
27 27 */
28 28 CodeMirror.commands.delSpaceToPrevTabStop = function(cm){
29 29 var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
30 30 if (!posEq(from, to)) { cm.replaceRange("", from, to); return; }
31 31 var cur = cm.getCursor(), line = cm.getLine(cur.line);
32 32 var tabsize = cm.getOption('tabSize');
33 33 var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize;
34 34 from = {ch:cur.ch-chToPrevTabStop,line:cur.line};
35 35 var select = cm.getRange(from,cur);
36 36 if( select.match(/^\ +$/) !== null){
37 37 cm.replaceRange("",from,cur);
38 38 } else {
39 39 cm.deleteH(-1,"char");
40 40 }
41 41 };
42 42
43 43
44 44 var IPython = (function (IPython) {
45 45 "use strict";
46 46
47 47 var utils = IPython.utils;
48 48 var key = IPython.utils.keycodes;
49 49
50 50 /**
51 51 * A Cell conceived to write code.
52 52 *
53 53 * The kernel doesn't have to be set at creation time, in that case
54 54 * it will be null and set_kernel has to be called later.
55 55 * @class CodeCell
56 56 * @extends IPython.Cell
57 57 *
58 58 * @constructor
59 59 * @param {Object|null} kernel
60 60 * @param {object|undefined} [options]
61 61 * @param [options.cm_config] {object} config to pass to CodeMirror
62 62 */
63 63 var CodeCell = function (kernel, options) {
64 64 this.kernel = kernel || null;
65 65 this.code_mirror = null;
66 66 this.input_prompt_number = null;
67 67 this.collapsed = false;
68 68 this.cell_type = "code";
69 69
70 70
71 71 var cm_overwrite_options = {
72 72 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
73 73 };
74 74
75 75 options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options});
76 76
77 77 IPython.Cell.apply(this,[options]);
78 78
79 79 var that = this;
80 80 this.element.focusout(
81 81 function() { that.auto_highlight(); }
82 82 );
83 83 };
84 84
85 85 CodeCell.options_default = {
86 86 cm_config : {
87 87 extraKeys: {
88 88 "Tab" : "indentMore",
89 89 "Shift-Tab" : "indentLess",
90 90 "Backspace" : "delSpaceToPrevTabStop",
91 91 "Cmd-/" : "toggleComment",
92 92 "Ctrl-/" : "toggleComment"
93 93 },
94 94 mode: 'ipython',
95 95 theme: 'ipython',
96 96 matchBrackets: true
97 97 }
98 98 };
99 99
100 100
101 101 CodeCell.prototype = new IPython.Cell();
102 102
103 103 /**
104 104 * @method auto_highlight
105 105 */
106 106 CodeCell.prototype.auto_highlight = function () {
107 107 this._auto_highlight(IPython.config.cell_magic_highlight);
108 108 };
109 109
110 110 /** @method create_element */
111 111 CodeCell.prototype.create_element = function () {
112 112 IPython.Cell.prototype.create_element.apply(this, arguments);
113 113
114 114 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell');
115 115 cell.attr('tabindex','2');
116 116
117 117 this.celltoolbar = new IPython.CellToolbar(this);
118 118
119 119 var input = $('<div></div>').addClass('input');
120 120 var vbox = $('<div/>').addClass('vbox box-flex1');
121 121 input.append($('<div/>').addClass('prompt input_prompt'));
122 122 vbox.append(this.celltoolbar.element);
123 123 var input_area = $('<div/>').addClass('input_area');
124 124 this.code_mirror = CodeMirror(input_area.get(0), this.cm_config);
125 125 $(this.code_mirror.getInputField()).attr("spellcheck", "false");
126 126 vbox.append(input_area);
127 127 input.append(vbox);
128 128 var output = $('<div></div>');
129 129 cell.append(input).append(output);
130 130 this.element = cell;
131 131 this.output_area = new IPython.OutputArea(output, true);
132 132
133 133 // construct a completer only if class exist
134 134 // otherwise no print view
135 135 if (IPython.Completer !== undefined)
136 136 {
137 137 this.completer = new IPython.Completer(this);
138 138 }
139 139 };
140 140
141 141 /**
142 142 * This method gets called in CodeMirror's onKeyDown/onKeyPress
143 143 * handlers and is used to provide custom key handling. Its return
144 144 * value is used to determine if CodeMirror should ignore the event:
145 145 * true = ignore, false = don't ignore.
146 146 * @method handle_codemirror_keyevent
147 147 */
148 148 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
149 149
150 150 var that = this;
151 151 // whatever key is pressed, first, cancel the tooltip request before
152 152 // they are sent, and remove tooltip if any, except for tab again
153 153 if (event.type === 'keydown' && event.which != key.TAB ) {
154 154 IPython.tooltip.remove_and_cancel_tooltip();
155 155 }
156 156
157 157 var cur = editor.getCursor();
158 158 if (event.keyCode === key.ENTER){
159 159 this.auto_highlight();
160 160 }
161 161
162 162 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
163 163 // Always ignore shift-enter in CodeMirror as we handle it.
164 164 return true;
165 165 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
166 166 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
167 167 // browser and keyboard layout !
168 168 // Pressing '(' , request tooltip, don't forget to reappend it
169 169 // The second argument says to hide the tooltip if the docstring
170 170 // is actually empty
171 171 IPython.tooltip.pending(that, true);
172 172 } else if (event.which === key.UPARROW && event.type === 'keydown') {
173 173 // If we are not at the top, let CM handle the up arrow and
174 174 // prevent the global keydown handler from handling it.
175 175 if (!that.at_top()) {
176 176 event.stop();
177 177 return false;
178 178 } else {
179 179 return true;
180 180 }
181 181 } else if (event.which === key.ESC) {
182 182 return IPython.tooltip.remove_and_cancel_tooltip(true);
183 183 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
184 184 // If we are not at the bottom, let CM handle the down arrow and
185 185 // prevent the global keydown handler from handling it.
186 186 if (!that.at_bottom()) {
187 187 event.stop();
188 188 return false;
189 189 } else {
190 190 return true;
191 191 }
192 192 } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) {
193 193 if (editor.somethingSelected()){
194 194 var anchor = editor.getCursor("anchor");
195 195 var head = editor.getCursor("head");
196 196 if( anchor.line != head.line){
197 197 return false;
198 198 }
199 199 }
200 200 IPython.tooltip.request(that);
201 201 event.stop();
202 202 return true;
203 203 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
204 204 // Tab completion.
205 205 //Do not trim here because of tooltip
206 206 if (editor.somethingSelected()) { return false; }
207 207 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
208 208 if (pre_cursor.trim() === "") {
209 209 // Don't autocomplete if the part of the line before the cursor
210 210 // is empty. In this case, let CodeMirror handle indentation.
211 211 return false;
212 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) {
213 IPython.tooltip.request(that);
214 // Prevent the event from bubbling up.
215 event.stop();
216 // Prevent CodeMirror from handling the tab.
217 return true;
218 212 } else {
219 213 event.stop();
220 214 this.completer.startCompletion();
221 215 return true;
222 216 }
223 217 } else {
224 218 // keypress/keyup also trigger on TAB press, and we don't want to
225 219 // use those to disable tab completion.
226 220 return false;
227 221 }
228 222 return false;
229 223 };
230 224
231 225
232 226 // Kernel related calls.
233 227
234 228 CodeCell.prototype.set_kernel = function (kernel) {
235 229 this.kernel = kernel;
236 230 };
237 231
238 232 /**
239 233 * Execute current code cell to the kernel
240 234 * @method execute
241 235 */
242 236 CodeCell.prototype.execute = function () {
243 237 this.output_area.clear_output();
244 238 this.set_input_prompt('*');
245 239 this.element.addClass("running");
246 240 if (this.last_msg_id) {
247 241 this.kernel.clear_callbacks_for_msg(this.last_msg_id);
248 242 }
249 243 var callbacks = this.get_callbacks();
250 244
251 245 this.last_msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false, store_history: true});
252 246 };
253 247
254 248 /**
255 249 * Construct the default callbacks for
256 250 * @method get_callbacks
257 251 */
258 252 CodeCell.prototype.get_callbacks = function () {
259 253 return {
260 254 shell : {
261 255 reply : $.proxy(this._handle_execute_reply, this),
262 256 payload : {
263 257 set_next_input : $.proxy(this._handle_set_next_input, this),
264 258 page : $.proxy(this._open_with_pager, this)
265 259 }
266 260 },
267 261 iopub : {
268 262 output : $.proxy(this.output_area.handle_output, this.output_area),
269 263 clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area),
270 264 },
271 265 input : $.proxy(this._handle_input_request, this)
272 266 };
273 267 };
274 268
275 269 CodeCell.prototype._open_with_pager = function (payload) {
276 270 $([IPython.events]).trigger('open_with_text.Pager', payload);
277 271 };
278 272
279 273 /**
280 274 * @method _handle_execute_reply
281 275 * @private
282 276 */
283 277 CodeCell.prototype._handle_execute_reply = function (msg) {
284 278 this.set_input_prompt(msg.content.execution_count);
285 279 this.element.removeClass("running");
286 280 $([IPython.events]).trigger('set_dirty.Notebook', {value: true});
287 281 };
288 282
289 283 /**
290 284 * @method _handle_set_next_input
291 285 * @private
292 286 */
293 287 CodeCell.prototype._handle_set_next_input = function (payload) {
294 288 var data = {'cell': this, 'text': payload.text};
295 289 $([IPython.events]).trigger('set_next_input.Notebook', data);
296 290 };
297 291
298 292 /**
299 293 * @method _handle_input_request
300 294 * @private
301 295 */
302 296 CodeCell.prototype._handle_input_request = function (msg) {
303 297 this.output_area.append_raw_input(msg);
304 298 };
305 299
306 300
307 301 // Basic cell manipulation.
308 302
309 303 CodeCell.prototype.select = function () {
310 304 IPython.Cell.prototype.select.apply(this);
311 305 this.code_mirror.refresh();
312 306 this.code_mirror.focus();
313 307 this.auto_highlight();
314 308 // We used to need an additional refresh() after the focus, but
315 309 // it appears that this has been fixed in CM. This bug would show
316 310 // up on FF when a newly loaded markdown cell was edited.
317 311 };
318 312
319 313
320 314 CodeCell.prototype.select_all = function () {
321 315 var start = {line: 0, ch: 0};
322 316 var nlines = this.code_mirror.lineCount();
323 317 var last_line = this.code_mirror.getLine(nlines-1);
324 318 var end = {line: nlines-1, ch: last_line.length};
325 319 this.code_mirror.setSelection(start, end);
326 320 };
327 321
328 322
329 323 CodeCell.prototype.collapse = function () {
330 324 this.collapsed = true;
331 325 this.output_area.collapse();
332 326 };
333 327
334 328
335 329 CodeCell.prototype.expand = function () {
336 330 this.collapsed = false;
337 331 this.output_area.expand();
338 332 };
339 333
340 334
341 335 CodeCell.prototype.toggle_output = function () {
342 336 this.collapsed = Boolean(1 - this.collapsed);
343 337 this.output_area.toggle_output();
344 338 };
345 339
346 340
347 341 CodeCell.prototype.toggle_output_scroll = function () {
348 342 this.output_area.toggle_scroll();
349 343 };
350 344
351 345
352 346 CodeCell.input_prompt_classical = function (prompt_value, lines_number) {
353 347 var ns = prompt_value || "&nbsp;";
354 348 return 'In&nbsp;[' + ns + ']:';
355 349 };
356 350
357 351 CodeCell.input_prompt_continuation = function (prompt_value, lines_number) {
358 352 var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)];
359 353 for(var i=1; i < lines_number; i++) {
360 354 html.push(['...:']);
361 355 }
362 356 return html.join('<br/>');
363 357 };
364 358
365 359 CodeCell.input_prompt_function = CodeCell.input_prompt_classical;
366 360
367 361
368 362 CodeCell.prototype.set_input_prompt = function (number) {
369 363 var nline = 1;
370 364 if (this.code_mirror !== undefined) {
371 365 nline = this.code_mirror.lineCount();
372 366 }
373 367 this.input_prompt_number = number;
374 368 var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline);
375 369 this.element.find('div.input_prompt').html(prompt_html);
376 370 };
377 371
378 372
379 373 CodeCell.prototype.clear_input = function () {
380 374 this.code_mirror.setValue('');
381 375 };
382 376
383 377
384 378 CodeCell.prototype.get_text = function () {
385 379 return this.code_mirror.getValue();
386 380 };
387 381
388 382
389 383 CodeCell.prototype.set_text = function (code) {
390 384 return this.code_mirror.setValue(code);
391 385 };
392 386
393 387
394 388 CodeCell.prototype.at_top = function () {
395 389 var cursor = this.code_mirror.getCursor();
396 390 if (cursor.line === 0 && cursor.ch === 0) {
397 391 return true;
398 392 } else {
399 393 return false;
400 394 }
401 395 };
402 396
403 397
404 398 CodeCell.prototype.at_bottom = function () {
405 399 var cursor = this.code_mirror.getCursor();
406 400 if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) {
407 401 return true;
408 402 } else {
409 403 return false;
410 404 }
411 405 };
412 406
413 407
414 408 CodeCell.prototype.clear_output = function (wait) {
415 409 this.output_area.clear_output(wait);
416 410 };
417 411
418 412
419 413 // JSON serialization
420 414
421 415 CodeCell.prototype.fromJSON = function (data) {
422 416 IPython.Cell.prototype.fromJSON.apply(this, arguments);
423 417 if (data.cell_type === 'code') {
424 418 if (data.input !== undefined) {
425 419 this.set_text(data.input);
426 420 // make this value the starting point, so that we can only undo
427 421 // to this state, instead of a blank cell
428 422 this.code_mirror.clearHistory();
429 423 this.auto_highlight();
430 424 }
431 425 if (data.prompt_number !== undefined) {
432 426 this.set_input_prompt(data.prompt_number);
433 427 } else {
434 428 this.set_input_prompt();
435 429 }
436 430 this.output_area.fromJSON(data.outputs);
437 431 if (data.collapsed !== undefined) {
438 432 if (data.collapsed) {
439 433 this.collapse();
440 434 } else {
441 435 this.expand();
442 436 }
443 437 }
444 438 }
445 439 };
446 440
447 441
448 442 CodeCell.prototype.toJSON = function () {
449 443 var data = IPython.Cell.prototype.toJSON.apply(this);
450 444 data.input = this.get_text();
451 445 data.cell_type = 'code';
452 446 if (this.input_prompt_number) {
453 447 data.prompt_number = this.input_prompt_number;
454 448 }
455 449 var outputs = this.output_area.toJSON();
456 450 data.outputs = outputs;
457 451 data.language = 'python';
458 452 data.collapsed = this.collapsed;
459 453 return data;
460 454 };
461 455
462 456
463 457 IPython.CodeCell = CodeCell;
464 458
465 459 return IPython;
466 460 }(IPython));
@@ -1,80 +1,79
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2012 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // Notebook
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 var IPython = (function (IPython) {
18 18 "use strict";
19 19 /**
20 20 * A place where some stuff can be confugured.
21 21 *
22 22 * @class config
23 23 * @static
24 24 *
25 25 **/
26 26 var default_config = {
27 27 /**
28 28 * Dictionary of object to autodetect highlight mode for code cell.
29 29 * Item of the dictionnary should take the form :
30 30 *
31 31 * key : {'reg':[list_of_regexp]}
32 32 *
33 33 * where `key` will be the code mirror mode name
34 34 * and `list_of_regexp` should be a list of regext that should match
35 35 * the first line of the cell to trigger this mode.
36 36 *
37 37 * if `key` is prefixed by the `magic_` prefix the codemirror `mode`
38 38 * will be applied only at the end of the first line
39 39 *
40 40 * @attribute cell_magic_highlight
41 41 * @example
42 42 * This would trigger javascript mode
43 43 * from the second line if first line start with `%%javascript` or `%%jsmagic`
44 44 *
45 45 * cell_magic_highlight['magic_javascript'] = {'reg':[/^%%javascript/,/^%%jsmagic/]}
46 46 * @example
47 47 * This would trigger javascript mode
48 48 * from the second line if first line start with `var`
49 49 *
50 50 * cell_magic_highlight['javascript'] = {'reg':[/^var/]}
51 51 */
52 52 cell_magic_highlight : {
53 53 'magic_javascript' :{'reg':[/^%%javascript/]}
54 54 ,'magic_perl' :{'reg':[/^%%perl/]}
55 55 ,'magic_ruby' :{'reg':[/^%%ruby/]}
56 56 ,'magic_python' :{'reg':[/^%%python3?/]}
57 57 ,'magic_shell' :{'reg':[/^%%bash/]}
58 58 ,'magic_r' :{'reg':[/^%%R/]}
59 59 ,'magic_text/x-cython' :{'reg':[/^%%cython/]}
60 60 },
61 61
62 62 /**
63 63 * same as `cell_magic_highlight` but for raw cells
64 64 * @attribute raw_cell_highlight
65 65 */
66 66 raw_cell_highlight : {
67 67 'diff' :{'reg':[/^diff/]}
68 68 },
69 69
70 tooltip_on_tab : true,
71 70 };
72 71
73 72 // use the same method to merge user configuration
74 73 IPython.config = {};
75 74 $.extend(IPython.config, default_config);
76 75
77 76 return IPython;
78 77
79 78 }(IPython));
80 79
@@ -1,439 +1,439
1 1 {
2 2 "metadata": {
3 3 "name": ""
4 4 },
5 5 "nbformat": 3,
6 6 "nbformat_minor": 0,
7 7 "worksheets": [
8 8 {
9 9 "cells": [
10 10 {
11 11 "cell_type": "heading",
12 12 "level": 1,
13 13 "metadata": {},
14 14 "source": [
15 15 "Running Code in the IPython Notebook"
16 16 ]
17 17 },
18 18 {
19 19 "cell_type": "markdown",
20 20 "metadata": {},
21 21 "source": [
22 22 "First and foremost, the IPython Notebook is an interactive environment for writing and running Python code."
23 23 ]
24 24 },
25 25 {
26 26 "cell_type": "heading",
27 27 "level": 2,
28 28 "metadata": {},
29 29 "source": [
30 30 "Code cells allow you to enter and run Python code"
31 31 ]
32 32 },
33 33 {
34 34 "cell_type": "markdown",
35 35 "metadata": {},
36 36 "source": [
37 37 "Run a code cell using `Shift-Enter` or pressing the \"Play\" button in the toolbar above:"
38 38 ]
39 39 },
40 40 {
41 41 "cell_type": "code",
42 42 "collapsed": false,
43 43 "input": [
44 44 "a = 10"
45 45 ],
46 46 "language": "python",
47 47 "metadata": {},
48 48 "outputs": [],
49 49 "prompt_number": 10
50 50 },
51 51 {
52 52 "cell_type": "code",
53 53 "collapsed": false,
54 54 "input": [
55 55 "print(a)"
56 56 ],
57 57 "language": "python",
58 58 "metadata": {},
59 59 "outputs": [
60 60 {
61 61 "output_type": "stream",
62 62 "stream": "stdout",
63 63 "text": [
64 64 "10\n"
65 65 ]
66 66 }
67 67 ],
68 68 "prompt_number": 11
69 69 },
70 70 {
71 71 "cell_type": "heading",
72 72 "level": 2,
73 73 "metadata": {},
74 74 "source": [
75 75 "Managing the IPython Kernel"
76 76 ]
77 77 },
78 78 {
79 79 "cell_type": "markdown",
80 80 "metadata": {},
81 81 "source": [
82 82 "Code is run in a separate process called the IPython Kernel. The Kernel can be interrupted or restarted. Try running the following cell and then hit the \"Stop\" button in the toolbar above."
83 83 ]
84 84 },
85 85 {
86 86 "cell_type": "code",
87 87 "collapsed": false,
88 88 "input": [
89 89 "import time\n",
90 90 "time.sleep(10)"
91 91 ],
92 92 "language": "python",
93 93 "metadata": {},
94 94 "outputs": [
95 95 {
96 96 "ename": "KeyboardInterrupt",
97 97 "evalue": "",
98 98 "output_type": "pyerr",
99 99 "traceback": [
100 100 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
101 101 "\u001b[0;32m<ipython-input-16-d7b436e260d5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
102 102 "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
103 103 ]
104 104 }
105 105 ],
106 106 "prompt_number": 16
107 107 },
108 108 {
109 109 "cell_type": "markdown",
110 110 "metadata": {},
111 111 "source": [
112 112 "If the Kernel dies you will be prompted to restart it. Here we call the low-level system libc.time routine with the wrong argument via\n",
113 113 "ctypes to segfault the Python interpreter:"
114 114 ]
115 115 },
116 116 {
117 117 "cell_type": "code",
118 118 "collapsed": false,
119 119 "input": [
120 120 "import sys\n",
121 121 "from ctypes import CDLL\n",
122 122 "# This will crash a Linux or Mac system; equivalent calls can be made on Windows\n",
123 123 "dll = 'dylib' if sys.platform == 'darwin' else 'so.6'\n",
124 124 "libc = CDLL(\"libc.%s\" % dll) \n",
125 125 "libc.time(-1) # BOOM!!"
126 126 ],
127 127 "language": "python",
128 128 "metadata": {},
129 129 "outputs": [],
130 130 "prompt_number": "*"
131 131 },
132 132 {
133 133 "cell_type": "heading",
134 134 "level": 2,
135 135 "metadata": {},
136 136 "source": [
137 137 "All of the goodness of IPython works"
138 138 ]
139 139 },
140 140 {
141 141 "cell_type": "markdown",
142 142 "metadata": {},
143 143 "source": [
144 144 "Here are two system aliases:"
145 145 ]
146 146 },
147 147 {
148 148 "cell_type": "code",
149 149 "collapsed": false,
150 150 "input": [
151 151 "pwd"
152 152 ],
153 153 "language": "python",
154 154 "metadata": {},
155 155 "outputs": [
156 156 {
157 157 "output_type": "pyout",
158 158 "prompt_number": 4,
159 159 "text": [
160 160 "u'/Users/bgranger/Documents/Computation/IPython/code/ipython/examples/notebooks'"
161 161 ]
162 162 }
163 163 ],
164 164 "prompt_number": 4
165 165 },
166 166 {
167 167 "cell_type": "code",
168 168 "collapsed": false,
169 169 "input": [
170 170 "ls"
171 171 ],
172 172 "language": "python",
173 173 "metadata": {},
174 174 "outputs": [
175 175 {
176 176 "output_type": "stream",
177 177 "stream": "stdout",
178 178 "text": [
179 179 "01_notebook_introduction.ipynb Octave Magic.ipynb\r\n",
180 180 "Animations Using clear_output.ipynb PyLab and Matplotlib.ipynb\r\n",
181 181 "Basic Output.ipynb R Magics.ipynb\r\n",
182 182 "Custom Display Logic.ipynb Running Code.ipynb\r\n",
183 183 "Cython Magics.ipynb Script Magics.ipynb\r\n",
184 184 "Data Publication API.ipynb SymPy Examples.ipynb\r\n",
185 185 "Display System.ipynb Trapezoid Rule.ipynb\r\n",
186 186 "JS Progress Bar.ipynb Typesetting Math Using MathJax.ipynb\r\n",
187 187 "Local Files.ipynb animation.m4v\r\n",
188 188 "Markdown Cells.ipynb python-logo.svg\r\n",
189 189 "Notebook Tour.ipynb\r\n"
190 190 ]
191 191 }
192 192 ],
193 193 "prompt_number": 2
194 194 },
195 195 {
196 196 "cell_type": "markdown",
197 197 "metadata": {},
198 198 "source": [
199 199 "Any command line program can be run using `!` with string interpolation from Python variables:"
200 200 ]
201 201 },
202 202 {
203 203 "cell_type": "code",
204 204 "collapsed": false,
205 205 "input": [
206 206 "message = 'The IPython notebook is great!'\n",
207 207 "# note: the echo command does not run on Windows, it's a unix command.\n",
208 208 "!echo $message"
209 209 ],
210 210 "language": "python",
211 211 "metadata": {},
212 212 "outputs": []
213 213 },
214 214 {
215 215 "cell_type": "markdown",
216 216 "metadata": {},
217 217 "source": [
218 218 "Tab completion works:"
219 219 ]
220 220 },
221 221 {
222 222 "cell_type": "code",
223 223 "collapsed": false,
224 224 "input": [
225 225 "import numpy\n",
226 226 "numpy.random."
227 227 ],
228 228 "language": "python",
229 229 "metadata": {},
230 230 "outputs": [],
231 231 "prompt_number": 9
232 232 },
233 233 {
234 234 "cell_type": "markdown",
235 235 "metadata": {},
236 236 "source": [
237 "Tab completion after `(` brings up a tooltip with the docstring:"
237 "Shift-Tab on selection, or after `(` brings up a tooltip with the docstring:"
238 238 ]
239 239 },
240 240 {
241 241 "cell_type": "code",
242 242 "collapsed": false,
243 243 "input": [
244 244 "numpy.random.rand("
245 245 ],
246 246 "language": "python",
247 247 "metadata": {},
248 248 "outputs": []
249 249 },
250 250 {
251 251 "cell_type": "markdown",
252 252 "metadata": {},
253 253 "source": [
254 254 "Adding `?` opens the docstring in the pager below:"
255 255 ]
256 256 },
257 257 {
258 258 "cell_type": "code",
259 259 "collapsed": false,
260 260 "input": [
261 261 "magic?"
262 262 ],
263 263 "language": "python",
264 264 "metadata": {},
265 265 "outputs": [],
266 266 "prompt_number": 8
267 267 },
268 268 {
269 269 "cell_type": "markdown",
270 270 "metadata": {},
271 271 "source": [
272 272 "Exceptions are formatted nicely:"
273 273 ]
274 274 },
275 275 {
276 276 "cell_type": "code",
277 277 "collapsed": false,
278 278 "input": [
279 279 "x = 1\n",
280 280 "y = 4\n",
281 281 "z = y/(1-x)"
282 282 ],
283 283 "language": "python",
284 284 "metadata": {},
285 285 "outputs": [
286 286 {
287 287 "ename": "ZeroDivisionError",
288 288 "evalue": "integer division or modulo by zero",
289 289 "output_type": "pyerr",
290 290 "traceback": [
291 291 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
292 292 "\u001b[0;32m<ipython-input-15-dc39888fd1d2>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mz\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
293 293 "\u001b[0;31mZeroDivisionError\u001b[0m: integer division or modulo by zero"
294 294 ]
295 295 }
296 296 ],
297 297 "prompt_number": 15
298 298 },
299 299 {
300 300 "cell_type": "heading",
301 301 "level": 2,
302 302 "metadata": {},
303 303 "source": [
304 304 "Working with external code"
305 305 ]
306 306 },
307 307 {
308 308 "cell_type": "markdown",
309 309 "metadata": {},
310 310 "source": [
311 311 "There are a number of ways of getting external code into code cells."
312 312 ]
313 313 },
314 314 {
315 315 "cell_type": "markdown",
316 316 "metadata": {},
317 317 "source": [
318 318 "Pasting code with `>>>` prompts works as expected:"
319 319 ]
320 320 },
321 321 {
322 322 "cell_type": "code",
323 323 "collapsed": false,
324 324 "input": [
325 325 ">>> the_world_is_flat = 1\n",
326 326 ">>> if the_world_is_flat:\n",
327 327 "... print(\"Be careful not to fall off!\")"
328 328 ],
329 329 "language": "python",
330 330 "metadata": {},
331 331 "outputs": [
332 332 {
333 333 "output_type": "stream",
334 334 "stream": "stdout",
335 335 "text": [
336 336 "Be careful not to fall off!\n"
337 337 ]
338 338 }
339 339 ],
340 340 "prompt_number": 1
341 341 },
342 342 {
343 343 "cell_type": "markdown",
344 344 "metadata": {},
345 345 "source": [
346 346 "The `%load` magic lets you load code from URLs or local files:"
347 347 ]
348 348 },
349 349 {
350 350 "cell_type": "code",
351 351 "collapsed": false,
352 352 "input": [
353 353 "%load?"
354 354 ],
355 355 "language": "python",
356 356 "metadata": {},
357 357 "outputs": [],
358 358 "prompt_number": 14
359 359 },
360 360 {
361 361 "cell_type": "code",
362 362 "collapsed": false,
363 363 "input": [
364 364 "%matplotlib inline"
365 365 ],
366 366 "language": "python",
367 367 "metadata": {},
368 368 "outputs": [],
369 369 "prompt_number": 1
370 370 },
371 371 {
372 372 "cell_type": "code",
373 373 "collapsed": false,
374 374 "input": [
375 375 "%load http://matplotlib.sourceforge.net/mpl_examples/pylab_examples/integral_demo.py"
376 376 ],
377 377 "language": "python",
378 378 "metadata": {},
379 379 "outputs": [],
380 380 "prompt_number": 2
381 381 },
382 382 {
383 383 "cell_type": "code",
384 384 "collapsed": false,
385 385 "input": [
386 386 "#!/usr/bin/env python\n",
387 387 "\n",
388 388 "# implement the example graphs/integral from pyx\n",
389 389 "from pylab import *\n",
390 390 "from matplotlib.patches import Polygon\n",
391 391 "\n",
392 392 "def func(x):\n",
393 393 " return (x-3)*(x-5)*(x-7)+85\n",
394 394 "\n",
395 395 "ax = subplot(111)\n",
396 396 "\n",
397 397 "a, b = 2, 9 # integral area\n",
398 398 "x = arange(0, 10, 0.01)\n",
399 399 "y = func(x)\n",
400 400 "plot(x, y, linewidth=1)\n",
401 401 "\n",
402 402 "# make the shaded region\n",
403 403 "ix = arange(a, b, 0.01)\n",
404 404 "iy = func(ix)\n",
405 405 "verts = [(a,0)] + list(zip(ix,iy)) + [(b,0)]\n",
406 406 "poly = Polygon(verts, facecolor='0.8', edgecolor='k')\n",
407 407 "ax.add_patch(poly)\n",
408 408 "\n",
409 409 "text(0.5 * (a + b), 30,\n",
410 410 " r\"$\\int_a^b f(x)\\mathrm{d}x$\", horizontalalignment='center',\n",
411 411 " fontsize=20)\n",
412 412 "\n",
413 413 "axis([0,10, 0, 180])\n",
414 414 "figtext(0.9, 0.05, 'x')\n",
415 415 "figtext(0.1, 0.9, 'y')\n",
416 416 "ax.set_xticks((a,b))\n",
417 417 "ax.set_xticklabels(('a','b'))\n",
418 418 "ax.set_yticks([])\n",
419 419 "show()\n"
420 420 ],
421 421 "language": "python",
422 422 "metadata": {},
423 423 "outputs": [
424 424 {
425 425 "metadata": {},
426 426 "output_type": "display_data",
427 427 "png": "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\nAAAAQvD/AKh2fy0Nfo/2AAAAAElFTkSuQmCC\n",
428 428 "text": [
429 429 "<matplotlib.figure.Figure at 0x110035290>"
430 430 ]
431 431 }
432 432 ],
433 433 "prompt_number": 3
434 434 }
435 435 ],
436 436 "metadata": {}
437 437 }
438 438 ]
439 } No newline at end of file
439 }
General Comments 0
You need to be logged in to leave comments. Login now