Show More
@@ -71,7 +71,6 b' import sys' | |||||
71 |
|
71 | |||
72 | # IPython modules |
|
72 | # IPython modules | |
73 | from IPython.utils.text import make_quoted_expr |
|
73 | from IPython.utils.text import make_quoted_expr | |
74 |
|
||||
75 | #----------------------------------------------------------------------------- |
|
74 | #----------------------------------------------------------------------------- | |
76 | # Globals |
|
75 | # Globals | |
77 | #----------------------------------------------------------------------------- |
|
76 | #----------------------------------------------------------------------------- | |
@@ -223,7 +222,7 b' class InputSplitter(object):' | |||||
223 | ---------- |
|
222 | ---------- | |
224 | input_mode : str |
|
223 | input_mode : str | |
225 |
|
224 | |||
226 |
One of 'append', 'replace' |
|
225 | One of ['append', 'replace']; default is 'append'. This controls how | |
227 | new inputs are used: in 'append' mode, they are appended to the |
|
226 | new inputs are used: in 'append' mode, they are appended to the | |
228 | existing buffer and the whole buffer is compiled; in 'replace' mode, |
|
227 | existing buffer and the whole buffer is compiled; in 'replace' mode, | |
229 | each new input completely replaces all prior inputs. Replace mode is |
|
228 | each new input completely replaces all prior inputs. Replace mode is | |
@@ -680,8 +679,10 b' def transform_ipy_prompt(line):' | |||||
680 |
|
679 | |||
681 | if not line or line.isspace(): |
|
680 | if not line or line.isspace(): | |
682 | return line |
|
681 | return line | |
|
682 | #print 'LINE: %r' % line # dbg | |||
683 | m = _ipy_prompt_re.match(line) |
|
683 | m = _ipy_prompt_re.match(line) | |
684 | if m: |
|
684 | if m: | |
|
685 | #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg | |||
685 | return line[len(m.group(0)):] |
|
686 | return line[len(m.group(0)):] | |
686 | else: |
|
687 | else: | |
687 | return line |
|
688 | return line | |
@@ -828,12 +829,30 b' class IPythonInputSplitter(InputSplitter):' | |||||
828 | # |
|
829 | # | |
829 | # FIXME: try to find a cleaner approach for this last bit. |
|
830 | # FIXME: try to find a cleaner approach for this last bit. | |
830 |
|
831 | |||
831 | for line in lines_list: |
|
832 | # If we were in 'replace' mode, since we're going to pump the parent | |
832 | if self._is_complete or not self._buffer or \ |
|
833 | # class by hand line by line, we need to temporarily switch out to | |
833 | (self._buffer and self._buffer[-1].rstrip().endswith(':')): |
|
834 | # 'append' mode, do a single manual reset and then feed the lines one | |
834 | for f in transforms: |
|
835 | # by one. Note that this only matters if the input has more than one | |
835 | line = f(line) |
|
836 | # line. | |
836 |
|
837 | changed_input_mode = False | ||
837 | out = super(IPythonInputSplitter, self).push(line) |
|
838 | ||
|
839 | if len(lines_list)>1 and self.input_mode == 'replace': | |||
|
840 | self.reset() | |||
|
841 | changed_input_mode = True | |||
|
842 | saved_input_mode = 'replace' | |||
|
843 | self.input_mode = 'append' | |||
838 |
|
844 | |||
|
845 | try: | |||
|
846 | push = super(IPythonInputSplitter, self).push | |||
|
847 | for line in lines_list: | |||
|
848 | if self._is_complete or not self._buffer or \ | |||
|
849 | (self._buffer and self._buffer[-1].rstrip().endswith(':')): | |||
|
850 | for f in transforms: | |||
|
851 | line = f(line) | |||
|
852 | ||||
|
853 | out = push(line) | |||
|
854 | finally: | |||
|
855 | if changed_input_mode: | |||
|
856 | self.input_mode = saved_input_mode | |||
|
857 | ||||
839 | return out |
|
858 | return out |
@@ -411,13 +411,15 b' syntax = \\' | |||||
411 | classic_prompt = |
|
411 | classic_prompt = | |
412 | [('>>> x=1', 'x=1'), |
|
412 | [('>>> x=1', 'x=1'), | |
413 | ('x=1', 'x=1'), # normal input is unmodified |
|
413 | ('x=1', 'x=1'), # normal input is unmodified | |
414 | (' ',' '), # blank lines are kept intact |
|
414 | (' ', ' '), # blank lines are kept intact | |
|
415 | ('... ', ''), # continuation prompts | |||
415 | ], |
|
416 | ], | |
416 |
|
417 | |||
417 | ipy_prompt = |
|
418 | ipy_prompt = | |
418 | [('In [1]: x=1', 'x=1'), |
|
419 | [('In [1]: x=1', 'x=1'), | |
419 | ('x=1', 'x=1'), # normal input is unmodified |
|
420 | ('x=1', 'x=1'), # normal input is unmodified | |
420 | (' ',' '), # blank lines are kept intact |
|
421 | (' ',' '), # blank lines are kept intact | |
|
422 | (' ....: ', ''), # continuation prompts | |||
421 | ], |
|
423 | ], | |
422 |
|
424 | |||
423 | # Tests for the escape transformer to leave normal code alone |
|
425 | # Tests for the escape transformer to leave normal code alone | |
@@ -474,9 +476,6 b' syntax = \\' | |||||
474 | ('/f a b', 'f(a, b)'), |
|
476 | ('/f a b', 'f(a, b)'), | |
475 | ], |
|
477 | ], | |
476 |
|
478 | |||
477 | # More complex multiline tests |
|
|||
478 | ## escaped_multiline = |
|
|||
479 | ## [()], |
|
|||
480 | ) |
|
479 | ) | |
481 |
|
480 | |||
482 | # multiline syntax examples. Each of these should be a list of lists, with |
|
481 | # multiline syntax examples. Each of these should be a list of lists, with | |
@@ -555,8 +554,9 b' class IPythonInputTestCase(InputSplitterTestCase):' | |||||
555 | In addition, this runs the tests over the syntax and syntax_ml dicts that |
|
554 | In addition, this runs the tests over the syntax and syntax_ml dicts that | |
556 | were tested by individual functions, as part of the OO interface. |
|
555 | were tested by individual functions, as part of the OO interface. | |
557 | """ |
|
556 | """ | |
|
557 | ||||
558 | def setUp(self): |
|
558 | def setUp(self): | |
559 | self.isp = isp.IPythonInputSplitter() |
|
559 | self.isp = isp.IPythonInputSplitter(input_mode='append') | |
560 |
|
560 | |||
561 | def test_syntax(self): |
|
561 | def test_syntax(self): | |
562 | """Call all single-line syntax tests from the main object""" |
|
562 | """Call all single-line syntax tests from the main object""" | |
@@ -569,7 +569,7 b' class IPythonInputTestCase(InputSplitterTestCase):' | |||||
569 | isp.push(raw) |
|
569 | isp.push(raw) | |
570 | out = isp.source_reset().rstrip() |
|
570 | out = isp.source_reset().rstrip() | |
571 | self.assertEqual(out, out_t) |
|
571 | self.assertEqual(out, out_t) | |
572 |
|
572 | |||
573 | def test_syntax_multiline(self): |
|
573 | def test_syntax_multiline(self): | |
574 | isp = self.isp |
|
574 | isp = self.isp | |
575 | for example in syntax_ml.itervalues(): |
|
575 | for example in syntax_ml.itervalues(): | |
@@ -583,15 +583,41 b' class IPythonInputTestCase(InputSplitterTestCase):' | |||||
583 | out_t = '\n'.join(out_t_parts).rstrip() |
|
583 | out_t = '\n'.join(out_t_parts).rstrip() | |
584 | self.assertEqual(out, out_t) |
|
584 | self.assertEqual(out, out_t) | |
585 |
|
585 | |||
586 |
|
586 | |||
|
587 | class BlockIPythonInputTestCase(IPythonInputTestCase): | |||
|
588 | ||||
|
589 | # Deactivate tests that don't make sense for the block mode | |||
|
590 | test_push3 = test_split = lambda s: None | |||
|
591 | ||||
|
592 | def setUp(self): | |||
|
593 | self.isp = isp.IPythonInputSplitter(input_mode='replace') | |||
|
594 | ||||
|
595 | def test_syntax_multiline(self): | |||
|
596 | isp = self.isp | |||
|
597 | for example in syntax_ml.itervalues(): | |||
|
598 | raw_parts = [] | |||
|
599 | out_t_parts = [] | |||
|
600 | for line_pairs in example: | |||
|
601 | for raw, out_t_part in line_pairs: | |||
|
602 | raw_parts.append(raw) | |||
|
603 | out_t_parts.append(out_t_part) | |||
|
604 | ||||
|
605 | raw = '\n'.join(raw_parts) | |||
|
606 | out_t = '\n'.join(out_t_parts) | |||
|
607 | ||||
|
608 | isp.push(raw) | |||
|
609 | out = isp.source_reset() | |||
|
610 | # Match ignoring trailing whitespace | |||
|
611 | self.assertEqual(out.rstrip(), out_t.rstrip()) | |||
|
612 | ||||
|
613 | ||||
587 | #----------------------------------------------------------------------------- |
|
614 | #----------------------------------------------------------------------------- | |
588 | # Main - use as a script |
|
615 | # Main - use as a script, mostly for developer experiments | |
589 | #----------------------------------------------------------------------------- |
|
616 | #----------------------------------------------------------------------------- | |
590 |
|
617 | |||
591 | if __name__ == '__main__': |
|
618 | if __name__ == '__main__': | |
592 | # A simple demo for interactive experimentation. This code will not get |
|
619 | # A simple demo for interactive experimentation. This code will not get | |
593 |
# picked up by any test suite. |
|
620 | # picked up by any test suite. | |
594 | # development. |
|
|||
595 | from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter |
|
621 | from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter | |
596 |
|
622 | |||
597 | # configure here the syntax to use, prompt and whether to autoindent |
|
623 | # configure here the syntax to use, prompt and whether to autoindent |
@@ -60,7 +60,7 b' class IPythonWidget(FrontendWidget):' | |||||
60 | out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: ' |
|
60 | out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: ' | |
61 |
|
61 | |||
62 | # FrontendWidget protected class variables. |
|
62 | # FrontendWidget protected class variables. | |
63 |
|
|
63 | _input_splitter_class = IPythonInputSplitter | |
64 |
|
64 | |||
65 | # IPythonWidget protected class variables. |
|
65 | # IPythonWidget protected class variables. | |
66 | _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic' |
|
66 | _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic' |
General Comments 0
You need to be logged in to leave comments.
Login now