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