##// END OF EJS Templates
[merge] Merging with upstream trunk.
Fernando Perez -
r2107:3611aca7 merge
parent child Browse files
Show More
@@ -0,0 +1,56 b''
1 """ Utilities for accessing the platform's clipboard.
2 """
3
4 import subprocess
5 import sys
6
7 from IPython.ipapi import TryNext
8
9
10 def win32_clipboard_get():
11 """ Get the current clipboard's text on Windows.
12
13 Requires Mark Hammond's pywin32 extensions.
14 """
15 try:
16 import win32clipboard
17 except ImportError:
18 message = ("Getting text from the clipboard requires the pywin32 "
19 "extensions: http://sourceforge.net/projects/pywin32/")
20 raise TryNext(message)
21 win32clipboard.OpenClipboard()
22 text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)
23 # FIXME: convert \r\n to \n?
24 win32clipboard.CloseClipboard()
25 return text
26
27 def osx_clipboard_get():
28 """ Get the clipboard's text on OS X.
29 """
30 p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'],
31 stdout=subprocess.PIPE)
32 text, stderr = p.communicate()
33 # Text comes in with old Mac \r line endings. Change them to \n.
34 text = text.replace('\r', '\n')
35 return text
36
37 def tkinter_clipboard_get():
38 """ Get the clipboard's text using Tkinter.
39
40 This is the default on systems that are not Windows or OS X. It may
41 interfere with other UI toolkits and should be replaced with an
42 implementation that uses that toolkit.
43 """
44 try:
45 import Tkinter
46 except ImportError:
47 message = ("Getting text from the clipboard on this platform "
48 "requires Tkinter.")
49 raise TryNext(message)
50 root = Tkinter.Tk()
51 root.withdraw()
52 text = root.clipboard_get()
53 root.destroy()
54 return text
55
56
@@ -3261,6 +3261,61 b' Defaulting color scheme to \'NoColor\'"""'
3261 page(self.shell.pycolorize(cont),
3261 page(self.shell.pycolorize(cont),
3262 screen_lines=self.shell.rc.screen_length)
3262 screen_lines=self.shell.rc.screen_length)
3263
3263
3264 def _rerun_pasted(self):
3265 """ Rerun a previously pasted command.
3266 """
3267 b = self.user_ns.get('pasted_block', None)
3268 if b is None:
3269 raise UsageError('No previous pasted block available')
3270 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3271 exec b in self.user_ns
3272
3273 def _get_pasted_lines(self, sentinel):
3274 """ Yield pasted lines until the user enters the given sentinel value.
3275 """
3276 from IPython import iplib
3277 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3278 while True:
3279 l = iplib.raw_input_original(':')
3280 if l == sentinel:
3281 return
3282 else:
3283 yield l
3284
3285 def _strip_pasted_lines_for_code(self, raw_lines):
3286 """ Strip non-code parts of a sequence of lines to return a block of
3287 code.
3288 """
3289 # Regular expressions that declare text we strip from the input:
3290 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3291 r'^\s*(\s?>)+', # Python input prompt
3292 r'^\s*\.{3,}', # Continuation prompts
3293 r'^\++',
3294 ]
3295
3296 strip_from_start = map(re.compile,strip_re)
3297
3298 lines = []
3299 for l in raw_lines:
3300 for pat in strip_from_start:
3301 l = pat.sub('',l)
3302 lines.append(l)
3303
3304 block = "\n".join(lines) + '\n'
3305 #print "block:\n",block
3306 return block
3307
3308 def _execute_block(self, block, par):
3309 """ Execute a block, or store it in a variable, per the user's request.
3310 """
3311 if not par:
3312 b = textwrap.dedent(block)
3313 self.user_ns['pasted_block'] = b
3314 exec b in self.user_ns
3315 else:
3316 self.user_ns[par] = SList(block.splitlines())
3317 print "Block assigned to '%s'" % par
3318
3264 def magic_cpaste(self, parameter_s=''):
3319 def magic_cpaste(self, parameter_s=''):
3265 """Allows you to paste & execute a pre-formatted code block from clipboard.
3320 """Allows you to paste & execute a pre-formatted code block from clipboard.
3266
3321
@@ -3286,50 +3341,60 b' Defaulting color scheme to \'NoColor\'"""'
3286 will be what was just pasted.
3341 will be what was just pasted.
3287
3342
3288 IPython statements (magics, shell escapes) are not supported (yet).
3343 IPython statements (magics, shell escapes) are not supported (yet).
3344
3345 See also
3346 --------
3347 %paste: automatically pull code from clipboard.
3289 """
3348 """
3349
3290 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3350 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3291 par = args.strip()
3351 par = args.strip()
3292 if opts.has_key('r'):
3352 if opts.has_key('r'):
3293 b = self.user_ns.get('pasted_block', None)
3353 self._rerun_pasted()
3294 if b is None:
3295 raise UsageError('No previous pasted block available')
3296 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3297 exec b in self.user_ns
3298 return
3354 return
3299
3355
3300 sentinel = opts.get('s','--')
3356 sentinel = opts.get('s','--')
3301
3357
3302 # Regular expressions that declare text we strip from the input:
3358 block = self._strip_pasted_lines_for_code(
3303 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3359 self._get_pasted_lines(sentinel))
3304 r'^\s*(\s?>)+', # Python input prompt
3305 r'^\s*\.{3,}', # Continuation prompts
3306 r'^\++',
3307 ]
3308
3360
3309 strip_from_start = map(re.compile,strip_re)
3361 self._execute_block(block, par)
3362
3363 def magic_paste(self, parameter_s=''):
3364 """Allows you to paste & execute a pre-formatted code block from clipboard.
3310
3365
3311 from IPython import iplib
3366 The text is pulled directly from the clipboard without user
3312 lines = []
3367 intervention.
3313 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3368
3314 while 1:
3369 The block is dedented prior to execution to enable execution of method
3315 l = iplib.raw_input_original(':')
3370 definitions. '>' and '+' characters at the beginning of a line are
3316 if l ==sentinel:
3371 ignored, to allow pasting directly from e-mails, diff files and
3317 break
3372 doctests (the '...' continuation prompt is also stripped). The
3318
3373 executed block is also assigned to variable named 'pasted_block' for
3319 for pat in strip_from_start:
3374 later editing with '%edit pasted_block'.
3320 l = pat.sub('',l)
3375
3321 lines.append(l)
3376 You can also pass a variable name as an argument, e.g. '%paste foo'.
3322
3377 This assigns the pasted block to variable 'foo' as string, without
3323 block = "\n".join(lines) + '\n'
3378 dedenting or executing it (preceding >>> and + is still stripped)
3324 #print "block:\n",block
3379
3325 if not par:
3380 '%paste -r' re-executes the block previously entered by cpaste.
3326 b = textwrap.dedent(block)
3381
3327 self.user_ns['pasted_block'] = b
3382 IPython statements (magics, shell escapes) are not supported (yet).
3328 exec b in self.user_ns
3383
3329 else:
3384 See also
3330 self.user_ns[par] = SList(block.splitlines())
3385 --------
3331 print "Block assigned to '%s'" % par
3386 %cpaste: manually paste code into terminal until you mark its end.
3332
3387 """
3388 opts,args = self.parse_options(parameter_s,'r:',mode='string')
3389 par = args.strip()
3390 if opts.has_key('r'):
3391 self._rerun_pasted()
3392 return
3393
3394 text = self.shell.hooks.clipboard_get()
3395 block = self._strip_pasted_lines_for_code(text.splitlines())
3396 self._execute_block(block, par)
3397
3333 def magic_quickref(self,arg):
3398 def magic_quickref(self,arg):
3334 """ Show a quick reference sheet """
3399 """ Show a quick reference sheet """
3335 import IPython.usage
3400 import IPython.usage
@@ -44,6 +44,7 b' somewhere in your configuration files or ipython command line.'
44 from IPython import ipapi
44 from IPython import ipapi
45
45
46 import os,bisect
46 import os,bisect
47 import sys
47 from genutils import Term,shell
48 from genutils import Term,shell
48 from pprint import PrettyPrinter
49 from pprint import PrettyPrinter
49
50
@@ -53,7 +54,8 b' from pprint import PrettyPrinter'
53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
54 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
55 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
55 'generate_prompt', 'generate_output_prompt','shell_hook',
56 'generate_prompt', 'generate_output_prompt','shell_hook',
56 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
57 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook',
58 'clipboard_get']
57 # vds: <<
59 # vds: <<
58
60
59 pformat = PrettyPrinter().pformat
61 pformat = PrettyPrinter().pformat
@@ -243,5 +245,20 b' def pre_prompt_hook(self):'
243 def pre_runcode_hook(self):
245 def pre_runcode_hook(self):
244 """ Executed before running the (prefiltered) code in IPython """
246 """ Executed before running the (prefiltered) code in IPython """
245 return None
247 return None
246
247
248
249 def clipboard_get(self):
250 """ Get text from the clipboard.
251 """
252 from IPython.clipboard import (osx_clipboard_get, tkinter_clipboard_get,
253 win32_clipboard_get)
254 if sys.platform == 'win32':
255 chain = [win32_clipboard_get, tkinter_clipboard_get]
256 elif sys.platform == 'darwin':
257 chain = [osx_clipboard_get, tkinter_clipboard_get]
258 else:
259 chain = [tkinter_clipboard_get]
260 dispatcher = CommandChainDispatcher()
261 for func in chain:
262 dispatcher.add(func)
263 text = dispatcher()
264 return text
@@ -252,3 +252,39 b' class TestMagicRun(object):'
252
252
253 def teardown(self):
253 def teardown(self):
254 self.tmpfile.close()
254 self.tmpfile.close()
255
256 # Multiple tests for clipboard pasting
257 def test_paste():
258
259 def paste(txt):
260 hooks.clipboard_get = lambda : txt
261 _ip.magic('paste')
262
263 # Inject fake clipboard hook but save original so we can restore it later
264 hooks = _ip.IP.hooks
265 user_ns = _ip.user_ns
266 original_clip = hooks.clipboard_get
267
268 try:
269 # Run tests with fake clipboard function
270 user_ns.pop('x', None)
271 paste('x=1')
272 yield (nt.assert_equal, user_ns['x'], 1)
273
274 user_ns.pop('x', None)
275 paste('>>> x=2')
276 yield (nt.assert_equal, user_ns['x'], 2)
277
278 paste("""
279 >>> x = [1,2,3]
280 >>> y = []
281 >>> for i in x:
282 ... y.append(i**2)
283 ...
284 """)
285 yield (nt.assert_equal, user_ns['x'], [1,2,3])
286 yield (nt.assert_equal, user_ns['y'], [1,4,9])
287
288 finally:
289 # Restore original hook
290 hooks.clipboard_get = original_clip
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now