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