Show More
@@ -1,362 +1,371 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 | // Tooltip |
|
9 | // Tooltip | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | // |
|
11 | // | |
12 | // you can set the autocall time by setting `IPython.tooltip.time_before_tooltip` in ms |
|
12 | // you can set the autocall time by setting `IPython.tooltip.time_before_tooltip` in ms | |
13 | // |
|
13 | // | |
14 | // you can configure the differents action of pressing tab several times in a row by |
|
14 | // you can configure the differents action of pressing tab several times in a row by | |
15 | // setting/appending different fonction in the array |
|
15 | // setting/appending different fonction in the array | |
16 | // IPython.tooltip.tabs_functions |
|
16 | // IPython.tooltip.tabs_functions | |
17 | // |
|
17 | // | |
18 | // eg : |
|
18 | // eg : | |
19 | // IPython.tooltip.tabs_functions[4] = function(){console.log('this is the action of the 4th tab pressing')} |
|
19 | // IPython.tooltip.tabs_functions[4] = function(){console.log('this is the action of the 4th tab pressing')} | |
20 | // |
|
20 | // | |
21 |
|
21 | |||
22 | var IPython = (function (IPython) { |
|
22 | var IPython = (function (IPython) { | |
23 | "use strict"; |
|
23 | "use strict"; | |
24 |
|
24 | |||
25 | var utils = IPython.utils; |
|
25 | var utils = IPython.utils; | |
26 |
|
26 | |||
27 | // tooltip constructor |
|
27 | // tooltip constructor | |
28 | var Tooltip = function () { |
|
28 | var Tooltip = function () { | |
29 | var that = this; |
|
29 | var that = this; | |
30 | this.time_before_tooltip = 1200; |
|
30 | this.time_before_tooltip = 1200; | |
31 |
|
31 | |||
32 | // handle to html |
|
32 | // handle to html | |
33 | this.tooltip = $('#tooltip'); |
|
33 | this.tooltip = $('#tooltip'); | |
34 | this._hidden = true; |
|
34 | this._hidden = true; | |
35 |
|
35 | |||
36 | // variable for consecutive call |
|
36 | // variable for consecutive call | |
37 | this._old_cell = null ; |
|
37 | this._old_cell = null ; | |
38 | this._old_request = null ; |
|
38 | this._old_request = null ; | |
39 | this._consecutive_counter = 0; |
|
39 | this._consecutive_counter = 0; | |
40 |
|
40 | |||
41 | // 'sticky ?' |
|
41 | // 'sticky ?' | |
42 | this._sticky = false; |
|
42 | this._sticky = false; | |
43 |
|
43 | |||
44 | // contain the button in the upper right corner |
|
44 | // contain the button in the upper right corner | |
45 | this.buttons = $('<div/>') |
|
45 | this.buttons = $('<div/>') | |
46 | .addClass('tooltipbuttons'); |
|
46 | .addClass('tooltipbuttons'); | |
47 |
|
47 | |||
48 | // will contain the docstring |
|
48 | // will contain the docstring | |
49 | this.text = $('<div/>') |
|
49 | this.text = $('<div/>') | |
50 | .addClass('tooltiptext') |
|
50 | .addClass('tooltiptext') | |
51 | .addClass('smalltooltip'); |
|
51 | .addClass('smalltooltip'); | |
52 |
|
52 | |||
53 | // build the buttons menu on the upper right |
|
53 | // build the buttons menu on the upper right | |
54 |
|
54 | |||
55 | // expand the tooltip to see more |
|
55 | // expand the tooltip to see more | |
56 | var expandlink=$('<a/>').attr('href',"#") |
|
56 | var expandlink=$('<a/>').attr('href',"#") | |
57 | .addClass("ui-corner-all") //rounded corner |
|
57 | .addClass("ui-corner-all") //rounded corner | |
58 | .attr('role',"button") |
|
58 | .attr('role',"button") | |
59 | .attr('id','expanbutton') |
|
59 | .attr('id','expanbutton') | |
60 | .attr('title','Grow the tooltip vertically (press tab 2 times)') |
|
60 | .attr('title','Grow the tooltip vertically (press tab 2 times)') | |
61 | .click(function(){that.expand()}) |
|
61 | .click(function(){that.expand()}) | |
62 | .append( |
|
62 | .append( | |
63 | $('<span/>').text('Expand') |
|
63 | $('<span/>').text('Expand') | |
64 | .addClass('ui-icon') |
|
64 | .addClass('ui-icon') | |
65 | .addClass('ui-icon-plus') |
|
65 | .addClass('ui-icon-plus') | |
66 | ); |
|
66 | ); | |
67 |
|
67 | |||
68 | // open in pager |
|
68 | // open in pager | |
69 | var morelink=$('<a/>').attr('href',"#") |
|
69 | var morelink=$('<a/>').attr('href',"#") | |
70 | .attr('role',"button") |
|
70 | .attr('role',"button") | |
71 | .addClass('ui-button') |
|
71 | .addClass('ui-button') | |
72 | .attr('title','show the current docstring in pager (press tab 4 times)'); |
|
72 | .attr('title','show the current docstring in pager (press tab 4 times)'); | |
73 | var morespan=$('<span/>').text('Open in Pager') |
|
73 | var morespan=$('<span/>').text('Open in Pager') | |
74 | .addClass('ui-icon') |
|
74 | .addClass('ui-icon') | |
75 | .addClass('ui-icon-arrowstop-l-n'); |
|
75 | .addClass('ui-icon-arrowstop-l-n'); | |
76 | morelink.append(morespan); |
|
76 | morelink.append(morespan); | |
77 | morelink.click(function(){ |
|
77 | morelink.click(function(){ | |
78 | that.showInPager(); |
|
78 | that.showInPager(); | |
79 | }); |
|
79 | }); | |
80 |
|
80 | |||
81 | // close the tooltip |
|
81 | // close the tooltip | |
82 | var closelink=$('<a/>').attr('href',"#") |
|
82 | var closelink=$('<a/>').attr('href',"#") | |
83 | .attr('role',"button") |
|
83 | .attr('role',"button") | |
84 | .addClass('ui-button'); |
|
84 | .addClass('ui-button'); | |
85 | var closespan=$('<span/>').text('Close') |
|
85 | var closespan=$('<span/>').text('Close') | |
86 | .addClass('ui-icon') |
|
86 | .addClass('ui-icon') | |
87 | .addClass('ui-icon-close'); |
|
87 | .addClass('ui-icon-close'); | |
88 | closelink.append(closespan); |
|
88 | closelink.append(closespan); | |
89 | closelink.click(function(){ |
|
89 | closelink.click(function(){ | |
90 | that.remove_and_cancel_tooltip(true); |
|
90 | that.remove_and_cancel_tooltip(true); | |
91 | }); |
|
91 | }); | |
92 |
|
92 | |||
93 | this._clocklink=$('<a/>').attr('href',"#"); |
|
93 | this._clocklink=$('<a/>').attr('href',"#"); | |
94 | this._clocklink.attr('role',"button"); |
|
94 | this._clocklink.attr('role',"button"); | |
95 | this._clocklink.addClass('ui-button'); |
|
95 | this._clocklink.addClass('ui-button'); | |
96 | this._clocklink.attr('title','Tootip is not dismissed while typing for 10 seconds'); |
|
96 | this._clocklink.attr('title','Tootip is not dismissed while typing for 10 seconds'); | |
97 | var clockspan=$('<span/>').text('Close'); |
|
97 | var clockspan=$('<span/>').text('Close'); | |
98 | clockspan.addClass('ui-icon'); |
|
98 | clockspan.addClass('ui-icon'); | |
99 | clockspan.addClass('ui-icon-clock'); |
|
99 | clockspan.addClass('ui-icon-clock'); | |
100 | this._clocklink.append(clockspan); |
|
100 | this._clocklink.append(clockspan); | |
101 | this._clocklink.click(function(){ |
|
101 | this._clocklink.click(function(){ | |
102 | that.cancel_stick(); |
|
102 | that.cancel_stick(); | |
103 | }); |
|
103 | }); | |
104 |
|
104 | |||
105 |
|
105 | |||
106 |
|
106 | |||
107 |
|
107 | |||
108 | //construct the tooltip |
|
108 | //construct the tooltip | |
109 | // add in the reverse order you want them to appear |
|
109 | // add in the reverse order you want them to appear | |
110 | this.buttons.append(closelink); |
|
110 | this.buttons.append(closelink); | |
111 | this.buttons.append(expandlink); |
|
111 | this.buttons.append(expandlink); | |
112 | this.buttons.append(morelink); |
|
112 | this.buttons.append(morelink); | |
113 | this.buttons.append(this._clocklink); |
|
113 | this.buttons.append(this._clocklink); | |
114 | this._clocklink.hide(); |
|
114 | this._clocklink.hide(); | |
115 |
|
115 | |||
116 |
|
116 | |||
117 | // we need a phony element to make the small arrow |
|
117 | // we need a phony element to make the small arrow | |
118 | // of the tooltip in css |
|
118 | // of the tooltip in css | |
119 | // we will move the arrow later |
|
119 | // we will move the arrow later | |
120 | this.arrow = $('<div/>').addClass('pretooltiparrow'); |
|
120 | this.arrow = $('<div/>').addClass('pretooltiparrow'); | |
121 | this.tooltip.append(this.buttons); |
|
121 | this.tooltip.append(this.buttons); | |
122 | this.tooltip.append(this.arrow); |
|
122 | this.tooltip.append(this.arrow); | |
123 | this.tooltip.append(this.text); |
|
123 | this.tooltip.append(this.text); | |
124 |
|
124 | |||
125 | // function that will be called if you press tab 1, 2, 3... times in a row |
|
125 | // function that will be called if you press tab 1, 2, 3... times in a row | |
126 |
this.tabs_functions = [ function(cell,text){ |
|
126 | this.tabs_functions = [ function(cell,text){ | |
127 |
|
|
127 | that._request_tooltip(cell,text); | |
128 | function(){that.stick()}, |
|
128 | IPython.notification_widget.set_message('tab again to expand pager',2500); | |
|
129 | }, | |||
|
130 | function(){ | |||
|
131 | that.expand(); | |||
|
132 | IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500); | |||
|
133 | }, | |||
|
134 | function(){ | |||
|
135 | that.stick(); | |||
|
136 | IPython.notification_widget.set_message('tab again to open help in pager',2500); | |||
|
137 | }, | |||
129 | function(cell){ |
|
138 | function(cell){ | |
130 | that.cancel_stick(); |
|
139 | that.cancel_stick(); | |
131 | that.showInPager(cell); |
|
140 | that.showInPager(cell); | |
132 | that._cmfocus(); |
|
141 | that._cmfocus(); | |
133 | } |
|
142 | } | |
134 | ]; |
|
143 | ]; | |
135 | // call after all the tabs function above have bee call to clean their effects |
|
144 | // call after all the tabs function above have bee call to clean their effects | |
136 | // if necessary |
|
145 | // if necessary | |
137 | this.reset_tabs_function = function(cell,text){ |
|
146 | this.reset_tabs_function = function(cell,text){ | |
138 | this._old_cell = (cell)? cell : null ; |
|
147 | this._old_cell = (cell)? cell : null ; | |
139 | this._old_request = (text) ? text : null ; |
|
148 | this._old_request = (text) ? text : null ; | |
140 | this._consecutive_counter = 0; |
|
149 | this._consecutive_counter = 0; | |
141 | } |
|
150 | } | |
142 | }; |
|
151 | }; | |
143 |
|
152 | |||
144 | Tooltip.prototype.showInPager = function(cell) |
|
153 | Tooltip.prototype.showInPager = function(cell) | |
145 | { |
|
154 | { | |
146 | // reexecute last call in pager by appending ? to show back in pager |
|
155 | // reexecute last call in pager by appending ? to show back in pager | |
147 | var that = this; |
|
156 | var that = this; | |
148 | var empty = function(){}; |
|
157 | var empty = function(){}; | |
149 | IPython.notebook.kernel.execute( |
|
158 | IPython.notebook.kernel.execute( | |
150 | that.name+'?', |
|
159 | that.name+'?', | |
151 | {'execute_reply':empty,'output':empty,'clear_output':empty,'cell':cell}, |
|
160 | {'execute_reply':empty,'output':empty,'clear_output':empty,'cell':cell}, | |
152 | {'silent':false} |
|
161 | {'silent':false} | |
153 | ); |
|
162 | ); | |
154 | this.remove_and_cancel_tooltip(); |
|
163 | this.remove_and_cancel_tooltip(); | |
155 | this._cmfocus(); |
|
164 | this._cmfocus(); | |
156 | } |
|
165 | } | |
157 |
|
166 | |||
158 | // grow the tooltip verticaly |
|
167 | // grow the tooltip verticaly | |
159 | Tooltip.prototype.expand = function(){ |
|
168 | Tooltip.prototype.expand = function(){ | |
160 | this.text.removeClass('smalltooltip'); |
|
169 | this.text.removeClass('smalltooltip'); | |
161 | this.text.addClass('bigtooltip'); |
|
170 | this.text.addClass('bigtooltip'); | |
162 | $('#expanbutton').hide('slow'); |
|
171 | $('#expanbutton').hide('slow'); | |
163 | this._cmfocus(); |
|
172 | this._cmfocus(); | |
164 | } |
|
173 | } | |
165 |
|
174 | |||
166 | // deal with all the logic of hiding the tooltip |
|
175 | // deal with all the logic of hiding the tooltip | |
167 | // and reset it's status |
|
176 | // and reset it's status | |
168 | Tooltip.prototype.hide = function() |
|
177 | Tooltip.prototype.hide = function() | |
169 | { |
|
178 | { | |
170 | this.tooltip.addClass('hide'); |
|
179 | this.tooltip.addClass('hide'); | |
171 | $('#expanbutton').show('slow'); |
|
180 | $('#expanbutton').show('slow'); | |
172 | this.text.removeClass('bigtooltip'); |
|
181 | this.text.removeClass('bigtooltip'); | |
173 | this.text.addClass('smalltooltip'); |
|
182 | this.text.addClass('smalltooltip'); | |
174 | // keep scroll top to be sure to always see the first line |
|
183 | // keep scroll top to be sure to always see the first line | |
175 | this.text.scrollTop(0); |
|
184 | this.text.scrollTop(0); | |
176 | this._hidden = true; |
|
185 | this._hidden = true; | |
177 | } |
|
186 | } | |
178 |
|
187 | |||
179 | Tooltip.prototype.remove_and_cancel_tooltip = function(force) { |
|
188 | Tooltip.prototype.remove_and_cancel_tooltip = function(force) { | |
180 | // note that we don't handle closing directly inside the calltip |
|
189 | // note that we don't handle closing directly inside the calltip | |
181 | // as in the completer, because it is not focusable, so won't |
|
190 | // as in the completer, because it is not focusable, so won't | |
182 | // get the event. |
|
191 | // get the event. | |
183 | if(this._sticky == false || force == true) |
|
192 | if(this._sticky == false || force == true) | |
184 | { |
|
193 | { | |
185 | this.hide(); |
|
194 | this.hide(); | |
186 | } |
|
195 | } | |
187 | this.cancel_pending(); |
|
196 | this.cancel_pending(); | |
188 | this.reset_tabs_function(); |
|
197 | this.reset_tabs_function(); | |
189 | } |
|
198 | } | |
190 |
|
199 | |||
191 | // cancel autocall done after '(' for example. |
|
200 | // cancel autocall done after '(' for example. | |
192 | Tooltip.prototype.cancel_pending = function(){ |
|
201 | Tooltip.prototype.cancel_pending = function(){ | |
193 | if (this._tooltip_timeout != null){ |
|
202 | if (this._tooltip_timeout != null){ | |
194 | clearTimeout(this._tooltip_timeout); |
|
203 | clearTimeout(this._tooltip_timeout); | |
195 | this._tooltip_timeout = null; |
|
204 | this._tooltip_timeout = null; | |
196 | } |
|
205 | } | |
197 | } |
|
206 | } | |
198 |
|
207 | |||
199 | // will trigger tooltip after timeout |
|
208 | // will trigger tooltip after timeout | |
200 | Tooltip.prototype.pending = function(cell) |
|
209 | Tooltip.prototype.pending = function(cell) | |
201 | { |
|
210 | { | |
202 | var that = this; |
|
211 | var that = this; | |
203 | this._tooltip_timeout = setTimeout(function(){that.request(cell)} , that.time_before_tooltip); |
|
212 | this._tooltip_timeout = setTimeout(function(){that.request(cell)} , that.time_before_tooltip); | |
204 | } |
|
213 | } | |
205 |
|
214 | |||
206 | Tooltip.prototype._request_tooltip = function(cell,func) |
|
215 | Tooltip.prototype._request_tooltip = function(cell,func) | |
207 | { |
|
216 | { | |
208 | // use internally just to make the request to the kernel |
|
217 | // use internally just to make the request to the kernel | |
209 |
|
218 | |||
210 | // Feel free to shorten this logic if you are better |
|
219 | // Feel free to shorten this logic if you are better | |
211 | // than me in regEx |
|
220 | // than me in regEx | |
212 | // basicaly you shoul be able to get xxx.xxx.xxx from |
|
221 | // basicaly you shoul be able to get xxx.xxx.xxx from | |
213 | // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2, |
|
222 | // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2, | |
214 | // remove everything between matchin bracket (need to iterate) |
|
223 | // remove everything between matchin bracket (need to iterate) | |
215 | var matchBracket = /\([^\(\)]+\)/g; |
|
224 | var matchBracket = /\([^\(\)]+\)/g; | |
216 | var endBracket = /\([^\(]*$/g; |
|
225 | var endBracket = /\([^\(]*$/g; | |
217 | var oldfunc = func; |
|
226 | var oldfunc = func; | |
218 |
|
227 | |||
219 | func = func.replace(matchBracket,""); |
|
228 | func = func.replace(matchBracket,""); | |
220 | while( oldfunc != func ) |
|
229 | while( oldfunc != func ) | |
221 | { |
|
230 | { | |
222 | oldfunc = func; |
|
231 | oldfunc = func; | |
223 | func = func.replace(matchBracket,""); |
|
232 | func = func.replace(matchBracket,""); | |
224 | } |
|
233 | } | |
225 | // remove everything after last open bracket |
|
234 | // remove everything after last open bracket | |
226 | func = func.replace(endBracket,""); |
|
235 | func = func.replace(endBracket,""); | |
227 |
|
236 | |||
228 | var re = /[a-z_][0-9a-z._]+$/gi; // casse insensitive |
|
237 | var re = /[a-z_][0-9a-z._]+$/gi; // casse insensitive | |
229 | var callbacks = {'object_info_reply': $.proxy(this.show,this)} |
|
238 | var callbacks = {'object_info_reply': $.proxy(this.show,this)} | |
230 | var msg_id = IPython.notebook.kernel.object_info_request(re.exec(func), callbacks); |
|
239 | var msg_id = IPython.notebook.kernel.object_info_request(re.exec(func), callbacks); | |
231 | } |
|
240 | } | |
232 |
|
241 | |||
233 | // make an imediate completion request |
|
242 | // make an imediate completion request | |
234 | Tooltip.prototype.request = function(cell) |
|
243 | Tooltip.prototype.request = function(cell) | |
235 | { |
|
244 | { | |
236 | // request(codecell) |
|
245 | // request(codecell) | |
237 | // Deal with extracting the text from the cell and counting |
|
246 | // Deal with extracting the text from the cell and counting | |
238 | // call in a row |
|
247 | // call in a row | |
239 |
|
248 | |||
240 | this.cancel_pending(); |
|
249 | this.cancel_pending(); | |
241 | var editor = cell.code_mirror; |
|
250 | var editor = cell.code_mirror; | |
242 | var cursor = editor.getCursor(); |
|
251 | var cursor = editor.getCursor(); | |
243 | var text = editor.getRange({line:cursor.line,ch:0},cursor).trim(); |
|
252 | var text = editor.getRange({line:cursor.line,ch:0},cursor).trim(); | |
244 |
|
253 | |||
245 | // need a permanent handel to codemirror for future auto recall |
|
254 | // need a permanent handel to codemirror for future auto recall | |
246 | this.code_mirror = editor; |
|
255 | this.code_mirror = editor; | |
247 |
|
256 | |||
248 | // now we treat the different number of keypress |
|
257 | // now we treat the different number of keypress | |
249 | // first if same cell, same text, increment counter by 1 |
|
258 | // first if same cell, same text, increment counter by 1 | |
250 | if( this._old_cell == cell && this._old_request == text && this._hidden == false) |
|
259 | if( this._old_cell == cell && this._old_request == text && this._hidden == false) | |
251 | { |
|
260 | { | |
252 | this._consecutive_counter++; |
|
261 | this._consecutive_counter++; | |
253 | } else { |
|
262 | } else { | |
254 | // else reset |
|
263 | // else reset | |
255 | this.cancel_stick(); |
|
264 | this.cancel_stick(); | |
256 | this.reset_tabs_function(cell,text); |
|
265 | this.reset_tabs_function(cell,text); | |
257 | } |
|
266 | } | |
258 |
|
267 | |||
259 | // don't do anything if line beggin with '(' or is empty |
|
268 | // don't do anything if line beggin with '(' or is empty | |
260 | if (text === "" || text === "(" ) { |
|
269 | if (text === "" || text === "(" ) { | |
261 | return; |
|
270 | return; | |
262 | } |
|
271 | } | |
263 |
|
272 | |||
264 | this.tabs_functions[this._consecutive_counter](cell,text); |
|
273 | this.tabs_functions[this._consecutive_counter](cell,text); | |
265 |
|
274 | |||
266 | // then if we are at the end of list function, reset |
|
275 | // then if we are at the end of list function, reset | |
267 | if (this._consecutive_counter == this.tabs_functions.length) |
|
276 | if (this._consecutive_counter == this.tabs_functions.length) | |
268 | this.reset_tabs_function(cell,text); |
|
277 | this.reset_tabs_function(cell,text); | |
269 |
|
278 | |||
270 | return; |
|
279 | return; | |
271 | } |
|
280 | } | |
272 |
|
281 | |||
273 | // cancel the option of having the tooltip to stick |
|
282 | // cancel the option of having the tooltip to stick | |
274 | Tooltip.prototype.cancel_stick = function() |
|
283 | Tooltip.prototype.cancel_stick = function() | |
275 | { |
|
284 | { | |
276 | clearTimeout(this._stick_timeout); |
|
285 | clearTimeout(this._stick_timeout); | |
277 | this._stick_timeout = null; |
|
286 | this._stick_timeout = null; | |
278 | this._clocklink.hide('slow'); |
|
287 | this._clocklink.hide('slow'); | |
279 | this._sticky = false; |
|
288 | this._sticky = false; | |
280 | } |
|
289 | } | |
281 |
|
290 | |||
282 | // put the tooltip in a sicky state for 10 seconds |
|
291 | // put the tooltip in a sicky state for 10 seconds | |
283 | // it won't be removed by remove_and_cancell() unless you called with |
|
292 | // it won't be removed by remove_and_cancell() unless you called with | |
284 | // the first parameter set to true. |
|
293 | // the first parameter set to true. | |
285 | // remove_and_cancell_tooltip(true) |
|
294 | // remove_and_cancell_tooltip(true) | |
286 | Tooltip.prototype.stick = function() |
|
295 | Tooltip.prototype.stick = function() | |
287 | { |
|
296 | { | |
288 | var that = this; |
|
297 | var that = this; | |
289 | this._sticky = true; |
|
298 | this._sticky = true; | |
290 | this._clocklink.show('slow'); |
|
299 | this._clocklink.show('slow'); | |
291 | this._stick_timeout = setTimeout( function(){ |
|
300 | this._stick_timeout = setTimeout( function(){ | |
292 | that._sticky = false; |
|
301 | that._sticky = false; | |
293 | that._clocklink.hide('slow'); |
|
302 | that._clocklink.hide('slow'); | |
294 | }, 10*1000 |
|
303 | }, 10*1000 | |
295 | ); |
|
304 | ); | |
296 | } |
|
305 | } | |
297 |
|
306 | |||
298 | // should be called with the kernel reply to actually show the tooltip |
|
307 | // should be called with the kernel reply to actually show the tooltip | |
299 | Tooltip.prototype.show = function(reply) |
|
308 | Tooltip.prototype.show = function(reply) | |
300 | { |
|
309 | { | |
301 | // move the bubble if it is not hidden |
|
310 | // move the bubble if it is not hidden | |
302 | // otherwise fade it |
|
311 | // otherwise fade it | |
303 | this.name = reply.name; |
|
312 | this.name = reply.name; | |
304 |
|
313 | |||
305 | // do some math to have the tooltip arrow on more or less on left or right |
|
314 | // do some math to have the tooltip arrow on more or less on left or right | |
306 | // width of the editor |
|
315 | // width of the editor | |
307 | var w = $(this.code_mirror.getScrollerElement()).width(); |
|
316 | var w = $(this.code_mirror.getScrollerElement()).width(); | |
308 | // ofset of the editor |
|
317 | // ofset of the editor | |
309 | var o = $(this.code_mirror.getScrollerElement()).offset(); |
|
318 | var o = $(this.code_mirror.getScrollerElement()).offset(); | |
310 | var pos = this.code_mirror.cursorCoords(); |
|
319 | var pos = this.code_mirror.cursorCoords(); | |
311 | var xinit = pos.x; |
|
320 | var xinit = pos.x; | |
312 | var xinter = o.left + (xinit-o.left)/w*(w-450); |
|
321 | var xinter = o.left + (xinit-o.left)/w*(w-450); | |
313 | var posarrowleft = xinit - xinter; |
|
322 | var posarrowleft = xinit - xinter; | |
314 |
|
323 | |||
315 |
|
324 | |||
316 | if( this._hidden == false) |
|
325 | if( this._hidden == false) | |
317 | { |
|
326 | { | |
318 | this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'}); |
|
327 | this.tooltip.animate({'left' : xinter-30+'px','top' :(pos.yBot+10)+'px'}); | |
319 | } else |
|
328 | } else | |
320 | { |
|
329 | { | |
321 | this.tooltip.css({'left' : xinter-30+'px'}); |
|
330 | this.tooltip.css({'left' : xinter-30+'px'}); | |
322 | this.tooltip.css({'top' :(pos.yBot+10)+'px'}); |
|
331 | this.tooltip.css({'top' :(pos.yBot+10)+'px'}); | |
323 | } |
|
332 | } | |
324 | this.arrow.animate({'left' : posarrowleft+'px'}); |
|
333 | this.arrow.animate({'left' : posarrowleft+'px'}); | |
325 | this.tooltip.removeClass('hidden') |
|
334 | this.tooltip.removeClass('hidden') | |
326 | this.tooltip.removeClass('hide'); |
|
335 | this.tooltip.removeClass('hide'); | |
327 | this._hidden = false; |
|
336 | this._hidden = false; | |
328 |
|
337 | |||
329 | // build docstring |
|
338 | // build docstring | |
330 | var defstring = reply.call_def; |
|
339 | var defstring = reply.call_def; | |
331 | if (defstring == null) { defstring = reply.init_definition; } |
|
340 | if (defstring == null) { defstring = reply.init_definition; } | |
332 | if (defstring == null) { defstring = reply.definition; } |
|
341 | if (defstring == null) { defstring = reply.definition; } | |
333 |
|
342 | |||
334 | var docstring = reply.call_docstring; |
|
343 | var docstring = reply.call_docstring; | |
335 | if (docstring == null) { docstring = reply.init_docstring; } |
|
344 | if (docstring == null) { docstring = reply.init_docstring; } | |
336 | if (docstring == null) { docstring = reply.docstring; } |
|
345 | if (docstring == null) { docstring = reply.docstring; } | |
337 | if (docstring == null) { docstring = "<empty docstring>"; } |
|
346 | if (docstring == null) { docstring = "<empty docstring>"; } | |
338 |
|
347 | |||
339 | this.text.children().remove(); |
|
348 | this.text.children().remove(); | |
340 |
|
349 | |||
341 | var pre=$('<pre/>').html(utils.fixConsole(docstring)); |
|
350 | var pre=$('<pre/>').html(utils.fixConsole(docstring)); | |
342 | if(defstring){ |
|
351 | if(defstring){ | |
343 | var defstring_html = $('<pre/>').html(utils.fixConsole(defstring)); |
|
352 | var defstring_html = $('<pre/>').html(utils.fixConsole(defstring)); | |
344 | this.text.append(defstring_html); |
|
353 | this.text.append(defstring_html); | |
345 | } |
|
354 | } | |
346 | this.text.append(pre); |
|
355 | this.text.append(pre); | |
347 | // keep scroll top to be sure to always see the first line |
|
356 | // keep scroll top to be sure to always see the first line | |
348 | this.text.scrollTop(0); |
|
357 | this.text.scrollTop(0); | |
349 | } |
|
358 | } | |
350 |
|
359 | |||
351 | // convenient funciton to have the correct codemirror back into focus |
|
360 | // convenient funciton to have the correct codemirror back into focus | |
352 | Tooltip.prototype._cmfocus = function() |
|
361 | Tooltip.prototype._cmfocus = function() | |
353 | { |
|
362 | { | |
354 | var cm = this.code_mirror; |
|
363 | var cm = this.code_mirror; | |
355 | setTimeout(function(){cm.focus();}, 50); |
|
364 | setTimeout(function(){cm.focus();}, 50); | |
356 | } |
|
365 | } | |
357 |
|
366 | |||
358 | IPython.Tooltip = Tooltip; |
|
367 | IPython.Tooltip = Tooltip; | |
359 |
|
368 | |||
360 | return IPython; |
|
369 | return IPython; | |
361 |
|
370 | |||
362 | }(IPython)); |
|
371 | }(IPython)); |
@@ -1,419 +1,482 b'' | |||||
1 | { |
|
1 | { | |
2 | "metadata": { |
|
2 | "metadata": { | |
3 | "name": "01_notebook_introduction" |
|
3 | "name": "01_notebook_introduction" | |
4 | }, |
|
4 | }, | |
5 | "nbformat": 3, |
|
5 | "nbformat": 3, | |
6 | "worksheets": [ |
|
6 | "worksheets": [ | |
7 | { |
|
7 | { | |
8 | "cells": [ |
|
8 | "cells": [ | |
9 | { |
|
9 | { | |
10 | "cell_type": "markdown", |
|
10 | "cell_type": "markdown", | |
11 | "source": [ |
|
11 | "source": [ | |
12 | "# An introduction to the IPython notebook", |
|
12 | "# An introduction to the IPython notebook", | |
13 | "", |
|
13 | "", | |
14 | "The IPython web notebook is a frontend that allows for new modes", |
|
14 | "The IPython web notebook is a frontend that allows for new modes", | |
15 | "of interaction with IPython: this web-based interface allows you to execute Python and IPython", |
|
15 | "of interaction with IPython: this web-based interface allows you to execute Python and IPython", | |
16 | "commands in each input cell just like you would at the IPython terminal or Qt console, but you can", |
|
16 | "commands in each input cell just like you would at the IPython terminal or Qt console, but you can", | |
17 | "also save an entire session as a document in a file with the `.ipynb` extension.", |
|
17 | "also save an entire session as a document in a file with the `.ipynb` extension.", | |
18 | "", |
|
18 | "", | |
19 | "The document you are reading now is precisely an example of one such notebook, and we will show you", |
|
19 | "The document you are reading now is precisely an example of one such notebook, and we will show you", | |
20 | "here how to best use this new interface.", |
|
20 | "here how to best use this new interface.", | |
21 | "", |
|
21 | "", | |
22 | "The first thing to understand is that a notebook consists of a sequence of 'cells' that can contain ", |
|
22 | "The first thing to understand is that a notebook consists of a sequence of 'cells' that can contain ", | |
23 | "either text (such as this one) or code meant for execution (such as the next one):", |
|
23 | "either text (such as this one) or code meant for execution (such as the next one):", | |
24 | "", |
|
24 | "", | |
25 | "* Text cells can be written using [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) ", |
|
25 | "* Text cells can be written using [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) ", | |
26 | "(in a future release we will also provide support for reStructuredText and Sphinx integration, and we ", |
|
26 | "(in a future release we will also provide support for reStructuredText and Sphinx integration, and we ", | |
27 | "welcome help from interested contributors to make that happen).", |
|
27 | "welcome help from interested contributors to make that happen).", | |
28 | "", |
|
28 | "", | |
29 | "* Code cells take IPython input (i.e. Python code, `%magics`, `!system calls`, etc) like IPython at", |
|
29 | "* Code cells take IPython input (i.e. Python code, `%magics`, `!system calls`, etc) like IPython at", | |
30 | "the terminal or at the Qt Console. The only difference is that in order to execute a cell, you *must*", |
|
30 | "the terminal or at the Qt Console. The only difference is that in order to execute a cell, you *must*", | |
31 | "use `Shift-Enter`, as pressing `Enter` will add a new line of text to the cell. When you type ", |
|
31 | "use `Shift-Enter`, as pressing `Enter` will add a new line of text to the cell. When you type ", | |
32 | "`Shift-Enter`, the cell content is executed, output displayed and a new cell is created below. Try", |
|
32 | "`Shift-Enter`, the cell content is executed, output displayed and a new cell is created below. Try", | |
33 | "it now by putting your cursor on the next cell and typing `Shift-Enter`:" |
|
33 | "it now by putting your cursor on the next cell and typing `Shift-Enter`:" | |
34 | ] |
|
34 | ] | |
35 | }, |
|
35 | }, | |
36 | { |
|
36 | { | |
37 | "cell_type": "code", |
|
37 | "cell_type": "code", | |
38 | "collapsed": false, |
|
|||
39 | "input": [ |
|
38 | "input": [ | |
40 | "\"This is the new IPython notebook\"" |
|
39 | "\"This is the new IPython notebook\"" | |
41 | ], |
|
40 | ], | |
42 | "language": "python", |
|
41 | "language": "python", | |
43 | "outputs": [ |
|
42 | "outputs": [ | |
44 | { |
|
43 | { | |
45 | "output_type": "pyout", |
|
44 | "output_type": "pyout", | |
46 | "prompt_number": 1, |
|
45 | "prompt_number": 1, | |
47 | "text": [ |
|
46 | "text": [ | |
48 | "'This is the new IPython notebook'" |
|
47 | "'This is the new IPython notebook'" | |
49 | ] |
|
48 | ] | |
50 | } |
|
49 | } | |
51 | ], |
|
50 | ], | |
52 | "prompt_number": 1 |
|
51 | "prompt_number": 1 | |
53 | }, |
|
52 | }, | |
54 | { |
|
53 | { | |
55 | "cell_type": "markdown", |
|
54 | "cell_type": "markdown", | |
56 | "source": [ |
|
55 | "source": [ | |
57 | "You can re-execute the same cell over and over as many times as you want. Simply put your", |
|
56 | "You can re-execute the same cell over and over as many times as you want. Simply put your", | |
58 | "cursor in the cell again, edit at will, and type `Shift-Enter` to execute. ", |
|
57 | "cursor in the cell again, edit at will, and type `Shift-Enter` to execute. ", | |
59 | "", |
|
58 | "", | |
60 | "**Tip:** A cell can also be executed", |
|
59 | "**Tip:** A cell can also be executed", | |
61 | "*in-place*, where IPython executes its content but leaves the cursor in the same cell. This is done by", |
|
60 | "*in-place*, where IPython executes its content but leaves the cursor in the same cell. This is done by", | |
62 | "typing `Ctrl-Enter` instead, and is useful if you want to quickly run a command to check something ", |
|
61 | "typing `Ctrl-Enter` instead, and is useful if you want to quickly run a command to check something ", | |
63 | "before tping the real content you want to leave in the cell. For example, in the next cell, try issuing", |
|
62 | "before tping the real content you want to leave in the cell. For example, in the next cell, try issuing", | |
64 | "several system commands in-place with `Ctrl-Enter`, such as `pwd` and then `ls`:" |
|
63 | "several system commands in-place with `Ctrl-Enter`, such as `pwd` and then `ls`:" | |
65 | ] |
|
64 | ] | |
66 | }, |
|
65 | }, | |
67 | { |
|
66 | { | |
68 | "cell_type": "code", |
|
67 | "cell_type": "code", | |
69 | "collapsed": false, |
|
|||
70 | "input": [ |
|
68 | "input": [ | |
71 | "ls" |
|
69 | "ls" | |
72 | ], |
|
70 | ], | |
73 | "language": "python", |
|
71 | "language": "python", | |
74 | "outputs": [ |
|
72 | "outputs": [ | |
75 | { |
|
73 | { | |
76 | "output_type": "stream", |
|
74 | "output_type": "stream", | |
77 | "stream": "stdout", |
|
75 | "stream": "stdout", | |
78 | "text": [ |
|
76 | "text": [ | |
79 | "00_notebook_tour.ipynb formatting.ipynb sympy_quantum_computing.ipynb", |
|
77 | "00_notebook_tour.ipynb formatting.ipynb sympy_quantum_computing.ipynb", | |
80 | "01_notebook_introduction.ipynb python-logo.svg trapezoid_rule.ipynb", |
|
78 | "01_notebook_introduction.ipynb python-logo.svg trapezoid_rule.ipynb", | |
81 | "display_protocol.ipynb sympy.ipynb" |
|
79 | "display_protocol.ipynb sympy.ipynb" | |
82 | ] |
|
80 | ] | |
83 | } |
|
81 | } | |
84 | ], |
|
82 | ], | |
85 | "prompt_number": 2 |
|
83 | "prompt_number": 2 | |
86 | }, |
|
84 | }, | |
87 | { |
|
85 | { | |
88 | "cell_type": "markdown", |
|
86 | "cell_type": "markdown", | |
89 | "source": [ |
|
87 | "source": [ | |
90 | "In a cell, you can type anything from a single python expression to an arbitrarily long amount of code ", |
|
88 | "In a cell, you can type anything from a single python expression to an arbitrarily long amount of code ", | |
91 | "(although for reasons of readability, you should probably limit this to a few dozen lines):" |
|
89 | "(although for reasons of readability, you should probably limit this to a few dozen lines):" | |
92 | ] |
|
90 | ] | |
93 | }, |
|
91 | }, | |
94 | { |
|
92 | { | |
95 | "cell_type": "code", |
|
93 | "cell_type": "code", | |
96 | "collapsed": false, |
|
|||
97 | "input": [ |
|
94 | "input": [ | |
98 | "def f(x):", |
|
95 | "def f(x):", | |
99 | " \"\"\"My function", |
|
96 | " \"\"\"My function", | |
100 | " x : parameter\"\"\"", |
|
97 | " x : parameter\"\"\"", | |
101 | " ", |
|
98 | " ", | |
102 | " return x+1", |
|
99 | " return x+1", | |
103 | "", |
|
100 | "", | |
104 | "print \"f(3) = \", f(3)" |
|
101 | "print \"f(3) = \", f(3)" | |
105 | ], |
|
102 | ], | |
106 | "language": "python", |
|
103 | "language": "python", | |
107 | "outputs": [ |
|
104 | "outputs": [ | |
108 | { |
|
105 | { | |
109 | "output_type": "stream", |
|
106 | "output_type": "stream", | |
110 | "stream": "stdout", |
|
107 | "stream": "stdout", | |
111 | "text": [ |
|
108 | "text": [ | |
112 | "f(3) = 4" |
|
109 | "f(3) = 4" | |
113 | ] |
|
110 | ] | |
114 | } |
|
111 | } | |
115 | ], |
|
112 | ], | |
116 | "prompt_number": 3 |
|
113 | "prompt_number": 3 | |
117 | }, |
|
114 | }, | |
118 | { |
|
115 | { | |
119 | "cell_type": "markdown", |
|
116 | "cell_type": "markdown", | |
120 | "source": [ |
|
117 | "source": [ | |
121 | "## User interface", |
|
118 | "## User interface", | |
122 | "", |
|
119 | "", | |
123 | "When you start a new notebook server with `ipython notebook`, your", |
|
120 | "When you start a new notebook server with `ipython notebook`, your", | |
124 | "browser should open into the *Dashboard*, a page listing all notebooks", |
|
121 | "browser should open into the *Dashboard*, a page listing all notebooks", | |
125 | "available in the current directory as well as letting you create new", |
|
122 | "available in the current directory as well as letting you create new", | |
126 | "notebooks. In this page, you can also drag and drop existing `.py` files", |
|
123 | "notebooks. In this page, you can also drag and drop existing `.py` files", | |
127 | "over the file list to import them as notebooks (see the manual for ", |
|
124 | "over the file list to import them as notebooks (see the manual for ", | |
128 | "[further details on how these files are ", |
|
125 | "[further details on how these files are ", | |
129 | "interpreted](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html)).", |
|
126 | "interpreted](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html)).", | |
130 | "", |
|
127 | "", | |
131 | "Once you open an existing notebook (like this one) or create a new one,", |
|
128 | "Once you open an existing notebook (like this one) or create a new one,", | |
132 | "you are in the main notebook interface, which consists of a main editing", |
|
129 | "you are in the main notebook interface, which consists of a main editing", | |
133 | "area (where these cells are contained) as well as a collapsible left panel, ", |
|
130 | "area (where these cells are contained) as well as a collapsible left panel, ", | |
134 | "a permanent header area at the top, and a pager that rises from the", |
|
131 | "a permanent header area at the top, and a pager that rises from the", | |
135 | "bottom when needed and can be collapsed again." |
|
132 | "bottom when needed and can be collapsed again." | |
136 | ] |
|
133 | ] | |
137 | }, |
|
134 | }, | |
138 | { |
|
135 | { | |
139 | "cell_type": "markdown", |
|
136 | "cell_type": "markdown", | |
140 | "source": [ |
|
137 | "source": [ | |
141 | "### Main editing area", |
|
138 | "### Main editing area", | |
142 | "", |
|
139 | "", | |
143 | "Here, you can move with the arrow keys or using the ", |
|
140 | "Here, you can move with the arrow keys or using the ", | |
144 | "scroll bars. The cursor enters code cells immediately, but only selects", |
|
141 | "scroll bars. The cursor enters code cells immediately, but only selects", | |
145 | "text (markdown) cells without entering in them; to enter a text cell,", |
|
142 | "text (markdown) cells without entering in them; to enter a text cell,", | |
146 | "use `Enter`, and `Shift-Enter` to exit it again (just like to execute a ", |
|
143 | "use `Enter`, and `Shift-Enter` to exit it again (just like to execute a ", | |
147 | "code cell)." |
|
144 | "code cell)." | |
148 | ] |
|
145 | ] | |
149 | }, |
|
146 | }, | |
150 | { |
|
147 | { | |
151 | "cell_type": "markdown", |
|
148 | "cell_type": "markdown", | |
152 | "source": [ |
|
149 | "source": [ | |
153 | "### Left panel", |
|
150 | "### Left panel", | |
154 | "", |
|
151 | "", | |
155 | "This panel contains a number of panes that can be", |
|
152 | "This panel contains a number of panes that can be", | |
156 | "collapsed vertically by clicking on their title bar, and the whole panel", |
|
153 | "collapsed vertically by clicking on their title bar, and the whole panel", | |
157 | "can also be collapsed by clicking on the vertical divider (note that you", |
|
154 | "can also be collapsed by clicking on the vertical divider (note that you", | |
158 | "can not *drag* the divider, for now you can only click on it).", |
|
155 | "can not *drag* the divider, for now you can only click on it).", | |
159 | "", |
|
156 | "", | |
160 | "The *Notebook* section contains actions that pertain to the whole notebook,", |
|
157 | "The *Notebook* section contains actions that pertain to the whole notebook,", | |
161 | "such as downloading the current notebook either in its original format", |
|
158 | "such as downloading the current notebook either in its original format", | |
162 | "or as a `.py` script, and printing it. When you click the `Print` button,", |
|
159 | "or as a `.py` script, and printing it. When you click the `Print` button,", | |
163 | "a new HTML page opens with a static copy of the notebook; you can then", |
|
160 | "a new HTML page opens with a static copy of the notebook; you can then", | |
164 | "use your web browser's mechanisms to save or print this file.", |
|
161 | "use your web browser's mechanisms to save or print this file.", | |
165 | "", |
|
162 | "", | |
166 | "The *Cell* section lets you manipulate individual cells, and the names should ", |
|
163 | "The *Cell* section lets you manipulate individual cells, and the names should ", | |
167 | "be fairly self-explanatory.", |
|
164 | "be fairly self-explanatory.", | |
168 | "", |
|
165 | "", | |
169 | "The *Kernel* section lets you signal the kernel executing your code. ", |
|
166 | "The *Kernel* section lets you signal the kernel executing your code. ", | |
170 | "`Interrupt` does the equivalent of hitting `Ctrl-C` at a terminal, and", |
|
167 | "`Interrupt` does the equivalent of hitting `Ctrl-C` at a terminal, and", | |
171 | "`Restart` fully kills the kernel process and starts a fresh one. Obviously", |
|
168 | "`Restart` fully kills the kernel process and starts a fresh one. Obviously", | |
172 | "this means that all your previous variables are destroyed, but it also", |
|
169 | "this means that all your previous variables are destroyed, but it also", | |
173 | "makes it easy to get a fresh kernel in which to re-execute a notebook, perhaps", |
|
170 | "makes it easy to get a fresh kernel in which to re-execute a notebook, perhaps", | |
174 | "after changing an extension module for which Python's `reload` mechanism", |
|
171 | "after changing an extension module for which Python's `reload` mechanism", | |
175 | "does not work. If you check the 'Kill kernel upon exit' box, when you ", |
|
172 | "does not work. If you check the 'Kill kernel upon exit' box, when you ", | |
176 | "close the page IPython will automatically shut down the running kernel;", |
|
173 | "close the page IPython will automatically shut down the running kernel;", | |
177 | "otherwise the kernels won't close until you stop the whole ", |
|
174 | "otherwise the kernels won't close until you stop the whole ", | |
178 | "", |
|
175 | "", | |
179 | "The *Help* section contains links to the documentation of some projects", |
|
176 | "The *Help* section contains links to the documentation of some projects", | |
180 | "closely related to IPython as well as the minimal keybindings you need to", |
|
177 | "closely related to IPython as well as the minimal keybindings you need to", | |
181 | "know. But you should use `Ctrl-m h` (or click the `QuickHelp` button at", |
|
178 | "know. But you should use `Ctrl-m h` (or click the `QuickHelp` button at", | |
182 | "the top) and learn some of the other keybindings, as it will make your ", |
|
179 | "the top) and learn some of the other keybindings, as it will make your ", | |
183 |
"workflow much more fluid and efficient." |
|
180 | "workflow much more fluid and efficient." | |
184 | "", |
|
|||
185 | "The *Configuration* section at the bottom lets you change some values", |
|
|||
186 | "related to the display of tooltips and the behavior of the tab completer." |
|
|||
187 | ] |
|
181 | ] | |
188 | }, |
|
182 | }, | |
189 | { |
|
183 | { | |
190 | "cell_type": "markdown", |
|
184 | "cell_type": "markdown", | |
191 | "source": [ |
|
185 | "source": [ | |
192 | "### Header bar", |
|
186 | "### Header bar", | |
193 | "", |
|
187 | "", | |
194 | "The header area at the top allows you to rename an existing ", |
|
188 | "The header area at the top allows you to rename an existing ", | |
195 | "notebook and open up a short help tooltip. This area also indicates", |
|
189 | "notebook and open up a short help tooltip. This area also indicates", | |
196 | "with a red **Busy** mark on the right whenever the kernel is busy executing", |
|
190 | "with a red **Busy** mark on the right whenever the kernel is busy executing", | |
197 | "code." |
|
191 | "code." | |
198 | ] |
|
192 | ] | |
199 | }, |
|
193 | }, | |
200 | { |
|
194 | { | |
201 | "cell_type": "markdown", |
|
195 | "cell_type": "markdown", | |
202 | "source": [ |
|
196 | "source": [ | |
203 | "### The pager at the bottom", |
|
197 | "### The pager at the bottom", | |
204 | "", |
|
198 | "", | |
205 | "Whenever IPython needs to display additional ", |
|
199 | "Whenever IPython needs to display additional ", | |
206 | "information, such as when you type `somefunction?` in a cell, the notebook", |
|
200 | "information, such as when you type `somefunction?` in a cell, the notebook", | |
207 | "opens a pane at the bottom where this information is shown. You can keep", |
|
201 | "opens a pane at the bottom where this information is shown. You can keep", | |
208 | "this pager pane open for reference (it doesn't block input in the main area)", |
|
202 | "this pager pane open for reference (it doesn't block input in the main area)", | |
209 | "or dismiss it by clicking on its divider bar." |
|
203 | "or dismiss it by clicking on its divider bar." | |
210 | ] |
|
204 | ] | |
211 | }, |
|
205 | }, | |
212 | { |
|
206 | { | |
213 | "cell_type": "markdown", |
|
207 | "cell_type": "markdown", | |
214 | "source": [ |
|
208 | "source": [ | |
215 | "### Tab completion and tooltips", |
|
209 | "### Tab completion and tooltips", | |
216 | "", |
|
210 | "", | |
217 | "The notebook uses the same underlying machinery for tab completion that ", |
|
211 | "The notebook uses the same underlying machinery for tab completion that ", | |
218 | "IPython uses at the terminal, but displays the information differently.", |
|
212 | "IPython uses at the terminal, but displays the information differently.", | |
219 | "Whey you complete with the `Tab` key, IPython shows a drop list with all", |
|
213 | "Whey you complete with the `Tab` key, IPython shows a drop list with all", | |
220 | "available completions. If you type more characters while this list is open,", |
|
214 | "available completions. If you type more characters while this list is open,", | |
221 | "IPython automatically eliminates from the list options that don't match the", |
|
215 | "IPython automatically eliminates from the list options that don't match the", | |
222 | "new characters; once there is only one option left you can hit `Tab` once", |
|
216 | "new characters; once there is only one option left you can hit `Tab` once", | |
223 | "more (or `Enter`) to complete. You can also select the completion you", |
|
217 | "more (or `Enter`) to complete. You can also select the completion you", | |
224 | "want with the arrow keys or the mouse, and then hit `Enter`.", |
|
218 | "want with the arrow keys or the mouse, and then hit `Enter`.", | |
225 | "", |
|
219 | "", | |
226 | "In addition, if you hit `Tab` inside of open parentheses, IPython will ", |
|
220 | "In addition, if you hit `Tab` inside of open parentheses, IPython will ", | |
227 | "search for the docstring of the last object left of the parens and will", |
|
221 | "search for the docstring of the last object left of the parens and will", | |
228 | "display it on a tooltip. For example, type `list(<TAB>` and you will", |
|
222 | "display it on a tooltip. For example, type `list(<TAB>` and you will", | |
229 | "see the docstring for the builtin `list` constructor:" |
|
223 | "see the docstring for the builtin `list` constructor:" | |
230 | ] |
|
224 | ] | |
231 | }, |
|
225 | }, | |
232 | { |
|
226 | { | |
233 | "cell_type": "code", |
|
227 | "cell_type": "code", | |
234 | "collapsed": true, |
|
|||
235 | "input": [ |
|
228 | "input": [ | |
236 | "# Position your cursor after the ( and hit the Tab key:", |
|
229 | "# Position your cursor after the ( and hit the Tab key:", | |
237 |
" |
|
230 | "range(" | |
238 | ], |
|
231 | ], | |
239 | "language": "python", |
|
232 | "language": "python", | |
240 | "outputs": [] |
|
233 | "outputs": [] | |
241 | }, |
|
234 | }, | |
242 | { |
|
235 | { | |
243 | "cell_type": "markdown", |
|
236 | "cell_type": "markdown", | |
244 | "source": [ |
|
237 | "source": [ | |
|
238 | "More over pressing tab several time in a row allows you change the behaviour of the tooltip.", | |||
|
239 | "", | |||
|
240 | "* firt `tab` press, you get a classical tooltip", | |||
|
241 | "* second time, the tooltip grow vertically, and allow you to scroll the docstring", | |||
|
242 | "* third tab press, tooltip, will be made sticky for 10 seconds, allowing you to carry on typing while it stays open.", | |||
|
243 | "* forth time press, the tooltip help is sent to the pager at the bottom of the screen , and is dismiss.", | |||
|
244 | "<script>", | |||
|
245 | " IPython.tooltip.tabs_functions = [ function(cell,text){", | |||
|
246 | " IPython.tooltip._request_tooltip(cell,text);", | |||
|
247 | " IPython.notification_widget.set_message('tab again to expand pager',2500);", | |||
|
248 | " setTimeout(function(){", | |||
|
249 | " $('.tooltiptext pre').text(\"function signture : You've invoked a tooltip !\\n\\nWell done! Here usualy lies the current function *call signature* and it's *docstring*. You can now expand the tooltip pressing <tab> a second time...\")},400);", | |||
|
250 | " },", | |||
|
251 | " function(){", | |||
|
252 | " IPython.tooltip.expand();", | |||
|
253 | " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);", | |||
|
254 | " setTimeout(function(){", | |||
|
255 | " $('.tooltiptext pre').text(\"Now the tooltip is expanded !\\", | |||
|
256 | " \\n\\nThis is really usefull if you have long docstring and if you want to be able to scroll them. \\", | |||
|
257 | "For example, I can give you many information about the tooltip:\\n - The tooltip is smart, and \\", | |||
|
258 | "you don't always need to press tab to invoke it, if you press an opening bracket `(` then nothing \\", | |||
|
259 | "for some time, tooltip will be invoked by itself.\\", | |||
|
260 | "\\n - Also you can hoover over the icon on the top right to know what they are dooing...\\", | |||
|
261 | "\\n\\nBack to the next lesson.\\n\\nSometime you need to the tooltip to stay on screen while\\", | |||
|
262 | "you type. That's the reason for the sticky mode (indicated by a small clock on the top left of the tooltip),\\", | |||
|
263 | "\\n\\nNow press <tab> a 3rd time and continue typing some text to test it...\")", | |||
|
264 | " },400);", | |||
|
265 | " },", | |||
|
266 | " function(){", | |||
|
267 | " var time = 35;", | |||
|
268 | " IPython.tooltip.stick(time);", | |||
|
269 | " $('.tooltiptext pre').text(\"Type more text !...\\n\\n range(7,125,3)\\n\\n The tooltip is in sticky mode, it won't be dismissed for at least 10 secondes \",400);", | |||
|
270 | " setTimeout(function(){", | |||
|
271 | " $('.tooltiptext pre').text(\"That was sticky mode...\\nI'll keep it on 15 more seconds just for you.\\n\\nLast thing you can do is send the current help displayed in the tooltip to the pager at the bottom of the screen. To do that, press tab 4 time in a row after a parenthesis. \\n\\n Now I'll stop bothering you and let you Play with the tooltip !\");", | |||
|
272 | " reset_tooltip()", | |||
|
273 | " },15000);", | |||
|
274 | " },", | |||
|
275 | " function(cell){", | |||
|
276 | " IPython.tooltip.cancel_stick();", | |||
|
277 | " reset_tooltip()", | |||
|
278 | " IPython.tooltip.showInPager(cell);", | |||
|
279 | " IPython.tooltip._cmfocus();", | |||
|
280 | " }", | |||
|
281 | " ];", | |||
|
282 | " ", | |||
|
283 | " reset_tooltip = function(){", | |||
|
284 | " IPython.tooltip.tabs_functions = [ function(cell,text){", | |||
|
285 | " IPython.tooltip._request_tooltip(cell,text);", | |||
|
286 | " IPython.notification_widget.set_message('tab again to expand pager',2500);", | |||
|
287 | " },", | |||
|
288 | " function(){", | |||
|
289 | " IPython.tooltip.expand();", | |||
|
290 | " IPython.notification_widget.set_message('tab again to make pager sticky for 10s',2500);", | |||
|
291 | " },", | |||
|
292 | " function(){", | |||
|
293 | " IPython.tooltip.stick();", | |||
|
294 | " IPython.notification_widget.set_message('tab again to open help in pager',2500);", | |||
|
295 | " },", | |||
|
296 | " function(cell){", | |||
|
297 | " IPython.tooltip.cancel_stick();", | |||
|
298 | " IPython.tooltip.showInPager(cell);", | |||
|
299 | " IPython.tooltip._cmfocus();", | |||
|
300 | " }", | |||
|
301 | " ];", | |||
|
302 | " }", | |||
|
303 | "</script>" | |||
|
304 | ] | |||
|
305 | }, | |||
|
306 | { | |||
|
307 | "cell_type": "markdown", | |||
|
308 | "source": [ | |||
245 | "## The frontend/kernel model", |
|
309 | "## The frontend/kernel model", | |
246 | "", |
|
310 | "", | |
247 | "The IPython notebook works on a client/server model where an *IPython kernel*", |
|
311 | "The IPython notebook works on a client/server model where an *IPython kernel*", | |
248 | "starts in a separate process and acts as a server to executes the code you type,", |
|
312 | "starts in a separate process and acts as a server to executes the code you type,", | |
249 | "while the web browser provides acts as a client, providing a front end environment", |
|
313 | "while the web browser provides acts as a client, providing a front end environment", | |
250 | "for you to type. But one kernel is capable of simultaneously talking to more than", |
|
314 | "for you to type. But one kernel is capable of simultaneously talking to more than", | |
251 | "one client, and they do not all need to be of the same kind. All IPython frontends", |
|
315 | "one client, and they do not all need to be of the same kind. All IPython frontends", | |
252 | "are capable of communicating with a kernel, and any number of them can be active", |
|
316 | "are capable of communicating with a kernel, and any number of them can be active", | |
253 | "at the same time. In addition to allowing you to have, for example, more than one", |
|
317 | "at the same time. In addition to allowing you to have, for example, more than one", | |
254 | "browser session active, this lets you connect clients with different user interface features.", |
|
318 | "browser session active, this lets you connect clients with different user interface features.", | |
255 | "", |
|
319 | "", | |
256 | "For example, you may want to connect a Qt console to your kernel and use it as a help", |
|
320 | "For example, you may want to connect a Qt console to your kernel and use it as a help", | |
257 | "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the", |
|
321 | "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the", | |
258 | "one in the notebook). You can start a new Qt console connected to your current kernel by ", |
|
322 | "one in the notebook). You can start a new Qt console connected to your current kernel by ", | |
259 | "using the `%qtconsole` magic, this will automatically detect the necessary connection", |
|
323 | "using the `%qtconsole` magic, this will automatically detect the necessary connection", | |
260 | "information.", |
|
324 | "information.", | |
261 | "", |
|
325 | "", | |
262 | "If you want to open one manually, or want to open a text console from a terminal, you can ", |
|
326 | "If you want to open one manually, or want to open a text console from a terminal, you can ", | |
263 | "get your kernel's connection information with the `%connect_info` magic:" |
|
327 | "get your kernel's connection information with the `%connect_info` magic:" | |
264 | ] |
|
328 | ] | |
265 | }, |
|
329 | }, | |
266 | { |
|
330 | { | |
267 | "cell_type": "code", |
|
331 | "cell_type": "code", | |
268 | "collapsed": false, |
|
|||
269 | "input": [ |
|
332 | "input": [ | |
270 | "%connect_info" |
|
333 | "%connect_info" | |
271 | ], |
|
334 | ], | |
272 | "language": "python", |
|
335 | "language": "python", | |
273 | "outputs": [ |
|
336 | "outputs": [ | |
274 | { |
|
337 | { | |
275 | "output_type": "stream", |
|
338 | "output_type": "stream", | |
276 | "stream": "stdout", |
|
339 | "stream": "stdout", | |
277 | "text": [ |
|
340 | "text": [ | |
278 | "{", |
|
341 | "{", | |
279 | " \"stdin_port\": 53970, ", |
|
342 | " \"stdin_port\": 53970, ", | |
280 | " \"ip\": \"127.0.0.1\", ", |
|
343 | " \"ip\": \"127.0.0.1\", ", | |
281 | " \"hb_port\": 53971, ", |
|
344 | " \"hb_port\": 53971, ", | |
282 | " \"key\": \"30daac61-6b73-4bae-a7d9-9dca538794d5\", ", |
|
345 | " \"key\": \"30daac61-6b73-4bae-a7d9-9dca538794d5\", ", | |
283 | " \"shell_port\": 53968, ", |
|
346 | " \"shell_port\": 53968, ", | |
284 | " \"iopub_port\": 53969", |
|
347 | " \"iopub_port\": 53969", | |
285 | "}", |
|
348 | "}", | |
286 | "", |
|
349 | "", | |
287 | "Paste the above JSON into a file, and connect with:", |
|
350 | "Paste the above JSON into a file, and connect with:", | |
288 | " $> ipython <app> --existing <file>", |
|
351 | " $> ipython <app> --existing <file>", | |
289 | "or, if you are local, you can connect with just:", |
|
352 | "or, if you are local, you can connect with just:", | |
290 | " $> ipython <app> --existing kernel-dd85d1cc-c335-44f4-bed8-f1a2173a819a.json ", |
|
353 | " $> ipython <app> --existing kernel-dd85d1cc-c335-44f4-bed8-f1a2173a819a.json ", | |
291 | "or even just:", |
|
354 | "or even just:", | |
292 | " $> ipython <app> --existing ", |
|
355 | " $> ipython <app> --existing ", | |
293 | "if this is the most recent IPython session you have started." |
|
356 | "if this is the most recent IPython session you have started." | |
294 | ] |
|
357 | ] | |
295 | } |
|
358 | } | |
296 | ], |
|
359 | ], | |
297 | "prompt_number": 4 |
|
360 | "prompt_number": 4 | |
298 | }, |
|
361 | }, | |
299 | { |
|
362 | { | |
300 | "cell_type": "markdown", |
|
363 | "cell_type": "markdown", | |
301 | "source": [ |
|
364 | "source": [ | |
302 | "## The kernel's `raw_input` and `%debug`", |
|
365 | "## The kernel's `raw_input` and `%debug`", | |
303 | "", |
|
366 | "", | |
304 | "The one feature the notebook currently doesn't support as a client is the ability to send data to the kernel's", |
|
367 | "The one feature the notebook currently doesn't support as a client is the ability to send data to the kernel's", | |
305 | "standard input socket. That is, if the kernel requires information to be typed interactively by calling the", |
|
368 | "standard input socket. That is, if the kernel requires information to be typed interactively by calling the", | |
306 | "builtin `raw_input` function, the notebook will be blocked. This happens for example if you run a script", |
|
369 | "builtin `raw_input` function, the notebook will be blocked. This happens for example if you run a script", | |
307 | "that queries interactively for parameters, and very importantly, is how the interactive IPython debugger that ", |
|
370 | "that queries interactively for parameters, and very importantly, is how the interactive IPython debugger that ", | |
308 | "activates when you type `%debug` works.", |
|
371 | "activates when you type `%debug` works.", | |
309 | "", |
|
372 | "", | |
310 | "So, in order to be able to use `%debug` or anything else that requires `raw_input`, you can either use a Qt ", |
|
373 | "So, in order to be able to use `%debug` or anything else that requires `raw_input`, you can either use a Qt ", | |
311 | "console or a terminal console:", |
|
374 | "console or a terminal console:", | |
312 | "", |
|
375 | "", | |
313 | "- From the notebook, typing `%qtconsole` finds all the necessary connection data for you.", |
|
376 | "- From the notebook, typing `%qtconsole` finds all the necessary connection data for you.", | |
314 | "- From the terminal, first type `%connect_info` while still in the notebook, and then copy and paste the ", |
|
377 | "- From the terminal, first type `%connect_info` while still in the notebook, and then copy and paste the ", | |
315 | "resulting information, using `qtconsole` or `console` depending on which type of client you want." |
|
378 | "resulting information, using `qtconsole` or `console` depending on which type of client you want." | |
316 | ] |
|
379 | ] | |
317 | }, |
|
380 | }, | |
318 | { |
|
381 | { | |
319 | "cell_type": "markdown", |
|
382 | "cell_type": "markdown", | |
320 | "source": [ |
|
383 | "source": [ | |
321 | "## Display of complex objects", |
|
384 | "## Display of complex objects", | |
322 | "", |
|
385 | "", | |
323 | "As the 'tour' notebook shows, the IPython notebook has fairly sophisticated display capabilities. In addition", |
|
386 | "As the 'tour' notebook shows, the IPython notebook has fairly sophisticated display capabilities. In addition", | |
324 | "to the examples there, you can study the `display_protocol` notebook in this same examples folder, to ", |
|
387 | "to the examples there, you can study the `display_protocol` notebook in this same examples folder, to ", | |
325 | "learn how to customize arbitrary objects (in your own code or external libraries) to display in the notebook", |
|
388 | "learn how to customize arbitrary objects (in your own code or external libraries) to display in the notebook", | |
326 | "in any way you want, including graphical forms or mathematical expressions." |
|
389 | "in any way you want, including graphical forms or mathematical expressions." | |
327 | ] |
|
390 | ] | |
328 | }, |
|
391 | }, | |
329 | { |
|
392 | { | |
330 | "cell_type": "markdown", |
|
393 | "cell_type": "markdown", | |
331 | "source": [ |
|
394 | "source": [ | |
332 | "## Plotting support", |
|
395 | "## Plotting support", | |
333 | "", |
|
396 | "", | |
334 | "As we've explained already, the notebook is just another frontend talking to the same IPython kernel that", |
|
397 | "As we've explained already, the notebook is just another frontend talking to the same IPython kernel that", | |
335 | "you're already familiar with, so the same options for plotting support apply.", |
|
398 | "you're already familiar with, so the same options for plotting support apply.", | |
336 | "", |
|
399 | "", | |
337 | "If you start the notebook with `--pylab`, you will get matplotlib's floating, interactive windows and you", |
|
400 | "If you start the notebook with `--pylab`, you will get matplotlib's floating, interactive windows and you", | |
338 | "can call the `display` function to paste figures into the notebook document. If you start it with ", |
|
401 | "can call the `display` function to paste figures into the notebook document. If you start it with ", | |
339 | "`--pylab inline`, all plots will appear inline automatically. In this regard, the notebook works identically", |
|
402 | "`--pylab inline`, all plots will appear inline automatically. In this regard, the notebook works identically", | |
340 | "to the Qt console.", |
|
403 | "to the Qt console.", | |
341 | "", |
|
404 | "", | |
342 | "Note that if you start the notebook server with pylab support, *all* kernels are automatically started in", |
|
405 | "Note that if you start the notebook server with pylab support, *all* kernels are automatically started in", | |
343 | "pylab mode and with the same choice of backend (i.e. floating windows or inline figures). But you can also", |
|
406 | "pylab mode and with the same choice of backend (i.e. floating windows or inline figures). But you can also", | |
344 | "start the notebook server simply by typing `ipython notebook`, and then selectively turn on pylab support ", |
|
407 | "start the notebook server simply by typing `ipython notebook`, and then selectively turn on pylab support ", | |
345 | "only for the notebooks you want by using the `%pylab` magic (see its docstring for details)." |
|
408 | "only for the notebooks you want by using the `%pylab` magic (see its docstring for details)." | |
346 | ] |
|
409 | ] | |
347 | }, |
|
410 | }, | |
348 | { |
|
411 | { | |
349 | "cell_type": "code", |
|
412 | "cell_type": "code", | |
350 | "collapsed": false, |
|
|||
351 | "input": [ |
|
413 | "input": [ | |
352 | "%pylab inline", |
|
414 | "%pylab inline", | |
353 | "plot(rand(100))" |
|
415 | "plot(rand(100))" | |
354 | ], |
|
416 | ], | |
355 | "language": "python", |
|
417 | "language": "python", | |
356 | "outputs": [ |
|
418 | "outputs": [ | |
357 | { |
|
419 | { | |
358 | "output_type": "stream", |
|
420 | "output_type": "stream", | |
359 | "stream": "stdout", |
|
421 | "stream": "stdout", | |
360 | "text": [ |
|
422 | "text": [ | |
361 | "", |
|
423 | "", | |
362 | "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].", |
|
424 | "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].", | |
363 | "For more information, type 'help(pylab)'." |
|
425 | "For more information, type 'help(pylab)'." | |
364 | ] |
|
426 | ] | |
365 | }, |
|
427 | }, | |
366 | { |
|
428 | { | |
367 | "output_type": "pyout", |
|
429 | "output_type": "pyout", | |
368 | "prompt_number": 5, |
|
430 | "prompt_number": 5, | |
369 | "text": [ |
|
431 | "text": [ | |
370 | "[<matplotlib.lines.Line2D at 0x11165bcd0>]" |
|
432 | "[<matplotlib.lines.Line2D at 0x11165bcd0>]" | |
371 | ] |
|
433 | ] | |
372 | }, |
|
434 | }, | |
373 | { |
|
435 | { | |
374 | "output_type": "display_data", |
|
436 | "output_type": "display_data", | |
375 | "png": "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\n" |
|
437 | "png": "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\n" | |
376 | } |
|
438 | } | |
377 | ], |
|
439 | ], | |
378 | "prompt_number": 5 |
|
440 | "prompt_number": 5 | |
379 | }, |
|
441 | }, | |
380 | { |
|
442 | { | |
381 | "cell_type": "markdown", |
|
443 | "cell_type": "markdown", | |
382 | "source": [ |
|
444 | "source": [ | |
383 | "## Security", |
|
445 | "## Security", | |
384 | "", |
|
446 | "", | |
385 | "By default the notebook only listens on localhost, so it does not expose your computer to attacks coming from", |
|
447 | "By default the notebook only listens on localhost, so it does not expose your computer to attacks coming from", | |
386 | "the internet. By default the notebook does not require any authentication, but you can configure it to", |
|
448 | "the internet. By default the notebook does not require any authentication, but you can configure it to", | |
387 | "ask for a password before allowing access to the files. ", |
|
449 | "ask for a password before allowing access to the files. ", | |
388 | "", |
|
450 | "", | |
389 | "Furthermore, you can require the notebook to encrypt all communications by using SSL and making all connections", |
|
451 | "Furthermore, you can require the notebook to encrypt all communications by using SSL and making all connections", | |
390 | "using the https protocol instead of plain http. This is a good idea if you decide to run your notebook on", |
|
452 | "using the https protocol instead of plain http. This is a good idea if you decide to run your notebook on", | |
391 | "addresses that are visible from the internet. For further details on how to configure this, see the", |
|
453 | "addresses that are visible from the internet. For further details on how to configure this, see the", | |
392 | "[security section](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html#security) of the ", |
|
454 | "[security section](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html#security) of the ", | |
393 | "manual.", |
|
455 | "manual.", | |
394 | "", |
|
456 | "", | |
395 | "Finally, note that you can also run a notebook with the `--read-only` flag, which lets you provide access", |
|
457 | "Finally, note that you can also run a notebook with the `--read-only` flag, which lets you provide access", | |
396 | "to your notebook documents to others without letting them execute code (which can be useful to broadcast", |
|
458 | "to your notebook documents to others without letting them execute code (which can be useful to broadcast", | |
397 | "a computation to colleagues or students, for example). The read-only flag behaves differently depending", |
|
459 | "a computation to colleagues or students, for example). The read-only flag behaves differently depending", | |
398 | "on whether the server has a password or not:", |
|
460 | "on whether the server has a password or not:", | |
399 | "", |
|
461 | "", | |
400 | "- Passwordless server: users directly see all notebooks in read-only mode.", |
|
462 | "- Passwordless server: users directly see all notebooks in read-only mode.", | |
401 | "- Password-protected server: users can see all notebooks in read-only mode, but a login button is available", |
|
463 | "- Password-protected server: users can see all notebooks in read-only mode, but a login button is available", | |
402 | "and once a user authenticates, he or she obtains write/execute privileges.", |
|
464 | "and once a user authenticates, he or she obtains write/execute privileges.", | |
403 | "", |
|
465 | "", | |
404 | "The first case above makes it easy to broadcast on the fly an existing notebook by simply starting a *second* ", |
|
466 | "The first case above makes it easy to broadcast on the fly an existing notebook by simply starting a *second* ", | |
405 | "notebook server in the same directory as the first, but in read-only mode. This can be done without having", |
|
467 | "notebook server in the same directory as the first, but in read-only mode. This can be done without having", | |
406 | "to configure a password first (which requires calling a hashing function and editing a configuration file)." |
|
468 | "to configure a password first (which requires calling a hashing function and editing a configuration file)." | |
407 | ] |
|
469 | ] | |
408 | }, |
|
470 | }, | |
409 | { |
|
471 | { | |
410 | "cell_type": "code", |
|
472 | "cell_type": "code", | |
411 | "collapsed": true, |
|
473 | "input": [ | |
412 | "input": [], |
|
474 | "" | |
|
475 | ], | |||
413 | "language": "python", |
|
476 | "language": "python", | |
414 | "outputs": [] |
|
477 | "outputs": [] | |
415 | } |
|
478 | } | |
416 | ] |
|
479 | ] | |
417 | } |
|
480 | } | |
418 | ] |
|
481 | ] | |
419 | } No newline at end of file |
|
482 | } |
General Comments 0
You need to be logged in to leave comments.
Login now