Show More
@@ -0,0 +1,56 | |||
|
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 |
@@ -3210,6 +3210,61 Defaulting color scheme to 'NoColor'""" | |||
|
3210 | 3210 | page(self.shell.pycolorize(cont), |
|
3211 | 3211 | screen_lines=self.shell.rc.screen_length) |
|
3212 | 3212 | |
|
3213 | def _rerun_pasted(self): | |
|
3214 | """ Rerun a previously pasted command. | |
|
3215 | """ | |
|
3216 | b = self.user_ns.get('pasted_block', None) | |
|
3217 | if b is None: | |
|
3218 | raise UsageError('No previous pasted block available') | |
|
3219 | print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)) | |
|
3220 | exec b in self.user_ns | |
|
3221 | ||
|
3222 | def _get_pasted_lines(self, sentinel): | |
|
3223 | """ Yield pasted lines until the user enters the given sentinel value. | |
|
3224 | """ | |
|
3225 | from IPython import iplib | |
|
3226 | print "Pasting code; enter '%s' alone on the line to stop." % sentinel | |
|
3227 | while True: | |
|
3228 | l = iplib.raw_input_original(':') | |
|
3229 | if l == sentinel: | |
|
3230 | return | |
|
3231 | else: | |
|
3232 | yield l | |
|
3233 | ||
|
3234 | def _strip_pasted_lines_for_code(self, raw_lines): | |
|
3235 | """ Strip non-code parts of a sequence of lines to return a block of | |
|
3236 | code. | |
|
3237 | """ | |
|
3238 | # Regular expressions that declare text we strip from the input: | |
|
3239 | strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt | |
|
3240 | r'^\s*(\s?>)+', # Python input prompt | |
|
3241 | r'^\s*\.{3,}', # Continuation prompts | |
|
3242 | r'^\++', | |
|
3243 | ] | |
|
3244 | ||
|
3245 | strip_from_start = map(re.compile,strip_re) | |
|
3246 | ||
|
3247 | lines = [] | |
|
3248 | for l in raw_lines: | |
|
3249 | for pat in strip_from_start: | |
|
3250 | l = pat.sub('',l) | |
|
3251 | lines.append(l) | |
|
3252 | ||
|
3253 | block = "\n".join(lines) + '\n' | |
|
3254 | #print "block:\n",block | |
|
3255 | return block | |
|
3256 | ||
|
3257 | def _execute_block(self, block, par): | |
|
3258 | """ Execute a block, or store it in a variable, per the user's request. | |
|
3259 | """ | |
|
3260 | if not par: | |
|
3261 | b = textwrap.dedent(block) | |
|
3262 | self.user_ns['pasted_block'] = b | |
|
3263 | exec b in self.user_ns | |
|
3264 | else: | |
|
3265 | self.user_ns[par] = SList(block.splitlines()) | |
|
3266 | print "Block assigned to '%s'" % par | |
|
3267 | ||
|
3213 | 3268 | def magic_cpaste(self, parameter_s=''): |
|
3214 | 3269 | """Allows you to paste & execute a pre-formatted code block from clipboard. |
|
3215 | 3270 | |
@@ -3239,46 +3294,47 Defaulting color scheme to 'NoColor'""" | |||
|
3239 | 3294 | opts,args = self.parse_options(parameter_s,'rs:',mode='string') |
|
3240 | 3295 | par = args.strip() |
|
3241 | 3296 | if opts.has_key('r'): |
|
3242 |
|
|
|
3243 | if b is None: | |
|
3244 | raise UsageError('No previous pasted block available') | |
|
3245 | print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)) | |
|
3246 | exec b in self.user_ns | |
|
3297 | self._rerun_pasted() | |
|
3247 | 3298 | return |
|
3248 | 3299 | |
|
3249 | 3300 | sentinel = opts.get('s','--') |
|
3250 | 3301 | |
|
3251 | # Regular expressions that declare text we strip from the input: | |
|
3252 | strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt | |
|
3253 | r'^\s*(\s?>)+', # Python input prompt | |
|
3254 | r'^\s*\.{3,}', # Continuation prompts | |
|
3255 | r'^\++', | |
|
3256 | ] | |
|
3302 | block = self._strip_pasted_lines_for_code( | |
|
3303 | self._get_pasted_lines(sentinel)) | |
|
3257 | 3304 | |
|
3258 | strip_from_start = map(re.compile,strip_re) | |
|
3305 | self._execute_block(block, par) | |
|
3306 | ||
|
3307 | def magic_paste(self, parameter_s=''): | |
|
3308 | """Allows you to paste & execute a pre-formatted code block from clipboard. | |
|
3259 | 3309 |
|
|
3260 | from IPython import iplib | |
|
3261 | lines = [] | |
|
3262 | print "Pasting code; enter '%s' alone on the line to stop." % sentinel | |
|
3263 | while 1: | |
|
3264 | l = iplib.raw_input_original(':') | |
|
3265 | if l ==sentinel: | |
|
3266 | break | |
|
3267 | ||
|
3268 | for pat in strip_from_start: | |
|
3269 | l = pat.sub('',l) | |
|
3270 | lines.append(l) | |
|
3271 | ||
|
3272 | block = "\n".join(lines) + '\n' | |
|
3273 | #print "block:\n",block | |
|
3274 | if not par: | |
|
3275 | b = textwrap.dedent(block) | |
|
3276 | self.user_ns['pasted_block'] = b | |
|
3277 | exec b in self.user_ns | |
|
3278 | else: | |
|
3279 | self.user_ns[par] = SList(block.splitlines()) | |
|
3280 | print "Block assigned to '%s'" % par | |
|
3281 | ||
|
3310 | The text is pulled directly from the clipboard without user | |
|
3311 | intervention. | |
|
3312 | ||
|
3313 | The block is dedented prior to execution to enable execution of method | |
|
3314 | definitions. '>' and '+' characters at the beginning of a line are | |
|
3315 | ignored, to allow pasting directly from e-mails, diff files and | |
|
3316 | doctests (the '...' continuation prompt is also stripped). The | |
|
3317 | executed block is also assigned to variable named 'pasted_block' for | |
|
3318 | later editing with '%edit pasted_block'. | |
|
3319 | ||
|
3320 | You can also pass a variable name as an argument, e.g. '%paste foo'. | |
|
3321 | This assigns the pasted block to variable 'foo' as string, without | |
|
3322 | dedenting or executing it (preceding >>> and + is still stripped) | |
|
3323 | ||
|
3324 | '%paste -r' re-executes the block previously entered by cpaste. | |
|
3325 | ||
|
3326 | IPython statements (magics, shell escapes) are not supported (yet). | |
|
3327 | """ | |
|
3328 | opts,args = self.parse_options(parameter_s,'r:',mode='string') | |
|
3329 | par = args.strip() | |
|
3330 | if opts.has_key('r'): | |
|
3331 | self._rerun_pasted() | |
|
3332 | return | |
|
3333 | ||
|
3334 | text = self.shell.hooks.clipboard_get() | |
|
3335 | block = self._strip_pasted_lines_for_code(text.splitlines()) | |
|
3336 | self._execute_block(block, par) | |
|
3337 | ||
|
3282 | 3338 | def magic_quickref(self,arg): |
|
3283 | 3339 | """ Show a quick reference sheet """ |
|
3284 | 3340 | import IPython.usage |
@@ -49,6 +49,7 __license__ = Release.license | |||
|
49 | 49 | __version__ = Release.version |
|
50 | 50 | |
|
51 | 51 | import os,bisect |
|
52 | import sys | |
|
52 | 53 | from genutils import Term,shell |
|
53 | 54 | from pprint import PrettyPrinter |
|
54 | 55 | |
@@ -58,7 +59,8 from pprint import PrettyPrinter | |||
|
58 | 59 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display', |
|
59 | 60 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
60 | 61 | 'generate_prompt', 'generate_output_prompt','shell_hook', |
|
61 |
'show_in_pager','pre_prompt_hook', 'pre_runcode_hook' |
|
|
62 | 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook', | |
|
63 | 'clipboard_get'] | |
|
62 | 64 | # vds: << |
|
63 | 65 | |
|
64 | 66 | pformat = PrettyPrinter().pformat |
@@ -248,5 +250,20 def pre_prompt_hook(self): | |||
|
248 | 250 | def pre_runcode_hook(self): |
|
249 | 251 | """ Executed before running the (prefiltered) code in IPython """ |
|
250 | 252 | return None |
|
251 | ||
|
252 | 253 | |
|
254 | def clipboard_get(self): | |
|
255 | """ Get text from the clipboard. | |
|
256 | """ | |
|
257 | from IPython.clipboard import (osx_clipboard_get, tkinter_clipboard_get, | |
|
258 | win32_clipboard_get) | |
|
259 | if sys.platform == 'win32': | |
|
260 | chain = [win32_clipboard_get, tkinter_clipboard_get] | |
|
261 | elif sys.platform == 'darwin': | |
|
262 | chain = [osx_clipboard_get, tkinter_clipboard_get] | |
|
263 | else: | |
|
264 | chain = [tkinter_clipboard_get] | |
|
265 | dispatcher = CommandChainDispatcher() | |
|
266 | for func in chain: | |
|
267 | dispatcher.add(func) | |
|
268 | text = dispatcher() | |
|
269 | return text |
General Comments 0
You need to be logged in to leave comments.
Login now