##// END OF EJS Templates
fix a couple typos in Qt from the msg spec update...
MinRK -
Show More
@@ -1,570 +1,570 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Usage information for the main IPython applications.
2 """Usage information for the main IPython applications.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008-2011 The IPython Development Team
5 # Copyright (C) 2008-2011 The IPython Development Team
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import sys
12 import sys
13 from IPython.core import release
13 from IPython.core import release
14
14
15 cl_usage = """\
15 cl_usage = """\
16 =========
16 =========
17 IPython
17 IPython
18 =========
18 =========
19
19
20 Tools for Interactive Computing in Python
20 Tools for Interactive Computing in Python
21 =========================================
21 =========================================
22
22
23 A Python shell with automatic history (input and output), dynamic object
23 A Python shell with automatic history (input and output), dynamic object
24 introspection, easier configuration, command completion, access to the
24 introspection, easier configuration, command completion, access to the
25 system shell and more. IPython can also be embedded in running programs.
25 system shell and more. IPython can also be embedded in running programs.
26
26
27
27
28 Usage
28 Usage
29
29
30 ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ...
30 ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ...
31
31
32 If invoked with no options, it executes the file and exits, passing the
32 If invoked with no options, it executes the file and exits, passing the
33 remaining arguments to the script, just as if you had specified the same
33 remaining arguments to the script, just as if you had specified the same
34 command with python. You may need to specify `--` before args to be passed
34 command with python. You may need to specify `--` before args to be passed
35 to the script, to prevent IPython from attempting to parse them. If you
35 to the script, to prevent IPython from attempting to parse them. If you
36 specify the option `-i` before the filename, it will enter an interactive
36 specify the option `-i` before the filename, it will enter an interactive
37 IPython session after running the script, rather than exiting. Files ending
37 IPython session after running the script, rather than exiting. Files ending
38 in .py will be treated as normal Python, but files ending in .ipy can
38 in .py will be treated as normal Python, but files ending in .ipy can
39 contain special IPython syntax (magic commands, shell expansions, etc.).
39 contain special IPython syntax (magic commands, shell expansions, etc.).
40
40
41 Almost all configuration in IPython is available via the command-line. Do
41 Almost all configuration in IPython is available via the command-line. Do
42 `ipython --help-all` to see all available options. For persistent
42 `ipython --help-all` to see all available options. For persistent
43 configuration, look into your `ipython_config.py` configuration file for
43 configuration, look into your `ipython_config.py` configuration file for
44 details.
44 details.
45
45
46 This file is typically installed in the `IPYTHONDIR` directory, and there
46 This file is typically installed in the `IPYTHONDIR` directory, and there
47 is a separate configuration directory for each profile. The default profile
47 is a separate configuration directory for each profile. The default profile
48 directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR
48 directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR
49 defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to
49 defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to
50 C:\\Documents and Settings\\YourUserName in most instances.
50 C:\\Documents and Settings\\YourUserName in most instances.
51
51
52 To initialize a profile with the default configuration file, do::
52 To initialize a profile with the default configuration file, do::
53
53
54 $> ipython profile create
54 $> ipython profile create
55
55
56 and start editing `IPYTHONDIR/profile_default/ipython_config.py`
56 and start editing `IPYTHONDIR/profile_default/ipython_config.py`
57
57
58 In IPython's documentation, we will refer to this directory as
58 In IPython's documentation, we will refer to this directory as
59 `IPYTHONDIR`, you can change its default location by creating an
59 `IPYTHONDIR`, you can change its default location by creating an
60 environment variable with this name and setting it to the desired path.
60 environment variable with this name and setting it to the desired path.
61
61
62 For more information, see the manual available in HTML and PDF in your
62 For more information, see the manual available in HTML and PDF in your
63 installation, or online at http://ipython.org/documentation.html.
63 installation, or online at http://ipython.org/documentation.html.
64 """
64 """
65
65
66 interactive_usage = """
66 interactive_usage = """
67 IPython -- An enhanced Interactive Python
67 IPython -- An enhanced Interactive Python
68 =========================================
68 =========================================
69
69
70 IPython offers a combination of convenient shell features, special commands
70 IPython offers a combination of convenient shell features, special commands
71 and a history mechanism for both input (command history) and output (results
71 and a history mechanism for both input (command history) and output (results
72 caching, similar to Mathematica). It is intended to be a fully compatible
72 caching, similar to Mathematica). It is intended to be a fully compatible
73 replacement for the standard Python interpreter, while offering vastly
73 replacement for the standard Python interpreter, while offering vastly
74 improved functionality and flexibility.
74 improved functionality and flexibility.
75
75
76 At your system command line, type 'ipython -h' to see the command line
76 At your system command line, type 'ipython -h' to see the command line
77 options available. This document only describes interactive features.
77 options available. This document only describes interactive features.
78
78
79 MAIN FEATURES
79 MAIN FEATURES
80 -------------
80 -------------
81
81
82 * Access to the standard Python help. As of Python 2.1, a help system is
82 * Access to the standard Python help. As of Python 2.1, a help system is
83 available with access to object docstrings and the Python manuals. Simply
83 available with access to object docstrings and the Python manuals. Simply
84 type 'help' (no quotes) to access it.
84 type 'help' (no quotes) to access it.
85
85
86 * Magic commands: type %magic for information on the magic subsystem.
86 * Magic commands: type %magic for information on the magic subsystem.
87
87
88 * System command aliases, via the %alias command or the configuration file(s).
88 * System command aliases, via the %alias command or the configuration file(s).
89
89
90 * Dynamic object information:
90 * Dynamic object information:
91
91
92 Typing ?word or word? prints detailed information about an object. If
92 Typing ?word or word? prints detailed information about an object. If
93 certain strings in the object are too long (docstrings, code, etc.) they get
93 certain strings in the object are too long (docstrings, code, etc.) they get
94 snipped in the center for brevity.
94 snipped in the center for brevity.
95
95
96 Typing ??word or word?? gives access to the full information without
96 Typing ??word or word?? gives access to the full information without
97 snipping long strings. Long strings are sent to the screen through the less
97 snipping long strings. Long strings are sent to the screen through the less
98 pager if longer than the screen, printed otherwise.
98 pager if longer than the screen, printed otherwise.
99
99
100 The ?/?? system gives access to the full source code for any object (if
100 The ?/?? system gives access to the full source code for any object (if
101 available), shows function prototypes and other useful information.
101 available), shows function prototypes and other useful information.
102
102
103 If you just want to see an object's docstring, type '%pdoc object' (without
103 If you just want to see an object's docstring, type '%pdoc object' (without
104 quotes, and without % if you have automagic on).
104 quotes, and without % if you have automagic on).
105
105
106 Both %pdoc and ?/?? give you access to documentation even on things which are
106 Both %pdoc and ?/?? give you access to documentation even on things which are
107 not explicitely defined. Try for example typing {}.get? or after import os,
107 not explicitely defined. Try for example typing {}.get? or after import os,
108 type os.path.abspath??. The magic functions %pdef, %source and %file operate
108 type os.path.abspath??. The magic functions %pdef, %source and %file operate
109 similarly.
109 similarly.
110
110
111 * Completion in the local namespace, by typing TAB at the prompt.
111 * Completion in the local namespace, by typing TAB at the prompt.
112
112
113 At any time, hitting tab will complete any available python commands or
113 At any time, hitting tab will complete any available python commands or
114 variable names, and show you a list of the possible completions if there's
114 variable names, and show you a list of the possible completions if there's
115 no unambiguous one. It will also complete filenames in the current directory.
115 no unambiguous one. It will also complete filenames in the current directory.
116
116
117 This feature requires the readline and rlcomplete modules, so it won't work
117 This feature requires the readline and rlcomplete modules, so it won't work
118 if your Python lacks readline support (such as under Windows).
118 if your Python lacks readline support (such as under Windows).
119
119
120 * Search previous command history in two ways (also requires readline):
120 * Search previous command history in two ways (also requires readline):
121
121
122 - Start typing, and then use Ctrl-p (previous,up) and Ctrl-n (next,down) to
122 - Start typing, and then use Ctrl-p (previous,up) and Ctrl-n (next,down) to
123 search through only the history items that match what you've typed so
123 search through only the history items that match what you've typed so
124 far. If you use Ctrl-p/Ctrl-n at a blank prompt, they just behave like
124 far. If you use Ctrl-p/Ctrl-n at a blank prompt, they just behave like
125 normal arrow keys.
125 normal arrow keys.
126
126
127 - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches
127 - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches
128 your history for lines that match what you've typed so far, completing as
128 your history for lines that match what you've typed so far, completing as
129 much as it can.
129 much as it can.
130
130
131 - %hist: search history by index (this does *not* require readline).
131 - %hist: search history by index (this does *not* require readline).
132
132
133 * Persistent command history across sessions.
133 * Persistent command history across sessions.
134
134
135 * Logging of input with the ability to save and restore a working session.
135 * Logging of input with the ability to save and restore a working session.
136
136
137 * System escape with !. Typing !ls will run 'ls' in the current directory.
137 * System escape with !. Typing !ls will run 'ls' in the current directory.
138
138
139 * The reload command does a 'deep' reload of a module: changes made to the
139 * The reload command does a 'deep' reload of a module: changes made to the
140 module since you imported will actually be available without having to exit.
140 module since you imported will actually be available without having to exit.
141
141
142 * Verbose and colored exception traceback printouts. See the magic xmode and
142 * Verbose and colored exception traceback printouts. See the magic xmode and
143 xcolor functions for details (just type %magic).
143 xcolor functions for details (just type %magic).
144
144
145 * Input caching system:
145 * Input caching system:
146
146
147 IPython offers numbered prompts (In/Out) with input and output caching. All
147 IPython offers numbered prompts (In/Out) with input and output caching. All
148 input is saved and can be retrieved as variables (besides the usual arrow
148 input is saved and can be retrieved as variables (besides the usual arrow
149 key recall).
149 key recall).
150
150
151 The following GLOBAL variables always exist (so don't overwrite them!):
151 The following GLOBAL variables always exist (so don't overwrite them!):
152 _i: stores previous input.
152 _i: stores previous input.
153 _ii: next previous.
153 _ii: next previous.
154 _iii: next-next previous.
154 _iii: next-next previous.
155 _ih : a list of all input _ih[n] is the input from line n.
155 _ih : a list of all input _ih[n] is the input from line n.
156
156
157 Additionally, global variables named _i<n> are dynamically created (<n>
157 Additionally, global variables named _i<n> are dynamically created (<n>
158 being the prompt counter), such that _i<n> == _ih[<n>]
158 being the prompt counter), such that _i<n> == _ih[<n>]
159
159
160 For example, what you typed at prompt 14 is available as _i14 and _ih[14].
160 For example, what you typed at prompt 14 is available as _i14 and _ih[14].
161
161
162 You can create macros which contain multiple input lines from this history,
162 You can create macros which contain multiple input lines from this history,
163 for later re-execution, with the %macro function.
163 for later re-execution, with the %macro function.
164
164
165 The history function %hist allows you to see any part of your input history
165 The history function %hist allows you to see any part of your input history
166 by printing a range of the _i variables. Note that inputs which contain
166 by printing a range of the _i variables. Note that inputs which contain
167 magic functions (%) appear in the history with a prepended comment. This is
167 magic functions (%) appear in the history with a prepended comment. This is
168 because they aren't really valid Python code, so you can't exec them.
168 because they aren't really valid Python code, so you can't exec them.
169
169
170 * Output caching system:
170 * Output caching system:
171
171
172 For output that is returned from actions, a system similar to the input
172 For output that is returned from actions, a system similar to the input
173 cache exists but using _ instead of _i. Only actions that produce a result
173 cache exists but using _ instead of _i. Only actions that produce a result
174 (NOT assignments, for example) are cached. If you are familiar with
174 (NOT assignments, for example) are cached. If you are familiar with
175 Mathematica, IPython's _ variables behave exactly like Mathematica's %
175 Mathematica, IPython's _ variables behave exactly like Mathematica's %
176 variables.
176 variables.
177
177
178 The following GLOBAL variables always exist (so don't overwrite them!):
178 The following GLOBAL variables always exist (so don't overwrite them!):
179 _ (one underscore): previous output.
179 _ (one underscore): previous output.
180 __ (two underscores): next previous.
180 __ (two underscores): next previous.
181 ___ (three underscores): next-next previous.
181 ___ (three underscores): next-next previous.
182
182
183 Global variables named _<n> are dynamically created (<n> being the prompt
183 Global variables named _<n> are dynamically created (<n> being the prompt
184 counter), such that the result of output <n> is always available as _<n>.
184 counter), such that the result of output <n> is always available as _<n>.
185
185
186 Finally, a global dictionary named _oh exists with entries for all lines
186 Finally, a global dictionary named _oh exists with entries for all lines
187 which generated output.
187 which generated output.
188
188
189 * Directory history:
189 * Directory history:
190
190
191 Your history of visited directories is kept in the global list _dh, and the
191 Your history of visited directories is kept in the global list _dh, and the
192 magic %cd command can be used to go to any entry in that list.
192 magic %cd command can be used to go to any entry in that list.
193
193
194 * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython)
194 * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython)
195
195
196 1. Auto-parentheses
196 1. Auto-parentheses
197
197
198 Callable objects (i.e. functions, methods, etc) can be invoked like
198 Callable objects (i.e. functions, methods, etc) can be invoked like
199 this (notice the commas between the arguments)::
199 this (notice the commas between the arguments)::
200
200
201 In [1]: callable_ob arg1, arg2, arg3
201 In [1]: callable_ob arg1, arg2, arg3
202
202
203 and the input will be translated to this::
203 and the input will be translated to this::
204
204
205 callable_ob(arg1, arg2, arg3)
205 callable_ob(arg1, arg2, arg3)
206
206
207 This feature is off by default (in rare cases it can produce
207 This feature is off by default (in rare cases it can produce
208 undesirable side-effects), but you can activate it at the command-line
208 undesirable side-effects), but you can activate it at the command-line
209 by starting IPython with `--autocall 1`, set it permanently in your
209 by starting IPython with `--autocall 1`, set it permanently in your
210 configuration file, or turn on at runtime with `%autocall 1`.
210 configuration file, or turn on at runtime with `%autocall 1`.
211
211
212 You can force auto-parentheses by using '/' as the first character
212 You can force auto-parentheses by using '/' as the first character
213 of a line. For example::
213 of a line. For example::
214
214
215 In [1]: /globals # becomes 'globals()'
215 In [1]: /globals # becomes 'globals()'
216
216
217 Note that the '/' MUST be the first character on the line! This
217 Note that the '/' MUST be the first character on the line! This
218 won't work::
218 won't work::
219
219
220 In [2]: print /globals # syntax error
220 In [2]: print /globals # syntax error
221
221
222 In most cases the automatic algorithm should work, so you should
222 In most cases the automatic algorithm should work, so you should
223 rarely need to explicitly invoke /. One notable exception is if you
223 rarely need to explicitly invoke /. One notable exception is if you
224 are trying to call a function with a list of tuples as arguments (the
224 are trying to call a function with a list of tuples as arguments (the
225 parenthesis will confuse IPython)::
225 parenthesis will confuse IPython)::
226
226
227 In [1]: zip (1,2,3),(4,5,6) # won't work
227 In [1]: zip (1,2,3),(4,5,6) # won't work
228
228
229 but this will work::
229 but this will work::
230
230
231 In [2]: /zip (1,2,3),(4,5,6)
231 In [2]: /zip (1,2,3),(4,5,6)
232 ------> zip ((1,2,3),(4,5,6))
232 ------> zip ((1,2,3),(4,5,6))
233 Out[2]= [(1, 4), (2, 5), (3, 6)]
233 Out[2]= [(1, 4), (2, 5), (3, 6)]
234
234
235 IPython tells you that it has altered your command line by
235 IPython tells you that it has altered your command line by
236 displaying the new command line preceded by -->. e.g.::
236 displaying the new command line preceded by -->. e.g.::
237
237
238 In [18]: callable list
238 In [18]: callable list
239 -------> callable (list)
239 -------> callable (list)
240
240
241 2. Auto-Quoting
241 2. Auto-Quoting
242
242
243 You can force auto-quoting of a function's arguments by using ',' as
243 You can force auto-quoting of a function's arguments by using ',' as
244 the first character of a line. For example::
244 the first character of a line. For example::
245
245
246 In [1]: ,my_function /home/me # becomes my_function("/home/me")
246 In [1]: ,my_function /home/me # becomes my_function("/home/me")
247
247
248 If you use ';' instead, the whole argument is quoted as a single
248 If you use ';' instead, the whole argument is quoted as a single
249 string (while ',' splits on whitespace)::
249 string (while ',' splits on whitespace)::
250
250
251 In [2]: ,my_function a b c # becomes my_function("a","b","c")
251 In [2]: ,my_function a b c # becomes my_function("a","b","c")
252 In [3]: ;my_function a b c # becomes my_function("a b c")
252 In [3]: ;my_function a b c # becomes my_function("a b c")
253
253
254 Note that the ',' MUST be the first character on the line! This
254 Note that the ',' MUST be the first character on the line! This
255 won't work::
255 won't work::
256
256
257 In [4]: x = ,my_function /home/me # syntax error
257 In [4]: x = ,my_function /home/me # syntax error
258 """
258 """
259
259
260 interactive_usage_min = """\
260 interactive_usage_min = """\
261 An enhanced console for Python.
261 An enhanced console for Python.
262 Some of its features are:
262 Some of its features are:
263 - Readline support if the readline library is present.
263 - Readline support if the readline library is present.
264 - Tab completion in the local namespace.
264 - Tab completion in the local namespace.
265 - Logging of input, see command-line options.
265 - Logging of input, see command-line options.
266 - System shell escape via ! , eg !ls.
266 - System shell escape via ! , eg !ls.
267 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
267 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
268 - Keeps track of locally defined variables via %who, %whos.
268 - Keeps track of locally defined variables via %who, %whos.
269 - Show object information with a ? eg ?x or x? (use ?? for more info).
269 - Show object information with a ? eg ?x or x? (use ?? for more info).
270 """
270 """
271
271
272 quick_reference = r"""
272 quick_reference = r"""
273 IPython -- An enhanced Interactive Python - Quick Reference Card
273 IPython -- An enhanced Interactive Python - Quick Reference Card
274 ================================================================
274 ================================================================
275
275
276 obj?, obj?? : Get help, or more help for object (also works as
276 obj?, obj?? : Get help, or more help for object (also works as
277 ?obj, ??obj).
277 ?obj, ??obj).
278 ?foo.*abc* : List names in 'foo' containing 'abc' in them.
278 ?foo.*abc* : List names in 'foo' containing 'abc' in them.
279 %magic : Information about IPython's 'magic' % functions.
279 %magic : Information about IPython's 'magic' % functions.
280
280
281 Magic functions are prefixed by % or %%, and typically take their arguments
281 Magic functions are prefixed by % or %%, and typically take their arguments
282 without parentheses, quotes or even commas for convenience. Line magics take a
282 without parentheses, quotes or even commas for convenience. Line magics take a
283 single % and cell magics are prefixed with two %%.
283 single % and cell magics are prefixed with two %%.
284
284
285 Example magic function calls:
285 Example magic function calls:
286
286
287 %alias d ls -F : 'd' is now an alias for 'ls -F'
287 %alias d ls -F : 'd' is now an alias for 'ls -F'
288 alias d ls -F : Works if 'alias' not a python name
288 alias d ls -F : Works if 'alias' not a python name
289 alist = %alias : Get list of aliases to 'alist'
289 alist = %alias : Get list of aliases to 'alist'
290 cd /usr/share : Obvious. cd -<tab> to choose from visited dirs.
290 cd /usr/share : Obvious. cd -<tab> to choose from visited dirs.
291 %cd?? : See help AND source for magic %cd
291 %cd?? : See help AND source for magic %cd
292 %timeit x=10 : time the 'x=10' statement with high precision.
292 %timeit x=10 : time the 'x=10' statement with high precision.
293 %%timeit x=2**100
293 %%timeit x=2**100
294 x**100 : time 'x*100' with a setup of 'x=2**100'; setup code is not
294 x**100 : time 'x*100' with a setup of 'x=2**100'; setup code is not
295 counted. This is an example of a cell magic.
295 counted. This is an example of a cell magic.
296
296
297 System commands:
297 System commands:
298
298
299 !cp a.txt b/ : System command escape, calls os.system()
299 !cp a.txt b/ : System command escape, calls os.system()
300 cp a.txt b/ : after %rehashx, most system commands work without !
300 cp a.txt b/ : after %rehashx, most system commands work without !
301 cp ${f}.txt $bar : Variable expansion in magics and system commands
301 cp ${f}.txt $bar : Variable expansion in magics and system commands
302 files = !ls /usr : Capture sytem command output
302 files = !ls /usr : Capture sytem command output
303 files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc'
303 files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc'
304
304
305 History:
305 History:
306
306
307 _i, _ii, _iii : Previous, next previous, next next previous input
307 _i, _ii, _iii : Previous, next previous, next next previous input
308 _i4, _ih[2:5] : Input history line 4, lines 2-4
308 _i4, _ih[2:5] : Input history line 4, lines 2-4
309 exec _i81 : Execute input history line #81 again
309 exec _i81 : Execute input history line #81 again
310 %rep 81 : Edit input history line #81
310 %rep 81 : Edit input history line #81
311 _, __, ___ : previous, next previous, next next previous output
311 _, __, ___ : previous, next previous, next next previous output
312 _dh : Directory history
312 _dh : Directory history
313 _oh : Output history
313 _oh : Output history
314 %hist : Command history. '%hist -g foo' search history for 'foo'
314 %hist : Command history. '%hist -g foo' search history for 'foo'
315
315
316 Autocall:
316 Autocall:
317
317
318 f 1,2 : f(1,2) # Off by default, enable with %autocall magic.
318 f 1,2 : f(1,2) # Off by default, enable with %autocall magic.
319 /f 1,2 : f(1,2) (forced autoparen)
319 /f 1,2 : f(1,2) (forced autoparen)
320 ,f 1 2 : f("1","2")
320 ,f 1 2 : f("1","2")
321 ;f 1 2 : f("1 2")
321 ;f 1 2 : f("1 2")
322
322
323 Remember: TAB completion works in many contexts, not just file names
323 Remember: TAB completion works in many contexts, not just file names
324 or python names.
324 or python names.
325
325
326 The following magic functions are currently available:
326 The following magic functions are currently available:
327
327
328 """
328 """
329
329
330 gui_reference = """\
330 gui_reference = """\
331 ===============================
331 ===============================
332 The graphical IPython console
332 The graphical IPython console
333 ===============================
333 ===============================
334
334
335 This console is designed to emulate the look, feel and workflow of a terminal
335 This console is designed to emulate the look, feel and workflow of a terminal
336 environment, while adding a number of enhancements that are simply not possible
336 environment, while adding a number of enhancements that are simply not possible
337 in a real terminal, such as inline syntax highlighting, true multiline editing,
337 in a real terminal, such as inline syntax highlighting, true multiline editing,
338 inline graphics and much more.
338 inline graphics and much more.
339
339
340 This quick reference document contains the basic information you'll need to
340 This quick reference document contains the basic information you'll need to
341 know to make the most efficient use of it. For the various command line
341 know to make the most efficient use of it. For the various command line
342 options available at startup, type ``ipython qtconsole --help`` at the command line.
342 options available at startup, type ``ipython qtconsole --help`` at the command line.
343
343
344
344
345 Multiline editing
345 Multiline editing
346 =================
346 =================
347
347
348 The graphical console is capable of true multiline editing, but it also tries
348 The graphical console is capable of true multiline editing, but it also tries
349 to behave intuitively like a terminal when possible. If you are used to
349 to behave intuitively like a terminal when possible. If you are used to
350 IPython's old terminal behavior, you should find the transition painless, and
350 IPython's old terminal behavior, you should find the transition painless, and
351 once you learn a few basic keybindings it will be a much more efficient
351 once you learn a few basic keybindings it will be a much more efficient
352 environment.
352 environment.
353
353
354 For single expressions or indented blocks, the console behaves almost like the
354 For single expressions or indented blocks, the console behaves almost like the
355 terminal IPython: single expressions are immediately evaluated, and indented
355 terminal IPython: single expressions are immediately evaluated, and indented
356 blocks are evaluated once a single blank line is entered::
356 blocks are evaluated once a single blank line is entered::
357
357
358 In [1]: print "Hello IPython!" # Enter was pressed at the end of the line
358 In [1]: print "Hello IPython!" # Enter was pressed at the end of the line
359 Hello IPython!
359 Hello IPython!
360
360
361 In [2]: for i in range(10):
361 In [2]: for i in range(10):
362 ...: print i,
362 ...: print i,
363 ...:
363 ...:
364 0 1 2 3 4 5 6 7 8 9
364 0 1 2 3 4 5 6 7 8 9
365
365
366 If you want to enter more than one expression in a single input block
366 If you want to enter more than one expression in a single input block
367 (something not possible in the terminal), you can use ``Control-Enter`` at the
367 (something not possible in the terminal), you can use ``Control-Enter`` at the
368 end of your first line instead of ``Enter``. At that point the console goes
368 end of your first line instead of ``Enter``. At that point the console goes
369 into 'cell mode' and even if your inputs are not indented, it will continue
369 into 'cell mode' and even if your inputs are not indented, it will continue
370 accepting arbitrarily many lines until either you enter an extra blank line or
370 accepting arbitrarily many lines until either you enter an extra blank line or
371 you hit ``Shift-Enter`` (the key binding that forces execution). When a
371 you hit ``Shift-Enter`` (the key binding that forces execution). When a
372 multiline cell is entered, IPython analyzes it and executes its code producing
372 multiline cell is entered, IPython analyzes it and executes its code producing
373 an ``Out[n]`` prompt only for the last expression in it, while the rest of the
373 an ``Out[n]`` prompt only for the last expression in it, while the rest of the
374 cell is executed as if it was a script. An example should clarify this::
374 cell is executed as if it was a script. An example should clarify this::
375
375
376 In [3]: x=1 # Hit C-Enter here
376 In [3]: x=1 # Hit C-Enter here
377 ...: y=2 # from now on, regular Enter is sufficient
377 ...: y=2 # from now on, regular Enter is sufficient
378 ...: z=3
378 ...: z=3
379 ...: x**2 # This does *not* produce an Out[] value
379 ...: x**2 # This does *not* produce an Out[] value
380 ...: x+y+z # Only the last expression does
380 ...: x+y+z # Only the last expression does
381 ...:
381 ...:
382 Out[3]: 6
382 Out[3]: 6
383
383
384 The behavior where an extra blank line forces execution is only active if you
384 The behavior where an extra blank line forces execution is only active if you
385 are actually typing at the keyboard each line, and is meant to make it mimic
385 are actually typing at the keyboard each line, and is meant to make it mimic
386 the IPython terminal behavior. If you paste a long chunk of input (for example
386 the IPython terminal behavior. If you paste a long chunk of input (for example
387 a long script copied form an editor or web browser), it can contain arbitrarily
387 a long script copied form an editor or web browser), it can contain arbitrarily
388 many intermediate blank lines and they won't cause any problems. As always,
388 many intermediate blank lines and they won't cause any problems. As always,
389 you can then make it execute by appending a blank line *at the end* or hitting
389 you can then make it execute by appending a blank line *at the end* or hitting
390 ``Shift-Enter`` anywhere within the cell.
390 ``Shift-Enter`` anywhere within the cell.
391
391
392 With the up arrow key, you can retrieve previous blocks of input that contain
392 With the up arrow key, you can retrieve previous blocks of input that contain
393 multiple lines. You can move inside of a multiline cell like you would in any
393 multiple lines. You can move inside of a multiline cell like you would in any
394 text editor. When you want it executed, the simplest thing to do is to hit the
394 text editor. When you want it executed, the simplest thing to do is to hit the
395 force execution key, ``Shift-Enter`` (though you can also navigate to the end
395 force execution key, ``Shift-Enter`` (though you can also navigate to the end
396 and append a blank line by using ``Enter`` twice).
396 and append a blank line by using ``Enter`` twice).
397
397
398 If you've edited a multiline cell and accidentally navigate out of it with the
398 If you've edited a multiline cell and accidentally navigate out of it with the
399 up or down arrow keys, IPython will clear the cell and replace it with the
399 up or down arrow keys, IPython will clear the cell and replace it with the
400 contents of the one above or below that you navigated to. If this was an
400 contents of the one above or below that you navigated to. If this was an
401 accident and you want to retrieve the cell you were editing, use the Undo
401 accident and you want to retrieve the cell you were editing, use the Undo
402 keybinding, ``Control-z``.
402 keybinding, ``Control-z``.
403
403
404
404
405 Key bindings
405 Key bindings
406 ============
406 ============
407
407
408 The IPython console supports most of the basic Emacs line-oriented keybindings,
408 The IPython console supports most of the basic Emacs line-oriented keybindings,
409 in addition to some of its own.
409 in addition to some of its own.
410
410
411 The keybinding prefixes mean:
411 The keybinding prefixes mean:
412
412
413 - ``C``: Control
413 - ``C``: Control
414 - ``S``: Shift
414 - ``S``: Shift
415 - ``M``: Meta (typically the Alt key)
415 - ``M``: Meta (typically the Alt key)
416
416
417 The keybindings themselves are:
417 The keybindings themselves are:
418
418
419 - ``Enter``: insert new line (may cause execution, see above).
419 - ``Enter``: insert new line (may cause execution, see above).
420 - ``C-Enter``: *force* new line, *never* causes execution.
420 - ``C-Enter``: *force* new line, *never* causes execution.
421 - ``S-Enter``: *force* execution regardless of where cursor is, no newline added.
421 - ``S-Enter``: *force* execution regardless of where cursor is, no newline added.
422 - ``Up``: step backwards through the history.
422 - ``Up``: step backwards through the history.
423 - ``Down``: step forwards through the history.
423 - ``Down``: step forwards through the history.
424 - ``S-Up``: search backwards through the history (like ``C-r`` in bash).
424 - ``S-Up``: search backwards through the history (like ``C-r`` in bash).
425 - ``S-Down``: search forwards through the history.
425 - ``S-Down``: search forwards through the history.
426 - ``C-c``: copy highlighted text to clipboard (prompts are automatically stripped).
426 - ``C-c``: copy highlighted text to clipboard (prompts are automatically stripped).
427 - ``C-S-c``: copy highlighted text to clipboard (prompts are not stripped).
427 - ``C-S-c``: copy highlighted text to clipboard (prompts are not stripped).
428 - ``C-v``: paste text from clipboard.
428 - ``C-v``: paste text from clipboard.
429 - ``C-z``: undo (retrieves lost text if you move out of a cell with the arrows).
429 - ``C-z``: undo (retrieves lost text if you move out of a cell with the arrows).
430 - ``C-S-z``: redo.
430 - ``C-S-z``: redo.
431 - ``C-o``: move to 'other' area, between pager and terminal.
431 - ``C-o``: move to 'other' area, between pager and terminal.
432 - ``C-l``: clear terminal.
432 - ``C-l``: clear terminal.
433 - ``C-a``: go to beginning of line.
433 - ``C-a``: go to beginning of line.
434 - ``C-e``: go to end of line.
434 - ``C-e``: go to end of line.
435 - ``C-u``: kill from cursor to the begining of the line.
435 - ``C-u``: kill from cursor to the begining of the line.
436 - ``C-k``: kill from cursor to the end of the line.
436 - ``C-k``: kill from cursor to the end of the line.
437 - ``C-y``: yank (paste)
437 - ``C-y``: yank (paste)
438 - ``C-p``: previous line (like up arrow)
438 - ``C-p``: previous line (like up arrow)
439 - ``C-n``: next line (like down arrow)
439 - ``C-n``: next line (like down arrow)
440 - ``C-f``: forward (like right arrow)
440 - ``C-f``: forward (like right arrow)
441 - ``C-b``: back (like left arrow)
441 - ``C-b``: back (like left arrow)
442 - ``C-d``: delete next character, or exits if input is empty
442 - ``C-d``: delete next character, or exits if input is empty
443 - ``M-<``: move to the beginning of the input region.
443 - ``M-<``: move to the beginning of the input region.
444 - ``M->``: move to the end of the input region.
444 - ``M->``: move to the end of the input region.
445 - ``M-d``: delete next word.
445 - ``M-d``: delete next word.
446 - ``M-Backspace``: delete previous word.
446 - ``M-Backspace``: delete previous word.
447 - ``C-.``: force a kernel restart (a confirmation dialog appears).
447 - ``C-.``: force a kernel restart (a confirmation dialog appears).
448 - ``C-+``: increase font size.
448 - ``C-+``: increase font size.
449 - ``C--``: decrease font size.
449 - ``C--``: decrease font size.
450 - ``C-M-Space``: toggle full screen. (Command-Control-Space on Mac OS X)
450 - ``C-M-Space``: toggle full screen. (Command-Control-Space on Mac OS X)
451
451
452 The IPython pager
452 The IPython pager
453 =================
453 =================
454
454
455 IPython will show long blocks of text from many sources using a builtin pager.
455 IPython will show long blocks of text from many sources using a builtin pager.
456 You can control where this pager appears with the ``--paging`` command-line
456 You can control where this pager appears with the ``--paging`` command-line
457 flag:
457 flag:
458
458
459 - ``inside`` [default]: the pager is overlaid on top of the main terminal. You
459 - ``inside`` [default]: the pager is overlaid on top of the main terminal. You
460 must quit the pager to get back to the terminal (similar to how a pager such
460 must quit the pager to get back to the terminal (similar to how a pager such
461 as ``less`` or ``more`` works).
461 as ``less`` or ``more`` works).
462
462
463 - ``vsplit``: the console is made double-tall, and the pager appears on the
463 - ``vsplit``: the console is made double-tall, and the pager appears on the
464 bottom area when needed. You can view its contents while using the terminal.
464 bottom area when needed. You can view its contents while using the terminal.
465
465
466 - ``hsplit``: the console is made double-wide, and the pager appears on the
466 - ``hsplit``: the console is made double-wide, and the pager appears on the
467 right area when needed. You can view its contents while using the terminal.
467 right area when needed. You can view its contents while using the terminal.
468
468
469 - ``none``: the console never pages output.
469 - ``none``: the console never pages output.
470
470
471 If you use the vertical or horizontal paging modes, you can navigate between
471 If you use the vertical or horizontal paging modes, you can navigate between
472 terminal and pager as follows:
472 terminal and pager as follows:
473
473
474 - Tab key: goes from pager to terminal (but not the other way around).
474 - Tab key: goes from pager to terminal (but not the other way around).
475 - Control-o: goes from one to another always.
475 - Control-o: goes from one to another always.
476 - Mouse: click on either.
476 - Mouse: click on either.
477
477
478 In all cases, the ``q`` or ``Escape`` keys quit the pager (when used with the
478 In all cases, the ``q`` or ``Escape`` keys quit the pager (when used with the
479 focus on the pager area).
479 focus on the pager area).
480
480
481 Running subprocesses
481 Running subprocesses
482 ====================
482 ====================
483
483
484 The graphical IPython console uses the ``pexpect`` module to run subprocesses
484 The graphical IPython console uses the ``pexpect`` module to run subprocesses
485 when you type ``!command``. This has a number of advantages (true asynchronous
485 when you type ``!command``. This has a number of advantages (true asynchronous
486 output from subprocesses as well as very robust termination of rogue
486 output from subprocesses as well as very robust termination of rogue
487 subprocesses with ``Control-C``), as well as some limitations. The main
487 subprocesses with ``Control-C``), as well as some limitations. The main
488 limitation is that you can *not* interact back with the subprocess, so anything
488 limitation is that you can *not* interact back with the subprocess, so anything
489 that invokes a pager or expects you to type input into it will block and hang
489 that invokes a pager or expects you to type input into it will block and hang
490 (you can kill it with ``Control-C``).
490 (you can kill it with ``Control-C``).
491
491
492 We have provided as magics ``%less`` to page files (aliased to ``%more``),
492 We have provided as magics ``%less`` to page files (aliased to ``%more``),
493 ``%clear`` to clear the terminal, and ``%man`` on Linux/OSX. These cover the
493 ``%clear`` to clear the terminal, and ``%man`` on Linux/OSX. These cover the
494 most common commands you'd want to call in your subshell and that would cause
494 most common commands you'd want to call in your subshell and that would cause
495 problems if invoked via ``!cmd``, but you need to be aware of this limitation.
495 problems if invoked via ``!cmd``, but you need to be aware of this limitation.
496
496
497 Display
497 Display
498 =======
498 =======
499
499
500 The IPython console can now display objects in a variety of formats, including
500 The IPython console can now display objects in a variety of formats, including
501 HTML, PNG and SVG. This is accomplished using the display functions in
501 HTML, PNG and SVG. This is accomplished using the display functions in
502 ``IPython.core.display``::
502 ``IPython.core.display``::
503
503
504 In [4]: from IPython.core.display import display, display_html
504 In [4]: from IPython.core.display import display, display_html
505
505
506 In [5]: from IPython.core.display import display_png, display_svg
506 In [5]: from IPython.core.display import display_png, display_svg
507
507
508 Python objects can simply be passed to these functions and the appropriate
508 Python objects can simply be passed to these functions and the appropriate
509 representations will be displayed in the console as long as the objects know
509 representations will be displayed in the console as long as the objects know
510 how to compute those representations. The easiest way of teaching objects how
510 how to compute those representations. The easiest way of teaching objects how
511 to format themselves in various representations is to define special methods
511 to format themselves in various representations is to define special methods
512 such as: ``_repr_html_``, ``_repr_svg_`` and ``_repr_png_``. IPython's display formatters
512 such as: ``_repr_html_``, ``_repr_svg_`` and ``_repr_png_``. IPython's display formatters
513 can also be given custom formatter functions for various types::
513 can also be given custom formatter functions for various types::
514
514
515 In [6]: ip = get_ipython()
515 In [6]: ip = get_ipython()
516
516
517 In [7]: html_formatter = ip.display_formatter.formatters['text/html']
517 In [7]: html_formatter = ip.display_formatter.formatters['text/html']
518
518
519 In [8]: html_formatter.for_type(Foo, foo_to_html)
519 In [8]: html_formatter.for_type(Foo, foo_to_html)
520
520
521 For further details, see ``IPython.core.formatters``.
521 For further details, see ``IPython.core.formatters``.
522
522
523 Inline matplotlib graphics
523 Inline matplotlib graphics
524 ==========================
524 ==========================
525
525
526 The IPython console is capable of displaying matplotlib figures inline, in SVG
526 The IPython console is capable of displaying matplotlib figures inline, in SVG
527 or PNG format. If started with the ``matplotlib=inline``, then all figures are
527 or PNG format. If started with the ``matplotlib=inline``, then all figures are
528 rendered inline automatically (PNG by default). If started with ``--matplotlib``
528 rendered inline automatically (PNG by default). If started with ``--matplotlib``
529 or ``matplotlib=<your backend>``, then a GUI backend will be used, but IPython's
529 or ``matplotlib=<your backend>``, then a GUI backend will be used, but IPython's
530 ``display()`` and ``getfigs()`` functions can be used to view plots inline::
530 ``display()`` and ``getfigs()`` functions can be used to view plots inline::
531
531
532 In [9]: display(*getfigs()) # display all figures inline
532 In [9]: display(*getfigs()) # display all figures inline
533
533
534 In[10]: display(*getfigs(1,2)) # display figures 1 and 2 inline
534 In[10]: display(*getfigs(1,2)) # display figures 1 and 2 inline
535 """
535 """
536
536
537
537
538 quick_guide = """\
538 quick_guide = """\
539 ? -> Introduction and overview of IPython's features.
539 ? -> Introduction and overview of IPython's features.
540 %quickref -> Quick reference.
540 %quickref -> Quick reference.
541 help -> Python's own help system.
541 help -> Python's own help system.
542 object? -> Details about 'object', use 'object??' for extra details.
542 object? -> Details about 'object', use 'object??' for extra details.
543 """
543 """
544
544
545 gui_note = """\
545 gui_note = """\
546 %guiref -> A brief reference about the graphical user interface.
546 %guiref -> A brief reference about the graphical user interface.
547 """
547 """
548
548
549 default_banner_parts = [
549 default_banner_parts = [
550 'Python %s\n' % (sys.version.split('\n')[0],),
550 'Python %s\n' % (sys.version.split('\n')[0],),
551 'Type "copyright", "credits" or "license" for more information.\n\n',
551 'Type "copyright", "credits" or "license" for more information.\n\n',
552 'IPython {version} -- An enhanced Interactive Python.\n'.format(
552 'IPython {version} -- An enhanced Interactive Python.\n'.format(
553 version=release.version,
553 version=release.version,
554 ),
554 ),
555 quick_guide
555 quick_guide
556 ]
556 ]
557
557
558 default_gui_banner_parts = default_banner_parts + [gui_note]
558 default_gui_banner_parts = default_banner_parts + [gui_note]
559
559
560 default_banner = ''.join(default_banner_parts)
560 default_banner = ''.join(default_banner_parts)
561
561
562 default_gui_banner = ''.join(default_gui_banner_parts)
562 default_gui_banner = ''.join(default_gui_banner_parts)
563
563
564 # page GUI Reference, for use as a magic:
564 # page GUI Reference, for use as a magic:
565
565
566 def page_guiref(arg_s=None):
566 def page_guiref(arg_s=None):
567 """Show a basic reference about the GUI Console."""
567 """Show a basic reference about the GUI Console."""
568 from IPython.core import page
568 from IPython.core import page
569 page.page(gui_reference, auto_html=True)
569 page.page(gui_reference)
570
570
@@ -1,561 +1,560 b''
1 """A FrontendWidget that emulates the interface of the console IPython.
1 """A FrontendWidget that emulates the interface of the console IPython.
2
2
3 This supports the additional functionality provided by the IPython kernel.
3 This supports the additional functionality provided by the IPython kernel.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 from collections import namedtuple
9 from collections import namedtuple
10 import os.path
10 import os.path
11 import re
11 import re
12 from subprocess import Popen
12 from subprocess import Popen
13 import sys
13 import sys
14 import time
14 import time
15 from textwrap import dedent
15 from textwrap import dedent
16
16
17 from IPython.external.qt import QtCore, QtGui
17 from IPython.external.qt import QtCore, QtGui
18
18
19 from IPython.core.inputsplitter import IPythonInputSplitter
19 from IPython.core.inputsplitter import IPythonInputSplitter
20 from IPython.core.release import version
20 from IPython.core.release import version
21 from IPython.core.inputtransformer import ipy_prompt
21 from IPython.core.inputtransformer import ipy_prompt
22 from IPython.utils.traitlets import Bool, Unicode
22 from IPython.utils.traitlets import Bool, Unicode
23 from .frontend_widget import FrontendWidget
23 from .frontend_widget import FrontendWidget
24 from . import styles
24 from . import styles
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Constants
27 # Constants
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 # Default strings to build and display input and output prompts (and separators
30 # Default strings to build and display input and output prompts (and separators
31 # in between)
31 # in between)
32 default_in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
32 default_in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
33 default_out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
33 default_out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
34 default_input_sep = '\n'
34 default_input_sep = '\n'
35 default_output_sep = ''
35 default_output_sep = ''
36 default_output_sep2 = ''
36 default_output_sep2 = ''
37
37
38 # Base path for most payload sources.
38 # Base path for most payload sources.
39 zmq_shell_source = 'IPython.kernel.zmq.zmqshell.ZMQInteractiveShell'
39 zmq_shell_source = 'IPython.kernel.zmq.zmqshell.ZMQInteractiveShell'
40
40
41 if sys.platform.startswith('win'):
41 if sys.platform.startswith('win'):
42 default_editor = 'notepad'
42 default_editor = 'notepad'
43 else:
43 else:
44 default_editor = ''
44 default_editor = ''
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # IPythonWidget class
47 # IPythonWidget class
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class IPythonWidget(FrontendWidget):
50 class IPythonWidget(FrontendWidget):
51 """ A FrontendWidget for an IPython kernel.
51 """ A FrontendWidget for an IPython kernel.
52 """
52 """
53
53
54 # If set, the 'custom_edit_requested(str, int)' signal will be emitted when
54 # If set, the 'custom_edit_requested(str, int)' signal will be emitted when
55 # an editor is needed for a file. This overrides 'editor' and 'editor_line'
55 # an editor is needed for a file. This overrides 'editor' and 'editor_line'
56 # settings.
56 # settings.
57 custom_edit = Bool(False)
57 custom_edit = Bool(False)
58 custom_edit_requested = QtCore.Signal(object, object)
58 custom_edit_requested = QtCore.Signal(object, object)
59
59
60 editor = Unicode(default_editor, config=True,
60 editor = Unicode(default_editor, config=True,
61 help="""
61 help="""
62 A command for invoking a system text editor. If the string contains a
62 A command for invoking a system text editor. If the string contains a
63 {filename} format specifier, it will be used. Otherwise, the filename
63 {filename} format specifier, it will be used. Otherwise, the filename
64 will be appended to the end the command.
64 will be appended to the end the command.
65 """)
65 """)
66
66
67 editor_line = Unicode(config=True,
67 editor_line = Unicode(config=True,
68 help="""
68 help="""
69 The editor command to use when a specific line number is requested. The
69 The editor command to use when a specific line number is requested. The
70 string should contain two format specifiers: {line} and {filename}. If
70 string should contain two format specifiers: {line} and {filename}. If
71 this parameter is not specified, the line number option to the %edit
71 this parameter is not specified, the line number option to the %edit
72 magic will be ignored.
72 magic will be ignored.
73 """)
73 """)
74
74
75 style_sheet = Unicode(config=True,
75 style_sheet = Unicode(config=True,
76 help="""
76 help="""
77 A CSS stylesheet. The stylesheet can contain classes for:
77 A CSS stylesheet. The stylesheet can contain classes for:
78 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
78 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
79 2. Pygments: .c, .k, .o, etc. (see PygmentsHighlighter)
79 2. Pygments: .c, .k, .o, etc. (see PygmentsHighlighter)
80 3. IPython: .error, .in-prompt, .out-prompt, etc
80 3. IPython: .error, .in-prompt, .out-prompt, etc
81 """)
81 """)
82
82
83 syntax_style = Unicode(config=True,
83 syntax_style = Unicode(config=True,
84 help="""
84 help="""
85 If not empty, use this Pygments style for syntax highlighting.
85 If not empty, use this Pygments style for syntax highlighting.
86 Otherwise, the style sheet is queried for Pygments style
86 Otherwise, the style sheet is queried for Pygments style
87 information.
87 information.
88 """)
88 """)
89
89
90 # Prompts.
90 # Prompts.
91 in_prompt = Unicode(default_in_prompt, config=True)
91 in_prompt = Unicode(default_in_prompt, config=True)
92 out_prompt = Unicode(default_out_prompt, config=True)
92 out_prompt = Unicode(default_out_prompt, config=True)
93 input_sep = Unicode(default_input_sep, config=True)
93 input_sep = Unicode(default_input_sep, config=True)
94 output_sep = Unicode(default_output_sep, config=True)
94 output_sep = Unicode(default_output_sep, config=True)
95 output_sep2 = Unicode(default_output_sep2, config=True)
95 output_sep2 = Unicode(default_output_sep2, config=True)
96
96
97 # FrontendWidget protected class variables.
97 # FrontendWidget protected class variables.
98 _input_splitter_class = IPythonInputSplitter
98 _input_splitter_class = IPythonInputSplitter
99 _prompt_transformer = IPythonInputSplitter(physical_line_transforms=[ipy_prompt()],
99 _prompt_transformer = IPythonInputSplitter(physical_line_transforms=[ipy_prompt()],
100 logical_line_transforms=[],
100 logical_line_transforms=[],
101 python_line_transforms=[],
101 python_line_transforms=[],
102 )
102 )
103
103
104 # IPythonWidget protected class variables.
104 # IPythonWidget protected class variables.
105 _PromptBlock = namedtuple('_PromptBlock', ['block', 'length', 'number'])
105 _PromptBlock = namedtuple('_PromptBlock', ['block', 'length', 'number'])
106 _payload_source_edit = 'edit_magic'
106 _payload_source_edit = 'edit_magic'
107 _payload_source_exit = 'ask_exit'
107 _payload_source_exit = 'ask_exit'
108 _payload_source_next_input = 'set_next_input'
108 _payload_source_next_input = 'set_next_input'
109 _payload_source_page = 'page'
109 _payload_source_page = 'page'
110 _retrying_history_request = False
110 _retrying_history_request = False
111 _starting = False
111 _starting = False
112
112
113 #---------------------------------------------------------------------------
113 #---------------------------------------------------------------------------
114 # 'object' interface
114 # 'object' interface
115 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
116
116
117 def __init__(self, *args, **kw):
117 def __init__(self, *args, **kw):
118 super(IPythonWidget, self).__init__(*args, **kw)
118 super(IPythonWidget, self).__init__(*args, **kw)
119
119
120 # IPythonWidget protected variables.
120 # IPythonWidget protected variables.
121 self._payload_handlers = {
121 self._payload_handlers = {
122 self._payload_source_edit : self._handle_payload_edit,
122 self._payload_source_edit : self._handle_payload_edit,
123 self._payload_source_exit : self._handle_payload_exit,
123 self._payload_source_exit : self._handle_payload_exit,
124 self._payload_source_page : self._handle_payload_page,
124 self._payload_source_page : self._handle_payload_page,
125 self._payload_source_next_input : self._handle_payload_next_input }
125 self._payload_source_next_input : self._handle_payload_next_input }
126 self._previous_prompt_obj = None
126 self._previous_prompt_obj = None
127 self._keep_kernel_on_exit = None
127 self._keep_kernel_on_exit = None
128
128
129 # Initialize widget styling.
129 # Initialize widget styling.
130 if self.style_sheet:
130 if self.style_sheet:
131 self._style_sheet_changed()
131 self._style_sheet_changed()
132 self._syntax_style_changed()
132 self._syntax_style_changed()
133 else:
133 else:
134 self.set_default_style()
134 self.set_default_style()
135
135
136 self._guiref_loaded = False
136 self._guiref_loaded = False
137
137
138 #---------------------------------------------------------------------------
138 #---------------------------------------------------------------------------
139 # 'BaseFrontendMixin' abstract interface
139 # 'BaseFrontendMixin' abstract interface
140 #---------------------------------------------------------------------------
140 #---------------------------------------------------------------------------
141 def _handle_complete_reply(self, rep):
141 def _handle_complete_reply(self, rep):
142 """ Reimplemented to support IPython's improved completion machinery.
142 """ Reimplemented to support IPython's improved completion machinery.
143 """
143 """
144 self.log.debug("complete: %s", rep.get('content', ''))
144 self.log.debug("complete: %s", rep.get('content', ''))
145 cursor = self._get_cursor()
145 cursor = self._get_cursor()
146 info = self._request_info.get('complete')
146 info = self._request_info.get('complete')
147 if info and info.id == rep['parent_header']['msg_id'] and \
147 if info and info.id == rep['parent_header']['msg_id'] and \
148 info.pos == cursor.position():
148 info.pos == cursor.position():
149 content = rep['content']
149 content = rep['content']
150 matches = content['matches']
150 matches = content['matches']
151 start = content['cursor_start']
151 start = content['cursor_start']
152 end = content['cursor_end']
152 end = content['cursor_end']
153
153
154 offset = end - start
154 offset = end - start
155 # Move the cursor to the start of the match and complete.
155 # Move the cursor to the start of the match and complete.
156 cursor.movePosition(QtGui.QTextCursor.Left, n=offset)
156 cursor.movePosition(QtGui.QTextCursor.Left, n=offset)
157 self._complete_with_items(cursor, matches)
157 self._complete_with_items(cursor, matches)
158
158
159 def _handle_execute_reply(self, msg):
159 def _handle_execute_reply(self, msg):
160 """ Reimplemented to support prompt requests.
160 """ Reimplemented to support prompt requests.
161 """
161 """
162 msg_id = msg['parent_header'].get('msg_id')
162 msg_id = msg['parent_header'].get('msg_id')
163 info = self._request_info['execute'].get(msg_id)
163 info = self._request_info['execute'].get(msg_id)
164 if info and info.kind == 'prompt':
164 if info and info.kind == 'prompt':
165 content = msg['content']
165 content = msg['content']
166 if content['status'] == 'aborted':
166 if content['status'] == 'aborted':
167 self._show_interpreter_prompt()
167 self._show_interpreter_prompt()
168 else:
168 else:
169 number = content['execution_count'] + 1
169 number = content['execution_count'] + 1
170 self._show_interpreter_prompt(number)
170 self._show_interpreter_prompt(number)
171 self._request_info['execute'].pop(msg_id)
171 self._request_info['execute'].pop(msg_id)
172 else:
172 else:
173 super(IPythonWidget, self)._handle_execute_reply(msg)
173 super(IPythonWidget, self)._handle_execute_reply(msg)
174
174
175 def _handle_history_reply(self, msg):
175 def _handle_history_reply(self, msg):
176 """ Implemented to handle history tail replies, which are only supported
176 """ Implemented to handle history tail replies, which are only supported
177 by the IPython kernel.
177 by the IPython kernel.
178 """
178 """
179 content = msg['content']
179 content = msg['content']
180 if 'history' not in content:
180 if 'history' not in content:
181 self.log.error("History request failed: %r"%content)
181 self.log.error("History request failed: %r"%content)
182 if content.get('status', '') == 'aborted' and \
182 if content.get('status', '') == 'aborted' and \
183 not self._retrying_history_request:
183 not self._retrying_history_request:
184 # a *different* action caused this request to be aborted, so
184 # a *different* action caused this request to be aborted, so
185 # we should try again.
185 # we should try again.
186 self.log.error("Retrying aborted history request")
186 self.log.error("Retrying aborted history request")
187 # prevent multiple retries of aborted requests:
187 # prevent multiple retries of aborted requests:
188 self._retrying_history_request = True
188 self._retrying_history_request = True
189 # wait out the kernel's queue flush, which is currently timed at 0.1s
189 # wait out the kernel's queue flush, which is currently timed at 0.1s
190 time.sleep(0.25)
190 time.sleep(0.25)
191 self.kernel_client.shell_channel.history(hist_access_type='tail',n=1000)
191 self.kernel_client.shell_channel.history(hist_access_type='tail',n=1000)
192 else:
192 else:
193 self._retrying_history_request = False
193 self._retrying_history_request = False
194 return
194 return
195 # reset retry flag
195 # reset retry flag
196 self._retrying_history_request = False
196 self._retrying_history_request = False
197 history_items = content['history']
197 history_items = content['history']
198 self.log.debug("Received history reply with %i entries", len(history_items))
198 self.log.debug("Received history reply with %i entries", len(history_items))
199 items = []
199 items = []
200 last_cell = u""
200 last_cell = u""
201 for _, _, cell in history_items:
201 for _, _, cell in history_items:
202 cell = cell.rstrip()
202 cell = cell.rstrip()
203 if cell != last_cell:
203 if cell != last_cell:
204 items.append(cell)
204 items.append(cell)
205 last_cell = cell
205 last_cell = cell
206 self._set_history(items)
206 self._set_history(items)
207
207
208 def _handle_execute_result(self, msg):
208 def _handle_execute_result(self, msg):
209 """ Reimplemented for IPython-style "display hook".
209 """ Reimplemented for IPython-style "display hook".
210 """
210 """
211 self.log.debug("execute_result: %s", msg.get('content', ''))
211 self.log.debug("execute_result: %s", msg.get('content', ''))
212 if not self._hidden and self._is_from_this_session(msg):
212 if not self._hidden and self._is_from_this_session(msg):
213 self.flush_clearoutput()
213 self.flush_clearoutput()
214 content = msg['content']
214 content = msg['content']
215 prompt_number = content.get('execution_count', 0)
215 prompt_number = content.get('execution_count', 0)
216 data = content['data']
216 data = content['data']
217 if 'text/plain' in data:
217 if 'text/plain' in data:
218 self._append_plain_text(self.output_sep, True)
218 self._append_plain_text(self.output_sep, True)
219 self._append_html(self._make_out_prompt(prompt_number), True)
219 self._append_html(self._make_out_prompt(prompt_number), True)
220 text = data['text/plain']
220 text = data['text/plain']
221 # If the repr is multiline, make sure we start on a new line,
221 # If the repr is multiline, make sure we start on a new line,
222 # so that its lines are aligned.
222 # so that its lines are aligned.
223 if "\n" in text and not self.output_sep.endswith("\n"):
223 if "\n" in text and not self.output_sep.endswith("\n"):
224 self._append_plain_text('\n', True)
224 self._append_plain_text('\n', True)
225 self._append_plain_text(text + self.output_sep2, True)
225 self._append_plain_text(text + self.output_sep2, True)
226
226
227 def _handle_display_data(self, msg):
227 def _handle_display_data(self, msg):
228 """ The base handler for the ``display_data`` message.
228 """ The base handler for the ``display_data`` message.
229 """
229 """
230 self.log.debug("display: %s", msg.get('content', ''))
230 self.log.debug("display: %s", msg.get('content', ''))
231 # For now, we don't display data from other frontends, but we
231 # For now, we don't display data from other frontends, but we
232 # eventually will as this allows all frontends to monitor the display
232 # eventually will as this allows all frontends to monitor the display
233 # data. But we need to figure out how to handle this in the GUI.
233 # data. But we need to figure out how to handle this in the GUI.
234 if not self._hidden and self._is_from_this_session(msg):
234 if not self._hidden and self._is_from_this_session(msg):
235 self.flush_clearoutput()
235 self.flush_clearoutput()
236 source = msg['content']['source']
237 data = msg['content']['data']
236 data = msg['content']['data']
238 metadata = msg['content']['metadata']
237 metadata = msg['content']['metadata']
239 # In the regular IPythonWidget, we simply print the plain text
238 # In the regular IPythonWidget, we simply print the plain text
240 # representation.
239 # representation.
241 if 'text/plain' in data:
240 if 'text/plain' in data:
242 text = data['text/plain']
241 text = data['text/plain']
243 self._append_plain_text(text, True)
242 self._append_plain_text(text, True)
244 # This newline seems to be needed for text and html output.
243 # This newline seems to be needed for text and html output.
245 self._append_plain_text(u'\n', True)
244 self._append_plain_text(u'\n', True)
246
245
247 def _handle_kernel_info_reply(self, rep):
246 def _handle_kernel_info_reply(self, rep):
248 """Handle kernel info replies."""
247 """Handle kernel info replies."""
249 content = rep['content']
248 content = rep['content']
250 if not self._guiref_loaded:
249 if not self._guiref_loaded:
251 if content.get('language') == 'python':
250 if content.get('language') == 'python':
252 self._load_guiref_magic()
251 self._load_guiref_magic()
253 self._guiref_loaded = True
252 self._guiref_loaded = True
254
253
255 self.kernel_banner = content.get('banner', '')
254 self.kernel_banner = content.get('banner', '')
256 if self._starting:
255 if self._starting:
257 # finish handling started channels
256 # finish handling started channels
258 self._starting = False
257 self._starting = False
259 super(IPythonWidget, self)._started_channels()
258 super(IPythonWidget, self)._started_channels()
260
259
261 def _started_channels(self):
260 def _started_channels(self):
262 """Reimplemented to make a history request and load %guiref."""
261 """Reimplemented to make a history request and load %guiref."""
263 self._starting = True
262 self._starting = True
264 # The reply will trigger %guiref load provided language=='python'
263 # The reply will trigger %guiref load provided language=='python'
265 self.kernel_client.kernel_info()
264 self.kernel_client.kernel_info()
266
265
267 self.kernel_client.shell_channel.history(hist_access_type='tail',
266 self.kernel_client.shell_channel.history(hist_access_type='tail',
268 n=1000)
267 n=1000)
269
268
270 def _load_guiref_magic(self):
269 def _load_guiref_magic(self):
271 """Load %guiref magic."""
270 """Load %guiref magic."""
272 self.kernel_client.shell_channel.execute('\n'.join([
271 self.kernel_client.shell_channel.execute('\n'.join([
273 "try:",
272 "try:",
274 " _usage",
273 " _usage",
275 "except:",
274 "except:",
276 " from IPython.core import usage as _usage",
275 " from IPython.core import usage as _usage",
277 " get_ipython().register_magic_function(_usage.page_guiref, 'line', 'guiref')",
276 " get_ipython().register_magic_function(_usage.page_guiref, 'line', 'guiref')",
278 " del _usage",
277 " del _usage",
279 ]), silent=True)
278 ]), silent=True)
280
279
281 #---------------------------------------------------------------------------
280 #---------------------------------------------------------------------------
282 # 'ConsoleWidget' public interface
281 # 'ConsoleWidget' public interface
283 #---------------------------------------------------------------------------
282 #---------------------------------------------------------------------------
284
283
285 #---------------------------------------------------------------------------
284 #---------------------------------------------------------------------------
286 # 'FrontendWidget' public interface
285 # 'FrontendWidget' public interface
287 #---------------------------------------------------------------------------
286 #---------------------------------------------------------------------------
288
287
289 def execute_file(self, path, hidden=False):
288 def execute_file(self, path, hidden=False):
290 """ Reimplemented to use the 'run' magic.
289 """ Reimplemented to use the 'run' magic.
291 """
290 """
292 # Use forward slashes on Windows to avoid escaping each separator.
291 # Use forward slashes on Windows to avoid escaping each separator.
293 if sys.platform == 'win32':
292 if sys.platform == 'win32':
294 path = os.path.normpath(path).replace('\\', '/')
293 path = os.path.normpath(path).replace('\\', '/')
295
294
296 # Perhaps we should not be using %run directly, but while we
295 # Perhaps we should not be using %run directly, but while we
297 # are, it is necessary to quote or escape filenames containing spaces
296 # are, it is necessary to quote or escape filenames containing spaces
298 # or quotes.
297 # or quotes.
299
298
300 # In earlier code here, to minimize escaping, we sometimes quoted the
299 # In earlier code here, to minimize escaping, we sometimes quoted the
301 # filename with single quotes. But to do this, this code must be
300 # filename with single quotes. But to do this, this code must be
302 # platform-aware, because run uses shlex rather than python string
301 # platform-aware, because run uses shlex rather than python string
303 # parsing, so that:
302 # parsing, so that:
304 # * In Win: single quotes can be used in the filename without quoting,
303 # * In Win: single quotes can be used in the filename without quoting,
305 # and we cannot use single quotes to quote the filename.
304 # and we cannot use single quotes to quote the filename.
306 # * In *nix: we can escape double quotes in a double quoted filename,
305 # * In *nix: we can escape double quotes in a double quoted filename,
307 # but can't escape single quotes in a single quoted filename.
306 # but can't escape single quotes in a single quoted filename.
308
307
309 # So to keep this code non-platform-specific and simple, we now only
308 # So to keep this code non-platform-specific and simple, we now only
310 # use double quotes to quote filenames, and escape when needed:
309 # use double quotes to quote filenames, and escape when needed:
311 if ' ' in path or "'" in path or '"' in path:
310 if ' ' in path or "'" in path or '"' in path:
312 path = '"%s"' % path.replace('"', '\\"')
311 path = '"%s"' % path.replace('"', '\\"')
313 self.execute('%%run %s' % path, hidden=hidden)
312 self.execute('%%run %s' % path, hidden=hidden)
314
313
315 #---------------------------------------------------------------------------
314 #---------------------------------------------------------------------------
316 # 'FrontendWidget' protected interface
315 # 'FrontendWidget' protected interface
317 #---------------------------------------------------------------------------
316 #---------------------------------------------------------------------------
318
317
319 def _process_execute_error(self, msg):
318 def _process_execute_error(self, msg):
320 """ Reimplemented for IPython-style traceback formatting.
319 """ Reimplemented for IPython-style traceback formatting.
321 """
320 """
322 content = msg['content']
321 content = msg['content']
323 traceback = '\n'.join(content['traceback']) + '\n'
322 traceback = '\n'.join(content['traceback']) + '\n'
324 if False:
323 if False:
325 # FIXME: For now, tracebacks come as plain text, so we can't use
324 # FIXME: For now, tracebacks come as plain text, so we can't use
326 # the html renderer yet. Once we refactor ultratb to produce
325 # the html renderer yet. Once we refactor ultratb to produce
327 # properly styled tracebacks, this branch should be the default
326 # properly styled tracebacks, this branch should be the default
328 traceback = traceback.replace(' ', '&nbsp;')
327 traceback = traceback.replace(' ', '&nbsp;')
329 traceback = traceback.replace('\n', '<br/>')
328 traceback = traceback.replace('\n', '<br/>')
330
329
331 ename = content['ename']
330 ename = content['ename']
332 ename_styled = '<span class="error">%s</span>' % ename
331 ename_styled = '<span class="error">%s</span>' % ename
333 traceback = traceback.replace(ename, ename_styled)
332 traceback = traceback.replace(ename, ename_styled)
334
333
335 self._append_html(traceback)
334 self._append_html(traceback)
336 else:
335 else:
337 # This is the fallback for now, using plain text with ansi escapes
336 # This is the fallback for now, using plain text with ansi escapes
338 self._append_plain_text(traceback)
337 self._append_plain_text(traceback)
339
338
340 def _process_execute_payload(self, item):
339 def _process_execute_payload(self, item):
341 """ Reimplemented to dispatch payloads to handler methods.
340 """ Reimplemented to dispatch payloads to handler methods.
342 """
341 """
343 handler = self._payload_handlers.get(item['source'])
342 handler = self._payload_handlers.get(item['source'])
344 if handler is None:
343 if handler is None:
345 # We have no handler for this type of payload, simply ignore it
344 # We have no handler for this type of payload, simply ignore it
346 return False
345 return False
347 else:
346 else:
348 handler(item)
347 handler(item)
349 return True
348 return True
350
349
351 def _show_interpreter_prompt(self, number=None):
350 def _show_interpreter_prompt(self, number=None):
352 """ Reimplemented for IPython-style prompts.
351 """ Reimplemented for IPython-style prompts.
353 """
352 """
354 # If a number was not specified, make a prompt number request.
353 # If a number was not specified, make a prompt number request.
355 if number is None:
354 if number is None:
356 msg_id = self.kernel_client.shell_channel.execute('', silent=True)
355 msg_id = self.kernel_client.shell_channel.execute('', silent=True)
357 info = self._ExecutionRequest(msg_id, 'prompt')
356 info = self._ExecutionRequest(msg_id, 'prompt')
358 self._request_info['execute'][msg_id] = info
357 self._request_info['execute'][msg_id] = info
359 return
358 return
360
359
361 # Show a new prompt and save information about it so that it can be
360 # Show a new prompt and save information about it so that it can be
362 # updated later if the prompt number turns out to be wrong.
361 # updated later if the prompt number turns out to be wrong.
363 self._prompt_sep = self.input_sep
362 self._prompt_sep = self.input_sep
364 self._show_prompt(self._make_in_prompt(number), html=True)
363 self._show_prompt(self._make_in_prompt(number), html=True)
365 block = self._control.document().lastBlock()
364 block = self._control.document().lastBlock()
366 length = len(self._prompt)
365 length = len(self._prompt)
367 self._previous_prompt_obj = self._PromptBlock(block, length, number)
366 self._previous_prompt_obj = self._PromptBlock(block, length, number)
368
367
369 # Update continuation prompt to reflect (possibly) new prompt length.
368 # Update continuation prompt to reflect (possibly) new prompt length.
370 self._set_continuation_prompt(
369 self._set_continuation_prompt(
371 self._make_continuation_prompt(self._prompt), html=True)
370 self._make_continuation_prompt(self._prompt), html=True)
372
371
373 def _show_interpreter_prompt_for_reply(self, msg):
372 def _show_interpreter_prompt_for_reply(self, msg):
374 """ Reimplemented for IPython-style prompts.
373 """ Reimplemented for IPython-style prompts.
375 """
374 """
376 # Update the old prompt number if necessary.
375 # Update the old prompt number if necessary.
377 content = msg['content']
376 content = msg['content']
378 # abort replies do not have any keys:
377 # abort replies do not have any keys:
379 if content['status'] == 'aborted':
378 if content['status'] == 'aborted':
380 if self._previous_prompt_obj:
379 if self._previous_prompt_obj:
381 previous_prompt_number = self._previous_prompt_obj.number
380 previous_prompt_number = self._previous_prompt_obj.number
382 else:
381 else:
383 previous_prompt_number = 0
382 previous_prompt_number = 0
384 else:
383 else:
385 previous_prompt_number = content['execution_count']
384 previous_prompt_number = content['execution_count']
386 if self._previous_prompt_obj and \
385 if self._previous_prompt_obj and \
387 self._previous_prompt_obj.number != previous_prompt_number:
386 self._previous_prompt_obj.number != previous_prompt_number:
388 block = self._previous_prompt_obj.block
387 block = self._previous_prompt_obj.block
389
388
390 # Make sure the prompt block has not been erased.
389 # Make sure the prompt block has not been erased.
391 if block.isValid() and block.text():
390 if block.isValid() and block.text():
392
391
393 # Remove the old prompt and insert a new prompt.
392 # Remove the old prompt and insert a new prompt.
394 cursor = QtGui.QTextCursor(block)
393 cursor = QtGui.QTextCursor(block)
395 cursor.movePosition(QtGui.QTextCursor.Right,
394 cursor.movePosition(QtGui.QTextCursor.Right,
396 QtGui.QTextCursor.KeepAnchor,
395 QtGui.QTextCursor.KeepAnchor,
397 self._previous_prompt_obj.length)
396 self._previous_prompt_obj.length)
398 prompt = self._make_in_prompt(previous_prompt_number)
397 prompt = self._make_in_prompt(previous_prompt_number)
399 self._prompt = self._insert_html_fetching_plain_text(
398 self._prompt = self._insert_html_fetching_plain_text(
400 cursor, prompt)
399 cursor, prompt)
401
400
402 # When the HTML is inserted, Qt blows away the syntax
401 # When the HTML is inserted, Qt blows away the syntax
403 # highlighting for the line, so we need to rehighlight it.
402 # highlighting for the line, so we need to rehighlight it.
404 self._highlighter.rehighlightBlock(cursor.block())
403 self._highlighter.rehighlightBlock(cursor.block())
405
404
406 self._previous_prompt_obj = None
405 self._previous_prompt_obj = None
407
406
408 # Show a new prompt with the kernel's estimated prompt number.
407 # Show a new prompt with the kernel's estimated prompt number.
409 self._show_interpreter_prompt(previous_prompt_number + 1)
408 self._show_interpreter_prompt(previous_prompt_number + 1)
410
409
411 #---------------------------------------------------------------------------
410 #---------------------------------------------------------------------------
412 # 'IPythonWidget' interface
411 # 'IPythonWidget' interface
413 #---------------------------------------------------------------------------
412 #---------------------------------------------------------------------------
414
413
415 def set_default_style(self, colors='lightbg'):
414 def set_default_style(self, colors='lightbg'):
416 """ Sets the widget style to the class defaults.
415 """ Sets the widget style to the class defaults.
417
416
418 Parameters
417 Parameters
419 ----------
418 ----------
420 colors : str, optional (default lightbg)
419 colors : str, optional (default lightbg)
421 Whether to use the default IPython light background or dark
420 Whether to use the default IPython light background or dark
422 background or B&W style.
421 background or B&W style.
423 """
422 """
424 colors = colors.lower()
423 colors = colors.lower()
425 if colors=='lightbg':
424 if colors=='lightbg':
426 self.style_sheet = styles.default_light_style_sheet
425 self.style_sheet = styles.default_light_style_sheet
427 self.syntax_style = styles.default_light_syntax_style
426 self.syntax_style = styles.default_light_syntax_style
428 elif colors=='linux':
427 elif colors=='linux':
429 self.style_sheet = styles.default_dark_style_sheet
428 self.style_sheet = styles.default_dark_style_sheet
430 self.syntax_style = styles.default_dark_syntax_style
429 self.syntax_style = styles.default_dark_syntax_style
431 elif colors=='nocolor':
430 elif colors=='nocolor':
432 self.style_sheet = styles.default_bw_style_sheet
431 self.style_sheet = styles.default_bw_style_sheet
433 self.syntax_style = styles.default_bw_syntax_style
432 self.syntax_style = styles.default_bw_syntax_style
434 else:
433 else:
435 raise KeyError("No such color scheme: %s"%colors)
434 raise KeyError("No such color scheme: %s"%colors)
436
435
437 #---------------------------------------------------------------------------
436 #---------------------------------------------------------------------------
438 # 'IPythonWidget' protected interface
437 # 'IPythonWidget' protected interface
439 #---------------------------------------------------------------------------
438 #---------------------------------------------------------------------------
440
439
441 def _edit(self, filename, line=None):
440 def _edit(self, filename, line=None):
442 """ Opens a Python script for editing.
441 """ Opens a Python script for editing.
443
442
444 Parameters
443 Parameters
445 ----------
444 ----------
446 filename : str
445 filename : str
447 A path to a local system file.
446 A path to a local system file.
448
447
449 line : int, optional
448 line : int, optional
450 A line of interest in the file.
449 A line of interest in the file.
451 """
450 """
452 if self.custom_edit:
451 if self.custom_edit:
453 self.custom_edit_requested.emit(filename, line)
452 self.custom_edit_requested.emit(filename, line)
454 elif not self.editor:
453 elif not self.editor:
455 self._append_plain_text('No default editor available.\n'
454 self._append_plain_text('No default editor available.\n'
456 'Specify a GUI text editor in the `IPythonWidget.editor` '
455 'Specify a GUI text editor in the `IPythonWidget.editor` '
457 'configurable to enable the %edit magic')
456 'configurable to enable the %edit magic')
458 else:
457 else:
459 try:
458 try:
460 filename = '"%s"' % filename
459 filename = '"%s"' % filename
461 if line and self.editor_line:
460 if line and self.editor_line:
462 command = self.editor_line.format(filename=filename,
461 command = self.editor_line.format(filename=filename,
463 line=line)
462 line=line)
464 else:
463 else:
465 try:
464 try:
466 command = self.editor.format()
465 command = self.editor.format()
467 except KeyError:
466 except KeyError:
468 command = self.editor.format(filename=filename)
467 command = self.editor.format(filename=filename)
469 else:
468 else:
470 command += ' ' + filename
469 command += ' ' + filename
471 except KeyError:
470 except KeyError:
472 self._append_plain_text('Invalid editor command.\n')
471 self._append_plain_text('Invalid editor command.\n')
473 else:
472 else:
474 try:
473 try:
475 Popen(command, shell=True)
474 Popen(command, shell=True)
476 except OSError:
475 except OSError:
477 msg = 'Opening editor with command "%s" failed.\n'
476 msg = 'Opening editor with command "%s" failed.\n'
478 self._append_plain_text(msg % command)
477 self._append_plain_text(msg % command)
479
478
480 def _make_in_prompt(self, number):
479 def _make_in_prompt(self, number):
481 """ Given a prompt number, returns an HTML In prompt.
480 """ Given a prompt number, returns an HTML In prompt.
482 """
481 """
483 try:
482 try:
484 body = self.in_prompt % number
483 body = self.in_prompt % number
485 except TypeError:
484 except TypeError:
486 # allow in_prompt to leave out number, e.g. '>>> '
485 # allow in_prompt to leave out number, e.g. '>>> '
487 body = self.in_prompt
486 body = self.in_prompt
488 return '<span class="in-prompt">%s</span>' % body
487 return '<span class="in-prompt">%s</span>' % body
489
488
490 def _make_continuation_prompt(self, prompt):
489 def _make_continuation_prompt(self, prompt):
491 """ Given a plain text version of an In prompt, returns an HTML
490 """ Given a plain text version of an In prompt, returns an HTML
492 continuation prompt.
491 continuation prompt.
493 """
492 """
494 end_chars = '...: '
493 end_chars = '...: '
495 space_count = len(prompt.lstrip('\n')) - len(end_chars)
494 space_count = len(prompt.lstrip('\n')) - len(end_chars)
496 body = '&nbsp;' * space_count + end_chars
495 body = '&nbsp;' * space_count + end_chars
497 return '<span class="in-prompt">%s</span>' % body
496 return '<span class="in-prompt">%s</span>' % body
498
497
499 def _make_out_prompt(self, number):
498 def _make_out_prompt(self, number):
500 """ Given a prompt number, returns an HTML Out prompt.
499 """ Given a prompt number, returns an HTML Out prompt.
501 """
500 """
502 body = self.out_prompt % number
501 body = self.out_prompt % number
503 return '<span class="out-prompt">%s</span>' % body
502 return '<span class="out-prompt">%s</span>' % body
504
503
505 #------ Payload handlers --------------------------------------------------
504 #------ Payload handlers --------------------------------------------------
506
505
507 # Payload handlers with a generic interface: each takes the opaque payload
506 # Payload handlers with a generic interface: each takes the opaque payload
508 # dict, unpacks it and calls the underlying functions with the necessary
507 # dict, unpacks it and calls the underlying functions with the necessary
509 # arguments.
508 # arguments.
510
509
511 def _handle_payload_edit(self, item):
510 def _handle_payload_edit(self, item):
512 self._edit(item['filename'], item['line_number'])
511 self._edit(item['filename'], item['line_number'])
513
512
514 def _handle_payload_exit(self, item):
513 def _handle_payload_exit(self, item):
515 self._keep_kernel_on_exit = item['keepkernel']
514 self._keep_kernel_on_exit = item['keepkernel']
516 self.exit_requested.emit(self)
515 self.exit_requested.emit(self)
517
516
518 def _handle_payload_next_input(self, item):
517 def _handle_payload_next_input(self, item):
519 self.input_buffer = item['text']
518 self.input_buffer = item['text']
520
519
521 def _handle_payload_page(self, item):
520 def _handle_payload_page(self, item):
522 # Since the plain text widget supports only a very small subset of HTML
521 # Since the plain text widget supports only a very small subset of HTML
523 # and we have no control over the HTML source, we only page HTML
522 # and we have no control over the HTML source, we only page HTML
524 # payloads in the rich text widget.
523 # payloads in the rich text widget.
525 data = item['data']
524 data = item['data']
526 if 'text/html' in data and self.kind == 'rich':
525 if 'text/html' in data and self.kind == 'rich':
527 self._page(data['text/html'], html=True)
526 self._page(data['text/html'], html=True)
528 else:
527 else:
529 self._page(data['text/plain'], html=False)
528 self._page(data['text/plain'], html=False)
530
529
531 #------ Trait change handlers --------------------------------------------
530 #------ Trait change handlers --------------------------------------------
532
531
533 def _style_sheet_changed(self):
532 def _style_sheet_changed(self):
534 """ Set the style sheets of the underlying widgets.
533 """ Set the style sheets of the underlying widgets.
535 """
534 """
536 self.setStyleSheet(self.style_sheet)
535 self.setStyleSheet(self.style_sheet)
537 if self._control is not None:
536 if self._control is not None:
538 self._control.document().setDefaultStyleSheet(self.style_sheet)
537 self._control.document().setDefaultStyleSheet(self.style_sheet)
539 bg_color = self._control.palette().window().color()
538 bg_color = self._control.palette().window().color()
540 self._ansi_processor.set_background_color(bg_color)
539 self._ansi_processor.set_background_color(bg_color)
541
540
542 if self._page_control is not None:
541 if self._page_control is not None:
543 self._page_control.document().setDefaultStyleSheet(self.style_sheet)
542 self._page_control.document().setDefaultStyleSheet(self.style_sheet)
544
543
545
544
546
545
547 def _syntax_style_changed(self):
546 def _syntax_style_changed(self):
548 """ Set the style for the syntax highlighter.
547 """ Set the style for the syntax highlighter.
549 """
548 """
550 if self._highlighter is None:
549 if self._highlighter is None:
551 # ignore premature calls
550 # ignore premature calls
552 return
551 return
553 if self.syntax_style:
552 if self.syntax_style:
554 self._highlighter.set_style(self.syntax_style)
553 self._highlighter.set_style(self.syntax_style)
555 else:
554 else:
556 self._highlighter.set_style_sheet(self.style_sheet)
555 self._highlighter.set_style_sheet(self.style_sheet)
557
556
558 #------ Trait default initializers -----------------------------------------
557 #------ Trait default initializers -----------------------------------------
559
558
560 def _banner_default(self):
559 def _banner_default(self):
561 return "IPython QtConsole {version}\n".format(version=version)
560 return "IPython QtConsole {version}\n".format(version=version)
@@ -1,335 +1,334 b''
1 # Copyright (c) IPython Development Team.
1 # Copyright (c) IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
2 # Distributed under the terms of the Modified BSD License.
3
3
4 from base64 import decodestring
4 from base64 import decodestring
5 import os
5 import os
6 import re
6 import re
7
7
8 from IPython.external.qt import QtCore, QtGui
8 from IPython.external.qt import QtCore, QtGui
9
9
10 from IPython.utils.path import ensure_dir_exists
10 from IPython.utils.path import ensure_dir_exists
11 from IPython.utils.traitlets import Bool
11 from IPython.utils.traitlets import Bool
12 from IPython.qt.svg import save_svg, svg_to_clipboard, svg_to_image
12 from IPython.qt.svg import save_svg, svg_to_clipboard, svg_to_image
13 from .ipython_widget import IPythonWidget
13 from .ipython_widget import IPythonWidget
14
14
15
15
16 class RichIPythonWidget(IPythonWidget):
16 class RichIPythonWidget(IPythonWidget):
17 """ An IPythonWidget that supports rich text, including lists, images, and
17 """ An IPythonWidget that supports rich text, including lists, images, and
18 tables. Note that raw performance will be reduced compared to the plain
18 tables. Note that raw performance will be reduced compared to the plain
19 text version.
19 text version.
20 """
20 """
21
21
22 # RichIPythonWidget protected class variables.
22 # RichIPythonWidget protected class variables.
23 _payload_source_plot = 'IPython.kernel.zmq.pylab.backend_payload.add_plot_payload'
23 _payload_source_plot = 'IPython.kernel.zmq.pylab.backend_payload.add_plot_payload'
24 _jpg_supported = Bool(False)
24 _jpg_supported = Bool(False)
25
25
26 # Used to determine whether a given html export attempt has already
26 # Used to determine whether a given html export attempt has already
27 # displayed a warning about being unable to convert a png to svg.
27 # displayed a warning about being unable to convert a png to svg.
28 _svg_warning_displayed = False
28 _svg_warning_displayed = False
29
29
30 #---------------------------------------------------------------------------
30 #---------------------------------------------------------------------------
31 # 'object' interface
31 # 'object' interface
32 #---------------------------------------------------------------------------
32 #---------------------------------------------------------------------------
33
33
34 def __init__(self, *args, **kw):
34 def __init__(self, *args, **kw):
35 """ Create a RichIPythonWidget.
35 """ Create a RichIPythonWidget.
36 """
36 """
37 kw['kind'] = 'rich'
37 kw['kind'] = 'rich'
38 super(RichIPythonWidget, self).__init__(*args, **kw)
38 super(RichIPythonWidget, self).__init__(*args, **kw)
39
39
40 # Configure the ConsoleWidget HTML exporter for our formats.
40 # Configure the ConsoleWidget HTML exporter for our formats.
41 self._html_exporter.image_tag = self._get_image_tag
41 self._html_exporter.image_tag = self._get_image_tag
42
42
43 # Dictionary for resolving document resource names to SVG data.
43 # Dictionary for resolving document resource names to SVG data.
44 self._name_to_svg_map = {}
44 self._name_to_svg_map = {}
45
45
46 # Do we support jpg ?
46 # Do we support jpg ?
47 # it seems that sometime jpg support is a plugin of QT, so try to assume
47 # it seems that sometime jpg support is a plugin of QT, so try to assume
48 # it is not always supported.
48 # it is not always supported.
49 _supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
49 _supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
50 self._jpg_supported = 'jpeg' in _supported_format
50 self._jpg_supported = 'jpeg' in _supported_format
51
51
52
52
53 #---------------------------------------------------------------------------
53 #---------------------------------------------------------------------------
54 # 'ConsoleWidget' public interface overides
54 # 'ConsoleWidget' public interface overides
55 #---------------------------------------------------------------------------
55 #---------------------------------------------------------------------------
56
56
57 def export_html(self):
57 def export_html(self):
58 """ Shows a dialog to export HTML/XML in various formats.
58 """ Shows a dialog to export HTML/XML in various formats.
59
59
60 Overridden in order to reset the _svg_warning_displayed flag prior
60 Overridden in order to reset the _svg_warning_displayed flag prior
61 to the export running.
61 to the export running.
62 """
62 """
63 self._svg_warning_displayed = False
63 self._svg_warning_displayed = False
64 super(RichIPythonWidget, self).export_html()
64 super(RichIPythonWidget, self).export_html()
65
65
66
66
67 #---------------------------------------------------------------------------
67 #---------------------------------------------------------------------------
68 # 'ConsoleWidget' protected interface
68 # 'ConsoleWidget' protected interface
69 #---------------------------------------------------------------------------
69 #---------------------------------------------------------------------------
70
70
71 def _context_menu_make(self, pos):
71 def _context_menu_make(self, pos):
72 """ Reimplemented to return a custom context menu for images.
72 """ Reimplemented to return a custom context menu for images.
73 """
73 """
74 format = self._control.cursorForPosition(pos).charFormat()
74 format = self._control.cursorForPosition(pos).charFormat()
75 name = format.stringProperty(QtGui.QTextFormat.ImageName)
75 name = format.stringProperty(QtGui.QTextFormat.ImageName)
76 if name:
76 if name:
77 menu = QtGui.QMenu()
77 menu = QtGui.QMenu()
78
78
79 menu.addAction('Copy Image', lambda: self._copy_image(name))
79 menu.addAction('Copy Image', lambda: self._copy_image(name))
80 menu.addAction('Save Image As...', lambda: self._save_image(name))
80 menu.addAction('Save Image As...', lambda: self._save_image(name))
81 menu.addSeparator()
81 menu.addSeparator()
82
82
83 svg = self._name_to_svg_map.get(name, None)
83 svg = self._name_to_svg_map.get(name, None)
84 if svg is not None:
84 if svg is not None:
85 menu.addSeparator()
85 menu.addSeparator()
86 menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
86 menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
87 menu.addAction('Save SVG As...',
87 menu.addAction('Save SVG As...',
88 lambda: save_svg(svg, self._control))
88 lambda: save_svg(svg, self._control))
89 else:
89 else:
90 menu = super(RichIPythonWidget, self)._context_menu_make(pos)
90 menu = super(RichIPythonWidget, self)._context_menu_make(pos)
91 return menu
91 return menu
92
92
93 #---------------------------------------------------------------------------
93 #---------------------------------------------------------------------------
94 # 'BaseFrontendMixin' abstract interface
94 # 'BaseFrontendMixin' abstract interface
95 #---------------------------------------------------------------------------
95 #---------------------------------------------------------------------------
96 def _pre_image_append(self, msg, prompt_number):
96 def _pre_image_append(self, msg, prompt_number):
97 """ Append the Out[] prompt and make the output nicer
97 """ Append the Out[] prompt and make the output nicer
98
98
99 Shared code for some the following if statement
99 Shared code for some the following if statement
100 """
100 """
101 self.log.debug("execute_result: %s", msg.get('content', ''))
101 self.log.debug("execute_result: %s", msg.get('content', ''))
102 self._append_plain_text(self.output_sep, True)
102 self._append_plain_text(self.output_sep, True)
103 self._append_html(self._make_out_prompt(prompt_number), True)
103 self._append_html(self._make_out_prompt(prompt_number), True)
104 self._append_plain_text('\n', True)
104 self._append_plain_text('\n', True)
105
105
106 def _handle_execute_result(self, msg):
106 def _handle_execute_result(self, msg):
107 """ Overridden to handle rich data types, like SVG.
107 """ Overridden to handle rich data types, like SVG.
108 """
108 """
109 if not self._hidden and self._is_from_this_session(msg):
109 if not self._hidden and self._is_from_this_session(msg):
110 self.flush_clearoutput()
110 self.flush_clearoutput()
111 content = msg['content']
111 content = msg['content']
112 prompt_number = content.get('execution_count', 0)
112 prompt_number = content.get('execution_count', 0)
113 data = content['data']
113 data = content['data']
114 metadata = msg['content']['metadata']
114 metadata = msg['content']['metadata']
115 if 'image/svg+xml' in data:
115 if 'image/svg+xml' in data:
116 self._pre_image_append(msg, prompt_number)
116 self._pre_image_append(msg, prompt_number)
117 self._append_svg(data['image/svg+xml'], True)
117 self._append_svg(data['image/svg+xml'], True)
118 self._append_html(self.output_sep2, True)
118 self._append_html(self.output_sep2, True)
119 elif 'image/png' in data:
119 elif 'image/png' in data:
120 self._pre_image_append(msg, prompt_number)
120 self._pre_image_append(msg, prompt_number)
121 png = decodestring(data['image/png'].encode('ascii'))
121 png = decodestring(data['image/png'].encode('ascii'))
122 self._append_png(png, True, metadata=metadata.get('image/png', None))
122 self._append_png(png, True, metadata=metadata.get('image/png', None))
123 self._append_html(self.output_sep2, True)
123 self._append_html(self.output_sep2, True)
124 elif 'image/jpeg' in data and self._jpg_supported:
124 elif 'image/jpeg' in data and self._jpg_supported:
125 self._pre_image_append(msg, prompt_number)
125 self._pre_image_append(msg, prompt_number)
126 jpg = decodestring(data['image/jpeg'].encode('ascii'))
126 jpg = decodestring(data['image/jpeg'].encode('ascii'))
127 self._append_jpg(jpg, True, metadata=metadata.get('image/jpeg', None))
127 self._append_jpg(jpg, True, metadata=metadata.get('image/jpeg', None))
128 self._append_html(self.output_sep2, True)
128 self._append_html(self.output_sep2, True)
129 else:
129 else:
130 # Default back to the plain text representation.
130 # Default back to the plain text representation.
131 return super(RichIPythonWidget, self)._handle_execute_result(msg)
131 return super(RichIPythonWidget, self)._handle_execute_result(msg)
132
132
133 def _handle_display_data(self, msg):
133 def _handle_display_data(self, msg):
134 """ Overridden to handle rich data types, like SVG.
134 """ Overridden to handle rich data types, like SVG.
135 """
135 """
136 if not self._hidden and self._is_from_this_session(msg):
136 if not self._hidden and self._is_from_this_session(msg):
137 self.flush_clearoutput()
137 self.flush_clearoutput()
138 source = msg['content']['source']
139 data = msg['content']['data']
138 data = msg['content']['data']
140 metadata = msg['content']['metadata']
139 metadata = msg['content']['metadata']
141 # Try to use the svg or html representations.
140 # Try to use the svg or html representations.
142 # FIXME: Is this the right ordering of things to try?
141 # FIXME: Is this the right ordering of things to try?
143 if 'image/svg+xml' in data:
142 if 'image/svg+xml' in data:
144 self.log.debug("display: %s", msg.get('content', ''))
143 self.log.debug("display: %s", msg.get('content', ''))
145 svg = data['image/svg+xml']
144 svg = data['image/svg+xml']
146 self._append_svg(svg, True)
145 self._append_svg(svg, True)
147 elif 'image/png' in data:
146 elif 'image/png' in data:
148 self.log.debug("display: %s", msg.get('content', ''))
147 self.log.debug("display: %s", msg.get('content', ''))
149 # PNG data is base64 encoded as it passes over the network
148 # PNG data is base64 encoded as it passes over the network
150 # in a JSON structure so we decode it.
149 # in a JSON structure so we decode it.
151 png = decodestring(data['image/png'].encode('ascii'))
150 png = decodestring(data['image/png'].encode('ascii'))
152 self._append_png(png, True, metadata=metadata.get('image/png', None))
151 self._append_png(png, True, metadata=metadata.get('image/png', None))
153 elif 'image/jpeg' in data and self._jpg_supported:
152 elif 'image/jpeg' in data and self._jpg_supported:
154 self.log.debug("display: %s", msg.get('content', ''))
153 self.log.debug("display: %s", msg.get('content', ''))
155 jpg = decodestring(data['image/jpeg'].encode('ascii'))
154 jpg = decodestring(data['image/jpeg'].encode('ascii'))
156 self._append_jpg(jpg, True, metadata=metadata.get('image/jpeg', None))
155 self._append_jpg(jpg, True, metadata=metadata.get('image/jpeg', None))
157 else:
156 else:
158 # Default back to the plain text representation.
157 # Default back to the plain text representation.
159 return super(RichIPythonWidget, self)._handle_display_data(msg)
158 return super(RichIPythonWidget, self)._handle_display_data(msg)
160
159
161 #---------------------------------------------------------------------------
160 #---------------------------------------------------------------------------
162 # 'RichIPythonWidget' protected interface
161 # 'RichIPythonWidget' protected interface
163 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
164
163
165 def _append_jpg(self, jpg, before_prompt=False, metadata=None):
164 def _append_jpg(self, jpg, before_prompt=False, metadata=None):
166 """ Append raw JPG data to the widget."""
165 """ Append raw JPG data to the widget."""
167 self._append_custom(self._insert_jpg, jpg, before_prompt, metadata=metadata)
166 self._append_custom(self._insert_jpg, jpg, before_prompt, metadata=metadata)
168
167
169 def _append_png(self, png, before_prompt=False, metadata=None):
168 def _append_png(self, png, before_prompt=False, metadata=None):
170 """ Append raw PNG data to the widget.
169 """ Append raw PNG data to the widget.
171 """
170 """
172 self._append_custom(self._insert_png, png, before_prompt, metadata=metadata)
171 self._append_custom(self._insert_png, png, before_prompt, metadata=metadata)
173
172
174 def _append_svg(self, svg, before_prompt=False):
173 def _append_svg(self, svg, before_prompt=False):
175 """ Append raw SVG data to the widget.
174 """ Append raw SVG data to the widget.
176 """
175 """
177 self._append_custom(self._insert_svg, svg, before_prompt)
176 self._append_custom(self._insert_svg, svg, before_prompt)
178
177
179 def _add_image(self, image):
178 def _add_image(self, image):
180 """ Adds the specified QImage to the document and returns a
179 """ Adds the specified QImage to the document and returns a
181 QTextImageFormat that references it.
180 QTextImageFormat that references it.
182 """
181 """
183 document = self._control.document()
182 document = self._control.document()
184 name = str(image.cacheKey())
183 name = str(image.cacheKey())
185 document.addResource(QtGui.QTextDocument.ImageResource,
184 document.addResource(QtGui.QTextDocument.ImageResource,
186 QtCore.QUrl(name), image)
185 QtCore.QUrl(name), image)
187 format = QtGui.QTextImageFormat()
186 format = QtGui.QTextImageFormat()
188 format.setName(name)
187 format.setName(name)
189 return format
188 return format
190
189
191 def _copy_image(self, name):
190 def _copy_image(self, name):
192 """ Copies the ImageResource with 'name' to the clipboard.
191 """ Copies the ImageResource with 'name' to the clipboard.
193 """
192 """
194 image = self._get_image(name)
193 image = self._get_image(name)
195 QtGui.QApplication.clipboard().setImage(image)
194 QtGui.QApplication.clipboard().setImage(image)
196
195
197 def _get_image(self, name):
196 def _get_image(self, name):
198 """ Returns the QImage stored as the ImageResource with 'name'.
197 """ Returns the QImage stored as the ImageResource with 'name'.
199 """
198 """
200 document = self._control.document()
199 document = self._control.document()
201 image = document.resource(QtGui.QTextDocument.ImageResource,
200 image = document.resource(QtGui.QTextDocument.ImageResource,
202 QtCore.QUrl(name))
201 QtCore.QUrl(name))
203 return image
202 return image
204
203
205 def _get_image_tag(self, match, path = None, format = "png"):
204 def _get_image_tag(self, match, path = None, format = "png"):
206 """ Return (X)HTML mark-up for the image-tag given by match.
205 """ Return (X)HTML mark-up for the image-tag given by match.
207
206
208 Parameters
207 Parameters
209 ----------
208 ----------
210 match : re.SRE_Match
209 match : re.SRE_Match
211 A match to an HTML image tag as exported by Qt, with
210 A match to an HTML image tag as exported by Qt, with
212 match.group("Name") containing the matched image ID.
211 match.group("Name") containing the matched image ID.
213
212
214 path : string|None, optional [default None]
213 path : string|None, optional [default None]
215 If not None, specifies a path to which supporting files may be
214 If not None, specifies a path to which supporting files may be
216 written (e.g., for linked images). If None, all images are to be
215 written (e.g., for linked images). If None, all images are to be
217 included inline.
216 included inline.
218
217
219 format : "png"|"svg"|"jpg", optional [default "png"]
218 format : "png"|"svg"|"jpg", optional [default "png"]
220 Format for returned or referenced images.
219 Format for returned or referenced images.
221 """
220 """
222 if format in ("png","jpg"):
221 if format in ("png","jpg"):
223 try:
222 try:
224 image = self._get_image(match.group("name"))
223 image = self._get_image(match.group("name"))
225 except KeyError:
224 except KeyError:
226 return "<b>Couldn't find image %s</b>" % match.group("name")
225 return "<b>Couldn't find image %s</b>" % match.group("name")
227
226
228 if path is not None:
227 if path is not None:
229 ensure_dir_exists(path)
228 ensure_dir_exists(path)
230 relpath = os.path.basename(path)
229 relpath = os.path.basename(path)
231 if image.save("%s/qt_img%s.%s" % (path, match.group("name"), format),
230 if image.save("%s/qt_img%s.%s" % (path, match.group("name"), format),
232 "PNG"):
231 "PNG"):
233 return '<img src="%s/qt_img%s.%s">' % (relpath,
232 return '<img src="%s/qt_img%s.%s">' % (relpath,
234 match.group("name"),format)
233 match.group("name"),format)
235 else:
234 else:
236 return "<b>Couldn't save image!</b>"
235 return "<b>Couldn't save image!</b>"
237 else:
236 else:
238 ba = QtCore.QByteArray()
237 ba = QtCore.QByteArray()
239 buffer_ = QtCore.QBuffer(ba)
238 buffer_ = QtCore.QBuffer(ba)
240 buffer_.open(QtCore.QIODevice.WriteOnly)
239 buffer_.open(QtCore.QIODevice.WriteOnly)
241 image.save(buffer_, format.upper())
240 image.save(buffer_, format.upper())
242 buffer_.close()
241 buffer_.close()
243 return '<img src="data:image/%s;base64,\n%s\n" />' % (
242 return '<img src="data:image/%s;base64,\n%s\n" />' % (
244 format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
243 format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
245
244
246 elif format == "svg":
245 elif format == "svg":
247 try:
246 try:
248 svg = str(self._name_to_svg_map[match.group("name")])
247 svg = str(self._name_to_svg_map[match.group("name")])
249 except KeyError:
248 except KeyError:
250 if not self._svg_warning_displayed:
249 if not self._svg_warning_displayed:
251 QtGui.QMessageBox.warning(self, 'Error converting PNG to SVG.',
250 QtGui.QMessageBox.warning(self, 'Error converting PNG to SVG.',
252 'Cannot convert PNG images to SVG, export with PNG figures instead. '
251 'Cannot convert PNG images to SVG, export with PNG figures instead. '
253 'If you want to export matplotlib figures as SVG, add '
252 'If you want to export matplotlib figures as SVG, add '
254 'to your ipython config:\n\n'
253 'to your ipython config:\n\n'
255 '\tc.InlineBackend.figure_format = \'svg\'\n\n'
254 '\tc.InlineBackend.figure_format = \'svg\'\n\n'
256 'And regenerate the figures.',
255 'And regenerate the figures.',
257 QtGui.QMessageBox.Ok)
256 QtGui.QMessageBox.Ok)
258 self._svg_warning_displayed = True
257 self._svg_warning_displayed = True
259 return ("<b>Cannot convert PNG images to SVG.</b> "
258 return ("<b>Cannot convert PNG images to SVG.</b> "
260 "You must export this session with PNG images. "
259 "You must export this session with PNG images. "
261 "If you want to export matplotlib figures as SVG, add to your config "
260 "If you want to export matplotlib figures as SVG, add to your config "
262 "<span>c.InlineBackend.figure_format = 'svg'</span> "
261 "<span>c.InlineBackend.figure_format = 'svg'</span> "
263 "and regenerate the figures.")
262 "and regenerate the figures.")
264
263
265 # Not currently checking path, because it's tricky to find a
264 # Not currently checking path, because it's tricky to find a
266 # cross-browser way to embed external SVG images (e.g., via
265 # cross-browser way to embed external SVG images (e.g., via
267 # object or embed tags).
266 # object or embed tags).
268
267
269 # Chop stand-alone header from matplotlib SVG
268 # Chop stand-alone header from matplotlib SVG
270 offset = svg.find("<svg")
269 offset = svg.find("<svg")
271 assert(offset > -1)
270 assert(offset > -1)
272
271
273 return svg[offset:]
272 return svg[offset:]
274
273
275 else:
274 else:
276 return '<b>Unrecognized image format</b>'
275 return '<b>Unrecognized image format</b>'
277
276
278 def _insert_jpg(self, cursor, jpg, metadata=None):
277 def _insert_jpg(self, cursor, jpg, metadata=None):
279 """ Insert raw PNG data into the widget."""
278 """ Insert raw PNG data into the widget."""
280 self._insert_img(cursor, jpg, 'jpg', metadata=metadata)
279 self._insert_img(cursor, jpg, 'jpg', metadata=metadata)
281
280
282 def _insert_png(self, cursor, png, metadata=None):
281 def _insert_png(self, cursor, png, metadata=None):
283 """ Insert raw PNG data into the widget.
282 """ Insert raw PNG data into the widget.
284 """
283 """
285 self._insert_img(cursor, png, 'png', metadata=metadata)
284 self._insert_img(cursor, png, 'png', metadata=metadata)
286
285
287 def _insert_img(self, cursor, img, fmt, metadata=None):
286 def _insert_img(self, cursor, img, fmt, metadata=None):
288 """ insert a raw image, jpg or png """
287 """ insert a raw image, jpg or png """
289 if metadata:
288 if metadata:
290 width = metadata.get('width', None)
289 width = metadata.get('width', None)
291 height = metadata.get('height', None)
290 height = metadata.get('height', None)
292 else:
291 else:
293 width = height = None
292 width = height = None
294 try:
293 try:
295 image = QtGui.QImage()
294 image = QtGui.QImage()
296 image.loadFromData(img, fmt.upper())
295 image.loadFromData(img, fmt.upper())
297 if width and height:
296 if width and height:
298 image = image.scaled(width, height, transformMode=QtCore.Qt.SmoothTransformation)
297 image = image.scaled(width, height, transformMode=QtCore.Qt.SmoothTransformation)
299 elif width and not height:
298 elif width and not height:
300 image = image.scaledToWidth(width, transformMode=QtCore.Qt.SmoothTransformation)
299 image = image.scaledToWidth(width, transformMode=QtCore.Qt.SmoothTransformation)
301 elif height and not width:
300 elif height and not width:
302 image = image.scaledToHeight(height, transformMode=QtCore.Qt.SmoothTransformation)
301 image = image.scaledToHeight(height, transformMode=QtCore.Qt.SmoothTransformation)
303 except ValueError:
302 except ValueError:
304 self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt)
303 self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt)
305 else:
304 else:
306 format = self._add_image(image)
305 format = self._add_image(image)
307 cursor.insertBlock()
306 cursor.insertBlock()
308 cursor.insertImage(format)
307 cursor.insertImage(format)
309 cursor.insertBlock()
308 cursor.insertBlock()
310
309
311 def _insert_svg(self, cursor, svg):
310 def _insert_svg(self, cursor, svg):
312 """ Insert raw SVG data into the widet.
311 """ Insert raw SVG data into the widet.
313 """
312 """
314 try:
313 try:
315 image = svg_to_image(svg)
314 image = svg_to_image(svg)
316 except ValueError:
315 except ValueError:
317 self._insert_plain_text(cursor, 'Received invalid SVG data.')
316 self._insert_plain_text(cursor, 'Received invalid SVG data.')
318 else:
317 else:
319 format = self._add_image(image)
318 format = self._add_image(image)
320 self._name_to_svg_map[format.name()] = svg
319 self._name_to_svg_map[format.name()] = svg
321 cursor.insertBlock()
320 cursor.insertBlock()
322 cursor.insertImage(format)
321 cursor.insertImage(format)
323 cursor.insertBlock()
322 cursor.insertBlock()
324
323
325 def _save_image(self, name, format='PNG'):
324 def _save_image(self, name, format='PNG'):
326 """ Shows a save dialog for the ImageResource with 'name'.
325 """ Shows a save dialog for the ImageResource with 'name'.
327 """
326 """
328 dialog = QtGui.QFileDialog(self._control, 'Save Image')
327 dialog = QtGui.QFileDialog(self._control, 'Save Image')
329 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
328 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
330 dialog.setDefaultSuffix(format.lower())
329 dialog.setDefaultSuffix(format.lower())
331 dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
330 dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
332 if dialog.exec_():
331 if dialog.exec_():
333 filename = dialog.selectedFiles()[0]
332 filename = dialog.selectedFiles()[0]
334 image = self._get_image(name)
333 image = self._get_image(name)
335 image.save(filename, format)
334 image.save(filename, format)
General Comments 0
You need to be logged in to leave comments. Login now