##// END OF EJS Templates
move hlen_before_cell into _replace_rlhist_multiline...
Julian Taylor -
Show More
@@ -1,612 +1,611
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-2010 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
17 17 import __builtin__
18 18 import bdb
19 19 import os
20 20 import re
21 21 import sys
22 22
23 23 try:
24 24 from contextlib import nested
25 25 except:
26 26 from IPython.utils.nested_context import nested
27 27
28 28 from IPython.core.error import TryNext
29 29 from IPython.core.usage import interactive_usage, default_banner
30 30 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
31 31 from IPython.lib.inputhook import enable_gui
32 32 from IPython.lib.pylabtools import pylab_activate
33 33 from IPython.testing.skipdoctest import skip_doctest
34 34 from IPython.utils import py3compat
35 35 from IPython.utils.terminal import toggle_set_term_title, set_term_title
36 36 from IPython.utils.process import abbrev_cwd
37 37 from IPython.utils.warn import warn
38 38 from IPython.utils.text import num_ini_spaces
39 39 from IPython.utils.traitlets import Int, CBool, Unicode
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Utilities
43 43 #-----------------------------------------------------------------------------
44 44
45 45 def get_default_editor():
46 46 try:
47 47 ed = os.environ['EDITOR']
48 48 except KeyError:
49 49 if os.name == 'posix':
50 50 ed = 'vi' # the only one guaranteed to be there!
51 51 else:
52 52 ed = 'notepad' # same in Windows!
53 53 return ed
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Main class
57 57 #-----------------------------------------------------------------------------
58 58
59 59 class TerminalInteractiveShell(InteractiveShell):
60 60
61 61 autoedit_syntax = CBool(False, config=True,
62 62 help="auto editing of files with syntax errors.")
63 63 banner = Unicode('')
64 64 banner1 = Unicode(default_banner, config=True,
65 65 help="""The part of the banner to be printed before the profile"""
66 66 )
67 67 banner2 = Unicode('', config=True,
68 68 help="""The part of the banner to be printed after the profile"""
69 69 )
70 70 confirm_exit = CBool(True, config=True,
71 71 help="""
72 72 Set to confirm when you try to exit IPython with an EOF (Control-D
73 73 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
74 74 you can force a direct exit without any confirmation.""",
75 75 )
76 76 # This display_banner only controls whether or not self.show_banner()
77 77 # is called when mainloop/interact are called. The default is False
78 78 # because for the terminal based application, the banner behavior
79 79 # is controlled by Global.display_banner, which IPythonApp looks at
80 80 # to determine if *it* should call show_banner() by hand or not.
81 81 display_banner = CBool(False) # This isn't configurable!
82 82 embedded = CBool(False)
83 83 embedded_active = CBool(False)
84 84 editor = Unicode(get_default_editor(), config=True,
85 85 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
86 86 )
87 87 pager = Unicode('less', config=True,
88 88 help="The shell program to be used for paging.")
89 89
90 90 screen_length = Int(0, config=True,
91 91 help=
92 92 """Number of lines of your screen, used to control printing of very
93 93 long strings. Strings longer than this number of lines will be sent
94 94 through a pager instead of directly printed. The default value for
95 95 this is 0, which means IPython will auto-detect your screen size every
96 96 time it needs to print certain potentially long strings (this doesn't
97 97 change the behavior of the 'print' keyword, it's only triggered
98 98 internally). If for some reason this isn't working well (it needs
99 99 curses support), specify it yourself. Otherwise don't change the
100 100 default.""",
101 101 )
102 102 term_title = CBool(False, config=True,
103 103 help="Enable auto setting the terminal title."
104 104 )
105 105
106 106 def __init__(self, config=None, ipython_dir=None, profile_dir=None, user_ns=None,
107 107 user_global_ns=None, custom_exceptions=((),None),
108 108 usage=None, banner1=None, banner2=None,
109 109 display_banner=None):
110 110
111 111 super(TerminalInteractiveShell, self).__init__(
112 112 config=config, profile_dir=profile_dir, user_ns=user_ns,
113 113 user_global_ns=user_global_ns, custom_exceptions=custom_exceptions
114 114 )
115 115 # use os.system instead of utils.process.system by default, except on Windows
116 116 if os.name == 'nt':
117 117 self.system = self.system_piped
118 118 else:
119 119 self.system = self.system_raw
120 120
121 121 self.init_term_title()
122 122 self.init_usage(usage)
123 123 self.init_banner(banner1, banner2, display_banner)
124 124
125 125 #-------------------------------------------------------------------------
126 126 # Things related to the terminal
127 127 #-------------------------------------------------------------------------
128 128
129 129 @property
130 130 def usable_screen_length(self):
131 131 if self.screen_length == 0:
132 132 return 0
133 133 else:
134 134 num_lines_bot = self.separate_in.count('\n')+1
135 135 return self.screen_length - num_lines_bot
136 136
137 137 def init_term_title(self):
138 138 # Enable or disable the terminal title.
139 139 if self.term_title:
140 140 toggle_set_term_title(True)
141 141 set_term_title('IPython: ' + abbrev_cwd())
142 142 else:
143 143 toggle_set_term_title(False)
144 144
145 145 #-------------------------------------------------------------------------
146 146 # Things related to aliases
147 147 #-------------------------------------------------------------------------
148 148
149 149 def init_alias(self):
150 150 # The parent class defines aliases that can be safely used with any
151 151 # frontend.
152 152 super(TerminalInteractiveShell, self).init_alias()
153 153
154 154 # Now define aliases that only make sense on the terminal, because they
155 155 # need direct access to the console in a way that we can't emulate in
156 156 # GUI or web frontend
157 157 if os.name == 'posix':
158 158 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
159 159 ('man', 'man')]
160 160 elif os.name == 'nt':
161 161 aliases = [('cls', 'cls')]
162 162
163 163
164 164 for name, cmd in aliases:
165 165 self.alias_manager.define_alias(name, cmd)
166 166
167 167 #-------------------------------------------------------------------------
168 168 # Things related to the banner and usage
169 169 #-------------------------------------------------------------------------
170 170
171 171 def _banner1_changed(self):
172 172 self.compute_banner()
173 173
174 174 def _banner2_changed(self):
175 175 self.compute_banner()
176 176
177 177 def _term_title_changed(self, name, new_value):
178 178 self.init_term_title()
179 179
180 180 def init_banner(self, banner1, banner2, display_banner):
181 181 if banner1 is not None:
182 182 self.banner1 = banner1
183 183 if banner2 is not None:
184 184 self.banner2 = banner2
185 185 if display_banner is not None:
186 186 self.display_banner = display_banner
187 187 self.compute_banner()
188 188
189 189 def show_banner(self, banner=None):
190 190 if banner is None:
191 191 banner = self.banner
192 192 self.write(banner)
193 193
194 194 def compute_banner(self):
195 195 self.banner = self.banner1
196 196 if self.profile and self.profile != 'default':
197 197 self.banner += '\nIPython profile: %s\n' % self.profile
198 198 if self.banner2:
199 199 self.banner += '\n' + self.banner2
200 200
201 201 def init_usage(self, usage=None):
202 202 if usage is None:
203 203 self.usage = interactive_usage
204 204 else:
205 205 self.usage = usage
206 206
207 207 #-------------------------------------------------------------------------
208 208 # Mainloop and code execution logic
209 209 #-------------------------------------------------------------------------
210 210
211 211 def mainloop(self, display_banner=None):
212 212 """Start the mainloop.
213 213
214 214 If an optional banner argument is given, it will override the
215 215 internally created default banner.
216 216 """
217 217
218 218 with nested(self.builtin_trap, self.display_trap):
219 219
220 220 while 1:
221 221 try:
222 222 self.interact(display_banner=display_banner)
223 223 #self.interact_with_readline()
224 224 # XXX for testing of a readline-decoupled repl loop, call
225 225 # interact_with_readline above
226 226 break
227 227 except KeyboardInterrupt:
228 228 # this should not be necessary, but KeyboardInterrupt
229 229 # handling seems rather unpredictable...
230 230 self.write("\nKeyboardInterrupt in interact()\n")
231 231
232 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
232 def _replace_rlhist_multiline(self, source_raw):
233 233 """Store multiple lines as a single entry in history"""
234 234 if self.multiline_history and self.has_readline:
235 235 hlen = self.readline.get_current_history_length()
236 for i in range(hlen - hlen_before_cell):
236 for i in range(hlen - self.hlen_before_cell):
237 237 self.readline.remove_history_item(hlen - i - 1)
238 238 stdin_encoding = sys.stdin.encoding or "utf-8"
239 239 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
240 240 stdin_encoding))
241 self.hlen_before_cell = self.readline.get_current_history_length()
241 242
242 243 def interact(self, display_banner=None):
243 244 """Closely emulate the interactive Python console."""
244 245
245 246 # batch run -> do not interact
246 247 if self.exit_now:
247 248 return
248 249
249 250 if display_banner is None:
250 251 display_banner = self.display_banner
251 252
252 253 if isinstance(display_banner, basestring):
253 254 self.show_banner(display_banner)
254 255 elif display_banner:
255 256 self.show_banner()
256 257
257 258 more = False
258 hlen_before_cell = self.readline.get_current_history_length()
259 259
260 260 # Mark activity in the builtins
261 261 __builtin__.__dict__['__IPYTHON__active'] += 1
262 262
263 263 if self.has_readline:
264 264 self.readline_startup_hook(self.pre_readline)
265 self.hlen_before_cell = self.readline.get_current_history_length()
265 266 # exit_now is set by a call to %Exit or %Quit, through the
266 267 # ask_exit callback.
267 268
268 269 while not self.exit_now:
269 270 self.hooks.pre_prompt_hook()
270 271 if more:
271 272 try:
272 273 prompt = self.hooks.generate_prompt(True)
273 274 except:
274 275 self.showtraceback()
275 276 if self.autoindent:
276 277 self.rl_do_indent = True
277 278
278 279 else:
279 280 try:
280 281 prompt = self.hooks.generate_prompt(False)
281 282 except:
282 283 self.showtraceback()
283 284 try:
284 285 line = self.raw_input(prompt)
285 286 if self.exit_now:
286 287 # quick exit on sys.std[in|out] close
287 288 break
288 289 if self.autoindent:
289 290 self.rl_do_indent = False
290 291
291 292 except KeyboardInterrupt:
292 293 #double-guard against keyboardinterrupts during kbdint handling
293 294 try:
294 295 self.write('\nKeyboardInterrupt\n')
295 296 source_raw = self.input_splitter.source_raw_reset()[1]
296 self._replace_rlhist_multiline(source_raw, hlen_before_cell)
297 hlen_before_cell = self.readline.get_current_history_length()
297 self._replace_rlhist_multiline(source_raw)
298 298 more = False
299 299 except KeyboardInterrupt:
300 300 pass
301 301 except EOFError:
302 302 if self.autoindent:
303 303 self.rl_do_indent = False
304 304 if self.has_readline:
305 305 self.readline_startup_hook(None)
306 306 self.write('\n')
307 307 self.exit()
308 308 except bdb.BdbQuit:
309 309 warn('The Python debugger has exited with a BdbQuit exception.\n'
310 310 'Because of how pdb handles the stack, it is impossible\n'
311 311 'for IPython to properly format this particular exception.\n'
312 312 'IPython will resume normal operation.')
313 313 except:
314 314 # exceptions here are VERY RARE, but they can be triggered
315 315 # asynchronously by signal handlers, for example.
316 316 self.showtraceback()
317 317 else:
318 318 self.input_splitter.push(line)
319 319 more = self.input_splitter.push_accepts_more()
320 320 if (self.SyntaxTB.last_syntax_error and
321 321 self.autoedit_syntax):
322 322 self.edit_syntax_error()
323 323 if not more:
324 324 source_raw = self.input_splitter.source_raw_reset()[1]
325 self._replace_rlhist_multiline(source_raw, hlen_before_cell)
326 hlen_before_cell = self.readline.get_current_history_length()
325 self._replace_rlhist_multiline(source_raw)
327 326 self.run_cell(source_raw, store_history=True)
328 327
329 328 # We are off again...
330 329 __builtin__.__dict__['__IPYTHON__active'] -= 1
331 330
332 331 # Turn off the exit flag, so the mainloop can be restarted if desired
333 332 self.exit_now = False
334 333
335 334 def raw_input(self, prompt=''):
336 335 """Write a prompt and read a line.
337 336
338 337 The returned line does not include the trailing newline.
339 338 When the user enters the EOF key sequence, EOFError is raised.
340 339
341 340 Optional inputs:
342 341
343 342 - prompt(''): a string to be printed to prompt the user.
344 343
345 344 - continue_prompt(False): whether this line is the first one or a
346 345 continuation in a sequence of inputs.
347 346 """
348 347 # Code run by the user may have modified the readline completer state.
349 348 # We must ensure that our completer is back in place.
350 349
351 350 if self.has_readline:
352 351 self.set_readline_completer()
353 352
354 353 try:
355 354 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
356 355 except ValueError:
357 356 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
358 357 " or sys.stdout.close()!\nExiting IPython!")
359 358 self.ask_exit()
360 359 return ""
361 360
362 361 # Try to be reasonably smart about not re-indenting pasted input more
363 362 # than necessary. We do this by trimming out the auto-indent initial
364 363 # spaces, if the user's actual input started itself with whitespace.
365 364 if self.autoindent:
366 365 if num_ini_spaces(line) > self.indent_current_nsp:
367 366 line = line[self.indent_current_nsp:]
368 367 self.indent_current_nsp = 0
369 368
370 369 return line
371 370
372 371 #-------------------------------------------------------------------------
373 372 # Methods to support auto-editing of SyntaxErrors.
374 373 #-------------------------------------------------------------------------
375 374
376 375 def edit_syntax_error(self):
377 376 """The bottom half of the syntax error handler called in the main loop.
378 377
379 378 Loop until syntax error is fixed or user cancels.
380 379 """
381 380
382 381 while self.SyntaxTB.last_syntax_error:
383 382 # copy and clear last_syntax_error
384 383 err = self.SyntaxTB.clear_err_state()
385 384 if not self._should_recompile(err):
386 385 return
387 386 try:
388 387 # may set last_syntax_error again if a SyntaxError is raised
389 388 self.safe_execfile(err.filename,self.user_ns)
390 389 except:
391 390 self.showtraceback()
392 391 else:
393 392 try:
394 393 f = file(err.filename)
395 394 try:
396 395 # This should be inside a display_trap block and I
397 396 # think it is.
398 397 sys.displayhook(f.read())
399 398 finally:
400 399 f.close()
401 400 except:
402 401 self.showtraceback()
403 402
404 403 def _should_recompile(self,e):
405 404 """Utility routine for edit_syntax_error"""
406 405
407 406 if e.filename in ('<ipython console>','<input>','<string>',
408 407 '<console>','<BackgroundJob compilation>',
409 408 None):
410 409
411 410 return False
412 411 try:
413 412 if (self.autoedit_syntax and
414 413 not self.ask_yes_no('Return to editor to correct syntax error? '
415 414 '[Y/n] ','y')):
416 415 return False
417 416 except EOFError:
418 417 return False
419 418
420 419 def int0(x):
421 420 try:
422 421 return int(x)
423 422 except TypeError:
424 423 return 0
425 424 # always pass integer line and offset values to editor hook
426 425 try:
427 426 self.hooks.fix_error_editor(e.filename,
428 427 int0(e.lineno),int0(e.offset),e.msg)
429 428 except TryNext:
430 429 warn('Could not open editor')
431 430 return False
432 431 return True
433 432
434 433 #-------------------------------------------------------------------------
435 434 # Things related to GUI support and pylab
436 435 #-------------------------------------------------------------------------
437 436
438 437 def enable_pylab(self, gui=None, import_all=True):
439 438 """Activate pylab support at runtime.
440 439
441 440 This turns on support for matplotlib, preloads into the interactive
442 441 namespace all of numpy and pylab, and configures IPython to correcdtly
443 442 interact with the GUI event loop. The GUI backend to be used can be
444 443 optionally selected with the optional :param:`gui` argument.
445 444
446 445 Parameters
447 446 ----------
448 447 gui : optional, string
449 448
450 449 If given, dictates the choice of matplotlib GUI backend to use
451 450 (should be one of IPython's supported backends, 'tk', 'qt', 'wx' or
452 451 'gtk'), otherwise we use the default chosen by matplotlib (as
453 452 dictated by the matplotlib build-time options plus the user's
454 453 matplotlibrc configuration file).
455 454 """
456 455 # We want to prevent the loading of pylab to pollute the user's
457 456 # namespace as shown by the %who* magics, so we execute the activation
458 457 # code in an empty namespace, and we update *both* user_ns and
459 458 # user_ns_hidden with this information.
460 459 ns = {}
461 460 gui = pylab_activate(ns, gui, import_all)
462 461 self.user_ns.update(ns)
463 462 self.user_ns_hidden.update(ns)
464 463 # Now we must activate the gui pylab wants to use, and fix %run to take
465 464 # plot updates into account
466 465 enable_gui(gui)
467 466 self.magic_run = self._pylab_magic_run
468 467
469 468 #-------------------------------------------------------------------------
470 469 # Things related to exiting
471 470 #-------------------------------------------------------------------------
472 471
473 472 def ask_exit(self):
474 473 """ Ask the shell to exit. Can be overiden and used as a callback. """
475 474 self.exit_now = True
476 475
477 476 def exit(self):
478 477 """Handle interactive exit.
479 478
480 479 This method calls the ask_exit callback."""
481 480 if self.confirm_exit:
482 481 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
483 482 self.ask_exit()
484 483 else:
485 484 self.ask_exit()
486 485
487 486 #------------------------------------------------------------------------
488 487 # Magic overrides
489 488 #------------------------------------------------------------------------
490 489 # Once the base class stops inheriting from magic, this code needs to be
491 490 # moved into a separate machinery as well. For now, at least isolate here
492 491 # the magics which this class needs to implement differently from the base
493 492 # class, or that are unique to it.
494 493
495 494 def magic_autoindent(self, parameter_s = ''):
496 495 """Toggle autoindent on/off (if available)."""
497 496
498 497 self.shell.set_autoindent()
499 498 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
500 499
501 500 @skip_doctest
502 501 def magic_cpaste(self, parameter_s=''):
503 502 """Paste & execute a pre-formatted code block from clipboard.
504 503
505 504 You must terminate the block with '--' (two minus-signs) or Ctrl-D alone on the
506 505 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
507 506 is the new sentinel for this operation)
508 507
509 508 The block is dedented prior to execution to enable execution of method
510 509 definitions. '>' and '+' characters at the beginning of a line are
511 510 ignored, to allow pasting directly from e-mails, diff files and
512 511 doctests (the '...' continuation prompt is also stripped). The
513 512 executed block is also assigned to variable named 'pasted_block' for
514 513 later editing with '%edit pasted_block'.
515 514
516 515 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
517 516 This assigns the pasted block to variable 'foo' as string, without
518 517 dedenting or executing it (preceding >>> and + is still stripped)
519 518
520 519 '%cpaste -r' re-executes the block previously entered by cpaste.
521 520
522 521 Do not be alarmed by garbled output on Windows (it's a readline bug).
523 522 Just press enter and type -- (and press enter again) and the block
524 523 will be what was just pasted.
525 524
526 525 IPython statements (magics, shell escapes) are not supported (yet).
527 526
528 527 See also
529 528 --------
530 529 paste: automatically pull code from clipboard.
531 530
532 531 Examples
533 532 --------
534 533 ::
535 534
536 535 In [8]: %cpaste
537 536 Pasting code; enter '--' alone on the line to stop.
538 537 :>>> a = ["world!", "Hello"]
539 538 :>>> print " ".join(sorted(a))
540 539 :--
541 540 Hello world!
542 541 """
543 542
544 543 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
545 544 par = args.strip()
546 545 if opts.has_key('r'):
547 546 self._rerun_pasted()
548 547 return
549 548
550 549 sentinel = opts.get('s','--')
551 550
552 551 block = self._strip_pasted_lines_for_code(
553 552 self._get_pasted_lines(sentinel))
554 553
555 554 self._execute_block(block, par)
556 555
557 556 def magic_paste(self, parameter_s=''):
558 557 """Paste & execute a pre-formatted code block from clipboard.
559 558
560 559 The text is pulled directly from the clipboard without user
561 560 intervention and printed back on the screen before execution (unless
562 561 the -q flag is given to force quiet mode).
563 562
564 563 The block is dedented prior to execution to enable execution of method
565 564 definitions. '>' and '+' characters at the beginning of a line are
566 565 ignored, to allow pasting directly from e-mails, diff files and
567 566 doctests (the '...' continuation prompt is also stripped). The
568 567 executed block is also assigned to variable named 'pasted_block' for
569 568 later editing with '%edit pasted_block'.
570 569
571 570 You can also pass a variable name as an argument, e.g. '%paste foo'.
572 571 This assigns the pasted block to variable 'foo' as string, without
573 572 dedenting or executing it (preceding >>> and + is still stripped)
574 573
575 574 Options
576 575 -------
577 576
578 577 -r: re-executes the block previously entered by cpaste.
579 578
580 579 -q: quiet mode: do not echo the pasted text back to the terminal.
581 580
582 581 IPython statements (magics, shell escapes) are not supported (yet).
583 582
584 583 See also
585 584 --------
586 585 cpaste: manually paste code into terminal until you mark its end.
587 586 """
588 587 opts,args = self.parse_options(parameter_s,'rq',mode='string')
589 588 par = args.strip()
590 589 if opts.has_key('r'):
591 590 self._rerun_pasted()
592 591 return
593 592
594 593 text = self.shell.hooks.clipboard_get()
595 594 block = self._strip_pasted_lines_for_code(text.splitlines())
596 595
597 596 # By default, echo back to terminal unless quiet mode is requested
598 597 if not opts.has_key('q'):
599 598 write = self.shell.write
600 599 write(self.shell.pycolorize(block))
601 600 if not block.endswith('\n'):
602 601 write('\n')
603 602 write("## -- End pasted text --\n")
604 603
605 604 self._execute_block(block, par)
606 605
607 606 def showindentationerror(self):
608 607 super(TerminalInteractiveShell, self).showindentationerror()
609 608 print("If you want to paste code into IPython, try the %paste magic function.")
610 609
611 610
612 611 InteractiveShellABC.register(TerminalInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now