##// END OF EJS Templates
Update docstring for InputSplitter.
Thomas Kluyver -
Show More
@@ -1,868 +1,862 b''
1 """Analysis of text input into executable blocks.
1 """Analysis of text input into executable blocks.
2
2
3 The main class in this module, :class:`InputSplitter`, is designed to break
3 The main class in this module, :class:`InputSplitter`, is designed to break
4 input from either interactive, line-by-line environments or block-based ones,
4 input from either interactive, line-by-line environments or block-based ones,
5 into standalone blocks that can be executed by Python as 'single' statements
5 into standalone blocks that can be executed by Python as 'single' statements
6 (thus triggering sys.displayhook).
6 (thus triggering sys.displayhook).
7
7
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 with full support for the extended IPython syntax (magics, system calls, etc).
9 with full support for the extended IPython syntax (magics, system calls, etc).
10
10
11 For more details, see the class docstring below.
11 For more details, see the class docstring below.
12
12
13 Syntax Transformations
13 Syntax Transformations
14 ----------------------
14 ----------------------
15
15
16 One of the main jobs of the code in this file is to apply all syntax
16 One of the main jobs of the code in this file is to apply all syntax
17 transformations that make up 'the IPython language', i.e. magics, shell
17 transformations that make up 'the IPython language', i.e. magics, shell
18 escapes, etc. All transformations should be implemented as *fully stateless*
18 escapes, etc. All transformations should be implemented as *fully stateless*
19 entities, that simply take one line as their input and return a line.
19 entities, that simply take one line as their input and return a line.
20 Internally for implementation purposes they may be a normal function or a
20 Internally for implementation purposes they may be a normal function or a
21 callable object, but the only input they receive will be a single line and they
21 callable object, but the only input they receive will be a single line and they
22 should only return a line, without holding any data-dependent state between
22 should only return a line, without holding any data-dependent state between
23 calls.
23 calls.
24
24
25 As an example, the EscapedTransformer is a class so we can more clearly group
25 As an example, the EscapedTransformer is a class so we can more clearly group
26 together the functionality of dispatching to individual functions based on the
26 together the functionality of dispatching to individual functions based on the
27 starting escape character, but the only method for public use is its call
27 starting escape character, but the only method for public use is its call
28 method.
28 method.
29
29
30
30
31 ToDo
31 ToDo
32 ----
32 ----
33
33
34 - Should we make push() actually raise an exception once push_accepts_more()
34 - Should we make push() actually raise an exception once push_accepts_more()
35 returns False?
35 returns False?
36
36
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 at least just attributes of a class so not really very exposed.
38 at least just attributes of a class so not really very exposed.
39
39
40 - Think about the best way to support dynamic things: automagic, autocall,
40 - Think about the best way to support dynamic things: automagic, autocall,
41 macros, etc.
41 macros, etc.
42
42
43 - Think of a better heuristic for the application of the transforms in
43 - Think of a better heuristic for the application of the transforms in
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 track indentation change events (indent, dedent, nothing) and apply them only
45 track indentation change events (indent, dedent, nothing) and apply them only
46 if the indentation went up, but not otherwise.
46 if the indentation went up, but not otherwise.
47
47
48 - Think of the cleanest way for supporting user-specified transformations (the
48 - Think of the cleanest way for supporting user-specified transformations (the
49 user prefilters we had before).
49 user prefilters we had before).
50
50
51 Authors
51 Authors
52 -------
52 -------
53
53
54 * Fernando Perez
54 * Fernando Perez
55 * Brian Granger
55 * Brian Granger
56 """
56 """
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Copyright (C) 2010 The IPython Development Team
58 # Copyright (C) 2010 The IPython Development Team
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63 from __future__ import print_function
63 from __future__ import print_function
64
64
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66 # Imports
66 # Imports
67 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
68 # stdlib
68 # stdlib
69 import ast
69 import ast
70 import codeop
70 import codeop
71 import re
71 import re
72 import sys
72 import sys
73
73
74 # IPython modules
74 # IPython modules
75 from IPython.utils.text import make_quoted_expr
75 from IPython.utils.text import make_quoted_expr
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Globals
78 # Globals
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81 # The escape sequences that define the syntax transformations IPython will
81 # The escape sequences that define the syntax transformations IPython will
82 # apply to user input. These can NOT be just changed here: many regular
82 # apply to user input. These can NOT be just changed here: many regular
83 # expressions and other parts of the code may use their hardcoded values, and
83 # expressions and other parts of the code may use their hardcoded values, and
84 # for all intents and purposes they constitute the 'IPython syntax', so they
84 # for all intents and purposes they constitute the 'IPython syntax', so they
85 # should be considered fixed.
85 # should be considered fixed.
86
86
87 ESC_SHELL = '!' # Send line to underlying system shell
87 ESC_SHELL = '!' # Send line to underlying system shell
88 ESC_SH_CAP = '!!' # Send line to system shell and capture output
88 ESC_SH_CAP = '!!' # Send line to system shell and capture output
89 ESC_HELP = '?' # Find information about object
89 ESC_HELP = '?' # Find information about object
90 ESC_HELP2 = '??' # Find extra-detailed information about object
90 ESC_HELP2 = '??' # Find extra-detailed information about object
91 ESC_MAGIC = '%' # Call magic function
91 ESC_MAGIC = '%' # Call magic function
92 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
92 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
93 ESC_QUOTE2 = ';' # Quote all args as a single string, call
93 ESC_QUOTE2 = ';' # Quote all args as a single string, call
94 ESC_PAREN = '/' # Call first argument with rest of line as arguments
94 ESC_PAREN = '/' # Call first argument with rest of line as arguments
95
95
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97 # Utilities
97 # Utilities
98 #-----------------------------------------------------------------------------
98 #-----------------------------------------------------------------------------
99
99
100 # FIXME: These are general-purpose utilities that later can be moved to the
100 # FIXME: These are general-purpose utilities that later can be moved to the
101 # general ward. Kept here for now because we're being very strict about test
101 # general ward. Kept here for now because we're being very strict about test
102 # coverage with this code, and this lets us ensure that we keep 100% coverage
102 # coverage with this code, and this lets us ensure that we keep 100% coverage
103 # while developing.
103 # while developing.
104
104
105 # compiled regexps for autoindent management
105 # compiled regexps for autoindent management
106 dedent_re = re.compile('|'.join([
106 dedent_re = re.compile('|'.join([
107 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
107 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
108 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
108 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
109 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
109 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
110 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
110 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
111 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
111 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
112 ]))
112 ]))
113 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
113 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
114
114
115 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
115 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
116 # before pure comments
116 # before pure comments
117 comment_line_re = re.compile('^\s*\#')
117 comment_line_re = re.compile('^\s*\#')
118
118
119
119
120 def num_ini_spaces(s):
120 def num_ini_spaces(s):
121 """Return the number of initial spaces in a string.
121 """Return the number of initial spaces in a string.
122
122
123 Note that tabs are counted as a single space. For now, we do *not* support
123 Note that tabs are counted as a single space. For now, we do *not* support
124 mixing of tabs and spaces in the user's input.
124 mixing of tabs and spaces in the user's input.
125
125
126 Parameters
126 Parameters
127 ----------
127 ----------
128 s : string
128 s : string
129
129
130 Returns
130 Returns
131 -------
131 -------
132 n : int
132 n : int
133 """
133 """
134
134
135 ini_spaces = ini_spaces_re.match(s)
135 ini_spaces = ini_spaces_re.match(s)
136 if ini_spaces:
136 if ini_spaces:
137 return ini_spaces.end()
137 return ini_spaces.end()
138 else:
138 else:
139 return 0
139 return 0
140
140
141
141
142 def remove_comments(src):
142 def remove_comments(src):
143 """Remove all comments from input source.
143 """Remove all comments from input source.
144
144
145 Note: comments are NOT recognized inside of strings!
145 Note: comments are NOT recognized inside of strings!
146
146
147 Parameters
147 Parameters
148 ----------
148 ----------
149 src : string
149 src : string
150 A single or multiline input string.
150 A single or multiline input string.
151
151
152 Returns
152 Returns
153 -------
153 -------
154 String with all Python comments removed.
154 String with all Python comments removed.
155 """
155 """
156
156
157 return re.sub('#.*', '', src)
157 return re.sub('#.*', '', src)
158
158
159
159
160 def get_input_encoding():
160 def get_input_encoding():
161 """Return the default standard input encoding.
161 """Return the default standard input encoding.
162
162
163 If sys.stdin has no encoding, 'ascii' is returned."""
163 If sys.stdin has no encoding, 'ascii' is returned."""
164 # There are strange environments for which sys.stdin.encoding is None. We
164 # There are strange environments for which sys.stdin.encoding is None. We
165 # ensure that a valid encoding is returned.
165 # ensure that a valid encoding is returned.
166 encoding = getattr(sys.stdin, 'encoding', None)
166 encoding = getattr(sys.stdin, 'encoding', None)
167 if encoding is None:
167 if encoding is None:
168 encoding = 'ascii'
168 encoding = 'ascii'
169 return encoding
169 return encoding
170
170
171 #-----------------------------------------------------------------------------
171 #-----------------------------------------------------------------------------
172 # Classes and functions for normal Python syntax handling
172 # Classes and functions for normal Python syntax handling
173 #-----------------------------------------------------------------------------
173 #-----------------------------------------------------------------------------
174
174
175 class InputSplitter(object):
175 class InputSplitter(object):
176 """An object that can split Python source input in executable blocks.
176 """An object that can accumulate lines of Python source before execution.
177
177
178 This object is designed to be used in one of two basic modes:
178 This object is designed to be fed python source line-by-line, using
179
179 :meth:`push`. It will return on each push whether the currently pushed
180 1. By feeding it python source line-by-line, using :meth:`push`. In this
180 code could be executed already. In addition, it provides a method called
181 mode, it will return on each push whether the currently pushed code
182 could be executed already. In addition, it provides a method called
183 :meth:`push_accepts_more` that can be used to query whether more input
181 :meth:`push_accepts_more` that can be used to query whether more input
184 can be pushed into a single interactive block.
182 can be pushed into a single interactive block.
185
183
186 2. By calling :meth:`split_blocks` with a single, multiline Python string,
187 that is then split into blocks each of which can be executed
188 interactively as a single statement.
189
190 This is a simple example of how an interactive terminal-based client can use
184 This is a simple example of how an interactive terminal-based client can use
191 this tool::
185 this tool::
192
186
193 isp = InputSplitter()
187 isp = InputSplitter()
194 while isp.push_accepts_more():
188 while isp.push_accepts_more():
195 indent = ' '*isp.indent_spaces
189 indent = ' '*isp.indent_spaces
196 prompt = '>>> ' + indent
190 prompt = '>>> ' + indent
197 line = indent + raw_input(prompt)
191 line = indent + raw_input(prompt)
198 isp.push(line)
192 isp.push(line)
199 print 'Input source was:\n', isp.source_reset(),
193 print 'Input source was:\n', isp.source_reset(),
200 """
194 """
201 # Number of spaces of indentation computed from input that has been pushed
195 # Number of spaces of indentation computed from input that has been pushed
202 # so far. This is the attributes callers should query to get the current
196 # so far. This is the attributes callers should query to get the current
203 # indentation level, in order to provide auto-indent facilities.
197 # indentation level, in order to provide auto-indent facilities.
204 indent_spaces = 0
198 indent_spaces = 0
205 # String, indicating the default input encoding. It is computed by default
199 # String, indicating the default input encoding. It is computed by default
206 # at initialization time via get_input_encoding(), but it can be reset by a
200 # at initialization time via get_input_encoding(), but it can be reset by a
207 # client with specific knowledge of the encoding.
201 # client with specific knowledge of the encoding.
208 encoding = ''
202 encoding = ''
209 # String where the current full source input is stored, properly encoded.
203 # String where the current full source input is stored, properly encoded.
210 # Reading this attribute is the normal way of querying the currently pushed
204 # Reading this attribute is the normal way of querying the currently pushed
211 # source code, that has been properly encoded.
205 # source code, that has been properly encoded.
212 source = ''
206 source = ''
213 # Code object corresponding to the current source. It is automatically
207 # Code object corresponding to the current source. It is automatically
214 # synced to the source, so it can be queried at any time to obtain the code
208 # synced to the source, so it can be queried at any time to obtain the code
215 # object; it will be None if the source doesn't compile to valid Python.
209 # object; it will be None if the source doesn't compile to valid Python.
216 code = None
210 code = None
217 # Input mode
211 # Input mode
218 input_mode = 'line'
212 input_mode = 'line'
219
213
220 # Private attributes
214 # Private attributes
221
215
222 # List with lines of input accumulated so far
216 # List with lines of input accumulated so far
223 _buffer = None
217 _buffer = None
224 # Command compiler
218 # Command compiler
225 _compile = None
219 _compile = None
226 # Mark when input has changed indentation all the way back to flush-left
220 # Mark when input has changed indentation all the way back to flush-left
227 _full_dedent = False
221 _full_dedent = False
228 # Boolean indicating whether the current block is complete
222 # Boolean indicating whether the current block is complete
229 _is_complete = None
223 _is_complete = None
230
224
231 def __init__(self, input_mode=None):
225 def __init__(self, input_mode=None):
232 """Create a new InputSplitter instance.
226 """Create a new InputSplitter instance.
233
227
234 Parameters
228 Parameters
235 ----------
229 ----------
236 input_mode : str
230 input_mode : str
237
231
238 One of ['line', 'cell']; default is 'line'.
232 One of ['line', 'cell']; default is 'line'.
239
233
240 The input_mode parameter controls how new inputs are used when fed via
234 The input_mode parameter controls how new inputs are used when fed via
241 the :meth:`push` method:
235 the :meth:`push` method:
242
236
243 - 'line': meant for line-oriented clients, inputs are appended one at a
237 - 'line': meant for line-oriented clients, inputs are appended one at a
244 time to the internal buffer and the whole buffer is compiled.
238 time to the internal buffer and the whole buffer is compiled.
245
239
246 - 'cell': meant for clients that can edit multi-line 'cells' of text at
240 - 'cell': meant for clients that can edit multi-line 'cells' of text at
247 a time. A cell can contain one or more blocks that can be compile in
241 a time. A cell can contain one or more blocks that can be compile in
248 'single' mode by Python. In this mode, each new input new input
242 'single' mode by Python. In this mode, each new input new input
249 completely replaces all prior inputs. Cell mode is thus equivalent
243 completely replaces all prior inputs. Cell mode is thus equivalent
250 to prepending a full reset() to every push() call.
244 to prepending a full reset() to every push() call.
251 """
245 """
252 self._buffer = []
246 self._buffer = []
253 self._compile = codeop.CommandCompiler()
247 self._compile = codeop.CommandCompiler()
254 self.encoding = get_input_encoding()
248 self.encoding = get_input_encoding()
255 self.input_mode = InputSplitter.input_mode if input_mode is None \
249 self.input_mode = InputSplitter.input_mode if input_mode is None \
256 else input_mode
250 else input_mode
257
251
258 def reset(self):
252 def reset(self):
259 """Reset the input buffer and associated state."""
253 """Reset the input buffer and associated state."""
260 self.indent_spaces = 0
254 self.indent_spaces = 0
261 self._buffer[:] = []
255 self._buffer[:] = []
262 self.source = ''
256 self.source = ''
263 self.code = None
257 self.code = None
264 self._is_complete = False
258 self._is_complete = False
265 self._full_dedent = False
259 self._full_dedent = False
266
260
267 def source_reset(self):
261 def source_reset(self):
268 """Return the input source and perform a full reset.
262 """Return the input source and perform a full reset.
269 """
263 """
270 out = self.source
264 out = self.source
271 self.reset()
265 self.reset()
272 return out
266 return out
273
267
274 def push(self, lines):
268 def push(self, lines):
275 """Push one or more lines of input.
269 """Push one or more lines of input.
276
270
277 This stores the given lines and returns a status code indicating
271 This stores the given lines and returns a status code indicating
278 whether the code forms a complete Python block or not.
272 whether the code forms a complete Python block or not.
279
273
280 Any exceptions generated in compilation are swallowed, but if an
274 Any exceptions generated in compilation are swallowed, but if an
281 exception was produced, the method returns True.
275 exception was produced, the method returns True.
282
276
283 Parameters
277 Parameters
284 ----------
278 ----------
285 lines : string
279 lines : string
286 One or more lines of Python input.
280 One or more lines of Python input.
287
281
288 Returns
282 Returns
289 -------
283 -------
290 is_complete : boolean
284 is_complete : boolean
291 True if the current input source (the result of the current input
285 True if the current input source (the result of the current input
292 plus prior inputs) forms a complete Python execution block. Note that
286 plus prior inputs) forms a complete Python execution block. Note that
293 this value is also stored as a private attribute (_is_complete), so it
287 this value is also stored as a private attribute (_is_complete), so it
294 can be queried at any time.
288 can be queried at any time.
295 """
289 """
296 if self.input_mode == 'cell':
290 if self.input_mode == 'cell':
297 self.reset()
291 self.reset()
298
292
299 self._store(lines)
293 self._store(lines)
300 source = self.source
294 source = self.source
301
295
302 # Before calling _compile(), reset the code object to None so that if an
296 # Before calling _compile(), reset the code object to None so that if an
303 # exception is raised in compilation, we don't mislead by having
297 # exception is raised in compilation, we don't mislead by having
304 # inconsistent code/source attributes.
298 # inconsistent code/source attributes.
305 self.code, self._is_complete = None, None
299 self.code, self._is_complete = None, None
306
300
307 # Honor termination lines properly
301 # Honor termination lines properly
308 if source.rstrip().endswith('\\'):
302 if source.rstrip().endswith('\\'):
309 return False
303 return False
310
304
311 self._update_indent(lines)
305 self._update_indent(lines)
312 try:
306 try:
313 self.code = self._compile(source, symbol="exec")
307 self.code = self._compile(source, symbol="exec")
314 # Invalid syntax can produce any of a number of different errors from
308 # Invalid syntax can produce any of a number of different errors from
315 # inside the compiler, so we have to catch them all. Syntax errors
309 # inside the compiler, so we have to catch them all. Syntax errors
316 # immediately produce a 'ready' block, so the invalid Python can be
310 # immediately produce a 'ready' block, so the invalid Python can be
317 # sent to the kernel for evaluation with possible ipython
311 # sent to the kernel for evaluation with possible ipython
318 # special-syntax conversion.
312 # special-syntax conversion.
319 except (SyntaxError, OverflowError, ValueError, TypeError,
313 except (SyntaxError, OverflowError, ValueError, TypeError,
320 MemoryError):
314 MemoryError):
321 self._is_complete = True
315 self._is_complete = True
322 else:
316 else:
323 # Compilation didn't produce any exceptions (though it may not have
317 # Compilation didn't produce any exceptions (though it may not have
324 # given a complete code object)
318 # given a complete code object)
325 self._is_complete = self.code is not None
319 self._is_complete = self.code is not None
326
320
327 return self._is_complete
321 return self._is_complete
328
322
329 def push_accepts_more(self):
323 def push_accepts_more(self):
330 """Return whether a block of interactive input can accept more input.
324 """Return whether a block of interactive input can accept more input.
331
325
332 This method is meant to be used by line-oriented frontends, who need to
326 This method is meant to be used by line-oriented frontends, who need to
333 guess whether a block is complete or not based solely on prior and
327 guess whether a block is complete or not based solely on prior and
334 current input lines. The InputSplitter considers it has a complete
328 current input lines. The InputSplitter considers it has a complete
335 interactive block and will not accept more input only when either a
329 interactive block and will not accept more input only when either a
336 SyntaxError is raised, or *all* of the following are true:
330 SyntaxError is raised, or *all* of the following are true:
337
331
338 1. The input compiles to a complete statement.
332 1. The input compiles to a complete statement.
339
333
340 2. The indentation level is flush-left (because if we are indented,
334 2. The indentation level is flush-left (because if we are indented,
341 like inside a function definition or for loop, we need to keep
335 like inside a function definition or for loop, we need to keep
342 reading new input).
336 reading new input).
343
337
344 3. There is one extra line consisting only of whitespace.
338 3. There is one extra line consisting only of whitespace.
345
339
346 Because of condition #3, this method should be used only by
340 Because of condition #3, this method should be used only by
347 *line-oriented* frontends, since it means that intermediate blank lines
341 *line-oriented* frontends, since it means that intermediate blank lines
348 are not allowed in function definitions (or any other indented block).
342 are not allowed in function definitions (or any other indented block).
349
343
350 Block-oriented frontends that have a separate keyboard event to
344 Block-oriented frontends that have a separate keyboard event to
351 indicate execution should use the :meth:`split_blocks` method instead.
345 indicate execution should use the :meth:`split_blocks` method instead.
352
346
353 If the current input produces a syntax error, this method immediately
347 If the current input produces a syntax error, this method immediately
354 returns False but does *not* raise the syntax error exception, as
348 returns False but does *not* raise the syntax error exception, as
355 typically clients will want to send invalid syntax to an execution
349 typically clients will want to send invalid syntax to an execution
356 backend which might convert the invalid syntax into valid Python via
350 backend which might convert the invalid syntax into valid Python via
357 one of the dynamic IPython mechanisms.
351 one of the dynamic IPython mechanisms.
358 """
352 """
359
353
360 # With incomplete input, unconditionally accept more
354 # With incomplete input, unconditionally accept more
361 if not self._is_complete:
355 if not self._is_complete:
362 return True
356 return True
363
357
364 # If we already have complete input and we're flush left, the answer
358 # If we already have complete input and we're flush left, the answer
365 # depends. In line mode, if there hasn't been any indentation,
359 # depends. In line mode, if there hasn't been any indentation,
366 # that's it. If we've come back from some indentation, we need
360 # that's it. If we've come back from some indentation, we need
367 # the blank final line to finish.
361 # the blank final line to finish.
368 # In cell mode, we need to check how many blocks the input so far
362 # In cell mode, we need to check how many blocks the input so far
369 # compiles into, because if there's already more than one full
363 # compiles into, because if there's already more than one full
370 # independent block of input, then the client has entered full
364 # independent block of input, then the client has entered full
371 # 'cell' mode and is feeding lines that each is complete. In this
365 # 'cell' mode and is feeding lines that each is complete. In this
372 # case we should then keep accepting. The Qt terminal-like console
366 # case we should then keep accepting. The Qt terminal-like console
373 # does precisely this, to provide the convenience of terminal-like
367 # does precisely this, to provide the convenience of terminal-like
374 # input of single expressions, but allowing the user (with a
368 # input of single expressions, but allowing the user (with a
375 # separate keystroke) to switch to 'cell' mode and type multiple
369 # separate keystroke) to switch to 'cell' mode and type multiple
376 # expressions in one shot.
370 # expressions in one shot.
377 if self.indent_spaces==0:
371 if self.indent_spaces==0:
378 if self.input_mode=='line':
372 if self.input_mode=='line':
379 if not self._full_dedent:
373 if not self._full_dedent:
380 return False
374 return False
381 else:
375 else:
382 try:
376 try:
383 code_ast = ast.parse(u''.join(self._buffer))
377 code_ast = ast.parse(u''.join(self._buffer))
384 except Exception:
378 except Exception:
385 return False
379 return False
386 else:
380 else:
387 if len(code_ast.body) == 1:
381 if len(code_ast.body) == 1:
388 return False
382 return False
389
383
390 # When input is complete, then termination is marked by an extra blank
384 # When input is complete, then termination is marked by an extra blank
391 # line at the end.
385 # line at the end.
392 last_line = self.source.splitlines()[-1]
386 last_line = self.source.splitlines()[-1]
393 return bool(last_line and not last_line.isspace())
387 return bool(last_line and not last_line.isspace())
394
388
395 #------------------------------------------------------------------------
389 #------------------------------------------------------------------------
396 # Private interface
390 # Private interface
397 #------------------------------------------------------------------------
391 #------------------------------------------------------------------------
398
392
399 def _find_indent(self, line):
393 def _find_indent(self, line):
400 """Compute the new indentation level for a single line.
394 """Compute the new indentation level for a single line.
401
395
402 Parameters
396 Parameters
403 ----------
397 ----------
404 line : str
398 line : str
405 A single new line of non-whitespace, non-comment Python input.
399 A single new line of non-whitespace, non-comment Python input.
406
400
407 Returns
401 Returns
408 -------
402 -------
409 indent_spaces : int
403 indent_spaces : int
410 New value for the indent level (it may be equal to self.indent_spaces
404 New value for the indent level (it may be equal to self.indent_spaces
411 if indentation doesn't change.
405 if indentation doesn't change.
412
406
413 full_dedent : boolean
407 full_dedent : boolean
414 Whether the new line causes a full flush-left dedent.
408 Whether the new line causes a full flush-left dedent.
415 """
409 """
416 indent_spaces = self.indent_spaces
410 indent_spaces = self.indent_spaces
417 full_dedent = self._full_dedent
411 full_dedent = self._full_dedent
418
412
419 inisp = num_ini_spaces(line)
413 inisp = num_ini_spaces(line)
420 if inisp < indent_spaces:
414 if inisp < indent_spaces:
421 indent_spaces = inisp
415 indent_spaces = inisp
422 if indent_spaces <= 0:
416 if indent_spaces <= 0:
423 #print 'Full dedent in text',self.source # dbg
417 #print 'Full dedent in text',self.source # dbg
424 full_dedent = True
418 full_dedent = True
425
419
426 if line[-1] == ':':
420 if line[-1] == ':':
427 indent_spaces += 4
421 indent_spaces += 4
428 elif dedent_re.match(line):
422 elif dedent_re.match(line):
429 indent_spaces -= 4
423 indent_spaces -= 4
430 if indent_spaces <= 0:
424 if indent_spaces <= 0:
431 full_dedent = True
425 full_dedent = True
432
426
433 # Safety
427 # Safety
434 if indent_spaces < 0:
428 if indent_spaces < 0:
435 indent_spaces = 0
429 indent_spaces = 0
436 #print 'safety' # dbg
430 #print 'safety' # dbg
437
431
438 return indent_spaces, full_dedent
432 return indent_spaces, full_dedent
439
433
440 def _update_indent(self, lines):
434 def _update_indent(self, lines):
441 for line in remove_comments(lines).splitlines():
435 for line in remove_comments(lines).splitlines():
442 if line and not line.isspace():
436 if line and not line.isspace():
443 self.indent_spaces, self._full_dedent = self._find_indent(line)
437 self.indent_spaces, self._full_dedent = self._find_indent(line)
444
438
445 def _store(self, lines, buffer=None, store='source'):
439 def _store(self, lines, buffer=None, store='source'):
446 """Store one or more lines of input.
440 """Store one or more lines of input.
447
441
448 If input lines are not newline-terminated, a newline is automatically
442 If input lines are not newline-terminated, a newline is automatically
449 appended."""
443 appended."""
450
444
451 if buffer is None:
445 if buffer is None:
452 buffer = self._buffer
446 buffer = self._buffer
453
447
454 if lines.endswith('\n'):
448 if lines.endswith('\n'):
455 buffer.append(lines)
449 buffer.append(lines)
456 else:
450 else:
457 buffer.append(lines+'\n')
451 buffer.append(lines+'\n')
458 setattr(self, store, self._set_source(buffer))
452 setattr(self, store, self._set_source(buffer))
459
453
460 def _set_source(self, buffer):
454 def _set_source(self, buffer):
461 return u''.join(buffer)
455 return u''.join(buffer)
462
456
463
457
464 #-----------------------------------------------------------------------------
458 #-----------------------------------------------------------------------------
465 # Functions and classes for IPython-specific syntactic support
459 # Functions and classes for IPython-specific syntactic support
466 #-----------------------------------------------------------------------------
460 #-----------------------------------------------------------------------------
467
461
468 # RegExp for splitting line contents into pre-char//first word-method//rest.
462 # RegExp for splitting line contents into pre-char//first word-method//rest.
469 # For clarity, each group in on one line.
463 # For clarity, each group in on one line.
470
464
471 line_split = re.compile("""
465 line_split = re.compile("""
472 ^(\s*) # any leading space
466 ^(\s*) # any leading space
473 ([,;/%]|!!?|\?\??) # escape character or characters
467 ([,;/%]|!!?|\?\??) # escape character or characters
474 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
468 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
475 # to correctly treat things like '?%magic'
469 # to correctly treat things like '?%magic'
476 (\s+.*$|$) # rest of line
470 (\s+.*$|$) # rest of line
477 """, re.VERBOSE)
471 """, re.VERBOSE)
478
472
479
473
480 def split_user_input(line):
474 def split_user_input(line):
481 """Split user input into early whitespace, esc-char, function part and rest.
475 """Split user input into early whitespace, esc-char, function part and rest.
482
476
483 This is currently handles lines with '=' in them in a very inconsistent
477 This is currently handles lines with '=' in them in a very inconsistent
484 manner.
478 manner.
485
479
486 Examples
480 Examples
487 ========
481 ========
488 >>> split_user_input('x=1')
482 >>> split_user_input('x=1')
489 ('', '', 'x=1', '')
483 ('', '', 'x=1', '')
490 >>> split_user_input('?')
484 >>> split_user_input('?')
491 ('', '?', '', '')
485 ('', '?', '', '')
492 >>> split_user_input('??')
486 >>> split_user_input('??')
493 ('', '??', '', '')
487 ('', '??', '', '')
494 >>> split_user_input(' ?')
488 >>> split_user_input(' ?')
495 (' ', '?', '', '')
489 (' ', '?', '', '')
496 >>> split_user_input(' ??')
490 >>> split_user_input(' ??')
497 (' ', '??', '', '')
491 (' ', '??', '', '')
498 >>> split_user_input('??x')
492 >>> split_user_input('??x')
499 ('', '??', 'x', '')
493 ('', '??', 'x', '')
500 >>> split_user_input('?x=1')
494 >>> split_user_input('?x=1')
501 ('', '', '?x=1', '')
495 ('', '', '?x=1', '')
502 >>> split_user_input('!ls')
496 >>> split_user_input('!ls')
503 ('', '!', 'ls', '')
497 ('', '!', 'ls', '')
504 >>> split_user_input(' !ls')
498 >>> split_user_input(' !ls')
505 (' ', '!', 'ls', '')
499 (' ', '!', 'ls', '')
506 >>> split_user_input('!!ls')
500 >>> split_user_input('!!ls')
507 ('', '!!', 'ls', '')
501 ('', '!!', 'ls', '')
508 >>> split_user_input(' !!ls')
502 >>> split_user_input(' !!ls')
509 (' ', '!!', 'ls', '')
503 (' ', '!!', 'ls', '')
510 >>> split_user_input(',ls')
504 >>> split_user_input(',ls')
511 ('', ',', 'ls', '')
505 ('', ',', 'ls', '')
512 >>> split_user_input(';ls')
506 >>> split_user_input(';ls')
513 ('', ';', 'ls', '')
507 ('', ';', 'ls', '')
514 >>> split_user_input(' ;ls')
508 >>> split_user_input(' ;ls')
515 (' ', ';', 'ls', '')
509 (' ', ';', 'ls', '')
516 >>> split_user_input('f.g(x)')
510 >>> split_user_input('f.g(x)')
517 ('', '', 'f.g(x)', '')
511 ('', '', 'f.g(x)', '')
518 >>> split_user_input('f.g (x)')
512 >>> split_user_input('f.g (x)')
519 ('', '', 'f.g', '(x)')
513 ('', '', 'f.g', '(x)')
520 >>> split_user_input('?%hist')
514 >>> split_user_input('?%hist')
521 ('', '?', '%hist', '')
515 ('', '?', '%hist', '')
522 >>> split_user_input('?x*')
516 >>> split_user_input('?x*')
523 ('', '?', 'x*', '')
517 ('', '?', 'x*', '')
524 """
518 """
525 match = line_split.match(line)
519 match = line_split.match(line)
526 if match:
520 if match:
527 lspace, esc, fpart, rest = match.groups()
521 lspace, esc, fpart, rest = match.groups()
528 else:
522 else:
529 # print "match failed for line '%s'" % line
523 # print "match failed for line '%s'" % line
530 try:
524 try:
531 fpart, rest = line.split(None, 1)
525 fpart, rest = line.split(None, 1)
532 except ValueError:
526 except ValueError:
533 # print "split failed for line '%s'" % line
527 # print "split failed for line '%s'" % line
534 fpart, rest = line,''
528 fpart, rest = line,''
535 lspace = re.match('^(\s*)(.*)', line).groups()[0]
529 lspace = re.match('^(\s*)(.*)', line).groups()[0]
536 esc = ''
530 esc = ''
537
531
538 # fpart has to be a valid python identifier, so it better be only pure
532 # fpart has to be a valid python identifier, so it better be only pure
539 # ascii, no unicode:
533 # ascii, no unicode:
540 try:
534 try:
541 fpart = fpart.encode('ascii')
535 fpart = fpart.encode('ascii')
542 except UnicodeEncodeError:
536 except UnicodeEncodeError:
543 lspace = unicode(lspace)
537 lspace = unicode(lspace)
544 rest = fpart + u' ' + rest
538 rest = fpart + u' ' + rest
545 fpart = u''
539 fpart = u''
546
540
547 #print 'line:<%s>' % line # dbg
541 #print 'line:<%s>' % line # dbg
548 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
542 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
549 return lspace, esc, fpart.strip(), rest.lstrip()
543 return lspace, esc, fpart.strip(), rest.lstrip()
550
544
551
545
552 # The escaped translators ALL receive a line where their own escape has been
546 # The escaped translators ALL receive a line where their own escape has been
553 # stripped. Only '?' is valid at the end of the line, all others can only be
547 # stripped. Only '?' is valid at the end of the line, all others can only be
554 # placed at the start.
548 # placed at the start.
555
549
556 class LineInfo(object):
550 class LineInfo(object):
557 """A single line of input and associated info.
551 """A single line of input and associated info.
558
552
559 This is a utility class that mostly wraps the output of
553 This is a utility class that mostly wraps the output of
560 :func:`split_user_input` into a convenient object to be passed around
554 :func:`split_user_input` into a convenient object to be passed around
561 during input transformations.
555 during input transformations.
562
556
563 Includes the following as properties:
557 Includes the following as properties:
564
558
565 line
559 line
566 The original, raw line
560 The original, raw line
567
561
568 lspace
562 lspace
569 Any early whitespace before actual text starts.
563 Any early whitespace before actual text starts.
570
564
571 esc
565 esc
572 The initial esc character (or characters, for double-char escapes like
566 The initial esc character (or characters, for double-char escapes like
573 '??' or '!!').
567 '??' or '!!').
574
568
575 fpart
569 fpart
576 The 'function part', which is basically the maximal initial sequence
570 The 'function part', which is basically the maximal initial sequence
577 of valid python identifiers and the '.' character. This is what is
571 of valid python identifiers and the '.' character. This is what is
578 checked for alias and magic transformations, used for auto-calling,
572 checked for alias and magic transformations, used for auto-calling,
579 etc.
573 etc.
580
574
581 rest
575 rest
582 Everything else on the line.
576 Everything else on the line.
583 """
577 """
584 def __init__(self, line):
578 def __init__(self, line):
585 self.line = line
579 self.line = line
586 self.lspace, self.esc, self.fpart, self.rest = \
580 self.lspace, self.esc, self.fpart, self.rest = \
587 split_user_input(line)
581 split_user_input(line)
588
582
589 def __str__(self):
583 def __str__(self):
590 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
584 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
591 self.fpart, self.rest)
585 self.fpart, self.rest)
592
586
593
587
594 # Transformations of the special syntaxes that don't rely on an explicit escape
588 # Transformations of the special syntaxes that don't rely on an explicit escape
595 # character but instead on patterns on the input line
589 # character but instead on patterns on the input line
596
590
597 # The core transformations are implemented as standalone functions that can be
591 # The core transformations are implemented as standalone functions that can be
598 # tested and validated in isolation. Each of these uses a regexp, we
592 # tested and validated in isolation. Each of these uses a regexp, we
599 # pre-compile these and keep them close to each function definition for clarity
593 # pre-compile these and keep them close to each function definition for clarity
600
594
601 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
595 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
602 r'\s*=\s*!\s*(?P<cmd>.*)')
596 r'\s*=\s*!\s*(?P<cmd>.*)')
603
597
604 def transform_assign_system(line):
598 def transform_assign_system(line):
605 """Handle the `files = !ls` syntax."""
599 """Handle the `files = !ls` syntax."""
606 m = _assign_system_re.match(line)
600 m = _assign_system_re.match(line)
607 if m is not None:
601 if m is not None:
608 cmd = m.group('cmd')
602 cmd = m.group('cmd')
609 lhs = m.group('lhs')
603 lhs = m.group('lhs')
610 expr = make_quoted_expr(cmd)
604 expr = make_quoted_expr(cmd)
611 new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
605 new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
612 return new_line
606 return new_line
613 return line
607 return line
614
608
615
609
616 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
610 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
617 r'\s*=\s*%\s*(?P<cmd>.*)')
611 r'\s*=\s*%\s*(?P<cmd>.*)')
618
612
619 def transform_assign_magic(line):
613 def transform_assign_magic(line):
620 """Handle the `a = %who` syntax."""
614 """Handle the `a = %who` syntax."""
621 m = _assign_magic_re.match(line)
615 m = _assign_magic_re.match(line)
622 if m is not None:
616 if m is not None:
623 cmd = m.group('cmd')
617 cmd = m.group('cmd')
624 lhs = m.group('lhs')
618 lhs = m.group('lhs')
625 expr = make_quoted_expr(cmd)
619 expr = make_quoted_expr(cmd)
626 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
620 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
627 return new_line
621 return new_line
628 return line
622 return line
629
623
630
624
631 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
625 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
632
626
633 def transform_classic_prompt(line):
627 def transform_classic_prompt(line):
634 """Handle inputs that start with '>>> ' syntax."""
628 """Handle inputs that start with '>>> ' syntax."""
635
629
636 if not line or line.isspace():
630 if not line or line.isspace():
637 return line
631 return line
638 m = _classic_prompt_re.match(line)
632 m = _classic_prompt_re.match(line)
639 if m:
633 if m:
640 return line[len(m.group(0)):]
634 return line[len(m.group(0)):]
641 else:
635 else:
642 return line
636 return line
643
637
644
638
645 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
639 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
646
640
647 def transform_ipy_prompt(line):
641 def transform_ipy_prompt(line):
648 """Handle inputs that start classic IPython prompt syntax."""
642 """Handle inputs that start classic IPython prompt syntax."""
649
643
650 if not line or line.isspace():
644 if not line or line.isspace():
651 return line
645 return line
652 #print 'LINE: %r' % line # dbg
646 #print 'LINE: %r' % line # dbg
653 m = _ipy_prompt_re.match(line)
647 m = _ipy_prompt_re.match(line)
654 if m:
648 if m:
655 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
649 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
656 return line[len(m.group(0)):]
650 return line[len(m.group(0)):]
657 else:
651 else:
658 return line
652 return line
659
653
660
654
661 def _make_help_call(target, esc, lspace):
655 def _make_help_call(target, esc, lspace):
662 """Prepares a pinfo(2)/psearch call from a target name and the escape
656 """Prepares a pinfo(2)/psearch call from a target name and the escape
663 (i.e. ? or ??)"""
657 (i.e. ? or ??)"""
664 method = 'pinfo2' if esc == '??' \
658 method = 'pinfo2' if esc == '??' \
665 else 'psearch' if '*' in target \
659 else 'psearch' if '*' in target \
666 else 'pinfo'
660 else 'pinfo'
667
661
668 tpl = '%sget_ipython().magic(u"%s %s")'
662 tpl = '%sget_ipython().magic(u"%s %s")'
669 return tpl % (lspace, method, target)
663 return tpl % (lspace, method, target)
670
664
671 _initial_space_re = re.compile(r'\s*')
665 _initial_space_re = re.compile(r'\s*')
672 _help_end_re = re.compile(r"""(%?
666 _help_end_re = re.compile(r"""(%?
673 [a-zA-Z_*][a-zA-Z0-9_*]* # Variable name
667 [a-zA-Z_*][a-zA-Z0-9_*]* # Variable name
674 (.[a-zA-Z_*][a-zA-Z0-9_*]*)* # .etc.etc
668 (.[a-zA-Z_*][a-zA-Z0-9_*]*)* # .etc.etc
675 )
669 )
676 (\?\??)$ # ? or ??""",
670 (\?\??)$ # ? or ??""",
677 re.VERBOSE)
671 re.VERBOSE)
678 def transform_help_end(line):
672 def transform_help_end(line):
679 """Translate lines with ?/?? at the end"""
673 """Translate lines with ?/?? at the end"""
680 m = _help_end_re.search(line)
674 m = _help_end_re.search(line)
681 if m is None:
675 if m is None:
682 return line
676 return line
683 target = m.group(1)
677 target = m.group(1)
684 esc = m.group(3)
678 esc = m.group(3)
685 lspace = _initial_space_re.match(line).group(0)
679 lspace = _initial_space_re.match(line).group(0)
686 return _make_help_call(target, esc, lspace)
680 return _make_help_call(target, esc, lspace)
687
681
688
682
689 class EscapedTransformer(object):
683 class EscapedTransformer(object):
690 """Class to transform lines that are explicitly escaped out."""
684 """Class to transform lines that are explicitly escaped out."""
691
685
692 def __init__(self):
686 def __init__(self):
693 tr = { ESC_SHELL : self._tr_system,
687 tr = { ESC_SHELL : self._tr_system,
694 ESC_SH_CAP : self._tr_system2,
688 ESC_SH_CAP : self._tr_system2,
695 ESC_HELP : self._tr_help,
689 ESC_HELP : self._tr_help,
696 ESC_HELP2 : self._tr_help,
690 ESC_HELP2 : self._tr_help,
697 ESC_MAGIC : self._tr_magic,
691 ESC_MAGIC : self._tr_magic,
698 ESC_QUOTE : self._tr_quote,
692 ESC_QUOTE : self._tr_quote,
699 ESC_QUOTE2 : self._tr_quote2,
693 ESC_QUOTE2 : self._tr_quote2,
700 ESC_PAREN : self._tr_paren }
694 ESC_PAREN : self._tr_paren }
701 self.tr = tr
695 self.tr = tr
702
696
703 # Support for syntax transformations that use explicit escapes typed by the
697 # Support for syntax transformations that use explicit escapes typed by the
704 # user at the beginning of a line
698 # user at the beginning of a line
705 @staticmethod
699 @staticmethod
706 def _tr_system(line_info):
700 def _tr_system(line_info):
707 "Translate lines escaped with: !"
701 "Translate lines escaped with: !"
708 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
702 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
709 return '%sget_ipython().system(%s)' % (line_info.lspace,
703 return '%sget_ipython().system(%s)' % (line_info.lspace,
710 make_quoted_expr(cmd))
704 make_quoted_expr(cmd))
711
705
712 @staticmethod
706 @staticmethod
713 def _tr_system2(line_info):
707 def _tr_system2(line_info):
714 "Translate lines escaped with: !!"
708 "Translate lines escaped with: !!"
715 cmd = line_info.line.lstrip()[2:]
709 cmd = line_info.line.lstrip()[2:]
716 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
710 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
717 make_quoted_expr(cmd))
711 make_quoted_expr(cmd))
718
712
719 @staticmethod
713 @staticmethod
720 def _tr_help(line_info):
714 def _tr_help(line_info):
721 "Translate lines escaped with: ?/??"
715 "Translate lines escaped with: ?/??"
722 # A naked help line should just fire the intro help screen
716 # A naked help line should just fire the intro help screen
723 if not line_info.line[1:]:
717 if not line_info.line[1:]:
724 return 'get_ipython().show_usage()'
718 return 'get_ipython().show_usage()'
725
719
726 return _make_help_call(line_info.fpart, line_info.esc, line_info.lspace)
720 return _make_help_call(line_info.fpart, line_info.esc, line_info.lspace)
727
721
728 @staticmethod
722 @staticmethod
729 def _tr_magic(line_info):
723 def _tr_magic(line_info):
730 "Translate lines escaped with: %"
724 "Translate lines escaped with: %"
731 tpl = '%sget_ipython().magic(%s)'
725 tpl = '%sget_ipython().magic(%s)'
732 cmd = make_quoted_expr(' '.join([line_info.fpart,
726 cmd = make_quoted_expr(' '.join([line_info.fpart,
733 line_info.rest]).strip())
727 line_info.rest]).strip())
734 return tpl % (line_info.lspace, cmd)
728 return tpl % (line_info.lspace, cmd)
735
729
736 @staticmethod
730 @staticmethod
737 def _tr_quote(line_info):
731 def _tr_quote(line_info):
738 "Translate lines escaped with: ,"
732 "Translate lines escaped with: ,"
739 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
733 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
740 '", "'.join(line_info.rest.split()) )
734 '", "'.join(line_info.rest.split()) )
741
735
742 @staticmethod
736 @staticmethod
743 def _tr_quote2(line_info):
737 def _tr_quote2(line_info):
744 "Translate lines escaped with: ;"
738 "Translate lines escaped with: ;"
745 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
739 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
746 line_info.rest)
740 line_info.rest)
747
741
748 @staticmethod
742 @staticmethod
749 def _tr_paren(line_info):
743 def _tr_paren(line_info):
750 "Translate lines escaped with: /"
744 "Translate lines escaped with: /"
751 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
745 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
752 ", ".join(line_info.rest.split()))
746 ", ".join(line_info.rest.split()))
753
747
754 def __call__(self, line):
748 def __call__(self, line):
755 """Class to transform lines that are explicitly escaped out.
749 """Class to transform lines that are explicitly escaped out.
756
750
757 This calls the above _tr_* static methods for the actual line
751 This calls the above _tr_* static methods for the actual line
758 translations."""
752 translations."""
759
753
760 # Empty lines just get returned unmodified
754 # Empty lines just get returned unmodified
761 if not line or line.isspace():
755 if not line or line.isspace():
762 return line
756 return line
763
757
764 # Get line endpoints, where the escapes can be
758 # Get line endpoints, where the escapes can be
765 line_info = LineInfo(line)
759 line_info = LineInfo(line)
766
760
767 if not line_info.esc in self.tr:
761 if not line_info.esc in self.tr:
768 # If we don't recognize the escape, don't modify the line
762 # If we don't recognize the escape, don't modify the line
769 return line
763 return line
770
764
771 return self.tr[line_info.esc](line_info)
765 return self.tr[line_info.esc](line_info)
772
766
773
767
774 # A function-looking object to be used by the rest of the code. The purpose of
768 # A function-looking object to be used by the rest of the code. The purpose of
775 # the class in this case is to organize related functionality, more than to
769 # the class in this case is to organize related functionality, more than to
776 # manage state.
770 # manage state.
777 transform_escaped = EscapedTransformer()
771 transform_escaped = EscapedTransformer()
778
772
779
773
780 class IPythonInputSplitter(InputSplitter):
774 class IPythonInputSplitter(InputSplitter):
781 """An input splitter that recognizes all of IPython's special syntax."""
775 """An input splitter that recognizes all of IPython's special syntax."""
782
776
783 # String with raw, untransformed input.
777 # String with raw, untransformed input.
784 source_raw = ''
778 source_raw = ''
785
779
786 # Private attributes
780 # Private attributes
787
781
788 # List with lines of raw input accumulated so far.
782 # List with lines of raw input accumulated so far.
789 _buffer_raw = None
783 _buffer_raw = None
790
784
791 def __init__(self, input_mode=None):
785 def __init__(self, input_mode=None):
792 InputSplitter.__init__(self, input_mode)
786 InputSplitter.__init__(self, input_mode)
793 self._buffer_raw = []
787 self._buffer_raw = []
794
788
795 def reset(self):
789 def reset(self):
796 """Reset the input buffer and associated state."""
790 """Reset the input buffer and associated state."""
797 InputSplitter.reset(self)
791 InputSplitter.reset(self)
798 self._buffer_raw[:] = []
792 self._buffer_raw[:] = []
799 self.source_raw = ''
793 self.source_raw = ''
800
794
801 def source_raw_reset(self):
795 def source_raw_reset(self):
802 """Return input and raw source and perform a full reset.
796 """Return input and raw source and perform a full reset.
803 """
797 """
804 out = self.source
798 out = self.source
805 out_r = self.source_raw
799 out_r = self.source_raw
806 self.reset()
800 self.reset()
807 return out, out_r
801 return out, out_r
808
802
809 def push(self, lines):
803 def push(self, lines):
810 """Push one or more lines of IPython input.
804 """Push one or more lines of IPython input.
811 """
805 """
812 if not lines:
806 if not lines:
813 return super(IPythonInputSplitter, self).push(lines)
807 return super(IPythonInputSplitter, self).push(lines)
814
808
815 # We must ensure all input is pure unicode
809 # We must ensure all input is pure unicode
816 if type(lines)==str:
810 if type(lines)==str:
817 lines = lines.decode(self.encoding)
811 lines = lines.decode(self.encoding)
818
812
819 lines_list = lines.splitlines()
813 lines_list = lines.splitlines()
820
814
821 transforms = [transform_escaped, transform_help_end,
815 transforms = [transform_escaped, transform_help_end,
822 transform_assign_system, transform_assign_magic,
816 transform_assign_system, transform_assign_magic,
823 transform_ipy_prompt, transform_classic_prompt]
817 transform_ipy_prompt, transform_classic_prompt]
824
818
825 # Transform logic
819 # Transform logic
826 #
820 #
827 # We only apply the line transformers to the input if we have either no
821 # We only apply the line transformers to the input if we have either no
828 # input yet, or complete input, or if the last line of the buffer ends
822 # input yet, or complete input, or if the last line of the buffer ends
829 # with ':' (opening an indented block). This prevents the accidental
823 # with ':' (opening an indented block). This prevents the accidental
830 # transformation of escapes inside multiline expressions like
824 # transformation of escapes inside multiline expressions like
831 # triple-quoted strings or parenthesized expressions.
825 # triple-quoted strings or parenthesized expressions.
832 #
826 #
833 # The last heuristic, while ugly, ensures that the first line of an
827 # The last heuristic, while ugly, ensures that the first line of an
834 # indented block is correctly transformed.
828 # indented block is correctly transformed.
835 #
829 #
836 # FIXME: try to find a cleaner approach for this last bit.
830 # FIXME: try to find a cleaner approach for this last bit.
837
831
838 # If we were in 'block' mode, since we're going to pump the parent
832 # If we were in 'block' mode, since we're going to pump the parent
839 # class by hand line by line, we need to temporarily switch out to
833 # class by hand line by line, we need to temporarily switch out to
840 # 'line' mode, do a single manual reset and then feed the lines one
834 # 'line' mode, do a single manual reset and then feed the lines one
841 # by one. Note that this only matters if the input has more than one
835 # by one. Note that this only matters if the input has more than one
842 # line.
836 # line.
843 changed_input_mode = False
837 changed_input_mode = False
844
838
845 if self.input_mode == 'cell':
839 if self.input_mode == 'cell':
846 self.reset()
840 self.reset()
847 changed_input_mode = True
841 changed_input_mode = True
848 saved_input_mode = 'cell'
842 saved_input_mode = 'cell'
849 self.input_mode = 'line'
843 self.input_mode = 'line'
850
844
851 # Store raw source before applying any transformations to it. Note
845 # Store raw source before applying any transformations to it. Note
852 # that this must be done *after* the reset() call that would otherwise
846 # that this must be done *after* the reset() call that would otherwise
853 # flush the buffer.
847 # flush the buffer.
854 self._store(lines, self._buffer_raw, 'source_raw')
848 self._store(lines, self._buffer_raw, 'source_raw')
855
849
856 try:
850 try:
857 push = super(IPythonInputSplitter, self).push
851 push = super(IPythonInputSplitter, self).push
858 for line in lines_list:
852 for line in lines_list:
859 if self._is_complete or not self._buffer or \
853 if self._is_complete or not self._buffer or \
860 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
854 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
861 for f in transforms:
855 for f in transforms:
862 line = f(line)
856 line = f(line)
863
857
864 out = push(line)
858 out = push(line)
865 finally:
859 finally:
866 if changed_input_mode:
860 if changed_input_mode:
867 self.input_mode = saved_input_mode
861 self.input_mode = saved_input_mode
868 return out
862 return out
General Comments 0
You need to be logged in to leave comments. Login now