##// END OF EJS Templates
fix for #10327 : get_ipython.magic() replaced with get_ipython.run_line_magic()
adityausathe -
Show More
@@ -1,525 +1,531 b''
1 """Input transformer classes to support IPython special syntax.
1 """Input transformer classes to support IPython special syntax.
2
2
3 This includes the machinery to recognise and transform ``%magic`` commands,
3 This includes the machinery to recognise and transform ``%magic`` commands,
4 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
4 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
5 """
5 """
6 import abc
6 import abc
7 import functools
7 import functools
8 import re
8 import re
9 from io import StringIO
9 from io import StringIO
10
10
11 from IPython.core.splitinput import LineInfo
11 from IPython.core.splitinput import LineInfo
12 from IPython.utils import tokenize2
12 from IPython.utils import tokenize2
13 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
13 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Globals
16 # Globals
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # The escape sequences that define the syntax transformations IPython will
19 # The escape sequences that define the syntax transformations IPython will
20 # apply to user input. These can NOT be just changed here: many regular
20 # apply to user input. These can NOT be just changed here: many regular
21 # expressions and other parts of the code may use their hardcoded values, and
21 # expressions and other parts of the code may use their hardcoded values, and
22 # for all intents and purposes they constitute the 'IPython syntax', so they
22 # for all intents and purposes they constitute the 'IPython syntax', so they
23 # should be considered fixed.
23 # should be considered fixed.
24
24
25 ESC_SHELL = '!' # Send line to underlying system shell
25 ESC_SHELL = '!' # Send line to underlying system shell
26 ESC_SH_CAP = '!!' # Send line to system shell and capture output
26 ESC_SH_CAP = '!!' # Send line to system shell and capture output
27 ESC_HELP = '?' # Find information about object
27 ESC_HELP = '?' # Find information about object
28 ESC_HELP2 = '??' # Find extra-detailed information about object
28 ESC_HELP2 = '??' # Find extra-detailed information about object
29 ESC_MAGIC = '%' # Call magic function
29 ESC_MAGIC = '%' # Call magic function
30 ESC_MAGIC2 = '%%' # Call cell-magic function
30 ESC_MAGIC2 = '%%' # Call cell-magic function
31 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
31 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
32 ESC_QUOTE2 = ';' # Quote all args as a single string, call
32 ESC_QUOTE2 = ';' # Quote all args as a single string, call
33 ESC_PAREN = '/' # Call first argument with rest of line as arguments
33 ESC_PAREN = '/' # Call first argument with rest of line as arguments
34
34
35 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
35 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
36 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
36 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
37 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
37 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
38
38
39
39
40 class InputTransformer(metaclass=abc.ABCMeta):
40 class InputTransformer(metaclass=abc.ABCMeta):
41 """Abstract base class for line-based input transformers."""
41 """Abstract base class for line-based input transformers."""
42
42
43 @abc.abstractmethod
43 @abc.abstractmethod
44 def push(self, line):
44 def push(self, line):
45 """Send a line of input to the transformer, returning the transformed
45 """Send a line of input to the transformer, returning the transformed
46 input or None if the transformer is waiting for more input.
46 input or None if the transformer is waiting for more input.
47
47
48 Must be overridden by subclasses.
48 Must be overridden by subclasses.
49
49
50 Implementations may raise ``SyntaxError`` if the input is invalid. No
50 Implementations may raise ``SyntaxError`` if the input is invalid. No
51 other exceptions may be raised.
51 other exceptions may be raised.
52 """
52 """
53 pass
53 pass
54
54
55 @abc.abstractmethod
55 @abc.abstractmethod
56 def reset(self):
56 def reset(self):
57 """Return, transformed any lines that the transformer has accumulated,
57 """Return, transformed any lines that the transformer has accumulated,
58 and reset its internal state.
58 and reset its internal state.
59
59
60 Must be overridden by subclasses.
60 Must be overridden by subclasses.
61 """
61 """
62 pass
62 pass
63
63
64 @classmethod
64 @classmethod
65 def wrap(cls, func):
65 def wrap(cls, func):
66 """Can be used by subclasses as a decorator, to return a factory that
66 """Can be used by subclasses as a decorator, to return a factory that
67 will allow instantiation with the decorated object.
67 will allow instantiation with the decorated object.
68 """
68 """
69 @functools.wraps(func)
69 @functools.wraps(func)
70 def transformer_factory(**kwargs):
70 def transformer_factory(**kwargs):
71 return cls(func, **kwargs)
71 return cls(func, **kwargs)
72
72
73 return transformer_factory
73 return transformer_factory
74
74
75 class StatelessInputTransformer(InputTransformer):
75 class StatelessInputTransformer(InputTransformer):
76 """Wrapper for a stateless input transformer implemented as a function."""
76 """Wrapper for a stateless input transformer implemented as a function."""
77 def __init__(self, func):
77 def __init__(self, func):
78 self.func = func
78 self.func = func
79
79
80 def __repr__(self):
80 def __repr__(self):
81 return "StatelessInputTransformer(func={0!r})".format(self.func)
81 return "StatelessInputTransformer(func={0!r})".format(self.func)
82
82
83 def push(self, line):
83 def push(self, line):
84 """Send a line of input to the transformer, returning the
84 """Send a line of input to the transformer, returning the
85 transformed input."""
85 transformed input."""
86 return self.func(line)
86 return self.func(line)
87
87
88 def reset(self):
88 def reset(self):
89 """No-op - exists for compatibility."""
89 """No-op - exists for compatibility."""
90 pass
90 pass
91
91
92 class CoroutineInputTransformer(InputTransformer):
92 class CoroutineInputTransformer(InputTransformer):
93 """Wrapper for an input transformer implemented as a coroutine."""
93 """Wrapper for an input transformer implemented as a coroutine."""
94 def __init__(self, coro, **kwargs):
94 def __init__(self, coro, **kwargs):
95 # Prime it
95 # Prime it
96 self.coro = coro(**kwargs)
96 self.coro = coro(**kwargs)
97 next(self.coro)
97 next(self.coro)
98
98
99 def __repr__(self):
99 def __repr__(self):
100 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
100 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
101
101
102 def push(self, line):
102 def push(self, line):
103 """Send a line of input to the transformer, returning the
103 """Send a line of input to the transformer, returning the
104 transformed input or None if the transformer is waiting for more
104 transformed input or None if the transformer is waiting for more
105 input.
105 input.
106 """
106 """
107 return self.coro.send(line)
107 return self.coro.send(line)
108
108
109 def reset(self):
109 def reset(self):
110 """Return, transformed any lines that the transformer has
110 """Return, transformed any lines that the transformer has
111 accumulated, and reset its internal state.
111 accumulated, and reset its internal state.
112 """
112 """
113 return self.coro.send(None)
113 return self.coro.send(None)
114
114
115 class TokenInputTransformer(InputTransformer):
115 class TokenInputTransformer(InputTransformer):
116 """Wrapper for a token-based input transformer.
116 """Wrapper for a token-based input transformer.
117
117
118 func should accept a list of tokens (5-tuples, see tokenize docs), and
118 func should accept a list of tokens (5-tuples, see tokenize docs), and
119 return an iterable which can be passed to tokenize.untokenize().
119 return an iterable which can be passed to tokenize.untokenize().
120 """
120 """
121 def __init__(self, func):
121 def __init__(self, func):
122 self.func = func
122 self.func = func
123 self.buf = []
123 self.buf = []
124 self.reset_tokenizer()
124 self.reset_tokenizer()
125
125
126 def reset_tokenizer(self):
126 def reset_tokenizer(self):
127 it = iter(self.buf)
127 it = iter(self.buf)
128 self.tokenizer = generate_tokens(it.__next__)
128 self.tokenizer = generate_tokens(it.__next__)
129
129
130 def push(self, line):
130 def push(self, line):
131 self.buf.append(line + '\n')
131 self.buf.append(line + '\n')
132 if all(l.isspace() for l in self.buf):
132 if all(l.isspace() for l in self.buf):
133 return self.reset()
133 return self.reset()
134
134
135 tokens = []
135 tokens = []
136 stop_at_NL = False
136 stop_at_NL = False
137 try:
137 try:
138 for intok in self.tokenizer:
138 for intok in self.tokenizer:
139 tokens.append(intok)
139 tokens.append(intok)
140 t = intok[0]
140 t = intok[0]
141 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
141 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
142 # Stop before we try to pull a line we don't have yet
142 # Stop before we try to pull a line we don't have yet
143 break
143 break
144 elif t == tokenize2.ERRORTOKEN:
144 elif t == tokenize2.ERRORTOKEN:
145 stop_at_NL = True
145 stop_at_NL = True
146 except TokenError:
146 except TokenError:
147 # Multi-line statement - stop and try again with the next line
147 # Multi-line statement - stop and try again with the next line
148 self.reset_tokenizer()
148 self.reset_tokenizer()
149 return None
149 return None
150
150
151 return self.output(tokens)
151 return self.output(tokens)
152
152
153 def output(self, tokens):
153 def output(self, tokens):
154 self.buf.clear()
154 self.buf.clear()
155 self.reset_tokenizer()
155 self.reset_tokenizer()
156 return untokenize(self.func(tokens)).rstrip('\n')
156 return untokenize(self.func(tokens)).rstrip('\n')
157
157
158 def reset(self):
158 def reset(self):
159 l = ''.join(self.buf)
159 l = ''.join(self.buf)
160 self.buf.clear()
160 self.buf.clear()
161 self.reset_tokenizer()
161 self.reset_tokenizer()
162 if l:
162 if l:
163 return l.rstrip('\n')
163 return l.rstrip('\n')
164
164
165 class assemble_python_lines(TokenInputTransformer):
165 class assemble_python_lines(TokenInputTransformer):
166 def __init__(self):
166 def __init__(self):
167 super(assemble_python_lines, self).__init__(None)
167 super(assemble_python_lines, self).__init__(None)
168
168
169 def output(self, tokens):
169 def output(self, tokens):
170 return self.reset()
170 return self.reset()
171
171
172 @CoroutineInputTransformer.wrap
172 @CoroutineInputTransformer.wrap
173 def assemble_logical_lines():
173 def assemble_logical_lines():
174 """Join lines following explicit line continuations (\)"""
174 """Join lines following explicit line continuations (\)"""
175 line = ''
175 line = ''
176 while True:
176 while True:
177 line = (yield line)
177 line = (yield line)
178 if not line or line.isspace():
178 if not line or line.isspace():
179 continue
179 continue
180
180
181 parts = []
181 parts = []
182 while line is not None:
182 while line is not None:
183 if line.endswith('\\') and (not has_comment(line)):
183 if line.endswith('\\') and (not has_comment(line)):
184 parts.append(line[:-1])
184 parts.append(line[:-1])
185 line = (yield None) # Get another line
185 line = (yield None) # Get another line
186 else:
186 else:
187 parts.append(line)
187 parts.append(line)
188 break
188 break
189
189
190 # Output
190 # Output
191 line = ''.join(parts)
191 line = ''.join(parts)
192
192
193 # Utilities
193 # Utilities
194 def _make_help_call(target, esc, lspace, next_input=None):
194 def _make_help_call(target, esc, lspace, next_input=None):
195 """Prepares a pinfo(2)/psearch call from a target name and the escape
195 """Prepares a pinfo(2)/psearch call from a target name and the escape
196 (i.e. ? or ??)"""
196 (i.e. ? or ??)"""
197 method = 'pinfo2' if esc == '??' \
197 method = 'pinfo2' if esc == '??' \
198 else 'psearch' if '*' in target \
198 else 'psearch' if '*' in target \
199 else 'pinfo'
199 else 'pinfo'
200 arg = " ".join([method, target])
200 arg = " ".join([method, target])
201 if next_input is None:
201 if next_input is None:
202 return '%sget_ipython().magic(%r)' % (lspace, arg)
202 return '%sget_ipython().magic(%r)' % (lspace, arg)
203 else:
203 else:
204 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
204 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
205 (lspace, next_input, arg)
205 (lspace, next_input, arg)
206
206
207 # These define the transformations for the different escape characters.
207 # These define the transformations for the different escape characters.
208 def _tr_system(line_info):
208 def _tr_system(line_info):
209 "Translate lines escaped with: !"
209 "Translate lines escaped with: !"
210 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
210 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
211 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
211 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
212
212
213 def _tr_system2(line_info):
213 def _tr_system2(line_info):
214 "Translate lines escaped with: !!"
214 "Translate lines escaped with: !!"
215 cmd = line_info.line.lstrip()[2:]
215 cmd = line_info.line.lstrip()[2:]
216 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
216 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
217
217
218 def _tr_help(line_info):
218 def _tr_help(line_info):
219 "Translate lines escaped with: ?/??"
219 "Translate lines escaped with: ?/??"
220 # A naked help line should just fire the intro help screen
220 # A naked help line should just fire the intro help screen
221 if not line_info.line[1:]:
221 if not line_info.line[1:]:
222 return 'get_ipython().show_usage()'
222 return 'get_ipython().show_usage()'
223
223
224 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
224 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
225
225
226 def _tr_magic(line_info):
226 def _tr_magic(line_info):
227 "Translate lines escaped with: %"
227 "Translate lines escaped with: %"
228 tpl = '%sget_ipython().magic(%r)'
228 tpl = '%sget_ipython().run_line_magic(%r, %r)'
229 if line_info.line.startswith(ESC_MAGIC2):
229 if line_info.line.startswith(ESC_MAGIC2):
230 return line_info.line
230 return line_info.line
231 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
231 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
232 return tpl % (line_info.pre, cmd)
232 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
233 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
234 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
235 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
233
236
234 def _tr_quote(line_info):
237 def _tr_quote(line_info):
235 "Translate lines escaped with: ,"
238 "Translate lines escaped with: ,"
236 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
239 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
237 '", "'.join(line_info.the_rest.split()) )
240 '", "'.join(line_info.the_rest.split()) )
238
241
239 def _tr_quote2(line_info):
242 def _tr_quote2(line_info):
240 "Translate lines escaped with: ;"
243 "Translate lines escaped with: ;"
241 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
242 line_info.the_rest)
245 line_info.the_rest)
243
246
244 def _tr_paren(line_info):
247 def _tr_paren(line_info):
245 "Translate lines escaped with: /"
248 "Translate lines escaped with: /"
246 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
249 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
247 ", ".join(line_info.the_rest.split()))
250 ", ".join(line_info.the_rest.split()))
248
251
249 tr = { ESC_SHELL : _tr_system,
252 tr = { ESC_SHELL : _tr_system,
250 ESC_SH_CAP : _tr_system2,
253 ESC_SH_CAP : _tr_system2,
251 ESC_HELP : _tr_help,
254 ESC_HELP : _tr_help,
252 ESC_HELP2 : _tr_help,
255 ESC_HELP2 : _tr_help,
253 ESC_MAGIC : _tr_magic,
256 ESC_MAGIC : _tr_magic,
254 ESC_QUOTE : _tr_quote,
257 ESC_QUOTE : _tr_quote,
255 ESC_QUOTE2 : _tr_quote2,
258 ESC_QUOTE2 : _tr_quote2,
256 ESC_PAREN : _tr_paren }
259 ESC_PAREN : _tr_paren }
257
260
258 @StatelessInputTransformer.wrap
261 @StatelessInputTransformer.wrap
259 def escaped_commands(line):
262 def escaped_commands(line):
260 """Transform escaped commands - %magic, !system, ?help + various autocalls.
263 """Transform escaped commands - %magic, !system, ?help + various autocalls.
261 """
264 """
262 if not line or line.isspace():
265 if not line or line.isspace():
263 return line
266 return line
264 lineinf = LineInfo(line)
267 lineinf = LineInfo(line)
265 if lineinf.esc not in tr:
268 if lineinf.esc not in tr:
266 return line
269 return line
267
270
268 return tr[lineinf.esc](lineinf)
271 return tr[lineinf.esc](lineinf)
269
272
270 _initial_space_re = re.compile(r'\s*')
273 _initial_space_re = re.compile(r'\s*')
271
274
272 _help_end_re = re.compile(r"""(%{0,2}
275 _help_end_re = re.compile(r"""(%{0,2}
273 [a-zA-Z_*][\w*]* # Variable name
276 [a-zA-Z_*][\w*]* # Variable name
274 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
277 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
275 )
278 )
276 (\?\??)$ # ? or ??
279 (\?\??)$ # ? or ??
277 """,
280 """,
278 re.VERBOSE)
281 re.VERBOSE)
279
282
280 # Extra pseudotokens for multiline strings and data structures
283 # Extra pseudotokens for multiline strings and data structures
281 _MULTILINE_STRING = object()
284 _MULTILINE_STRING = object()
282 _MULTILINE_STRUCTURE = object()
285 _MULTILINE_STRUCTURE = object()
283
286
284 def _line_tokens(line):
287 def _line_tokens(line):
285 """Helper for has_comment and ends_in_comment_or_string."""
288 """Helper for has_comment and ends_in_comment_or_string."""
286 readline = StringIO(line).readline
289 readline = StringIO(line).readline
287 toktypes = set()
290 toktypes = set()
288 try:
291 try:
289 for t in generate_tokens(readline):
292 for t in generate_tokens(readline):
290 toktypes.add(t[0])
293 toktypes.add(t[0])
291 except TokenError as e:
294 except TokenError as e:
292 # There are only two cases where a TokenError is raised.
295 # There are only two cases where a TokenError is raised.
293 if 'multi-line string' in e.args[0]:
296 if 'multi-line string' in e.args[0]:
294 toktypes.add(_MULTILINE_STRING)
297 toktypes.add(_MULTILINE_STRING)
295 else:
298 else:
296 toktypes.add(_MULTILINE_STRUCTURE)
299 toktypes.add(_MULTILINE_STRUCTURE)
297 return toktypes
300 return toktypes
298
301
299 def has_comment(src):
302 def has_comment(src):
300 """Indicate whether an input line has (i.e. ends in, or is) a comment.
303 """Indicate whether an input line has (i.e. ends in, or is) a comment.
301
304
302 This uses tokenize, so it can distinguish comments from # inside strings.
305 This uses tokenize, so it can distinguish comments from # inside strings.
303
306
304 Parameters
307 Parameters
305 ----------
308 ----------
306 src : string
309 src : string
307 A single line input string.
310 A single line input string.
308
311
309 Returns
312 Returns
310 -------
313 -------
311 comment : bool
314 comment : bool
312 True if source has a comment.
315 True if source has a comment.
313 """
316 """
314 return (tokenize2.COMMENT in _line_tokens(src))
317 return (tokenize2.COMMENT in _line_tokens(src))
315
318
316 def ends_in_comment_or_string(src):
319 def ends_in_comment_or_string(src):
317 """Indicates whether or not an input line ends in a comment or within
320 """Indicates whether or not an input line ends in a comment or within
318 a multiline string.
321 a multiline string.
319
322
320 Parameters
323 Parameters
321 ----------
324 ----------
322 src : string
325 src : string
323 A single line input string.
326 A single line input string.
324
327
325 Returns
328 Returns
326 -------
329 -------
327 comment : bool
330 comment : bool
328 True if source ends in a comment or multiline string.
331 True if source ends in a comment or multiline string.
329 """
332 """
330 toktypes = _line_tokens(src)
333 toktypes = _line_tokens(src)
331 return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
334 return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
332
335
333
336
334 @StatelessInputTransformer.wrap
337 @StatelessInputTransformer.wrap
335 def help_end(line):
338 def help_end(line):
336 """Translate lines with ?/?? at the end"""
339 """Translate lines with ?/?? at the end"""
337 m = _help_end_re.search(line)
340 m = _help_end_re.search(line)
338 if m is None or ends_in_comment_or_string(line):
341 if m is None or ends_in_comment_or_string(line):
339 return line
342 return line
340 target = m.group(1)
343 target = m.group(1)
341 esc = m.group(3)
344 esc = m.group(3)
342 lspace = _initial_space_re.match(line).group(0)
345 lspace = _initial_space_re.match(line).group(0)
343
346
344 # If we're mid-command, put it back on the next prompt for the user.
347 # If we're mid-command, put it back on the next prompt for the user.
345 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
348 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
346
349
347 return _make_help_call(target, esc, lspace, next_input)
350 return _make_help_call(target, esc, lspace, next_input)
348
351
349
352
350 @CoroutineInputTransformer.wrap
353 @CoroutineInputTransformer.wrap
351 def cellmagic(end_on_blank_line=False):
354 def cellmagic(end_on_blank_line=False):
352 """Captures & transforms cell magics.
355 """Captures & transforms cell magics.
353
356
354 After a cell magic is started, this stores up any lines it gets until it is
357 After a cell magic is started, this stores up any lines it gets until it is
355 reset (sent None).
358 reset (sent None).
356 """
359 """
357 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
360 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
358 cellmagic_help_re = re.compile('%%\w+\?')
361 cellmagic_help_re = re.compile('%%\w+\?')
359 line = ''
362 line = ''
360 while True:
363 while True:
361 line = (yield line)
364 line = (yield line)
362 # consume leading empty lines
365 # consume leading empty lines
363 while not line:
366 while not line:
364 line = (yield line)
367 line = (yield line)
365
368
366 if not line.startswith(ESC_MAGIC2):
369 if not line.startswith(ESC_MAGIC2):
367 # This isn't a cell magic, idle waiting for reset then start over
370 # This isn't a cell magic, idle waiting for reset then start over
368 while line is not None:
371 while line is not None:
369 line = (yield line)
372 line = (yield line)
370 continue
373 continue
371
374
372 if cellmagic_help_re.match(line):
375 if cellmagic_help_re.match(line):
373 # This case will be handled by help_end
376 # This case will be handled by help_end
374 continue
377 continue
375
378
376 first = line
379 first = line
377 body = []
380 body = []
378 line = (yield None)
381 line = (yield None)
379 while (line is not None) and \
382 while (line is not None) and \
380 ((line.strip() != '') or not end_on_blank_line):
383 ((line.strip() != '') or not end_on_blank_line):
381 body.append(line)
384 body.append(line)
382 line = (yield None)
385 line = (yield None)
383
386
384 # Output
387 # Output
385 magic_name, _, first = first.partition(' ')
388 magic_name, _, first = first.partition(' ')
386 magic_name = magic_name.lstrip(ESC_MAGIC2)
389 magic_name = magic_name.lstrip(ESC_MAGIC2)
387 line = tpl % (magic_name, first, u'\n'.join(body))
390 line = tpl % (magic_name, first, u'\n'.join(body))
388
391
389
392
390 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
393 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
391 """Remove matching input prompts from a block of input.
394 """Remove matching input prompts from a block of input.
392
395
393 Parameters
396 Parameters
394 ----------
397 ----------
395 prompt_re : regular expression
398 prompt_re : regular expression
396 A regular expression matching any input prompt (including continuation)
399 A regular expression matching any input prompt (including continuation)
397 initial_re : regular expression, optional
400 initial_re : regular expression, optional
398 A regular expression matching only the initial prompt, but not continuation.
401 A regular expression matching only the initial prompt, but not continuation.
399 If no initial expression is given, prompt_re will be used everywhere.
402 If no initial expression is given, prompt_re will be used everywhere.
400 Used mainly for plain Python prompts, where the continuation prompt
403 Used mainly for plain Python prompts, where the continuation prompt
401 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
404 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
402
405
403 If initial_re and prompt_re differ,
406 If initial_re and prompt_re differ,
404 only initial_re will be tested against the first line.
407 only initial_re will be tested against the first line.
405 If any prompt is found on the first two lines,
408 If any prompt is found on the first two lines,
406 prompts will be stripped from the rest of the block.
409 prompts will be stripped from the rest of the block.
407 """
410 """
408 if initial_re is None:
411 if initial_re is None:
409 initial_re = prompt_re
412 initial_re = prompt_re
410 line = ''
413 line = ''
411 while True:
414 while True:
412 line = (yield line)
415 line = (yield line)
413
416
414 # First line of cell
417 # First line of cell
415 if line is None:
418 if line is None:
416 continue
419 continue
417 out, n1 = initial_re.subn('', line, count=1)
420 out, n1 = initial_re.subn('', line, count=1)
418 if turnoff_re and not n1:
421 if turnoff_re and not n1:
419 if turnoff_re.match(line):
422 if turnoff_re.match(line):
420 # We're in e.g. a cell magic; disable this transformer for
423 # We're in e.g. a cell magic; disable this transformer for
421 # the rest of the cell.
424 # the rest of the cell.
422 while line is not None:
425 while line is not None:
423 line = (yield line)
426 line = (yield line)
424 continue
427 continue
425
428
426 line = (yield out)
429 line = (yield out)
427
430
428 if line is None:
431 if line is None:
429 continue
432 continue
430 # check for any prompt on the second line of the cell,
433 # check for any prompt on the second line of the cell,
431 # because people often copy from just after the first prompt,
434 # because people often copy from just after the first prompt,
432 # so we might not see it in the first line.
435 # so we might not see it in the first line.
433 out, n2 = prompt_re.subn('', line, count=1)
436 out, n2 = prompt_re.subn('', line, count=1)
434 line = (yield out)
437 line = (yield out)
435
438
436 if n1 or n2:
439 if n1 or n2:
437 # Found a prompt in the first two lines - check for it in
440 # Found a prompt in the first two lines - check for it in
438 # the rest of the cell as well.
441 # the rest of the cell as well.
439 while line is not None:
442 while line is not None:
440 line = (yield prompt_re.sub('', line, count=1))
443 line = (yield prompt_re.sub('', line, count=1))
441
444
442 else:
445 else:
443 # Prompts not in input - wait for reset
446 # Prompts not in input - wait for reset
444 while line is not None:
447 while line is not None:
445 line = (yield line)
448 line = (yield line)
446
449
447 @CoroutineInputTransformer.wrap
450 @CoroutineInputTransformer.wrap
448 def classic_prompt():
451 def classic_prompt():
449 """Strip the >>>/... prompts of the Python interactive shell."""
452 """Strip the >>>/... prompts of the Python interactive shell."""
450 # FIXME: non-capturing version (?:...) usable?
453 # FIXME: non-capturing version (?:...) usable?
451 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
454 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
452 initial_re = re.compile(r'^>>>( |$)')
455 initial_re = re.compile(r'^>>>( |$)')
453 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
456 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
454 turnoff_re = re.compile(r'^[%!]')
457 turnoff_re = re.compile(r'^[%!]')
455 return _strip_prompts(prompt_re, initial_re, turnoff_re)
458 return _strip_prompts(prompt_re, initial_re, turnoff_re)
456
459
457 @CoroutineInputTransformer.wrap
460 @CoroutineInputTransformer.wrap
458 def ipy_prompt():
461 def ipy_prompt():
459 """Strip IPython's In [1]:/...: prompts."""
462 """Strip IPython's In [1]:/...: prompts."""
460 # FIXME: non-capturing version (?:...) usable?
463 # FIXME: non-capturing version (?:...) usable?
461 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
464 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
462 # Disable prompt stripping inside cell magics
465 # Disable prompt stripping inside cell magics
463 turnoff_re = re.compile(r'^%%')
466 turnoff_re = re.compile(r'^%%')
464 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
467 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
465
468
466
469
467 @CoroutineInputTransformer.wrap
470 @CoroutineInputTransformer.wrap
468 def leading_indent():
471 def leading_indent():
469 """Remove leading indentation.
472 """Remove leading indentation.
470
473
471 If the first line starts with a spaces or tabs, the same whitespace will be
474 If the first line starts with a spaces or tabs, the same whitespace will be
472 removed from each following line until it is reset.
475 removed from each following line until it is reset.
473 """
476 """
474 space_re = re.compile(r'^[ \t]+')
477 space_re = re.compile(r'^[ \t]+')
475 line = ''
478 line = ''
476 while True:
479 while True:
477 line = (yield line)
480 line = (yield line)
478
481
479 if line is None:
482 if line is None:
480 continue
483 continue
481
484
482 m = space_re.match(line)
485 m = space_re.match(line)
483 if m:
486 if m:
484 space = m.group(0)
487 space = m.group(0)
485 while line is not None:
488 while line is not None:
486 if line.startswith(space):
489 if line.startswith(space):
487 line = line[len(space):]
490 line = line[len(space):]
488 line = (yield line)
491 line = (yield line)
489 else:
492 else:
490 # No leading spaces - wait for reset
493 # No leading spaces - wait for reset
491 while line is not None:
494 while line is not None:
492 line = (yield line)
495 line = (yield line)
493
496
494
497
495 _assign_pat = \
498 _assign_pat = \
496 r'''(?P<lhs>(\s*)
499 r'''(?P<lhs>(\s*)
497 ([\w\.]+) # Initial identifier
500 ([\w\.]+) # Initial identifier
498 (\s*,\s*
501 (\s*,\s*
499 \*?[\w\.]+)* # Further identifiers for unpacking
502 \*?[\w\.]+)* # Further identifiers for unpacking
500 \s*?,? # Trailing comma
503 \s*?,? # Trailing comma
501 )
504 )
502 \s*=\s*
505 \s*=\s*
503 '''
506 '''
504
507
505 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
508 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
506 assign_system_template = '%s = get_ipython().getoutput(%r)'
509 assign_system_template = '%s = get_ipython().getoutput(%r)'
507 @StatelessInputTransformer.wrap
510 @StatelessInputTransformer.wrap
508 def assign_from_system(line):
511 def assign_from_system(line):
509 """Transform assignment from system commands (e.g. files = !ls)"""
512 """Transform assignment from system commands (e.g. files = !ls)"""
510 m = assign_system_re.match(line)
513 m = assign_system_re.match(line)
511 if m is None:
514 if m is None:
512 return line
515 return line
513
516
514 return assign_system_template % m.group('lhs', 'cmd')
517 return assign_system_template % m.group('lhs', 'cmd')
515
518
516 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
519 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
517 assign_magic_template = '%s = get_ipython().magic(%r)'
520 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
518 @StatelessInputTransformer.wrap
521 @StatelessInputTransformer.wrap
519 def assign_from_magic(line):
522 def assign_from_magic(line):
520 """Transform assignment from magic commands (e.g. a = %who_ls)"""
523 """Transform assignment from magic commands (e.g. a = %who_ls)"""
521 m = assign_magic_re.match(line)
524 m = assign_magic_re.match(line)
522 if m is None:
525 if m is None:
523 return line
526 return line
524
527 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
525 return assign_magic_template % m.group('lhs', 'cmd')
528 m_lhs, m_cmd = m.group('lhs', 'cmd')
529 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
530 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
531 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
@@ -1,318 +1,318 b''
1 """Implementation of magic functions related to History.
1 """Implementation of magic functions related to History.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012, IPython Development Team.
4 # Copyright (c) 2012, IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import os
16 import os
17 import sys
17 import sys
18 from io import open as io_open
18 from io import open as io_open
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core.error import StdinNotImplementedError
21 from IPython.core.error import StdinNotImplementedError
22 from IPython.core.magic import Magics, magics_class, line_magic
22 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.core.magic_arguments import (argument, magic_arguments,
23 from IPython.core.magic_arguments import (argument, magic_arguments,
24 parse_argstring)
24 parse_argstring)
25 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.testing.skipdoctest import skip_doctest
26 from IPython.utils import io
26 from IPython.utils import io
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Magics class implementation
29 # Magics class implementation
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32
32
33 _unspecified = object()
33 _unspecified = object()
34
34
35
35
36 @magics_class
36 @magics_class
37 class HistoryMagics(Magics):
37 class HistoryMagics(Magics):
38
38
39 @magic_arguments()
39 @magic_arguments()
40 @argument(
40 @argument(
41 '-n', dest='print_nums', action='store_true', default=False,
41 '-n', dest='print_nums', action='store_true', default=False,
42 help="""
42 help="""
43 print line numbers for each input.
43 print line numbers for each input.
44 This feature is only available if numbered prompts are in use.
44 This feature is only available if numbered prompts are in use.
45 """)
45 """)
46 @argument(
46 @argument(
47 '-o', dest='get_output', action='store_true', default=False,
47 '-o', dest='get_output', action='store_true', default=False,
48 help="also print outputs for each input.")
48 help="also print outputs for each input.")
49 @argument(
49 @argument(
50 '-p', dest='pyprompts', action='store_true', default=False,
50 '-p', dest='pyprompts', action='store_true', default=False,
51 help="""
51 help="""
52 print classic '>>>' python prompts before each input.
52 print classic '>>>' python prompts before each input.
53 This is useful for making documentation, and in conjunction
53 This is useful for making documentation, and in conjunction
54 with -o, for producing doctest-ready output.
54 with -o, for producing doctest-ready output.
55 """)
55 """)
56 @argument(
56 @argument(
57 '-t', dest='raw', action='store_false', default=True,
57 '-t', dest='raw', action='store_false', default=True,
58 help="""
58 help="""
59 print the 'translated' history, as IPython understands it.
59 print the 'translated' history, as IPython understands it.
60 IPython filters your input and converts it all into valid Python
60 IPython filters your input and converts it all into valid Python
61 source before executing it (things like magics or aliases are turned
61 source before executing it (things like magics or aliases are turned
62 into function calls, for example). With this option, you'll see the
62 into function calls, for example). With this option, you'll see the
63 native history instead of the user-entered version: '%%cd /' will be
63 native history instead of the user-entered version: '%%cd /' will be
64 seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'.
64 seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
65 """)
65 """)
66 @argument(
66 @argument(
67 '-f', dest='filename',
67 '-f', dest='filename',
68 help="""
68 help="""
69 FILENAME: instead of printing the output to the screen, redirect
69 FILENAME: instead of printing the output to the screen, redirect
70 it to the given file. The file is always overwritten, though *when
70 it to the given file. The file is always overwritten, though *when
71 it can*, IPython asks for confirmation first. In particular, running
71 it can*, IPython asks for confirmation first. In particular, running
72 the command 'history -f FILENAME' from the IPython Notebook
72 the command 'history -f FILENAME' from the IPython Notebook
73 interface will replace FILENAME even if it already exists *without*
73 interface will replace FILENAME even if it already exists *without*
74 confirmation.
74 confirmation.
75 """)
75 """)
76 @argument(
76 @argument(
77 '-g', dest='pattern', nargs='*', default=None,
77 '-g', dest='pattern', nargs='*', default=None,
78 help="""
78 help="""
79 treat the arg as a glob pattern to search for in (full) history.
79 treat the arg as a glob pattern to search for in (full) history.
80 This includes the saved history (almost all commands ever written).
80 This includes the saved history (almost all commands ever written).
81 The pattern may contain '?' to match one unknown character and '*'
81 The pattern may contain '?' to match one unknown character and '*'
82 to match any number of unknown characters. Use '%%hist -g' to show
82 to match any number of unknown characters. Use '%%hist -g' to show
83 full saved history (may be very long).
83 full saved history (may be very long).
84 """)
84 """)
85 @argument(
85 @argument(
86 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
86 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
87 help="""
87 help="""
88 get the last n lines from all sessions. Specify n as a single
88 get the last n lines from all sessions. Specify n as a single
89 arg, or the default is the last 10 lines.
89 arg, or the default is the last 10 lines.
90 """)
90 """)
91 @argument(
91 @argument(
92 '-u', dest='unique', action='store_true',
92 '-u', dest='unique', action='store_true',
93 help="""
93 help="""
94 when searching history using `-g`, show only unique history.
94 when searching history using `-g`, show only unique history.
95 """)
95 """)
96 @argument('range', nargs='*')
96 @argument('range', nargs='*')
97 @skip_doctest
97 @skip_doctest
98 @line_magic
98 @line_magic
99 def history(self, parameter_s = ''):
99 def history(self, parameter_s = ''):
100 """Print input history (_i<n> variables), with most recent last.
100 """Print input history (_i<n> variables), with most recent last.
101
101
102 By default, input history is printed without line numbers so it can be
102 By default, input history is printed without line numbers so it can be
103 directly pasted into an editor. Use -n to show them.
103 directly pasted into an editor. Use -n to show them.
104
104
105 By default, all input history from the current session is displayed.
105 By default, all input history from the current session is displayed.
106 Ranges of history can be indicated using the syntax:
106 Ranges of history can be indicated using the syntax:
107
107
108 ``4``
108 ``4``
109 Line 4, current session
109 Line 4, current session
110 ``4-6``
110 ``4-6``
111 Lines 4-6, current session
111 Lines 4-6, current session
112 ``243/1-5``
112 ``243/1-5``
113 Lines 1-5, session 243
113 Lines 1-5, session 243
114 ``~2/7``
114 ``~2/7``
115 Line 7, session 2 before current
115 Line 7, session 2 before current
116 ``~8/1-~6/5``
116 ``~8/1-~6/5``
117 From the first line of 8 sessions ago, to the fifth line of 6
117 From the first line of 8 sessions ago, to the fifth line of 6
118 sessions ago.
118 sessions ago.
119
119
120 Multiple ranges can be entered, separated by spaces
120 Multiple ranges can be entered, separated by spaces
121
121
122 The same syntax is used by %macro, %save, %edit, %rerun
122 The same syntax is used by %macro, %save, %edit, %rerun
123
123
124 Examples
124 Examples
125 --------
125 --------
126 ::
126 ::
127
127
128 In [6]: %history -n 4-6
128 In [6]: %history -n 4-6
129 4:a = 12
129 4:a = 12
130 5:print a**2
130 5:print a**2
131 6:%history -n 4-6
131 6:%history -n 4-6
132
132
133 """
133 """
134
134
135 args = parse_argstring(self.history, parameter_s)
135 args = parse_argstring(self.history, parameter_s)
136
136
137 # For brevity
137 # For brevity
138 history_manager = self.shell.history_manager
138 history_manager = self.shell.history_manager
139
139
140 def _format_lineno(session, line):
140 def _format_lineno(session, line):
141 """Helper function to format line numbers properly."""
141 """Helper function to format line numbers properly."""
142 if session in (0, history_manager.session_number):
142 if session in (0, history_manager.session_number):
143 return str(line)
143 return str(line)
144 return "%s/%s" % (session, line)
144 return "%s/%s" % (session, line)
145
145
146 # Check if output to specific file was requested.
146 # Check if output to specific file was requested.
147 outfname = args.filename
147 outfname = args.filename
148 if not outfname:
148 if not outfname:
149 outfile = sys.stdout # default
149 outfile = sys.stdout # default
150 # We don't want to close stdout at the end!
150 # We don't want to close stdout at the end!
151 close_at_end = False
151 close_at_end = False
152 else:
152 else:
153 if os.path.exists(outfname):
153 if os.path.exists(outfname):
154 try:
154 try:
155 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
155 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
156 except StdinNotImplementedError:
156 except StdinNotImplementedError:
157 ans = True
157 ans = True
158 if not ans:
158 if not ans:
159 print('Aborting.')
159 print('Aborting.')
160 return
160 return
161 print("Overwriting file.")
161 print("Overwriting file.")
162 outfile = io_open(outfname, 'w', encoding='utf-8')
162 outfile = io_open(outfname, 'w', encoding='utf-8')
163 close_at_end = True
163 close_at_end = True
164
164
165 print_nums = args.print_nums
165 print_nums = args.print_nums
166 get_output = args.get_output
166 get_output = args.get_output
167 pyprompts = args.pyprompts
167 pyprompts = args.pyprompts
168 raw = args.raw
168 raw = args.raw
169
169
170 pattern = None
170 pattern = None
171 limit = None if args.limit is _unspecified else args.limit
171 limit = None if args.limit is _unspecified else args.limit
172
172
173 if args.pattern is not None:
173 if args.pattern is not None:
174 if args.pattern:
174 if args.pattern:
175 pattern = "*" + " ".join(args.pattern) + "*"
175 pattern = "*" + " ".join(args.pattern) + "*"
176 else:
176 else:
177 pattern = "*"
177 pattern = "*"
178 hist = history_manager.search(pattern, raw=raw, output=get_output,
178 hist = history_manager.search(pattern, raw=raw, output=get_output,
179 n=limit, unique=args.unique)
179 n=limit, unique=args.unique)
180 print_nums = True
180 print_nums = True
181 elif args.limit is not _unspecified:
181 elif args.limit is not _unspecified:
182 n = 10 if limit is None else limit
182 n = 10 if limit is None else limit
183 hist = history_manager.get_tail(n, raw=raw, output=get_output)
183 hist = history_manager.get_tail(n, raw=raw, output=get_output)
184 else:
184 else:
185 if args.range: # Get history by ranges
185 if args.range: # Get history by ranges
186 hist = history_manager.get_range_by_str(" ".join(args.range),
186 hist = history_manager.get_range_by_str(" ".join(args.range),
187 raw, get_output)
187 raw, get_output)
188 else: # Just get history for the current session
188 else: # Just get history for the current session
189 hist = history_manager.get_range(raw=raw, output=get_output)
189 hist = history_manager.get_range(raw=raw, output=get_output)
190
190
191 # We could be displaying the entire history, so let's not try to pull
191 # We could be displaying the entire history, so let's not try to pull
192 # it into a list in memory. Anything that needs more space will just
192 # it into a list in memory. Anything that needs more space will just
193 # misalign.
193 # misalign.
194 width = 4
194 width = 4
195
195
196 for session, lineno, inline in hist:
196 for session, lineno, inline in hist:
197 # Print user history with tabs expanded to 4 spaces. The GUI
197 # Print user history with tabs expanded to 4 spaces. The GUI
198 # clients use hard tabs for easier usability in auto-indented code,
198 # clients use hard tabs for easier usability in auto-indented code,
199 # but we want to produce PEP-8 compliant history for safe pasting
199 # but we want to produce PEP-8 compliant history for safe pasting
200 # into an editor.
200 # into an editor.
201 if get_output:
201 if get_output:
202 inline, output = inline
202 inline, output = inline
203 inline = inline.expandtabs(4).rstrip()
203 inline = inline.expandtabs(4).rstrip()
204
204
205 multiline = "\n" in inline
205 multiline = "\n" in inline
206 line_sep = '\n' if multiline else ' '
206 line_sep = '\n' if multiline else ' '
207 if print_nums:
207 if print_nums:
208 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
208 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
209 line_sep), file=outfile, end=u'')
209 line_sep), file=outfile, end=u'')
210 if pyprompts:
210 if pyprompts:
211 print(u">>> ", end=u"", file=outfile)
211 print(u">>> ", end=u"", file=outfile)
212 if multiline:
212 if multiline:
213 inline = "\n... ".join(inline.splitlines()) + "\n..."
213 inline = "\n... ".join(inline.splitlines()) + "\n..."
214 print(inline, file=outfile)
214 print(inline, file=outfile)
215 if get_output and output:
215 if get_output and output:
216 print(output, file=outfile)
216 print(output, file=outfile)
217
217
218 if close_at_end:
218 if close_at_end:
219 outfile.close()
219 outfile.close()
220
220
221 @line_magic
221 @line_magic
222 def recall(self, arg):
222 def recall(self, arg):
223 r"""Repeat a command, or get command to input line for editing.
223 r"""Repeat a command, or get command to input line for editing.
224
224
225 %recall and %rep are equivalent.
225 %recall and %rep are equivalent.
226
226
227 - %recall (no arguments):
227 - %recall (no arguments):
228
228
229 Place a string version of last computation result (stored in the
229 Place a string version of last computation result (stored in the
230 special '_' variable) to the next input prompt. Allows you to create
230 special '_' variable) to the next input prompt. Allows you to create
231 elaborate command lines without using copy-paste::
231 elaborate command lines without using copy-paste::
232
232
233 In[1]: l = ["hei", "vaan"]
233 In[1]: l = ["hei", "vaan"]
234 In[2]: "".join(l)
234 In[2]: "".join(l)
235 Out[2]: heivaan
235 Out[2]: heivaan
236 In[3]: %recall
236 In[3]: %recall
237 In[4]: heivaan_ <== cursor blinking
237 In[4]: heivaan_ <== cursor blinking
238
238
239 %recall 45
239 %recall 45
240
240
241 Place history line 45 on the next input prompt. Use %hist to find
241 Place history line 45 on the next input prompt. Use %hist to find
242 out the number.
242 out the number.
243
243
244 %recall 1-4
244 %recall 1-4
245
245
246 Combine the specified lines into one cell, and place it on the next
246 Combine the specified lines into one cell, and place it on the next
247 input prompt. See %history for the slice syntax.
247 input prompt. See %history for the slice syntax.
248
248
249 %recall foo+bar
249 %recall foo+bar
250
250
251 If foo+bar can be evaluated in the user namespace, the result is
251 If foo+bar can be evaluated in the user namespace, the result is
252 placed at the next input prompt. Otherwise, the history is searched
252 placed at the next input prompt. Otherwise, the history is searched
253 for lines which contain that substring, and the most recent one is
253 for lines which contain that substring, and the most recent one is
254 placed at the next input prompt.
254 placed at the next input prompt.
255 """
255 """
256 if not arg: # Last output
256 if not arg: # Last output
257 self.shell.set_next_input(str(self.shell.user_ns["_"]))
257 self.shell.set_next_input(str(self.shell.user_ns["_"]))
258 return
258 return
259 # Get history range
259 # Get history range
260 histlines = self.shell.history_manager.get_range_by_str(arg)
260 histlines = self.shell.history_manager.get_range_by_str(arg)
261 cmd = "\n".join(x[2] for x in histlines)
261 cmd = "\n".join(x[2] for x in histlines)
262 if cmd:
262 if cmd:
263 self.shell.set_next_input(cmd.rstrip())
263 self.shell.set_next_input(cmd.rstrip())
264 return
264 return
265
265
266 try: # Variable in user namespace
266 try: # Variable in user namespace
267 cmd = str(eval(arg, self.shell.user_ns))
267 cmd = str(eval(arg, self.shell.user_ns))
268 except Exception: # Search for term in history
268 except Exception: # Search for term in history
269 histlines = self.shell.history_manager.search("*"+arg+"*")
269 histlines = self.shell.history_manager.search("*"+arg+"*")
270 for h in reversed([x[2] for x in histlines]):
270 for h in reversed([x[2] for x in histlines]):
271 if 'recall' in h or 'rep' in h:
271 if 'recall' in h or 'rep' in h:
272 continue
272 continue
273 self.shell.set_next_input(h.rstrip())
273 self.shell.set_next_input(h.rstrip())
274 return
274 return
275 else:
275 else:
276 self.shell.set_next_input(cmd.rstrip())
276 self.shell.set_next_input(cmd.rstrip())
277 print("Couldn't evaluate or find in history:", arg)
277 print("Couldn't evaluate or find in history:", arg)
278
278
279 @line_magic
279 @line_magic
280 def rerun(self, parameter_s=''):
280 def rerun(self, parameter_s=''):
281 """Re-run previous input
281 """Re-run previous input
282
282
283 By default, you can specify ranges of input history to be repeated
283 By default, you can specify ranges of input history to be repeated
284 (as with %history). With no arguments, it will repeat the last line.
284 (as with %history). With no arguments, it will repeat the last line.
285
285
286 Options:
286 Options:
287
287
288 -l <n> : Repeat the last n lines of input, not including the
288 -l <n> : Repeat the last n lines of input, not including the
289 current command.
289 current command.
290
290
291 -g foo : Repeat the most recent line which contains foo
291 -g foo : Repeat the most recent line which contains foo
292 """
292 """
293 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
293 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
294 if "l" in opts: # Last n lines
294 if "l" in opts: # Last n lines
295 n = int(opts['l'])
295 n = int(opts['l'])
296 hist = self.shell.history_manager.get_tail(n)
296 hist = self.shell.history_manager.get_tail(n)
297 elif "g" in opts: # Search
297 elif "g" in opts: # Search
298 p = "*"+opts['g']+"*"
298 p = "*"+opts['g']+"*"
299 hist = list(self.shell.history_manager.search(p))
299 hist = list(self.shell.history_manager.search(p))
300 for l in reversed(hist):
300 for l in reversed(hist):
301 if "rerun" not in l[2]:
301 if "rerun" not in l[2]:
302 hist = [l] # The last match which isn't a %rerun
302 hist = [l] # The last match which isn't a %rerun
303 break
303 break
304 else:
304 else:
305 hist = [] # No matches except %rerun
305 hist = [] # No matches except %rerun
306 elif args: # Specify history ranges
306 elif args: # Specify history ranges
307 hist = self.shell.history_manager.get_range_by_str(args)
307 hist = self.shell.history_manager.get_range_by_str(args)
308 else: # Last line
308 else: # Last line
309 hist = self.shell.history_manager.get_tail(1)
309 hist = self.shell.history_manager.get_tail(1)
310 hist = [x[2] for x in hist]
310 hist = [x[2] for x in hist]
311 if not hist:
311 if not hist:
312 print("No lines in history match specification")
312 print("No lines in history match specification")
313 return
313 return
314 histlines = "\n".join(hist)
314 histlines = "\n".join(hist)
315 print("=== Executing: ===")
315 print("=== Executing: ===")
316 print(histlines)
316 print(histlines)
317 print("=== Output: ===")
317 print("=== Output: ===")
318 self.shell.run_cell("\n".join(hist), store_history=False)
318 self.shell.run_cell("\n".join(hist), store_history=False)
@@ -1,706 +1,709 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 from keyword import iskeyword
12 from keyword import iskeyword
13 import re
13 import re
14
14
15 from IPython.core.autocall import IPyAutocall
15 from IPython.core.autocall import IPyAutocall
16 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
17 from IPython.core.inputsplitter import (
17 from IPython.core.inputsplitter import (
18 ESC_MAGIC,
18 ESC_MAGIC,
19 ESC_QUOTE,
19 ESC_QUOTE,
20 ESC_QUOTE2,
20 ESC_QUOTE2,
21 ESC_PAREN,
21 ESC_PAREN,
22 )
22 )
23 from IPython.core.macro import Macro
23 from IPython.core.macro import Macro
24 from IPython.core.splitinput import LineInfo
24 from IPython.core.splitinput import LineInfo
25
25
26 from traitlets import (
26 from traitlets import (
27 List, Integer, Unicode, Bool, Instance, CRegExp
27 List, Integer, Unicode, Bool, Instance, CRegExp
28 )
28 )
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 # Global utilities, errors and constants
31 # Global utilities, errors and constants
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34
34
35 class PrefilterError(Exception):
35 class PrefilterError(Exception):
36 pass
36 pass
37
37
38
38
39 # RegExp to identify potential function names
39 # RegExp to identify potential function names
40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
41
41
42 # RegExp to exclude strings with this start from autocalling. In
42 # RegExp to exclude strings with this start from autocalling. In
43 # particular, all binary operators should be excluded, so that if foo is
43 # particular, all binary operators should be excluded, so that if foo is
44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
45 # characters '!=()' don't need to be checked for, as the checkPythonChars
45 # characters '!=()' don't need to be checked for, as the checkPythonChars
46 # routine explicitely does so, to catch direct calls and rebindings of
46 # routine explicitely does so, to catch direct calls and rebindings of
47 # existing names.
47 # existing names.
48
48
49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
50 # it affects the rest of the group in square brackets.
50 # it affects the rest of the group in square brackets.
51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
52 r'|^is |^not |^in |^and |^or ')
52 r'|^is |^not |^in |^and |^or ')
53
53
54 # try to catch also methods for stuff in lists/tuples/dicts: off
54 # try to catch also methods for stuff in lists/tuples/dicts: off
55 # (experimental). For this to work, the line_split regexp would need
55 # (experimental). For this to work, the line_split regexp would need
56 # to be modified so it wouldn't break things at '['. That line is
56 # to be modified so it wouldn't break things at '['. That line is
57 # nasty enough that I shouldn't change it until I can test it _well_.
57 # nasty enough that I shouldn't change it until I can test it _well_.
58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
59
59
60
60
61 # Handler Check Utilities
61 # Handler Check Utilities
62 def is_shadowed(identifier, ip):
62 def is_shadowed(identifier, ip):
63 """Is the given identifier defined in one of the namespaces which shadow
63 """Is the given identifier defined in one of the namespaces which shadow
64 the alias and magic namespaces? Note that an identifier is different
64 the alias and magic namespaces? Note that an identifier is different
65 than ifun, because it can not contain a '.' character."""
65 than ifun, because it can not contain a '.' character."""
66 # This is much safer than calling ofind, which can change state
66 # This is much safer than calling ofind, which can change state
67 return (identifier in ip.user_ns \
67 return (identifier in ip.user_ns \
68 or identifier in ip.user_global_ns \
68 or identifier in ip.user_global_ns \
69 or identifier in ip.ns_table['builtin']\
69 or identifier in ip.ns_table['builtin']\
70 or iskeyword(identifier))
70 or iskeyword(identifier))
71
71
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Main Prefilter manager
74 # Main Prefilter manager
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76
76
77
77
78 class PrefilterManager(Configurable):
78 class PrefilterManager(Configurable):
79 """Main prefilter component.
79 """Main prefilter component.
80
80
81 The IPython prefilter is run on all user input before it is run. The
81 The IPython prefilter is run on all user input before it is run. The
82 prefilter consumes lines of input and produces transformed lines of
82 prefilter consumes lines of input and produces transformed lines of
83 input.
83 input.
84
84
85 The iplementation consists of two phases:
85 The iplementation consists of two phases:
86
86
87 1. Transformers
87 1. Transformers
88 2. Checkers and handlers
88 2. Checkers and handlers
89
89
90 Over time, we plan on deprecating the checkers and handlers and doing
90 Over time, we plan on deprecating the checkers and handlers and doing
91 everything in the transformers.
91 everything in the transformers.
92
92
93 The transformers are instances of :class:`PrefilterTransformer` and have
93 The transformers are instances of :class:`PrefilterTransformer` and have
94 a single method :meth:`transform` that takes a line and returns a
94 a single method :meth:`transform` that takes a line and returns a
95 transformed line. The transformation can be accomplished using any
95 transformed line. The transformation can be accomplished using any
96 tool, but our current ones use regular expressions for speed.
96 tool, but our current ones use regular expressions for speed.
97
97
98 After all the transformers have been run, the line is fed to the checkers,
98 After all the transformers have been run, the line is fed to the checkers,
99 which are instances of :class:`PrefilterChecker`. The line is passed to
99 which are instances of :class:`PrefilterChecker`. The line is passed to
100 the :meth:`check` method, which either returns `None` or a
100 the :meth:`check` method, which either returns `None` or a
101 :class:`PrefilterHandler` instance. If `None` is returned, the other
101 :class:`PrefilterHandler` instance. If `None` is returned, the other
102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
103 the line is passed to the :meth:`handle` method of the returned
103 the line is passed to the :meth:`handle` method of the returned
104 handler and no further checkers are tried.
104 handler and no further checkers are tried.
105
105
106 Both transformers and checkers have a `priority` attribute, that determines
106 Both transformers and checkers have a `priority` attribute, that determines
107 the order in which they are called. Smaller priorities are tried first.
107 the order in which they are called. Smaller priorities are tried first.
108
108
109 Both transformers and checkers also have `enabled` attribute, which is
109 Both transformers and checkers also have `enabled` attribute, which is
110 a boolean that determines if the instance is used.
110 a boolean that determines if the instance is used.
111
111
112 Users or developers can change the priority or enabled attribute of
112 Users or developers can change the priority or enabled attribute of
113 transformers or checkers, but they must call the :meth:`sort_checkers`
113 transformers or checkers, but they must call the :meth:`sort_checkers`
114 or :meth:`sort_transformers` method after changing the priority.
114 or :meth:`sort_transformers` method after changing the priority.
115 """
115 """
116
116
117 multi_line_specials = Bool(True).tag(config=True)
117 multi_line_specials = Bool(True).tag(config=True)
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
119
119
120 def __init__(self, shell=None, **kwargs):
120 def __init__(self, shell=None, **kwargs):
121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
122 self.shell = shell
122 self.shell = shell
123 self.init_transformers()
123 self.init_transformers()
124 self.init_handlers()
124 self.init_handlers()
125 self.init_checkers()
125 self.init_checkers()
126
126
127 #-------------------------------------------------------------------------
127 #-------------------------------------------------------------------------
128 # API for managing transformers
128 # API for managing transformers
129 #-------------------------------------------------------------------------
129 #-------------------------------------------------------------------------
130
130
131 def init_transformers(self):
131 def init_transformers(self):
132 """Create the default transformers."""
132 """Create the default transformers."""
133 self._transformers = []
133 self._transformers = []
134 for transformer_cls in _default_transformers:
134 for transformer_cls in _default_transformers:
135 transformer_cls(
135 transformer_cls(
136 shell=self.shell, prefilter_manager=self, parent=self
136 shell=self.shell, prefilter_manager=self, parent=self
137 )
137 )
138
138
139 def sort_transformers(self):
139 def sort_transformers(self):
140 """Sort the transformers by priority.
140 """Sort the transformers by priority.
141
141
142 This must be called after the priority of a transformer is changed.
142 This must be called after the priority of a transformer is changed.
143 The :meth:`register_transformer` method calls this automatically.
143 The :meth:`register_transformer` method calls this automatically.
144 """
144 """
145 self._transformers.sort(key=lambda x: x.priority)
145 self._transformers.sort(key=lambda x: x.priority)
146
146
147 @property
147 @property
148 def transformers(self):
148 def transformers(self):
149 """Return a list of checkers, sorted by priority."""
149 """Return a list of checkers, sorted by priority."""
150 return self._transformers
150 return self._transformers
151
151
152 def register_transformer(self, transformer):
152 def register_transformer(self, transformer):
153 """Register a transformer instance."""
153 """Register a transformer instance."""
154 if transformer not in self._transformers:
154 if transformer not in self._transformers:
155 self._transformers.append(transformer)
155 self._transformers.append(transformer)
156 self.sort_transformers()
156 self.sort_transformers()
157
157
158 def unregister_transformer(self, transformer):
158 def unregister_transformer(self, transformer):
159 """Unregister a transformer instance."""
159 """Unregister a transformer instance."""
160 if transformer in self._transformers:
160 if transformer in self._transformers:
161 self._transformers.remove(transformer)
161 self._transformers.remove(transformer)
162
162
163 #-------------------------------------------------------------------------
163 #-------------------------------------------------------------------------
164 # API for managing checkers
164 # API for managing checkers
165 #-------------------------------------------------------------------------
165 #-------------------------------------------------------------------------
166
166
167 def init_checkers(self):
167 def init_checkers(self):
168 """Create the default checkers."""
168 """Create the default checkers."""
169 self._checkers = []
169 self._checkers = []
170 for checker in _default_checkers:
170 for checker in _default_checkers:
171 checker(
171 checker(
172 shell=self.shell, prefilter_manager=self, parent=self
172 shell=self.shell, prefilter_manager=self, parent=self
173 )
173 )
174
174
175 def sort_checkers(self):
175 def sort_checkers(self):
176 """Sort the checkers by priority.
176 """Sort the checkers by priority.
177
177
178 This must be called after the priority of a checker is changed.
178 This must be called after the priority of a checker is changed.
179 The :meth:`register_checker` method calls this automatically.
179 The :meth:`register_checker` method calls this automatically.
180 """
180 """
181 self._checkers.sort(key=lambda x: x.priority)
181 self._checkers.sort(key=lambda x: x.priority)
182
182
183 @property
183 @property
184 def checkers(self):
184 def checkers(self):
185 """Return a list of checkers, sorted by priority."""
185 """Return a list of checkers, sorted by priority."""
186 return self._checkers
186 return self._checkers
187
187
188 def register_checker(self, checker):
188 def register_checker(self, checker):
189 """Register a checker instance."""
189 """Register a checker instance."""
190 if checker not in self._checkers:
190 if checker not in self._checkers:
191 self._checkers.append(checker)
191 self._checkers.append(checker)
192 self.sort_checkers()
192 self.sort_checkers()
193
193
194 def unregister_checker(self, checker):
194 def unregister_checker(self, checker):
195 """Unregister a checker instance."""
195 """Unregister a checker instance."""
196 if checker in self._checkers:
196 if checker in self._checkers:
197 self._checkers.remove(checker)
197 self._checkers.remove(checker)
198
198
199 #-------------------------------------------------------------------------
199 #-------------------------------------------------------------------------
200 # API for managing handlers
200 # API for managing handlers
201 #-------------------------------------------------------------------------
201 #-------------------------------------------------------------------------
202
202
203 def init_handlers(self):
203 def init_handlers(self):
204 """Create the default handlers."""
204 """Create the default handlers."""
205 self._handlers = {}
205 self._handlers = {}
206 self._esc_handlers = {}
206 self._esc_handlers = {}
207 for handler in _default_handlers:
207 for handler in _default_handlers:
208 handler(
208 handler(
209 shell=self.shell, prefilter_manager=self, parent=self
209 shell=self.shell, prefilter_manager=self, parent=self
210 )
210 )
211
211
212 @property
212 @property
213 def handlers(self):
213 def handlers(self):
214 """Return a dict of all the handlers."""
214 """Return a dict of all the handlers."""
215 return self._handlers
215 return self._handlers
216
216
217 def register_handler(self, name, handler, esc_strings):
217 def register_handler(self, name, handler, esc_strings):
218 """Register a handler instance by name with esc_strings."""
218 """Register a handler instance by name with esc_strings."""
219 self._handlers[name] = handler
219 self._handlers[name] = handler
220 for esc_str in esc_strings:
220 for esc_str in esc_strings:
221 self._esc_handlers[esc_str] = handler
221 self._esc_handlers[esc_str] = handler
222
222
223 def unregister_handler(self, name, handler, esc_strings):
223 def unregister_handler(self, name, handler, esc_strings):
224 """Unregister a handler instance by name with esc_strings."""
224 """Unregister a handler instance by name with esc_strings."""
225 try:
225 try:
226 del self._handlers[name]
226 del self._handlers[name]
227 except KeyError:
227 except KeyError:
228 pass
228 pass
229 for esc_str in esc_strings:
229 for esc_str in esc_strings:
230 h = self._esc_handlers.get(esc_str)
230 h = self._esc_handlers.get(esc_str)
231 if h is handler:
231 if h is handler:
232 del self._esc_handlers[esc_str]
232 del self._esc_handlers[esc_str]
233
233
234 def get_handler_by_name(self, name):
234 def get_handler_by_name(self, name):
235 """Get a handler by its name."""
235 """Get a handler by its name."""
236 return self._handlers.get(name)
236 return self._handlers.get(name)
237
237
238 def get_handler_by_esc(self, esc_str):
238 def get_handler_by_esc(self, esc_str):
239 """Get a handler by its escape string."""
239 """Get a handler by its escape string."""
240 return self._esc_handlers.get(esc_str)
240 return self._esc_handlers.get(esc_str)
241
241
242 #-------------------------------------------------------------------------
242 #-------------------------------------------------------------------------
243 # Main prefiltering API
243 # Main prefiltering API
244 #-------------------------------------------------------------------------
244 #-------------------------------------------------------------------------
245
245
246 def prefilter_line_info(self, line_info):
246 def prefilter_line_info(self, line_info):
247 """Prefilter a line that has been converted to a LineInfo object.
247 """Prefilter a line that has been converted to a LineInfo object.
248
248
249 This implements the checker/handler part of the prefilter pipe.
249 This implements the checker/handler part of the prefilter pipe.
250 """
250 """
251 # print "prefilter_line_info: ", line_info
251 # print "prefilter_line_info: ", line_info
252 handler = self.find_handler(line_info)
252 handler = self.find_handler(line_info)
253 return handler.handle(line_info)
253 return handler.handle(line_info)
254
254
255 def find_handler(self, line_info):
255 def find_handler(self, line_info):
256 """Find a handler for the line_info by trying checkers."""
256 """Find a handler for the line_info by trying checkers."""
257 for checker in self.checkers:
257 for checker in self.checkers:
258 if checker.enabled:
258 if checker.enabled:
259 handler = checker.check(line_info)
259 handler = checker.check(line_info)
260 if handler:
260 if handler:
261 return handler
261 return handler
262 return self.get_handler_by_name('normal')
262 return self.get_handler_by_name('normal')
263
263
264 def transform_line(self, line, continue_prompt):
264 def transform_line(self, line, continue_prompt):
265 """Calls the enabled transformers in order of increasing priority."""
265 """Calls the enabled transformers in order of increasing priority."""
266 for transformer in self.transformers:
266 for transformer in self.transformers:
267 if transformer.enabled:
267 if transformer.enabled:
268 line = transformer.transform(line, continue_prompt)
268 line = transformer.transform(line, continue_prompt)
269 return line
269 return line
270
270
271 def prefilter_line(self, line, continue_prompt=False):
271 def prefilter_line(self, line, continue_prompt=False):
272 """Prefilter a single input line as text.
272 """Prefilter a single input line as text.
273
273
274 This method prefilters a single line of text by calling the
274 This method prefilters a single line of text by calling the
275 transformers and then the checkers/handlers.
275 transformers and then the checkers/handlers.
276 """
276 """
277
277
278 # print "prefilter_line: ", line, continue_prompt
278 # print "prefilter_line: ", line, continue_prompt
279 # All handlers *must* return a value, even if it's blank ('').
279 # All handlers *must* return a value, even if it's blank ('').
280
280
281 # save the line away in case we crash, so the post-mortem handler can
281 # save the line away in case we crash, so the post-mortem handler can
282 # record it
282 # record it
283 self.shell._last_input_line = line
283 self.shell._last_input_line = line
284
284
285 if not line:
285 if not line:
286 # Return immediately on purely empty lines, so that if the user
286 # Return immediately on purely empty lines, so that if the user
287 # previously typed some whitespace that started a continuation
287 # previously typed some whitespace that started a continuation
288 # prompt, he can break out of that loop with just an empty line.
288 # prompt, he can break out of that loop with just an empty line.
289 # This is how the default python prompt works.
289 # This is how the default python prompt works.
290 return ''
290 return ''
291
291
292 # At this point, we invoke our transformers.
292 # At this point, we invoke our transformers.
293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
294 line = self.transform_line(line, continue_prompt)
294 line = self.transform_line(line, continue_prompt)
295
295
296 # Now we compute line_info for the checkers and handlers
296 # Now we compute line_info for the checkers and handlers
297 line_info = LineInfo(line, continue_prompt)
297 line_info = LineInfo(line, continue_prompt)
298
298
299 # the input history needs to track even empty lines
299 # the input history needs to track even empty lines
300 stripped = line.strip()
300 stripped = line.strip()
301
301
302 normal_handler = self.get_handler_by_name('normal')
302 normal_handler = self.get_handler_by_name('normal')
303 if not stripped:
303 if not stripped:
304 return normal_handler.handle(line_info)
304 return normal_handler.handle(line_info)
305
305
306 # special handlers are only allowed for single line statements
306 # special handlers are only allowed for single line statements
307 if continue_prompt and not self.multi_line_specials:
307 if continue_prompt and not self.multi_line_specials:
308 return normal_handler.handle(line_info)
308 return normal_handler.handle(line_info)
309
309
310 prefiltered = self.prefilter_line_info(line_info)
310 prefiltered = self.prefilter_line_info(line_info)
311 # print "prefiltered line: %r" % prefiltered
311 # print "prefiltered line: %r" % prefiltered
312 return prefiltered
312 return prefiltered
313
313
314 def prefilter_lines(self, lines, continue_prompt=False):
314 def prefilter_lines(self, lines, continue_prompt=False):
315 """Prefilter multiple input lines of text.
315 """Prefilter multiple input lines of text.
316
316
317 This is the main entry point for prefiltering multiple lines of
317 This is the main entry point for prefiltering multiple lines of
318 input. This simply calls :meth:`prefilter_line` for each line of
318 input. This simply calls :meth:`prefilter_line` for each line of
319 input.
319 input.
320
320
321 This covers cases where there are multiple lines in the user entry,
321 This covers cases where there are multiple lines in the user entry,
322 which is the case when the user goes back to a multiline history
322 which is the case when the user goes back to a multiline history
323 entry and presses enter.
323 entry and presses enter.
324 """
324 """
325 llines = lines.rstrip('\n').split('\n')
325 llines = lines.rstrip('\n').split('\n')
326 # We can get multiple lines in one shot, where multiline input 'blends'
326 # We can get multiple lines in one shot, where multiline input 'blends'
327 # into one line, in cases like recalling from the readline history
327 # into one line, in cases like recalling from the readline history
328 # buffer. We need to make sure that in such cases, we correctly
328 # buffer. We need to make sure that in such cases, we correctly
329 # communicate downstream which line is first and which are continuation
329 # communicate downstream which line is first and which are continuation
330 # ones.
330 # ones.
331 if len(llines) > 1:
331 if len(llines) > 1:
332 out = '\n'.join([self.prefilter_line(line, lnum>0)
332 out = '\n'.join([self.prefilter_line(line, lnum>0)
333 for lnum, line in enumerate(llines) ])
333 for lnum, line in enumerate(llines) ])
334 else:
334 else:
335 out = self.prefilter_line(llines[0], continue_prompt)
335 out = self.prefilter_line(llines[0], continue_prompt)
336
336
337 return out
337 return out
338
338
339 #-----------------------------------------------------------------------------
339 #-----------------------------------------------------------------------------
340 # Prefilter transformers
340 # Prefilter transformers
341 #-----------------------------------------------------------------------------
341 #-----------------------------------------------------------------------------
342
342
343
343
344 class PrefilterTransformer(Configurable):
344 class PrefilterTransformer(Configurable):
345 """Transform a line of user input."""
345 """Transform a line of user input."""
346
346
347 priority = Integer(100).tag(config=True)
347 priority = Integer(100).tag(config=True)
348 # Transformers don't currently use shell or prefilter_manager, but as we
348 # Transformers don't currently use shell or prefilter_manager, but as we
349 # move away from checkers and handlers, they will need them.
349 # move away from checkers and handlers, they will need them.
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
352 enabled = Bool(True).tag(config=True)
352 enabled = Bool(True).tag(config=True)
353
353
354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
355 super(PrefilterTransformer, self).__init__(
355 super(PrefilterTransformer, self).__init__(
356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
357 )
357 )
358 self.prefilter_manager.register_transformer(self)
358 self.prefilter_manager.register_transformer(self)
359
359
360 def transform(self, line, continue_prompt):
360 def transform(self, line, continue_prompt):
361 """Transform a line, returning the new one."""
361 """Transform a line, returning the new one."""
362 return None
362 return None
363
363
364 def __repr__(self):
364 def __repr__(self):
365 return "<%s(priority=%r, enabled=%r)>" % (
365 return "<%s(priority=%r, enabled=%r)>" % (
366 self.__class__.__name__, self.priority, self.enabled)
366 self.__class__.__name__, self.priority, self.enabled)
367
367
368
368
369 #-----------------------------------------------------------------------------
369 #-----------------------------------------------------------------------------
370 # Prefilter checkers
370 # Prefilter checkers
371 #-----------------------------------------------------------------------------
371 #-----------------------------------------------------------------------------
372
372
373
373
374 class PrefilterChecker(Configurable):
374 class PrefilterChecker(Configurable):
375 """Inspect an input line and return a handler for that line."""
375 """Inspect an input line and return a handler for that line."""
376
376
377 priority = Integer(100).tag(config=True)
377 priority = Integer(100).tag(config=True)
378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
380 enabled = Bool(True).tag(config=True)
380 enabled = Bool(True).tag(config=True)
381
381
382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
383 super(PrefilterChecker, self).__init__(
383 super(PrefilterChecker, self).__init__(
384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
385 )
385 )
386 self.prefilter_manager.register_checker(self)
386 self.prefilter_manager.register_checker(self)
387
387
388 def check(self, line_info):
388 def check(self, line_info):
389 """Inspect line_info and return a handler instance or None."""
389 """Inspect line_info and return a handler instance or None."""
390 return None
390 return None
391
391
392 def __repr__(self):
392 def __repr__(self):
393 return "<%s(priority=%r, enabled=%r)>" % (
393 return "<%s(priority=%r, enabled=%r)>" % (
394 self.__class__.__name__, self.priority, self.enabled)
394 self.__class__.__name__, self.priority, self.enabled)
395
395
396
396
397 class EmacsChecker(PrefilterChecker):
397 class EmacsChecker(PrefilterChecker):
398
398
399 priority = Integer(100).tag(config=True)
399 priority = Integer(100).tag(config=True)
400 enabled = Bool(False).tag(config=True)
400 enabled = Bool(False).tag(config=True)
401
401
402 def check(self, line_info):
402 def check(self, line_info):
403 "Emacs ipython-mode tags certain input lines."
403 "Emacs ipython-mode tags certain input lines."
404 if line_info.line.endswith('# PYTHON-MODE'):
404 if line_info.line.endswith('# PYTHON-MODE'):
405 return self.prefilter_manager.get_handler_by_name('emacs')
405 return self.prefilter_manager.get_handler_by_name('emacs')
406 else:
406 else:
407 return None
407 return None
408
408
409
409
410 class MacroChecker(PrefilterChecker):
410 class MacroChecker(PrefilterChecker):
411
411
412 priority = Integer(250).tag(config=True)
412 priority = Integer(250).tag(config=True)
413
413
414 def check(self, line_info):
414 def check(self, line_info):
415 obj = self.shell.user_ns.get(line_info.ifun)
415 obj = self.shell.user_ns.get(line_info.ifun)
416 if isinstance(obj, Macro):
416 if isinstance(obj, Macro):
417 return self.prefilter_manager.get_handler_by_name('macro')
417 return self.prefilter_manager.get_handler_by_name('macro')
418 else:
418 else:
419 return None
419 return None
420
420
421
421
422 class IPyAutocallChecker(PrefilterChecker):
422 class IPyAutocallChecker(PrefilterChecker):
423
423
424 priority = Integer(300).tag(config=True)
424 priority = Integer(300).tag(config=True)
425
425
426 def check(self, line_info):
426 def check(self, line_info):
427 "Instances of IPyAutocall in user_ns get autocalled immediately"
427 "Instances of IPyAutocall in user_ns get autocalled immediately"
428 obj = self.shell.user_ns.get(line_info.ifun, None)
428 obj = self.shell.user_ns.get(line_info.ifun, None)
429 if isinstance(obj, IPyAutocall):
429 if isinstance(obj, IPyAutocall):
430 obj.set_ip(self.shell)
430 obj.set_ip(self.shell)
431 return self.prefilter_manager.get_handler_by_name('auto')
431 return self.prefilter_manager.get_handler_by_name('auto')
432 else:
432 else:
433 return None
433 return None
434
434
435
435
436 class AssignmentChecker(PrefilterChecker):
436 class AssignmentChecker(PrefilterChecker):
437
437
438 priority = Integer(600).tag(config=True)
438 priority = Integer(600).tag(config=True)
439
439
440 def check(self, line_info):
440 def check(self, line_info):
441 """Check to see if user is assigning to a var for the first time, in
441 """Check to see if user is assigning to a var for the first time, in
442 which case we want to avoid any sort of automagic / autocall games.
442 which case we want to avoid any sort of automagic / autocall games.
443
443
444 This allows users to assign to either alias or magic names true python
444 This allows users to assign to either alias or magic names true python
445 variables (the magic/alias systems always take second seat to true
445 variables (the magic/alias systems always take second seat to true
446 python code). E.g. ls='hi', or ls,that=1,2"""
446 python code). E.g. ls='hi', or ls,that=1,2"""
447 if line_info.the_rest:
447 if line_info.the_rest:
448 if line_info.the_rest[0] in '=,':
448 if line_info.the_rest[0] in '=,':
449 return self.prefilter_manager.get_handler_by_name('normal')
449 return self.prefilter_manager.get_handler_by_name('normal')
450 else:
450 else:
451 return None
451 return None
452
452
453
453
454 class AutoMagicChecker(PrefilterChecker):
454 class AutoMagicChecker(PrefilterChecker):
455
455
456 priority = Integer(700).tag(config=True)
456 priority = Integer(700).tag(config=True)
457
457
458 def check(self, line_info):
458 def check(self, line_info):
459 """If the ifun is magic, and automagic is on, run it. Note: normal,
459 """If the ifun is magic, and automagic is on, run it. Note: normal,
460 non-auto magic would already have been triggered via '%' in
460 non-auto magic would already have been triggered via '%' in
461 check_esc_chars. This just checks for automagic. Also, before
461 check_esc_chars. This just checks for automagic. Also, before
462 triggering the magic handler, make sure that there is nothing in the
462 triggering the magic handler, make sure that there is nothing in the
463 user namespace which could shadow it."""
463 user namespace which could shadow it."""
464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
465 return None
465 return None
466
466
467 # We have a likely magic method. Make sure we should actually call it.
467 # We have a likely magic method. Make sure we should actually call it.
468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
469 return None
469 return None
470
470
471 head = line_info.ifun.split('.',1)[0]
471 head = line_info.ifun.split('.',1)[0]
472 if is_shadowed(head, self.shell):
472 if is_shadowed(head, self.shell):
473 return None
473 return None
474
474
475 return self.prefilter_manager.get_handler_by_name('magic')
475 return self.prefilter_manager.get_handler_by_name('magic')
476
476
477
477
478 class PythonOpsChecker(PrefilterChecker):
478 class PythonOpsChecker(PrefilterChecker):
479
479
480 priority = Integer(900).tag(config=True)
480 priority = Integer(900).tag(config=True)
481
481
482 def check(self, line_info):
482 def check(self, line_info):
483 """If the 'rest' of the line begins with a function call or pretty much
483 """If the 'rest' of the line begins with a function call or pretty much
484 any python operator, we should simply execute the line (regardless of
484 any python operator, we should simply execute the line (regardless of
485 whether or not there's a possible autocall expansion). This avoids
485 whether or not there's a possible autocall expansion). This avoids
486 spurious (and very confusing) geattr() accesses."""
486 spurious (and very confusing) geattr() accesses."""
487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
488 return self.prefilter_manager.get_handler_by_name('normal')
488 return self.prefilter_manager.get_handler_by_name('normal')
489 else:
489 else:
490 return None
490 return None
491
491
492
492
493 class AutocallChecker(PrefilterChecker):
493 class AutocallChecker(PrefilterChecker):
494
494
495 priority = Integer(1000).tag(config=True)
495 priority = Integer(1000).tag(config=True)
496
496
497 function_name_regexp = CRegExp(re_fun_name,
497 function_name_regexp = CRegExp(re_fun_name,
498 help="RegExp to identify potential function names."
498 help="RegExp to identify potential function names."
499 ).tag(config=True)
499 ).tag(config=True)
500 exclude_regexp = CRegExp(re_exclude_auto,
500 exclude_regexp = CRegExp(re_exclude_auto,
501 help="RegExp to exclude strings with this start from autocalling."
501 help="RegExp to exclude strings with this start from autocalling."
502 ).tag(config=True)
502 ).tag(config=True)
503
503
504 def check(self, line_info):
504 def check(self, line_info):
505 "Check if the initial word/function is callable and autocall is on."
505 "Check if the initial word/function is callable and autocall is on."
506 if not self.shell.autocall:
506 if not self.shell.autocall:
507 return None
507 return None
508
508
509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
510 if not oinfo['found']:
510 if not oinfo['found']:
511 return None
511 return None
512
512
513 ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
513 ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
514 ifun = line_info.ifun
514 ifun = line_info.ifun
515 line = line_info.line
515 line = line_info.line
516 if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
516 if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
517 return None
517 return None
518
518
519 if callable(oinfo['obj']) \
519 if callable(oinfo['obj']) \
520 and (not self.exclude_regexp.match(line_info.the_rest)) \
520 and (not self.exclude_regexp.match(line_info.the_rest)) \
521 and self.function_name_regexp.match(line_info.ifun):
521 and self.function_name_regexp.match(line_info.ifun):
522 return self.prefilter_manager.get_handler_by_name('auto')
522 return self.prefilter_manager.get_handler_by_name('auto')
523 else:
523 else:
524 return None
524 return None
525
525
526
526
527 #-----------------------------------------------------------------------------
527 #-----------------------------------------------------------------------------
528 # Prefilter handlers
528 # Prefilter handlers
529 #-----------------------------------------------------------------------------
529 #-----------------------------------------------------------------------------
530
530
531
531
532 class PrefilterHandler(Configurable):
532 class PrefilterHandler(Configurable):
533
533
534 handler_name = Unicode('normal')
534 handler_name = Unicode('normal')
535 esc_strings = List([])
535 esc_strings = List([])
536 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
536 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
537 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
537 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
538
538
539 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
539 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
540 super(PrefilterHandler, self).__init__(
540 super(PrefilterHandler, self).__init__(
541 shell=shell, prefilter_manager=prefilter_manager, **kwargs
541 shell=shell, prefilter_manager=prefilter_manager, **kwargs
542 )
542 )
543 self.prefilter_manager.register_handler(
543 self.prefilter_manager.register_handler(
544 self.handler_name,
544 self.handler_name,
545 self,
545 self,
546 self.esc_strings
546 self.esc_strings
547 )
547 )
548
548
549 def handle(self, line_info):
549 def handle(self, line_info):
550 # print "normal: ", line_info
550 # print "normal: ", line_info
551 """Handle normal input lines. Use as a template for handlers."""
551 """Handle normal input lines. Use as a template for handlers."""
552
552
553 # With autoindent on, we need some way to exit the input loop, and I
553 # With autoindent on, we need some way to exit the input loop, and I
554 # don't want to force the user to have to backspace all the way to
554 # don't want to force the user to have to backspace all the way to
555 # clear the line. The rule will be in this case, that either two
555 # clear the line. The rule will be in this case, that either two
556 # lines of pure whitespace in a row, or a line of pure whitespace but
556 # lines of pure whitespace in a row, or a line of pure whitespace but
557 # of a size different to the indent level, will exit the input loop.
557 # of a size different to the indent level, will exit the input loop.
558 line = line_info.line
558 line = line_info.line
559 continue_prompt = line_info.continue_prompt
559 continue_prompt = line_info.continue_prompt
560
560
561 if (continue_prompt and
561 if (continue_prompt and
562 self.shell.autoindent and
562 self.shell.autoindent and
563 line.isspace() and
563 line.isspace() and
564 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
564 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
565 line = ''
565 line = ''
566
566
567 return line
567 return line
568
568
569 def __str__(self):
569 def __str__(self):
570 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
570 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
571
571
572
572
573 class MacroHandler(PrefilterHandler):
573 class MacroHandler(PrefilterHandler):
574 handler_name = Unicode("macro")
574 handler_name = Unicode("macro")
575
575
576 def handle(self, line_info):
576 def handle(self, line_info):
577 obj = self.shell.user_ns.get(line_info.ifun)
577 obj = self.shell.user_ns.get(line_info.ifun)
578 pre_space = line_info.pre_whitespace
578 pre_space = line_info.pre_whitespace
579 line_sep = "\n" + pre_space
579 line_sep = "\n" + pre_space
580 return pre_space + line_sep.join(obj.value.splitlines())
580 return pre_space + line_sep.join(obj.value.splitlines())
581
581
582
582
583 class MagicHandler(PrefilterHandler):
583 class MagicHandler(PrefilterHandler):
584
584
585 handler_name = Unicode('magic')
585 handler_name = Unicode('magic')
586 esc_strings = List([ESC_MAGIC])
586 esc_strings = List([ESC_MAGIC])
587
587
588 def handle(self, line_info):
588 def handle(self, line_info):
589 """Execute magic functions."""
589 """Execute magic functions."""
590 ifun = line_info.ifun
590 ifun = line_info.ifun
591 the_rest = line_info.the_rest
591 the_rest = line_info.the_rest
592 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
592 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
593 (ifun + " " + the_rest))
593 t_arg_s = ifun + " " + the_rest
594 t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ')
595 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
596 cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s)
594 return cmd
597 return cmd
595
598
596
599
597 class AutoHandler(PrefilterHandler):
600 class AutoHandler(PrefilterHandler):
598
601
599 handler_name = Unicode('auto')
602 handler_name = Unicode('auto')
600 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
603 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
601
604
602 def handle(self, line_info):
605 def handle(self, line_info):
603 """Handle lines which can be auto-executed, quoting if requested."""
606 """Handle lines which can be auto-executed, quoting if requested."""
604 line = line_info.line
607 line = line_info.line
605 ifun = line_info.ifun
608 ifun = line_info.ifun
606 the_rest = line_info.the_rest
609 the_rest = line_info.the_rest
607 esc = line_info.esc
610 esc = line_info.esc
608 continue_prompt = line_info.continue_prompt
611 continue_prompt = line_info.continue_prompt
609 obj = line_info.ofind(self.shell)['obj']
612 obj = line_info.ofind(self.shell)['obj']
610
613
611 # This should only be active for single-line input!
614 # This should only be active for single-line input!
612 if continue_prompt:
615 if continue_prompt:
613 return line
616 return line
614
617
615 force_auto = isinstance(obj, IPyAutocall)
618 force_auto = isinstance(obj, IPyAutocall)
616
619
617 # User objects sometimes raise exceptions on attribute access other
620 # User objects sometimes raise exceptions on attribute access other
618 # than AttributeError (we've seen it in the past), so it's safest to be
621 # than AttributeError (we've seen it in the past), so it's safest to be
619 # ultra-conservative here and catch all.
622 # ultra-conservative here and catch all.
620 try:
623 try:
621 auto_rewrite = obj.rewrite
624 auto_rewrite = obj.rewrite
622 except Exception:
625 except Exception:
623 auto_rewrite = True
626 auto_rewrite = True
624
627
625 if esc == ESC_QUOTE:
628 if esc == ESC_QUOTE:
626 # Auto-quote splitting on whitespace
629 # Auto-quote splitting on whitespace
627 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
630 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
628 elif esc == ESC_QUOTE2:
631 elif esc == ESC_QUOTE2:
629 # Auto-quote whole string
632 # Auto-quote whole string
630 newcmd = '%s("%s")' % (ifun,the_rest)
633 newcmd = '%s("%s")' % (ifun,the_rest)
631 elif esc == ESC_PAREN:
634 elif esc == ESC_PAREN:
632 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
635 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
633 else:
636 else:
634 # Auto-paren.
637 # Auto-paren.
635 if force_auto:
638 if force_auto:
636 # Don't rewrite if it is already a call.
639 # Don't rewrite if it is already a call.
637 do_rewrite = not the_rest.startswith('(')
640 do_rewrite = not the_rest.startswith('(')
638 else:
641 else:
639 if not the_rest:
642 if not the_rest:
640 # We only apply it to argument-less calls if the autocall
643 # We only apply it to argument-less calls if the autocall
641 # parameter is set to 2.
644 # parameter is set to 2.
642 do_rewrite = (self.shell.autocall >= 2)
645 do_rewrite = (self.shell.autocall >= 2)
643 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
646 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
644 # Don't autocall in this case: item access for an object
647 # Don't autocall in this case: item access for an object
645 # which is BOTH callable and implements __getitem__.
648 # which is BOTH callable and implements __getitem__.
646 do_rewrite = False
649 do_rewrite = False
647 else:
650 else:
648 do_rewrite = True
651 do_rewrite = True
649
652
650 # Figure out the rewritten command
653 # Figure out the rewritten command
651 if do_rewrite:
654 if do_rewrite:
652 if the_rest.endswith(';'):
655 if the_rest.endswith(';'):
653 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
656 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
654 else:
657 else:
655 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
658 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
656 else:
659 else:
657 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
660 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
658 return normal_handler.handle(line_info)
661 return normal_handler.handle(line_info)
659
662
660 # Display the rewritten call
663 # Display the rewritten call
661 if auto_rewrite:
664 if auto_rewrite:
662 self.shell.auto_rewrite_input(newcmd)
665 self.shell.auto_rewrite_input(newcmd)
663
666
664 return newcmd
667 return newcmd
665
668
666
669
667 class EmacsHandler(PrefilterHandler):
670 class EmacsHandler(PrefilterHandler):
668
671
669 handler_name = Unicode('emacs')
672 handler_name = Unicode('emacs')
670 esc_strings = List([])
673 esc_strings = List([])
671
674
672 def handle(self, line_info):
675 def handle(self, line_info):
673 """Handle input lines marked by python-mode."""
676 """Handle input lines marked by python-mode."""
674
677
675 # Currently, nothing is done. Later more functionality can be added
678 # Currently, nothing is done. Later more functionality can be added
676 # here if needed.
679 # here if needed.
677
680
678 # The input cache shouldn't be updated
681 # The input cache shouldn't be updated
679 return line_info.line
682 return line_info.line
680
683
681
684
682 #-----------------------------------------------------------------------------
685 #-----------------------------------------------------------------------------
683 # Defaults
686 # Defaults
684 #-----------------------------------------------------------------------------
687 #-----------------------------------------------------------------------------
685
688
686
689
687 _default_transformers = [
690 _default_transformers = [
688 ]
691 ]
689
692
690 _default_checkers = [
693 _default_checkers = [
691 EmacsChecker,
694 EmacsChecker,
692 MacroChecker,
695 MacroChecker,
693 IPyAutocallChecker,
696 IPyAutocallChecker,
694 AssignmentChecker,
697 AssignmentChecker,
695 AutoMagicChecker,
698 AutoMagicChecker,
696 PythonOpsChecker,
699 PythonOpsChecker,
697 AutocallChecker
700 AutocallChecker
698 ]
701 ]
699
702
700 _default_handlers = [
703 _default_handlers = [
701 PrefilterHandler,
704 PrefilterHandler,
702 MacroHandler,
705 MacroHandler,
703 MagicHandler,
706 MagicHandler,
704 AutoHandler,
707 AutoHandler,
705 EmacsHandler
708 EmacsHandler
706 ]
709 ]
General Comments 0
You need to be logged in to leave comments. Login now