##// END OF EJS Templates
Minor updates to reflect comments
mr.Shu -
Show More
@@ -1,733 +1,736 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Subclass of InteractiveShell for terminal based frontends."""
2 """Subclass of InteractiveShell for terminal based frontends."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 import bdb
18 import bdb
19 import os
19 import os
20 import re
20 import re
21 import sys
21 import sys
22 import textwrap
22 import textwrap
23
23
24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
25 # use the with keyword's new builtin support for nested managers
25 # use the with keyword's new builtin support for nested managers
26 try:
26 try:
27 from contextlib import nested
27 from contextlib import nested
28 except:
28 except:
29 from IPython.utils.nested_context import nested
29 from IPython.utils.nested_context import nested
30
30
31 from IPython.core.error import TryNext, UsageError
31 from IPython.core.error import TryNext, UsageError
32 from IPython.core.usage import interactive_usage, default_banner
32 from IPython.core.usage import interactive_usage, default_banner
33 from IPython.core.inputsplitter import IPythonInputSplitter
33 from IPython.core.inputsplitter import IPythonInputSplitter
34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
35 from IPython.core.magic import Magics, magics_class, line_magic
35 from IPython.core.magic import Magics, magics_class, line_magic
36 from IPython.testing.skipdoctest import skip_doctest
36 from IPython.testing.skipdoctest import skip_doctest
37 from IPython.utils.encoding import get_stream_enc
37 from IPython.utils.encoding import get_stream_enc
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
40 from IPython.utils.process import abbrev_cwd
40 from IPython.utils.process import abbrev_cwd
41 from IPython.utils.warn import warn, error
41 from IPython.utils.warn import warn, error
42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
43 from IPython.utils.traitlets import Integer, CBool, Unicode
43 from IPython.utils.traitlets import Integer, CBool, Unicode
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Utilities
46 # Utilities
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49 def get_default_editor():
49 def get_default_editor():
50 try:
50 try:
51 ed = os.environ['EDITOR']
51 ed = os.environ['EDITOR']
52 except KeyError:
52 except KeyError:
53 if os.name == 'posix':
53 if os.name == 'posix':
54 ed = 'vi' # the only one guaranteed to be there!
54 ed = 'vi' # the only one guaranteed to be there!
55 else:
55 else:
56 ed = 'notepad' # same in Windows!
56 ed = 'notepad' # same in Windows!
57 return ed
57 return ed
58
58
59
59
60 def get_pasted_lines(sentinel, l_input=py3compat.input):
60 def get_pasted_lines(sentinel, l_input=py3compat.input):
61 """ Yield pasted lines until the user enters the given sentinel value.
61 """ Yield pasted lines until the user enters the given sentinel value.
62 """
62 """
63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
64 % sentinel)
64 % sentinel)
65 while True:
65 while True:
66 try:
66 try:
67 l = l_input(':')
67 l = l_input(':')
68 if l == sentinel:
68 if l == sentinel:
69 return
69 return
70 else:
70 else:
71 yield l
71 yield l
72 except EOFError:
72 except EOFError:
73 print('<EOF>')
73 print('<EOF>')
74 return
74 return
75
75
76
76
77 #------------------------------------------------------------------------
77 #------------------------------------------------------------------------
78 # Terminal-specific magics
78 # Terminal-specific magics
79 #------------------------------------------------------------------------
79 #------------------------------------------------------------------------
80
80
81 @magics_class
81 @magics_class
82 class TerminalMagics(Magics):
82 class TerminalMagics(Magics):
83 def __init__(self, shell):
83 def __init__(self, shell):
84 super(TerminalMagics, self).__init__(shell)
84 super(TerminalMagics, self).__init__(shell)
85 self.input_splitter = IPythonInputSplitter(input_mode='line')
85 self.input_splitter = IPythonInputSplitter(input_mode='line')
86
86
87 def cleanup_input(self, block):
87 def cleanup_input(self, block):
88 """Apply all possible IPython cleanups to an input block.
88 """Apply all possible IPython cleanups to an input block.
89
89
90 This means:
90 This means:
91
91
92 - remove any global leading whitespace (dedent)
92 - remove any global leading whitespace (dedent)
93 - remove any email quotes ('>') if they are present in *all* lines
93 - remove any email quotes ('>') if they are present in *all* lines
94 - apply all static inputsplitter transforms and break into sub-blocks
94 - apply all static inputsplitter transforms and break into sub-blocks
95 - apply prefilter() to each sub-block that is a single line.
95 - apply prefilter() to each sub-block that is a single line.
96
96
97 Parameters
97 Parameters
98 ----------
98 ----------
99 block : str
99 block : str
100 A possibly multiline input string of code.
100 A possibly multiline input string of code.
101
101
102 Returns
102 Returns
103 -------
103 -------
104 transformed block : str
104 transformed block : str
105 The input, with all transformations above applied.
105 The input, with all transformations above applied.
106 """
106 """
107 # We have to effectively implement client-side the loop that is done by
107 # We have to effectively implement client-side the loop that is done by
108 # the terminal frontend, and furthermore do it on a block that can
108 # the terminal frontend, and furthermore do it on a block that can
109 # possibly contain multiple statments pasted in one go.
109 # possibly contain multiple statments pasted in one go.
110
110
111 # First, run the input through the block splitting code. We should
111 # First, run the input through the block splitting code. We should
112 # eventually make this a self-contained method in the inputsplitter.
112 # eventually make this a self-contained method in the inputsplitter.
113 isp = self.input_splitter
113 isp = self.input_splitter
114 isp.reset()
114 isp.reset()
115 b = textwrap.dedent(block)
115 b = textwrap.dedent(block)
116
116
117 # Remove email quotes first. These must be consistently applied to
117 # Remove email quotes first. These must be consistently applied to
118 # *all* lines to be removed
118 # *all* lines to be removed
119 b = strip_email_quotes(b)
119 b = strip_email_quotes(b)
120
120
121 # Split the input into independent sub-blocks so we can later do
121 # Split the input into independent sub-blocks so we can later do
122 # prefiltering (which must be done *only* to single-line inputs)
122 # prefiltering (which must be done *only* to single-line inputs)
123 blocks = []
123 blocks = []
124 last_block = []
124 last_block = []
125 for line in b.splitlines():
125 for line in b.splitlines():
126 isp.push(line)
126 isp.push(line)
127 last_block.append(line)
127 last_block.append(line)
128 if not isp.push_accepts_more():
128 if not isp.push_accepts_more():
129 blocks.append(isp.source_reset())
129 blocks.append(isp.source_reset())
130 last_block = []
130 last_block = []
131 if last_block:
131 if last_block:
132 blocks.append('\n'.join(last_block))
132 blocks.append('\n'.join(last_block))
133
133
134 # Now, apply prefiltering to any one-line block to match the behavior
134 # Now, apply prefiltering to any one-line block to match the behavior
135 # of the interactive terminal
135 # of the interactive terminal
136 final_blocks = []
136 final_blocks = []
137 for block in blocks:
137 for block in blocks:
138 lines = block.splitlines()
138 lines = block.splitlines()
139 if len(lines) == 1:
139 if len(lines) == 1:
140 final_blocks.append(self.shell.prefilter(lines[0]))
140 final_blocks.append(self.shell.prefilter(lines[0]))
141 else:
141 else:
142 final_blocks.append(block)
142 final_blocks.append(block)
143
143
144 # We now have the final version of the input code as a list of blocks,
144 # We now have the final version of the input code as a list of blocks,
145 # with all inputsplitter transformations applied and single-line blocks
145 # with all inputsplitter transformations applied and single-line blocks
146 # run through prefilter. For further processing, turn into a single
146 # run through prefilter. For further processing, turn into a single
147 # string as the rest of our apis use string inputs.
147 # string as the rest of our apis use string inputs.
148 return '\n'.join(final_blocks)
148 return '\n'.join(final_blocks)
149
149
150 def store_or_execute(self, block, name):
150 def store_or_execute(self, block, name):
151 """ Execute a block, or store it in a variable, per the user's request.
151 """ Execute a block, or store it in a variable, per the user's request.
152 """
152 """
153 self.shell.using_magics = True
154
153
155 b = self.cleanup_input(block)
154 b = self.cleanup_input(block)
156 if name:
155 if name:
157 # If storing it for further editing
156 # If storing it for further editing
158 self.shell.user_ns[name] = SList(b.splitlines())
157 self.shell.user_ns[name] = SList(b.splitlines())
159 print("Block assigned to '%s'" % name)
158 print("Block assigned to '%s'" % name)
160 else:
159 else:
161 self.shell.user_ns['pasted_block'] = b
160 self.shell.user_ns['pasted_block'] = b
161 self.shell.using_paste_magics = True
162 self.shell.run_cell(b)
162 self.shell.run_cell(b)
163 self.shell.using_paste_magics = True
163
164
164 def rerun_pasted(self, name='pasted_block'):
165 def rerun_pasted(self, name='pasted_block'):
165 """ Rerun a previously pasted command.
166 """ Rerun a previously pasted command.
166 """
167 """
167 b = self.shell.user_ns.get(name)
168 b = self.shell.user_ns.get(name)
168
169
169 # Sanity checks
170 # Sanity checks
170 if b is None:
171 if b is None:
171 raise UsageError('No previous pasted block available')
172 raise UsageError('No previous pasted block available')
172 if not isinstance(b, basestring):
173 if not isinstance(b, basestring):
173 raise UsageError(
174 raise UsageError(
174 "Variable 'pasted_block' is not a string, can't execute")
175 "Variable 'pasted_block' is not a string, can't execute")
175
176
176 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
177 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
177 self.shell.run_cell(b)
178 self.shell.run_cell(b)
178
179
179 @line_magic
180 @line_magic
180 def autoindent(self, parameter_s = ''):
181 def autoindent(self, parameter_s = ''):
181 """Toggle autoindent on/off (if available)."""
182 """Toggle autoindent on/off (if available)."""
182
183
183 self.shell.set_autoindent()
184 self.shell.set_autoindent()
184 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
185 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
185
186
186 @skip_doctest
187 @skip_doctest
187 @line_magic
188 @line_magic
188 def cpaste(self, parameter_s=''):
189 def cpaste(self, parameter_s=''):
189 """Paste & execute a pre-formatted code block from clipboard.
190 """Paste & execute a pre-formatted code block from clipboard.
190
191
191 You must terminate the block with '--' (two minus-signs) or Ctrl-D
192 You must terminate the block with '--' (two minus-signs) or Ctrl-D
192 alone on the line. You can also provide your own sentinel with '%paste
193 alone on the line. You can also provide your own sentinel with '%paste
193 -s %%' ('%%' is the new sentinel for this operation)
194 -s %%' ('%%' is the new sentinel for this operation)
194
195
195 The block is dedented prior to execution to enable execution of method
196 The block is dedented prior to execution to enable execution of method
196 definitions. '>' and '+' characters at the beginning of a line are
197 definitions. '>' and '+' characters at the beginning of a line are
197 ignored, to allow pasting directly from e-mails, diff files and
198 ignored, to allow pasting directly from e-mails, diff files and
198 doctests (the '...' continuation prompt is also stripped). The
199 doctests (the '...' continuation prompt is also stripped). The
199 executed block is also assigned to variable named 'pasted_block' for
200 executed block is also assigned to variable named 'pasted_block' for
200 later editing with '%edit pasted_block'.
201 later editing with '%edit pasted_block'.
201
202
202 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
203 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
203 This assigns the pasted block to variable 'foo' as string, without
204 This assigns the pasted block to variable 'foo' as string, without
204 dedenting or executing it (preceding >>> and + is still stripped)
205 dedenting or executing it (preceding >>> and + is still stripped)
205
206
206 '%cpaste -r' re-executes the block previously entered by cpaste.
207 '%cpaste -r' re-executes the block previously entered by cpaste.
207
208
208 Do not be alarmed by garbled output on Windows (it's a readline bug).
209 Do not be alarmed by garbled output on Windows (it's a readline bug).
209 Just press enter and type -- (and press enter again) and the block
210 Just press enter and type -- (and press enter again) and the block
210 will be what was just pasted.
211 will be what was just pasted.
211
212
212 IPython statements (magics, shell escapes) are not supported (yet).
213 IPython statements (magics, shell escapes) are not supported (yet).
213
214
214 See also
215 See also
215 --------
216 --------
216 paste: automatically pull code from clipboard.
217 paste: automatically pull code from clipboard.
217
218
218 Examples
219 Examples
219 --------
220 --------
220 ::
221 ::
221
222
222 In [8]: %cpaste
223 In [8]: %cpaste
223 Pasting code; enter '--' alone on the line to stop.
224 Pasting code; enter '--' alone on the line to stop.
224 :>>> a = ["world!", "Hello"]
225 :>>> a = ["world!", "Hello"]
225 :>>> print " ".join(sorted(a))
226 :>>> print " ".join(sorted(a))
226 :--
227 :--
227 Hello world!
228 Hello world!
228 """
229 """
229 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
230 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
230 if 'r' in opts:
231 if 'r' in opts:
231 self.rerun_pasted()
232 self.rerun_pasted()
232 return
233 return
233
234
234 sentinel = opts.get('s', '--')
235 sentinel = opts.get('s', '--')
235 block = '\n'.join(get_pasted_lines(sentinel))
236 block = '\n'.join(get_pasted_lines(sentinel))
236 self.store_or_execute(block, name)
237 self.store_or_execute(block, name)
237
238
238 @line_magic
239 @line_magic
239 def paste(self, parameter_s=''):
240 def paste(self, parameter_s=''):
240 """Paste & execute a pre-formatted code block from clipboard.
241 """Paste & execute a pre-formatted code block from clipboard.
241
242
242 The text is pulled directly from the clipboard without user
243 The text is pulled directly from the clipboard without user
243 intervention and printed back on the screen before execution (unless
244 intervention and printed back on the screen before execution (unless
244 the -q flag is given to force quiet mode).
245 the -q flag is given to force quiet mode).
245
246
246 The block is dedented prior to execution to enable execution of method
247 The block is dedented prior to execution to enable execution of method
247 definitions. '>' and '+' characters at the beginning of a line are
248 definitions. '>' and '+' characters at the beginning of a line are
248 ignored, to allow pasting directly from e-mails, diff files and
249 ignored, to allow pasting directly from e-mails, diff files and
249 doctests (the '...' continuation prompt is also stripped). The
250 doctests (the '...' continuation prompt is also stripped). The
250 executed block is also assigned to variable named 'pasted_block' for
251 executed block is also assigned to variable named 'pasted_block' for
251 later editing with '%edit pasted_block'.
252 later editing with '%edit pasted_block'.
252
253
253 You can also pass a variable name as an argument, e.g. '%paste foo'.
254 You can also pass a variable name as an argument, e.g. '%paste foo'.
254 This assigns the pasted block to variable 'foo' as string, without
255 This assigns the pasted block to variable 'foo' as string, without
255 executing it (preceding >>> and + is still stripped).
256 executing it (preceding >>> and + is still stripped).
256
257
257 Options
258 Options
258 -------
259 -------
259
260
260 -r: re-executes the block previously entered by cpaste.
261 -r: re-executes the block previously entered by cpaste.
261
262
262 -q: quiet mode: do not echo the pasted text back to the terminal.
263 -q: quiet mode: do not echo the pasted text back to the terminal.
263
264
264 IPython statements (magics, shell escapes) are not supported (yet).
265 IPython statements (magics, shell escapes) are not supported (yet).
265
266
266 See also
267 See also
267 --------
268 --------
268 cpaste: manually paste code into terminal until you mark its end.
269 cpaste: manually paste code into terminal until you mark its end.
269 """
270 """
270 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
271 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
271 if 'r' in opts:
272 if 'r' in opts:
272 self.rerun_pasted()
273 self.rerun_pasted()
273 return
274 return
274 try:
275 try:
275 block = self.shell.hooks.clipboard_get()
276 block = self.shell.hooks.clipboard_get()
276 except TryNext as clipboard_exc:
277 except TryNext as clipboard_exc:
277 message = getattr(clipboard_exc, 'args')
278 message = getattr(clipboard_exc, 'args')
278 if message:
279 if message:
279 error(message[0])
280 error(message[0])
280 else:
281 else:
281 error('Could not get text from the clipboard.')
282 error('Could not get text from the clipboard.')
282 return
283 return
283
284
284 # By default, echo back to terminal unless quiet mode is requested
285 # By default, echo back to terminal unless quiet mode is requested
285 if 'q' not in opts:
286 if 'q' not in opts:
286 write = self.shell.write
287 write = self.shell.write
287 write(self.shell.pycolorize(block))
288 write(self.shell.pycolorize(block))
288 if not block.endswith('\n'):
289 if not block.endswith('\n'):
289 write('\n')
290 write('\n')
290 write("## -- End pasted text --\n")
291 write("## -- End pasted text --\n")
291
292
292 self.store_or_execute(block, name)
293 self.store_or_execute(block, name)
293
294
294 # Class-level: add a '%cls' magic only on Windows
295 # Class-level: add a '%cls' magic only on Windows
295 if sys.platform == 'win32':
296 if sys.platform == 'win32':
296 @line_magic
297 @line_magic
297 def cls(self, s):
298 def cls(self, s):
298 """Clear screen.
299 """Clear screen.
299 """
300 """
300 os.system("cls")
301 os.system("cls")
301
302
302 #-----------------------------------------------------------------------------
303 #-----------------------------------------------------------------------------
303 # Main class
304 # Main class
304 #-----------------------------------------------------------------------------
305 #-----------------------------------------------------------------------------
305
306
306 class TerminalInteractiveShell(InteractiveShell):
307 class TerminalInteractiveShell(InteractiveShell):
307
308
308 autoedit_syntax = CBool(False, config=True,
309 autoedit_syntax = CBool(False, config=True,
309 help="auto editing of files with syntax errors.")
310 help="auto editing of files with syntax errors.")
310 banner = Unicode('')
311 banner = Unicode('')
311 banner1 = Unicode(default_banner, config=True,
312 banner1 = Unicode(default_banner, config=True,
312 help="""The part of the banner to be printed before the profile"""
313 help="""The part of the banner to be printed before the profile"""
313 )
314 )
314 banner2 = Unicode('', config=True,
315 banner2 = Unicode('', config=True,
315 help="""The part of the banner to be printed after the profile"""
316 help="""The part of the banner to be printed after the profile"""
316 )
317 )
317 confirm_exit = CBool(True, config=True,
318 confirm_exit = CBool(True, config=True,
318 help="""
319 help="""
319 Set to confirm when you try to exit IPython with an EOF (Control-D
320 Set to confirm when you try to exit IPython with an EOF (Control-D
320 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
321 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
321 you can force a direct exit without any confirmation.""",
322 you can force a direct exit without any confirmation.""",
322 )
323 )
323 # This display_banner only controls whether or not self.show_banner()
324 # This display_banner only controls whether or not self.show_banner()
324 # is called when mainloop/interact are called. The default is False
325 # is called when mainloop/interact are called. The default is False
325 # because for the terminal based application, the banner behavior
326 # because for the terminal based application, the banner behavior
326 # is controlled by Global.display_banner, which IPythonApp looks at
327 # is controlled by Global.display_banner, which IPythonApp looks at
327 # to determine if *it* should call show_banner() by hand or not.
328 # to determine if *it* should call show_banner() by hand or not.
328 display_banner = CBool(False) # This isn't configurable!
329 display_banner = CBool(False) # This isn't configurable!
329 embedded = CBool(False)
330 embedded = CBool(False)
330 embedded_active = CBool(False)
331 embedded_active = CBool(False)
331 editor = Unicode(get_default_editor(), config=True,
332 editor = Unicode(get_default_editor(), config=True,
332 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
333 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
333 )
334 )
334 pager = Unicode('less', config=True,
335 pager = Unicode('less', config=True,
335 help="The shell program to be used for paging.")
336 help="The shell program to be used for paging.")
336
337
337 screen_length = Integer(0, config=True,
338 screen_length = Integer(0, config=True,
338 help=
339 help=
339 """Number of lines of your screen, used to control printing of very
340 """Number of lines of your screen, used to control printing of very
340 long strings. Strings longer than this number of lines will be sent
341 long strings. Strings longer than this number of lines will be sent
341 through a pager instead of directly printed. The default value for
342 through a pager instead of directly printed. The default value for
342 this is 0, which means IPython will auto-detect your screen size every
343 this is 0, which means IPython will auto-detect your screen size every
343 time it needs to print certain potentially long strings (this doesn't
344 time it needs to print certain potentially long strings (this doesn't
344 change the behavior of the 'print' keyword, it's only triggered
345 change the behavior of the 'print' keyword, it's only triggered
345 internally). If for some reason this isn't working well (it needs
346 internally). If for some reason this isn't working well (it needs
346 curses support), specify it yourself. Otherwise don't change the
347 curses support), specify it yourself. Otherwise don't change the
347 default.""",
348 default.""",
348 )
349 )
349 term_title = CBool(False, config=True,
350 term_title = CBool(False, config=True,
350 help="Enable auto setting the terminal title."
351 help="Enable auto setting the terminal title."
351 )
352 )
352
353
353 using_magics = CBool(False)
354 # This `using_paste_magics` is used to detect whether the code is being
355 # executed via paste magics functions
356 using_paste_magics = CBool(False)
354
357
355 # In the terminal, GUI control is done via PyOS_InputHook
358 # In the terminal, GUI control is done via PyOS_InputHook
356 from IPython.lib.inputhook import enable_gui
359 from IPython.lib.inputhook import enable_gui
357 enable_gui = staticmethod(enable_gui)
360 enable_gui = staticmethod(enable_gui)
358
361
359 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
362 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
360 user_ns=None, user_module=None, custom_exceptions=((),None),
363 user_ns=None, user_module=None, custom_exceptions=((),None),
361 usage=None, banner1=None, banner2=None, display_banner=None):
364 usage=None, banner1=None, banner2=None, display_banner=None):
362
365
363 super(TerminalInteractiveShell, self).__init__(
366 super(TerminalInteractiveShell, self).__init__(
364 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
367 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
365 user_module=user_module, custom_exceptions=custom_exceptions
368 user_module=user_module, custom_exceptions=custom_exceptions
366 )
369 )
367 # use os.system instead of utils.process.system by default,
370 # use os.system instead of utils.process.system by default,
368 # because piped system doesn't make sense in the Terminal:
371 # because piped system doesn't make sense in the Terminal:
369 self.system = self.system_raw
372 self.system = self.system_raw
370
373
371 self.init_term_title()
374 self.init_term_title()
372 self.init_usage(usage)
375 self.init_usage(usage)
373 self.init_banner(banner1, banner2, display_banner)
376 self.init_banner(banner1, banner2, display_banner)
374
377
375 #-------------------------------------------------------------------------
378 #-------------------------------------------------------------------------
376 # Things related to the terminal
379 # Things related to the terminal
377 #-------------------------------------------------------------------------
380 #-------------------------------------------------------------------------
378
381
379 @property
382 @property
380 def usable_screen_length(self):
383 def usable_screen_length(self):
381 if self.screen_length == 0:
384 if self.screen_length == 0:
382 return 0
385 return 0
383 else:
386 else:
384 num_lines_bot = self.separate_in.count('\n')+1
387 num_lines_bot = self.separate_in.count('\n')+1
385 return self.screen_length - num_lines_bot
388 return self.screen_length - num_lines_bot
386
389
387 def init_term_title(self):
390 def init_term_title(self):
388 # Enable or disable the terminal title.
391 # Enable or disable the terminal title.
389 if self.term_title:
392 if self.term_title:
390 toggle_set_term_title(True)
393 toggle_set_term_title(True)
391 set_term_title('IPython: ' + abbrev_cwd())
394 set_term_title('IPython: ' + abbrev_cwd())
392 else:
395 else:
393 toggle_set_term_title(False)
396 toggle_set_term_title(False)
394
397
395 #-------------------------------------------------------------------------
398 #-------------------------------------------------------------------------
396 # Things related to aliases
399 # Things related to aliases
397 #-------------------------------------------------------------------------
400 #-------------------------------------------------------------------------
398
401
399 def init_alias(self):
402 def init_alias(self):
400 # The parent class defines aliases that can be safely used with any
403 # The parent class defines aliases that can be safely used with any
401 # frontend.
404 # frontend.
402 super(TerminalInteractiveShell, self).init_alias()
405 super(TerminalInteractiveShell, self).init_alias()
403
406
404 # Now define aliases that only make sense on the terminal, because they
407 # Now define aliases that only make sense on the terminal, because they
405 # need direct access to the console in a way that we can't emulate in
408 # need direct access to the console in a way that we can't emulate in
406 # GUI or web frontend
409 # GUI or web frontend
407 if os.name == 'posix':
410 if os.name == 'posix':
408 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
411 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
409 ('man', 'man')]
412 ('man', 'man')]
410 elif os.name == 'nt':
413 elif os.name == 'nt':
411 aliases = [('cls', 'cls')]
414 aliases = [('cls', 'cls')]
412
415
413
416
414 for name, cmd in aliases:
417 for name, cmd in aliases:
415 self.alias_manager.define_alias(name, cmd)
418 self.alias_manager.define_alias(name, cmd)
416
419
417 #-------------------------------------------------------------------------
420 #-------------------------------------------------------------------------
418 # Things related to the banner and usage
421 # Things related to the banner and usage
419 #-------------------------------------------------------------------------
422 #-------------------------------------------------------------------------
420
423
421 def _banner1_changed(self):
424 def _banner1_changed(self):
422 self.compute_banner()
425 self.compute_banner()
423
426
424 def _banner2_changed(self):
427 def _banner2_changed(self):
425 self.compute_banner()
428 self.compute_banner()
426
429
427 def _term_title_changed(self, name, new_value):
430 def _term_title_changed(self, name, new_value):
428 self.init_term_title()
431 self.init_term_title()
429
432
430 def init_banner(self, banner1, banner2, display_banner):
433 def init_banner(self, banner1, banner2, display_banner):
431 if banner1 is not None:
434 if banner1 is not None:
432 self.banner1 = banner1
435 self.banner1 = banner1
433 if banner2 is not None:
436 if banner2 is not None:
434 self.banner2 = banner2
437 self.banner2 = banner2
435 if display_banner is not None:
438 if display_banner is not None:
436 self.display_banner = display_banner
439 self.display_banner = display_banner
437 self.compute_banner()
440 self.compute_banner()
438
441
439 def show_banner(self, banner=None):
442 def show_banner(self, banner=None):
440 if banner is None:
443 if banner is None:
441 banner = self.banner
444 banner = self.banner
442 self.write(banner)
445 self.write(banner)
443
446
444 def compute_banner(self):
447 def compute_banner(self):
445 self.banner = self.banner1
448 self.banner = self.banner1
446 if self.profile and self.profile != 'default':
449 if self.profile and self.profile != 'default':
447 self.banner += '\nIPython profile: %s\n' % self.profile
450 self.banner += '\nIPython profile: %s\n' % self.profile
448 if self.banner2:
451 if self.banner2:
449 self.banner += '\n' + self.banner2
452 self.banner += '\n' + self.banner2
450
453
451 def init_usage(self, usage=None):
454 def init_usage(self, usage=None):
452 if usage is None:
455 if usage is None:
453 self.usage = interactive_usage
456 self.usage = interactive_usage
454 else:
457 else:
455 self.usage = usage
458 self.usage = usage
456
459
457 #-------------------------------------------------------------------------
460 #-------------------------------------------------------------------------
458 # Mainloop and code execution logic
461 # Mainloop and code execution logic
459 #-------------------------------------------------------------------------
462 #-------------------------------------------------------------------------
460
463
461 def mainloop(self, display_banner=None):
464 def mainloop(self, display_banner=None):
462 """Start the mainloop.
465 """Start the mainloop.
463
466
464 If an optional banner argument is given, it will override the
467 If an optional banner argument is given, it will override the
465 internally created default banner.
468 internally created default banner.
466 """
469 """
467
470
468 with nested(self.builtin_trap, self.display_trap):
471 with nested(self.builtin_trap, self.display_trap):
469
472
470 while 1:
473 while 1:
471 try:
474 try:
472 self.interact(display_banner=display_banner)
475 self.interact(display_banner=display_banner)
473 #self.interact_with_readline()
476 #self.interact_with_readline()
474 # XXX for testing of a readline-decoupled repl loop, call
477 # XXX for testing of a readline-decoupled repl loop, call
475 # interact_with_readline above
478 # interact_with_readline above
476 break
479 break
477 except KeyboardInterrupt:
480 except KeyboardInterrupt:
478 # this should not be necessary, but KeyboardInterrupt
481 # this should not be necessary, but KeyboardInterrupt
479 # handling seems rather unpredictable...
482 # handling seems rather unpredictable...
480 self.write("\nKeyboardInterrupt in interact()\n")
483 self.write("\nKeyboardInterrupt in interact()\n")
481
484
482 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
485 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
483 """Store multiple lines as a single entry in history"""
486 """Store multiple lines as a single entry in history"""
484
487
485 # do nothing without readline or disabled multiline
488 # do nothing without readline or disabled multiline
486 if not self.has_readline or not self.multiline_history:
489 if not self.has_readline or not self.multiline_history:
487 return hlen_before_cell
490 return hlen_before_cell
488
491
489 # windows rl has no remove_history_item
492 # windows rl has no remove_history_item
490 if not hasattr(self.readline, "remove_history_item"):
493 if not hasattr(self.readline, "remove_history_item"):
491 return hlen_before_cell
494 return hlen_before_cell
492
495
493 # skip empty cells
496 # skip empty cells
494 if not source_raw.rstrip():
497 if not source_raw.rstrip():
495 return hlen_before_cell
498 return hlen_before_cell
496
499
497 # nothing changed do nothing, e.g. when rl removes consecutive dups
500 # nothing changed do nothing, e.g. when rl removes consecutive dups
498 hlen = self.readline.get_current_history_length()
501 hlen = self.readline.get_current_history_length()
499 if hlen == hlen_before_cell:
502 if hlen == hlen_before_cell:
500 return hlen_before_cell
503 return hlen_before_cell
501
504
502 for i in range(hlen - hlen_before_cell):
505 for i in range(hlen - hlen_before_cell):
503 self.readline.remove_history_item(hlen - i - 1)
506 self.readline.remove_history_item(hlen - i - 1)
504 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
507 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
505 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
508 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
506 stdin_encoding))
509 stdin_encoding))
507 return self.readline.get_current_history_length()
510 return self.readline.get_current_history_length()
508
511
509 def interact(self, display_banner=None):
512 def interact(self, display_banner=None):
510 """Closely emulate the interactive Python console."""
513 """Closely emulate the interactive Python console."""
511
514
512 # batch run -> do not interact
515 # batch run -> do not interact
513 if self.exit_now:
516 if self.exit_now:
514 return
517 return
515
518
516 if display_banner is None:
519 if display_banner is None:
517 display_banner = self.display_banner
520 display_banner = self.display_banner
518
521
519 if isinstance(display_banner, basestring):
522 if isinstance(display_banner, basestring):
520 self.show_banner(display_banner)
523 self.show_banner(display_banner)
521 elif display_banner:
524 elif display_banner:
522 self.show_banner()
525 self.show_banner()
523
526
524 more = False
527 more = False
525
528
526 if self.has_readline:
529 if self.has_readline:
527 self.readline_startup_hook(self.pre_readline)
530 self.readline_startup_hook(self.pre_readline)
528 hlen_b4_cell = self.readline.get_current_history_length()
531 hlen_b4_cell = self.readline.get_current_history_length()
529 else:
532 else:
530 hlen_b4_cell = 0
533 hlen_b4_cell = 0
531 # exit_now is set by a call to %Exit or %Quit, through the
534 # exit_now is set by a call to %Exit or %Quit, through the
532 # ask_exit callback.
535 # ask_exit callback.
533
536
534 while not self.exit_now:
537 while not self.exit_now:
535 self.hooks.pre_prompt_hook()
538 self.hooks.pre_prompt_hook()
536 if more:
539 if more:
537 try:
540 try:
538 prompt = self.prompt_manager.render('in2')
541 prompt = self.prompt_manager.render('in2')
539 except:
542 except:
540 self.showtraceback()
543 self.showtraceback()
541 if self.autoindent:
544 if self.autoindent:
542 self.rl_do_indent = True
545 self.rl_do_indent = True
543
546
544 else:
547 else:
545 try:
548 try:
546 prompt = self.separate_in + self.prompt_manager.render('in')
549 prompt = self.separate_in + self.prompt_manager.render('in')
547 except:
550 except:
548 self.showtraceback()
551 self.showtraceback()
549 try:
552 try:
550 line = self.raw_input(prompt)
553 line = self.raw_input(prompt)
551 if self.exit_now:
554 if self.exit_now:
552 # quick exit on sys.std[in|out] close
555 # quick exit on sys.std[in|out] close
553 break
556 break
554 if self.autoindent:
557 if self.autoindent:
555 self.rl_do_indent = False
558 self.rl_do_indent = False
556
559
557 except KeyboardInterrupt:
560 except KeyboardInterrupt:
558 #double-guard against keyboardinterrupts during kbdint handling
561 #double-guard against keyboardinterrupts during kbdint handling
559 try:
562 try:
560 self.write('\nKeyboardInterrupt\n')
563 self.write('\nKeyboardInterrupt\n')
561 source_raw = self.input_splitter.source_raw_reset()[1]
564 source_raw = self.input_splitter.source_raw_reset()[1]
562 hlen_b4_cell = \
565 hlen_b4_cell = \
563 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
566 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
564 more = False
567 more = False
565 except KeyboardInterrupt:
568 except KeyboardInterrupt:
566 pass
569 pass
567 except EOFError:
570 except EOFError:
568 if self.autoindent:
571 if self.autoindent:
569 self.rl_do_indent = False
572 self.rl_do_indent = False
570 if self.has_readline:
573 if self.has_readline:
571 self.readline_startup_hook(None)
574 self.readline_startup_hook(None)
572 self.write('\n')
575 self.write('\n')
573 self.exit()
576 self.exit()
574 except bdb.BdbQuit:
577 except bdb.BdbQuit:
575 warn('The Python debugger has exited with a BdbQuit exception.\n'
578 warn('The Python debugger has exited with a BdbQuit exception.\n'
576 'Because of how pdb handles the stack, it is impossible\n'
579 'Because of how pdb handles the stack, it is impossible\n'
577 'for IPython to properly format this particular exception.\n'
580 'for IPython to properly format this particular exception.\n'
578 'IPython will resume normal operation.')
581 'IPython will resume normal operation.')
579 except:
582 except:
580 # exceptions here are VERY RARE, but they can be triggered
583 # exceptions here are VERY RARE, but they can be triggered
581 # asynchronously by signal handlers, for example.
584 # asynchronously by signal handlers, for example.
582 self.showtraceback()
585 self.showtraceback()
583 else:
586 else:
584 self.input_splitter.push(line)
587 self.input_splitter.push(line)
585 more = self.input_splitter.push_accepts_more()
588 more = self.input_splitter.push_accepts_more()
586 if (self.SyntaxTB.last_syntax_error and
589 if (self.SyntaxTB.last_syntax_error and
587 self.autoedit_syntax):
590 self.autoedit_syntax):
588 self.edit_syntax_error()
591 self.edit_syntax_error()
589 if not more:
592 if not more:
590 source_raw = self.input_splitter.source_raw_reset()[1]
593 source_raw = self.input_splitter.source_raw_reset()[1]
591 self.run_cell(source_raw, store_history=True)
594 self.run_cell(source_raw, store_history=True)
592 hlen_b4_cell = \
595 hlen_b4_cell = \
593 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
596 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
594
597
595 # Turn off the exit flag, so the mainloop can be restarted if desired
598 # Turn off the exit flag, so the mainloop can be restarted if desired
596 self.exit_now = False
599 self.exit_now = False
597
600
598 def raw_input(self, prompt=''):
601 def raw_input(self, prompt=''):
599 """Write a prompt and read a line.
602 """Write a prompt and read a line.
600
603
601 The returned line does not include the trailing newline.
604 The returned line does not include the trailing newline.
602 When the user enters the EOF key sequence, EOFError is raised.
605 When the user enters the EOF key sequence, EOFError is raised.
603
606
604 Optional inputs:
607 Optional inputs:
605
608
606 - prompt(''): a string to be printed to prompt the user.
609 - prompt(''): a string to be printed to prompt the user.
607
610
608 - continue_prompt(False): whether this line is the first one or a
611 - continue_prompt(False): whether this line is the first one or a
609 continuation in a sequence of inputs.
612 continuation in a sequence of inputs.
610 """
613 """
611 # Code run by the user may have modified the readline completer state.
614 # Code run by the user may have modified the readline completer state.
612 # We must ensure that our completer is back in place.
615 # We must ensure that our completer is back in place.
613
616
614 if self.has_readline:
617 if self.has_readline:
615 self.set_readline_completer()
618 self.set_readline_completer()
616
619
617 # raw_input expects str, but we pass it unicode sometimes
620 # raw_input expects str, but we pass it unicode sometimes
618 prompt = py3compat.cast_bytes_py2(prompt)
621 prompt = py3compat.cast_bytes_py2(prompt)
619
622
620 try:
623 try:
621 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
624 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
622 except ValueError:
625 except ValueError:
623 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
626 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
624 " or sys.stdout.close()!\nExiting IPython!\n")
627 " or sys.stdout.close()!\nExiting IPython!\n")
625 self.ask_exit()
628 self.ask_exit()
626 return ""
629 return ""
627
630
628 # Try to be reasonably smart about not re-indenting pasted input more
631 # Try to be reasonably smart about not re-indenting pasted input more
629 # than necessary. We do this by trimming out the auto-indent initial
632 # than necessary. We do this by trimming out the auto-indent initial
630 # spaces, if the user's actual input started itself with whitespace.
633 # spaces, if the user's actual input started itself with whitespace.
631 if self.autoindent:
634 if self.autoindent:
632 if num_ini_spaces(line) > self.indent_current_nsp:
635 if num_ini_spaces(line) > self.indent_current_nsp:
633 line = line[self.indent_current_nsp:]
636 line = line[self.indent_current_nsp:]
634 self.indent_current_nsp = 0
637 self.indent_current_nsp = 0
635
638
636 return line
639 return line
637
640
638 #-------------------------------------------------------------------------
641 #-------------------------------------------------------------------------
639 # Methods to support auto-editing of SyntaxErrors.
642 # Methods to support auto-editing of SyntaxErrors.
640 #-------------------------------------------------------------------------
643 #-------------------------------------------------------------------------
641
644
642 def edit_syntax_error(self):
645 def edit_syntax_error(self):
643 """The bottom half of the syntax error handler called in the main loop.
646 """The bottom half of the syntax error handler called in the main loop.
644
647
645 Loop until syntax error is fixed or user cancels.
648 Loop until syntax error is fixed or user cancels.
646 """
649 """
647
650
648 while self.SyntaxTB.last_syntax_error:
651 while self.SyntaxTB.last_syntax_error:
649 # copy and clear last_syntax_error
652 # copy and clear last_syntax_error
650 err = self.SyntaxTB.clear_err_state()
653 err = self.SyntaxTB.clear_err_state()
651 if not self._should_recompile(err):
654 if not self._should_recompile(err):
652 return
655 return
653 try:
656 try:
654 # may set last_syntax_error again if a SyntaxError is raised
657 # may set last_syntax_error again if a SyntaxError is raised
655 self.safe_execfile(err.filename,self.user_ns)
658 self.safe_execfile(err.filename,self.user_ns)
656 except:
659 except:
657 self.showtraceback()
660 self.showtraceback()
658 else:
661 else:
659 try:
662 try:
660 f = open(err.filename)
663 f = open(err.filename)
661 try:
664 try:
662 # This should be inside a display_trap block and I
665 # This should be inside a display_trap block and I
663 # think it is.
666 # think it is.
664 sys.displayhook(f.read())
667 sys.displayhook(f.read())
665 finally:
668 finally:
666 f.close()
669 f.close()
667 except:
670 except:
668 self.showtraceback()
671 self.showtraceback()
669
672
670 def _should_recompile(self,e):
673 def _should_recompile(self,e):
671 """Utility routine for edit_syntax_error"""
674 """Utility routine for edit_syntax_error"""
672
675
673 if e.filename in ('<ipython console>','<input>','<string>',
676 if e.filename in ('<ipython console>','<input>','<string>',
674 '<console>','<BackgroundJob compilation>',
677 '<console>','<BackgroundJob compilation>',
675 None):
678 None):
676
679
677 return False
680 return False
678 try:
681 try:
679 if (self.autoedit_syntax and
682 if (self.autoedit_syntax and
680 not self.ask_yes_no('Return to editor to correct syntax error? '
683 not self.ask_yes_no('Return to editor to correct syntax error? '
681 '[Y/n] ','y')):
684 '[Y/n] ','y')):
682 return False
685 return False
683 except EOFError:
686 except EOFError:
684 return False
687 return False
685
688
686 def int0(x):
689 def int0(x):
687 try:
690 try:
688 return int(x)
691 return int(x)
689 except TypeError:
692 except TypeError:
690 return 0
693 return 0
691 # always pass integer line and offset values to editor hook
694 # always pass integer line and offset values to editor hook
692 try:
695 try:
693 self.hooks.fix_error_editor(e.filename,
696 self.hooks.fix_error_editor(e.filename,
694 int0(e.lineno),int0(e.offset),e.msg)
697 int0(e.lineno),int0(e.offset),e.msg)
695 except TryNext:
698 except TryNext:
696 warn('Could not open editor')
699 warn('Could not open editor')
697 return False
700 return False
698 return True
701 return True
699
702
700 #-------------------------------------------------------------------------
703 #-------------------------------------------------------------------------
701 # Things related to exiting
704 # Things related to exiting
702 #-------------------------------------------------------------------------
705 #-------------------------------------------------------------------------
703
706
704 def ask_exit(self):
707 def ask_exit(self):
705 """ Ask the shell to exit. Can be overiden and used as a callback. """
708 """ Ask the shell to exit. Can be overiden and used as a callback. """
706 self.exit_now = True
709 self.exit_now = True
707
710
708 def exit(self):
711 def exit(self):
709 """Handle interactive exit.
712 """Handle interactive exit.
710
713
711 This method calls the ask_exit callback."""
714 This method calls the ask_exit callback."""
712 if self.confirm_exit:
715 if self.confirm_exit:
713 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
716 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
714 self.ask_exit()
717 self.ask_exit()
715 else:
718 else:
716 self.ask_exit()
719 self.ask_exit()
717
720
718 #-------------------------------------------------------------------------
721 #-------------------------------------------------------------------------
719 # Things related to magics
722 # Things related to magics
720 #-------------------------------------------------------------------------
723 #-------------------------------------------------------------------------
721
724
722 def init_magics(self):
725 def init_magics(self):
723 super(TerminalInteractiveShell, self).init_magics()
726 super(TerminalInteractiveShell, self).init_magics()
724 self.register_magics(TerminalMagics)
727 self.register_magics(TerminalMagics)
725
728
726 def showindentationerror(self):
729 def showindentationerror(self):
727 super(TerminalInteractiveShell, self).showindentationerror()
730 super(TerminalInteractiveShell, self).showindentationerror()
728 if not self.using_magics:
731 if not self.using_magics:
729 print("If you want to paste code into IPython, try the "
732 print("If you want to paste code into IPython, try the "
730 "%paste and %cpaste magic functions.")
733 "%paste and %cpaste magic functions.")
731
734
732
735
733 InteractiveShellABC.register(TerminalInteractiveShell)
736 InteractiveShellABC.register(TerminalInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now