##// END OF EJS Templates
Fix paste/cpaste bug and refactor/cleanup that code a lot....
Fernando Perez -
Show More
@@ -25,7 +25,6 b' import sys'
25 import shutil
25 import shutil
26 import re
26 import re
27 import time
27 import time
28 import textwrap
29 from StringIO import StringIO
28 from StringIO import StringIO
30 from getopt import getopt,GetoptError
29 from getopt import getopt,GetoptError
31 from pprint import pformat
30 from pprint import pformat
@@ -3203,65 +3202,6 b' Defaulting color scheme to \'NoColor\'"""'
3203
3202
3204 page.page(self.shell.pycolorize(cont))
3203 page.page(self.shell.pycolorize(cont))
3205
3204
3206 def _rerun_pasted(self):
3207 """ Rerun a previously pasted command.
3208 """
3209 b = self.user_ns.get('pasted_block', None)
3210 if b is None:
3211 raise UsageError('No previous pasted block available')
3212 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3213 exec b in self.user_ns
3214
3215 def _get_pasted_lines(self, sentinel):
3216 """ Yield pasted lines until the user enters the given sentinel value.
3217 """
3218 from IPython.core import interactiveshell
3219 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3220 while True:
3221 try:
3222 l = self.shell.raw_input_original(':')
3223 if l == sentinel:
3224 return
3225 else:
3226 yield l
3227 except EOFError:
3228 print '<EOF>'
3229 return
3230
3231 def _strip_pasted_lines_for_code(self, raw_lines):
3232 """ Strip non-code parts of a sequence of lines to return a block of
3233 code.
3234 """
3235 # Regular expressions that declare text we strip from the input:
3236 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3237 r'^\s*(\s?>)+', # Python input prompt
3238 r'^\s*\.{3,}', # Continuation prompts
3239 r'^\++',
3240 ]
3241
3242 strip_from_start = map(re.compile,strip_re)
3243
3244 lines = []
3245 for l in raw_lines:
3246 for pat in strip_from_start:
3247 l = pat.sub('',l)
3248 lines.append(l)
3249
3250 block = "\n".join(lines) + '\n'
3251 #print "block:\n",block
3252 return block
3253
3254 def _execute_block(self, block, par):
3255 """ Execute a block, or store it in a variable, per the user's request.
3256 """
3257 if not par:
3258 b = textwrap.dedent(block)
3259 self.user_ns['pasted_block'] = b
3260 self.run_cell(b)
3261 else:
3262 self.user_ns[par] = SList(block.splitlines())
3263 print "Block assigned to '%s'" % par
3264
3265 def magic_quickref(self,arg):
3205 def magic_quickref(self,arg):
3266 """ Show a quick reference sheet """
3206 """ Show a quick reference sheet """
3267 import IPython.core.usage
3207 import IPython.core.usage
@@ -355,14 +355,15 b' def test_cpaste():'
355 _ip.user_ns['code_ran'] = True
355 _ip.user_ns['code_ran'] = True
356 return 'run' # return string so '+ run()' doesn't result in success
356 return 'run' # return string so '+ run()' doesn't result in success
357
357
358 tests = {'pass': ["> > > run()",
358 tests = {'pass': ["run()",
359 ">>> > run()",
359 "In [1]: run()",
360 "+++ run()",
360 "In [1]: if 1:\n ...: run()",
361 "++ run()",
361 ">>> run()",
362 " >>> run()"],
362 " >>> run()",
363
363 ],
364 'fail': ["+ + run()",
364
365 " ++ run()"]}
365 'fail': ["1 + run()",
366 "++ run()"]}
366
367
367 _ip.user_ns['run'] = run
368 _ip.user_ns['run'] = run
368
369
@@ -19,6 +19,7 b' import bdb'
19 import os
19 import os
20 import re
20 import re
21 import sys
21 import sys
22 import textwrap
22
23
23 try:
24 try:
24 from contextlib import nested
25 from contextlib import nested
@@ -35,7 +36,7 b' from IPython.utils import py3compat'
35 from IPython.utils.terminal import toggle_set_term_title, set_term_title
36 from IPython.utils.terminal import toggle_set_term_title, set_term_title
36 from IPython.utils.process import abbrev_cwd
37 from IPython.utils.process import abbrev_cwd
37 from IPython.utils.warn import warn, error
38 from IPython.utils.warn import warn, error
38 from IPython.utils.text import num_ini_spaces
39 from IPython.utils.text import num_ini_spaces, SList
39 from IPython.utils.traitlets import Integer, CBool, Unicode
40 from IPython.utils.traitlets import Integer, CBool, Unicode
40
41
41 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
@@ -52,6 +53,48 b' def get_default_editor():'
52 ed = 'notepad' # same in Windows!
53 ed = 'notepad' # same in Windows!
53 return ed
54 return ed
54
55
56
57 def get_pasted_lines(sentinel, input=raw_input):
58 """ Yield pasted lines until the user enters the given sentinel value.
59 """
60 print "Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
61 % sentinel
62 while True:
63 try:
64 l = input(':')
65 if l == sentinel:
66 return
67 else:
68 yield l
69 except EOFError:
70 print '<EOF>'
71 return
72
73
74 def store_or_execute(shell, block, name):
75 """ Execute a block, or store it in a variable, per the user's request.
76 """
77 if name:
78 # If storing it for further editing, run the prefilter on it
79 shell.user_ns[name] = SList(shell.prefilter(block).splitlines())
80 print "Block assigned to '%s'" % name
81 else:
82 # For execution we just dedent it, as all other filtering is
83 # automatically applied by run_cell
84 b = textwrap.dedent(block)
85 shell.user_ns['pasted_block'] = b
86 shell.run_cell(b)
87
88
89 def rerun_pasted(shell):
90 """ Rerun a previously pasted command.
91 """
92 b = shell.user_ns.get('pasted_block')
93 if b is None:
94 raise UsageError('No previous pasted block available')
95 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
96 shell.run_cell(b)
97
55 #-----------------------------------------------------------------------------
98 #-----------------------------------------------------------------------------
56 # Main class
99 # Main class
57 #-----------------------------------------------------------------------------
100 #-----------------------------------------------------------------------------
@@ -523,9 +566,9 b' class TerminalInteractiveShell(InteractiveShell):'
523 def magic_cpaste(self, parameter_s=''):
566 def magic_cpaste(self, parameter_s=''):
524 """Paste & execute a pre-formatted code block from clipboard.
567 """Paste & execute a pre-formatted code block from clipboard.
525
568
526 You must terminate the block with '--' (two minus-signs) or Ctrl-D alone on the
569 You must terminate the block with '--' (two minus-signs) or Ctrl-D
527 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
570 alone on the line. You can also provide your own sentinel with '%paste
528 is the new sentinel for this operation)
571 -s %%' ('%%' is the new sentinel for this operation)
529
572
530 The block is dedented prior to execution to enable execution of method
573 The block is dedented prior to execution to enable execution of method
531 definitions. '>' and '+' characters at the beginning of a line are
574 definitions. '>' and '+' characters at the beginning of a line are
@@ -562,18 +605,15 b' class TerminalInteractiveShell(InteractiveShell):'
562 Hello world!
605 Hello world!
563 """
606 """
564
607
565 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
608 opts, args = self.parse_options(parameter_s, 'rs:', mode='string')
566 par = args.strip()
609 name = args.strip()
567 if opts.has_key('r'):
610 if 'r' in opts:
568 self._rerun_pasted()
611 rerun_pasted(self.shell)
569 return
612 return
570
613
571 sentinel = opts.get('s','--')
614 sentinel = opts.get('s', '--')
572
615 block = '\n'.join(get_pasted_lines(sentinel))
573 block = self._strip_pasted_lines_for_code(
616 store_or_execute(self.shell, block, name)
574 self._get_pasted_lines(sentinel))
575
576 self._execute_block(block, par)
577
617
578 def magic_paste(self, parameter_s=''):
618 def magic_paste(self, parameter_s=''):
579 """Paste & execute a pre-formatted code block from clipboard.
619 """Paste & execute a pre-formatted code block from clipboard.
@@ -606,10 +646,10 b' class TerminalInteractiveShell(InteractiveShell):'
606 --------
646 --------
607 cpaste: manually paste code into terminal until you mark its end.
647 cpaste: manually paste code into terminal until you mark its end.
608 """
648 """
609 opts,args = self.parse_options(parameter_s,'rq',mode='string')
649 opts, args = self.parse_options(parameter_s, 'rq', mode='string')
610 par = args.strip()
650 name = args.strip()
611 if opts.has_key('r'):
651 if 'r' in opts:
612 self._rerun_pasted()
652 rerun_pasted(self.shell)
613 return
653 return
614 try:
654 try:
615 text = self.shell.hooks.clipboard_get()
655 text = self.shell.hooks.clipboard_get()
@@ -623,14 +663,14 b' class TerminalInteractiveShell(InteractiveShell):'
623 return
663 return
624
664
625 # By default, echo back to terminal unless quiet mode is requested
665 # By default, echo back to terminal unless quiet mode is requested
626 if not opts.has_key('q'):
666 if 'q' not in opts:
627 write = self.shell.write
667 write = self.shell.write
628 write(self.shell.pycolorize(block))
668 write(self.shell.pycolorize(block))
629 if not block.endswith('\n'):
669 if not block.endswith('\n'):
630 write('\n')
670 write('\n')
631 write("## -- End pasted text --\n")
671 write("## -- End pasted text --\n")
632
672
633 self._execute_block(block, par)
673 store_or_execute(self.shell, block, name)
634
674
635 if sys.platform == 'win32':
675 if sys.platform == 'win32':
636 def magic_cls(self, s):
676 def magic_cls(self, s):
General Comments 0
You need to be logged in to leave comments. Login now