##// END OF EJS Templates
Fix paste/cpaste magic
Takumasa Nakamura -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,214 +1,214 b''
1 1 """Extra magics for terminal use."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6
7 7 from logging import error
8 8 import os
9 9 import sys
10 10
11 11 from IPython.core.error import TryNext, UsageError
12 12 from IPython.core.magic import Magics, magics_class, line_magic
13 13 from IPython.lib.clipboard import ClipboardEmpty
14 14 from IPython.testing.skipdoctest import skip_doctest
15 15 from IPython.utils.text import SList, strip_email_quotes
16 16 from IPython.utils import py3compat
17 17
18 18 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
19 19 """ Yield pasted lines until the user enters the given sentinel value.
20 20 """
21 21 if not quiet:
22 22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
23 23 % sentinel)
24 24 prompt = ":"
25 25 else:
26 26 prompt = ""
27 27 while True:
28 28 try:
29 29 l = l_input(prompt)
30 30 if l == sentinel:
31 31 return
32 32 else:
33 33 yield l
34 34 except EOFError:
35 35 print('<EOF>')
36 36 return
37 37
38 38
39 39 @magics_class
40 40 class TerminalMagics(Magics):
41 41 def __init__(self, shell):
42 42 super(TerminalMagics, self).__init__(shell)
43 43
44 44 def store_or_execute(self, block, name, store_history=False):
45 45 """ Execute a block, or store it in a variable, per the user's request.
46 46 """
47 47 if name:
48 48 # If storing it for further editing
49 49 self.shell.user_ns[name] = SList(block.splitlines())
50 50 print("Block assigned to '%s'" % name)
51 51 else:
52 52 b = self.preclean_input(block)
53 53 self.shell.user_ns['pasted_block'] = b
54 54 self.shell.using_paste_magics = True
55 55 try:
56 56 self.shell.run_cell(b, store_history)
57 57 finally:
58 58 self.shell.using_paste_magics = False
59 59
60 60 def preclean_input(self, block):
61 61 lines = block.splitlines()
62 62 while lines and not lines[0].strip():
63 63 lines = lines[1:]
64 64 return strip_email_quotes('\n'.join(lines))
65 65
66 66 def rerun_pasted(self, name='pasted_block'):
67 67 """ Rerun a previously pasted command.
68 68 """
69 69 b = self.shell.user_ns.get(name)
70 70
71 71 # Sanity checks
72 72 if b is None:
73 73 raise UsageError('No previous pasted block available')
74 74 if not isinstance(b, str):
75 75 raise UsageError(
76 76 "Variable 'pasted_block' is not a string, can't execute")
77 77
78 78 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
79 79 self.shell.run_cell(b)
80 80
81 81 @line_magic
82 82 def autoindent(self, parameter_s = ''):
83 83 """Toggle autoindent on/off (deprecated)"""
84 84 self.shell.set_autoindent()
85 85 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
86 86
87 87 @skip_doctest
88 88 @line_magic
89 89 def cpaste(self, parameter_s=''):
90 90 """Paste & execute a pre-formatted code block from clipboard.
91 91
92 92 You must terminate the block with '--' (two minus-signs) or Ctrl-D
93 93 alone on the line. You can also provide your own sentinel with '%paste
94 94 -s %%' ('%%' is the new sentinel for this operation).
95 95
96 96 The block is dedented prior to execution to enable execution of method
97 97 definitions. '>' and '+' characters at the beginning of a line are
98 98 ignored, to allow pasting directly from e-mails, diff files and
99 99 doctests (the '...' continuation prompt is also stripped). The
100 100 executed block is also assigned to variable named 'pasted_block' for
101 101 later editing with '%edit pasted_block'.
102 102
103 103 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
104 104 This assigns the pasted block to variable 'foo' as string, without
105 105 dedenting or executing it (preceding >>> and + is still stripped)
106 106
107 107 '%cpaste -r' re-executes the block previously entered by cpaste.
108 108 '%cpaste -q' suppresses any additional output messages.
109 109
110 110 Do not be alarmed by garbled output on Windows (it's a readline bug).
111 111 Just press enter and type -- (and press enter again) and the block
112 112 will be what was just pasted.
113 113
114 114 Shell escapes are not supported (yet).
115 115
116 116 See Also
117 117 --------
118 118 paste : automatically pull code from clipboard.
119 119
120 120 Examples
121 121 --------
122 122 ::
123 123
124 124 In [8]: %cpaste
125 125 Pasting code; enter '--' alone on the line to stop.
126 126 :>>> a = ["world!", "Hello"]
127 127 :>>> print(" ".join(sorted(a)))
128 128 :--
129 129 Hello world!
130 130
131 131 ::
132 132 In [8]: %cpaste
133 133 Pasting code; enter '--' alone on the line to stop.
134 134 :>>> %alias_magic t timeit
135 135 :>>> %t -n1 pass
136 136 :--
137 137 Created `%t` as an alias for `%timeit`.
138 138 Created `%%t` as an alias for `%%timeit`.
139 139 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
140 140 """
141 141 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
142 142 if 'r' in opts:
143 143 self.rerun_pasted()
144 144 return
145 145
146 146 quiet = ('q' in opts)
147 147
148 148 sentinel = opts.get('s', u'--')
149 149 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
150 self.store_or_execute(block, name, store_history=False)
150 self.store_or_execute(block, name, store_history=True)
151 151
152 152 @line_magic
153 153 def paste(self, parameter_s=''):
154 154 """Paste & execute a pre-formatted code block from clipboard.
155 155
156 156 The text is pulled directly from the clipboard without user
157 157 intervention and printed back on the screen before execution (unless
158 158 the -q flag is given to force quiet mode).
159 159
160 160 The block is dedented prior to execution to enable execution of method
161 161 definitions. '>' and '+' characters at the beginning of a line are
162 162 ignored, to allow pasting directly from e-mails, diff files and
163 163 doctests (the '...' continuation prompt is also stripped). The
164 164 executed block is also assigned to variable named 'pasted_block' for
165 165 later editing with '%edit pasted_block'.
166 166
167 167 You can also pass a variable name as an argument, e.g. '%paste foo'.
168 168 This assigns the pasted block to variable 'foo' as string, without
169 169 executing it (preceding >>> and + is still stripped).
170 170
171 171 Options:
172 172
173 173 -r: re-executes the block previously entered by cpaste.
174 174
175 175 -q: quiet mode: do not echo the pasted text back to the terminal.
176 176
177 177 IPython statements (magics, shell escapes) are not supported (yet).
178 178
179 179 See Also
180 180 --------
181 181 cpaste : manually paste code into terminal until you mark its end.
182 182 """
183 183 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
184 184 if 'r' in opts:
185 185 self.rerun_pasted()
186 186 return
187 187 try:
188 188 block = self.shell.hooks.clipboard_get()
189 189 except TryNext as clipboard_exc:
190 190 message = getattr(clipboard_exc, 'args')
191 191 if message:
192 192 error(message[0])
193 193 else:
194 194 error('Could not get text from the clipboard.')
195 195 return
196 196 except ClipboardEmpty as e:
197 197 raise UsageError("The clipboard appears to be empty") from e
198 198
199 199 # By default, echo back to terminal unless quiet mode is requested
200 200 if 'q' not in opts:
201 201 sys.stdout.write(self.shell.pycolorize(block))
202 202 if not block.endswith("\n"):
203 203 sys.stdout.write("\n")
204 204 sys.stdout.write("## -- End pasted text --\n")
205 205
206 206 self.store_or_execute(block, name, store_history=True)
207 207
208 208 # Class-level: add a '%cls' magic only on Windows
209 209 if sys.platform == 'win32':
210 210 @line_magic
211 211 def cls(self, s):
212 212 """Clear screen.
213 213 """
214 214 os.system("cls")
General Comments 0
You need to be logged in to leave comments. Login now