Show More
@@ -60,6 +60,7 b' Authors' | |||
|
60 | 60 | # Distributed under the terms of the BSD License. The full license is in |
|
61 | 61 | # the file COPYING, distributed as part of this software. |
|
62 | 62 | #----------------------------------------------------------------------------- |
|
63 | from __future__ import print_function | |
|
63 | 64 | |
|
64 | 65 | #----------------------------------------------------------------------------- |
|
65 | 66 | # Imports |
@@ -71,6 +72,7 b' import sys' | |||
|
71 | 72 | |
|
72 | 73 | # IPython modules |
|
73 | 74 | from IPython.utils.text import make_quoted_expr |
|
75 | ||
|
74 | 76 | #----------------------------------------------------------------------------- |
|
75 | 77 | # Globals |
|
76 | 78 | #----------------------------------------------------------------------------- |
@@ -81,14 +83,14 b' from IPython.utils.text import make_quoted_expr' | |||
|
81 | 83 | # for all intents and purposes they constitute the 'IPython syntax', so they |
|
82 | 84 | # should be considered fixed. |
|
83 | 85 | |
|
84 | ESC_SHELL = '!' | |
|
85 | ESC_SH_CAP = '!!' | |
|
86 | ESC_HELP = '?' | |
|
87 | ESC_HELP2 = '??' | |
|
88 | ESC_MAGIC = '%' | |
|
89 | ESC_QUOTE = ',' | |
|
90 | ESC_QUOTE2 = ';' | |
|
91 | ESC_PAREN = '/' | |
|
86 | ESC_SHELL = '!' # Send line to underlying system shell | |
|
87 | ESC_SH_CAP = '!!' # Send line to system shell and capture output | |
|
88 | ESC_HELP = '?' # Find information about object | |
|
89 | ESC_HELP2 = '??' # Find extra-detailed information about object | |
|
90 | ESC_MAGIC = '%' # Call magic function | |
|
91 | ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call | |
|
92 | ESC_QUOTE2 = ';' # Quote all args as a single string, call | |
|
93 | ESC_PAREN = '/' # Call first argument with rest of line as arguments | |
|
92 | 94 | |
|
93 | 95 | #----------------------------------------------------------------------------- |
|
94 | 96 | # Utilities |
@@ -308,7 +310,7 b' class InputSplitter(object):' | |||
|
308 | 310 | ---------- |
|
309 | 311 | input_mode : str |
|
310 | 312 | |
|
311 |
One of ['line', ' |
|
|
313 | One of ['line', 'cell']; default is 'line'. | |
|
312 | 314 | |
|
313 | 315 | The input_mode parameter controls how new inputs are used when fed via |
|
314 | 316 | the :meth:`push` method: |
@@ -316,10 +318,11 b' class InputSplitter(object):' | |||
|
316 | 318 | - 'line': meant for line-oriented clients, inputs are appended one at a |
|
317 | 319 | time to the internal buffer and the whole buffer is compiled. |
|
318 | 320 | |
|
319 |
- ' |
|
|
320 | a time. Each new input new input completely replaces all prior | |
|
321 | inputs. Block mode is thus equivalent to prepending a full reset() | |
|
322 | to every push() call. | |
|
321 | - 'cell': meant for clients that can edit multi-line 'cells' of text at | |
|
322 | a time. A cell can contain one or more blocks that can be compile in | |
|
323 | 'single' mode by Python. In this mode, each new input new input | |
|
324 | completely replaces all prior inputs. Cell mode is thus equivalent | |
|
325 | to prepending a full reset() to every push() call. | |
|
323 | 326 | """ |
|
324 | 327 | self._buffer = [] |
|
325 | 328 | self._compile = codeop.CommandCompiler() |
@@ -365,7 +368,7 b' class InputSplitter(object):' | |||
|
365 | 368 | this value is also stored as a private attribute (_is_complete), so it |
|
366 | 369 | can be queried at any time. |
|
367 | 370 | """ |
|
368 |
if self.input_mode == ' |
|
|
371 | if self.input_mode == 'cell': | |
|
369 | 372 | self.reset() |
|
370 | 373 | |
|
371 | 374 | # If the source code has leading blanks, add 'if 1:\n' to it |
@@ -433,13 +436,31 b' class InputSplitter(object):' | |||
|
433 | 436 | backend which might convert the invalid syntax into valid Python via |
|
434 | 437 | one of the dynamic IPython mechanisms. |
|
435 | 438 | """ |
|
436 | ||
|
439 | ||
|
440 | # With incomplete input, unconditionally accept more | |
|
437 | 441 | if not self._is_complete: |
|
438 | 442 | return True |
|
439 | 443 | |
|
444 | # If we already have complete input and we're flush left, the answer | |
|
445 | # depends. In line mode, we're done. But in cell mode, we need to | |
|
446 | # check how many blocks the input so far compiles into, because if | |
|
447 | # there's already more than one full independent block of input, then | |
|
448 | # the client has entered full 'cell' mode and is feeding lines that | |
|
449 | # each is complete. In this case we should then keep accepting. | |
|
450 | # The Qt terminal-like console does precisely this, to provide the | |
|
451 | # convenience of terminal-like input of single expressions, but | |
|
452 | # allowing the user (with a separate keystroke) to switch to 'cell' | |
|
453 | # mode and type multiple expressions in one shot. | |
|
440 | 454 | if self.indent_spaces==0: |
|
441 | return False | |
|
442 | ||
|
455 | if self.input_mode=='line': | |
|
456 | return False | |
|
457 | else: | |
|
458 | nblocks = len(split_blocks(''.join(self._buffer))) | |
|
459 | if nblocks==1: | |
|
460 | return False | |
|
461 | ||
|
462 | # When input is complete, then termination is marked by an extra blank | |
|
463 | # line at the end. | |
|
443 | 464 | last_line = self.source.splitlines()[-1] |
|
444 | 465 | return bool(last_line and not last_line.isspace()) |
|
445 | 466 | |
@@ -934,10 +955,10 b' class IPythonInputSplitter(InputSplitter):' | |||
|
934 | 955 | # line. |
|
935 | 956 | changed_input_mode = False |
|
936 | 957 | |
|
937 |
if len(lines_list)>1 and self.input_mode == ' |
|
|
958 | if len(lines_list)>1 and self.input_mode == 'cell': | |
|
938 | 959 | self.reset() |
|
939 | 960 | changed_input_mode = True |
|
940 |
saved_input_mode = ' |
|
|
961 | saved_input_mode = 'cell' | |
|
941 | 962 | self.input_mode = 'line' |
|
942 | 963 | |
|
943 | 964 | try: |
@@ -204,7 +204,7 b' class InputSplitterTestCase(unittest.TestCase):' | |||
|
204 | 204 | |
|
205 | 205 | def test_replace_mode(self): |
|
206 | 206 | isp = self.isp |
|
207 |
isp.input_mode = ' |
|
|
207 | isp.input_mode = 'cell' | |
|
208 | 208 | isp.push('x=1') |
|
209 | 209 | self.assertEqual(isp.source, 'x=1\n') |
|
210 | 210 | isp.push('x=2') |
@@ -591,7 +591,7 b' class BlockIPythonInputTestCase(IPythonInputTestCase):' | |||
|
591 | 591 | test_push3 = test_split = lambda s: None |
|
592 | 592 | |
|
593 | 593 | def setUp(self): |
|
594 |
self.isp = isp.IPythonInputSplitter(input_mode=' |
|
|
594 | self.isp = isp.IPythonInputSplitter(input_mode='cell') | |
|
595 | 595 | |
|
596 | 596 | def test_syntax_multiline(self): |
|
597 | 597 | isp = self.isp |
@@ -363,6 +363,11 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
363 | 363 | # disable the undo/redo history, but just to be safe: |
|
364 | 364 | self._control.setUndoRedoEnabled(False) |
|
365 | 365 | |
|
366 | # Flush all state from the input splitter so the next round of | |
|
367 | # reading input starts with a clean buffer. | |
|
368 | self._input_splitter.reset() | |
|
369 | ||
|
370 | # Call actual execution | |
|
366 | 371 | self._execute(source, hidden) |
|
367 | 372 | |
|
368 | 373 | else: |
@@ -1,3 +1,5 b'' | |||
|
1 | from __future__ import print_function | |
|
2 | ||
|
1 | 3 | # Standard library imports |
|
2 | 4 | from collections import namedtuple |
|
3 | 5 | import signal |
@@ -114,7 +116,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||
|
114 | 116 | self._copy_raw_action = QtGui.QAction('Copy (Raw Text)', None) |
|
115 | 117 | self._hidden = False |
|
116 | 118 | self._highlighter = FrontendHighlighter(self) |
|
117 |
self._input_splitter = self._input_splitter_class(input_mode=' |
|
|
119 | self._input_splitter = self._input_splitter_class(input_mode='cell') | |
|
118 | 120 | self._kernel_manager = None |
|
119 | 121 | self._possible_kernel_restart = False |
|
120 | 122 | self._request_info = {} |
@@ -236,6 +238,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||
|
236 | 238 | """ Reimplemented for auto-indentation. |
|
237 | 239 | """ |
|
238 | 240 | super(FrontendWidget, self)._insert_continuation_prompt(cursor) |
|
241 | #print('SPACES:', self._input_splitter.indent_spaces) # dbg | |
|
239 | 242 | spaces = self._input_splitter.indent_spaces |
|
240 | 243 | cursor.insertText('\t' * (spaces / self.tab_width)) |
|
241 | 244 | cursor.insertText(' ' * (spaces % self.tab_width)) |
General Comments 0
You need to be logged in to leave comments.
Login now