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