Show More
@@ -141,6 +141,7 b' def num_ini_spaces(s):' | |||||
141 | else: |
|
141 | else: | |
142 | return 0 |
|
142 | return 0 | |
143 |
|
143 | |||
|
144 | last_blank_re = re.compile(r'^.*\n\s+$', re.MULTILINE) | |||
144 |
|
145 | |||
145 | def last_blank(src): |
|
146 | def last_blank(src): | |
146 | """Determine if the input source ends in a blank. |
|
147 | """Determine if the input source ends in a blank. | |
@@ -152,9 +153,22 b' def last_blank(src):' | |||||
152 | src : string |
|
153 | src : string | |
153 | A single or multiline string. |
|
154 | A single or multiline string. | |
154 | """ |
|
155 | """ | |
155 | if not src: return False |
|
156 | return src == '\n' or bool(last_blank_re.match(src)) | |
156 | ll = src.splitlines()[-1] |
|
157 | ||
157 | return (ll == '') or ll.isspace() |
|
158 | ||
|
159 | last_two_blanks_re = re.compile(r'^.*\n\s*\n\s*$', re.MULTILINE) | |||
|
160 | ||||
|
161 | def last_two_blanks(src): | |||
|
162 | """Determine if the input source ends in two blanks. | |||
|
163 | ||||
|
164 | A blank is either a newline or a line consisting of whitespace. | |||
|
165 | ||||
|
166 | Parameters | |||
|
167 | ---------- | |||
|
168 | src : string | |||
|
169 | A single or multiline string. | |||
|
170 | """ | |||
|
171 | return bool(last_two_blanks_re.match(src)) | |||
158 |
|
172 | |||
159 |
|
173 | |||
160 | def remove_comments(src): |
|
174 | def remove_comments(src): | |
@@ -820,6 +834,76 b' class IPythonInputSplitter(InputSplitter):' | |||||
820 | out = push(line) |
|
834 | out = push(line) | |
821 | return out |
|
835 | return out | |
822 |
|
836 | |||
|
837 | ||||
|
838 | def _push_cell_mode(self, lines): | |||
|
839 | """Push in cell mode. | |||
|
840 | ||||
|
841 | This means that we get the entire cell with each call. Between resets, | |||
|
842 | the calls simply add more text to the input.""" | |||
|
843 | ||||
|
844 | if lines.startswith('%%'): | |||
|
845 | # Cell magics bypass all further transformations | |||
|
846 | self.cell_magic_mode = True | |||
|
847 | first, _, body = lines.partition('\n') | |||
|
848 | magic_name, _, line = first.partition(' ') | |||
|
849 | magic_name = magic_name.lstrip(ESC_MAGIC) | |||
|
850 | # We store the body of the cell and create a call to a method that | |||
|
851 | # will use this stored value. This is ugly, but it's a first cut to | |||
|
852 | # get it all working, as right now changing the return API of our | |||
|
853 | # methods would require major refactoring. | |||
|
854 | self.cell_magic_parts = [body] | |||
|
855 | tpl = 'get_ipython()._cell_magic(%r, %r)' | |||
|
856 | tlines = tpl % (magic_name, line) | |||
|
857 | self._store(tlines) | |||
|
858 | self._store(lines, self._buffer_raw, 'source_raw') | |||
|
859 | self._is_complete = last_two_blanks(lines) | |||
|
860 | return self._is_complete | |||
|
861 | ||||
|
862 | lines_list = lines.splitlines() | |||
|
863 | ||||
|
864 | transforms = [transform_ipy_prompt, transform_classic_prompt, | |||
|
865 | transform_help_end, transform_escaped, | |||
|
866 | transform_assign_system, transform_assign_magic] | |||
|
867 | ||||
|
868 | # Transform logic | |||
|
869 | # | |||
|
870 | # We only apply the line transformers to the input if we have either no | |||
|
871 | # input yet, or complete input, or if the last line of the buffer ends | |||
|
872 | # with ':' (opening an indented block). This prevents the accidental | |||
|
873 | # transformation of escapes inside multiline expressions like | |||
|
874 | # triple-quoted strings or parenthesized expressions. | |||
|
875 | # | |||
|
876 | # The last heuristic, while ugly, ensures that the first line of an | |||
|
877 | # indented block is correctly transformed. | |||
|
878 | # | |||
|
879 | # FIXME: try to find a cleaner approach for this last bit. | |||
|
880 | ||||
|
881 | # In cell mode, since we're going to pump the parent class by hand line | |||
|
882 | # by line, we need to temporarily switch out to 'line' mode, do a | |||
|
883 | # single manual reset and then feed the lines one by one. Note that | |||
|
884 | # this only matters if the input has more than one line. | |||
|
885 | self.reset() | |||
|
886 | self.input_mode = 'line' | |||
|
887 | ||||
|
888 | # Store raw source before applying any transformations to it. Note | |||
|
889 | # that this must be done *after* the reset() call that would otherwise | |||
|
890 | # flush the buffer. | |||
|
891 | self._store(lines, self._buffer_raw, 'source_raw') | |||
|
892 | ||||
|
893 | try: | |||
|
894 | push = super(IPythonInputSplitter, self).push | |||
|
895 | buf = self._buffer | |||
|
896 | for line in lines_list: | |||
|
897 | if self._is_complete or not buf or \ | |||
|
898 | (buf and buf[-1].rstrip().endswith((':', ','))): | |||
|
899 | for f in transforms: | |||
|
900 | line = f(line) | |||
|
901 | ||||
|
902 | out = push(line) | |||
|
903 | finally: | |||
|
904 | self.input_mode = 'cell' | |||
|
905 | return out | |||
|
906 | ||||
823 | def push(self, lines): |
|
907 | def push(self, lines): | |
824 | """Push one or more lines of IPython input. |
|
908 | """Push one or more lines of IPython input. | |
825 |
|
909 | |||
@@ -843,8 +927,6 b' class IPythonInputSplitter(InputSplitter):' | |||||
843 | this value is also stored as a private attribute (_is_complete), so it |
|
927 | this value is also stored as a private attribute (_is_complete), so it | |
844 | can be queried at any time. |
|
928 | can be queried at any time. | |
845 | """ |
|
929 | """ | |
846 | print('mode:', self.input_mode) |
|
|||
847 | print('lines:',repr(lines)) |
|
|||
848 | if not lines: |
|
930 | if not lines: | |
849 | return super(IPythonInputSplitter, self).push(lines) |
|
931 | return super(IPythonInputSplitter, self).push(lines) | |
850 |
|
932 | |||
@@ -853,9 +935,8 b' class IPythonInputSplitter(InputSplitter):' | |||||
853 |
|
935 | |||
854 | if self.input_mode == 'line': |
|
936 | if self.input_mode == 'line': | |
855 | return self._push_line_mode(lines) |
|
937 | return self._push_line_mode(lines) | |
856 |
|
938 | else: | ||
857 | ## else: |
|
939 | return self._push_cell_mode(lines) | |
858 | ## return self._push_cell_mode(lines) |
|
|||
859 |
|
940 | |||
860 | lines_list = lines.splitlines() |
|
941 | lines_list = lines.splitlines() | |
861 |
|
942 |
@@ -604,12 +604,27 b' def test_last_blank():' | |||||
604 | nt.assert_false(isp.last_blank('abc')) |
|
604 | nt.assert_false(isp.last_blank('abc')) | |
605 | nt.assert_false(isp.last_blank('abc\n')) |
|
605 | nt.assert_false(isp.last_blank('abc\n')) | |
606 | nt.assert_false(isp.last_blank('abc\na')) |
|
606 | nt.assert_false(isp.last_blank('abc\na')) | |
|
607 | ||||
607 | nt.assert_true(isp.last_blank('\n')) |
|
608 | nt.assert_true(isp.last_blank('\n')) | |
608 | nt.assert_true(isp.last_blank('\n ')) |
|
609 | nt.assert_true(isp.last_blank('\n ')) | |
609 | nt.assert_true(isp.last_blank('abc\n ')) |
|
610 | nt.assert_true(isp.last_blank('abc\n ')) | |
610 | nt.assert_true(isp.last_blank('abc\n\n')) |
|
611 | nt.assert_true(isp.last_blank('abc\n\n')) | |
611 |
|
612 | |||
612 |
|
613 | |||
|
614 | def test_last_two_blanks(): | |||
|
615 | nt.assert_false(isp.last_two_blanks('')) | |||
|
616 | nt.assert_false(isp.last_two_blanks('abc')) | |||
|
617 | nt.assert_false(isp.last_two_blanks('abc\n')) | |||
|
618 | nt.assert_false(isp.last_two_blanks('abc\n\na')) | |||
|
619 | ||||
|
620 | nt.assert_true(isp.last_two_blanks('\n\n')) | |||
|
621 | nt.assert_true(isp.last_two_blanks('\n\n ')) | |||
|
622 | nt.assert_true(isp.last_two_blanks('\n \n')) | |||
|
623 | nt.assert_true(isp.last_two_blanks('abc\n \n')) | |||
|
624 | nt.assert_true(isp.last_two_blanks('abc\n\n ')) | |||
|
625 | nt.assert_true(isp.last_two_blanks('abc\n\n')) | |||
|
626 | ||||
|
627 | ||||
613 | def test_cell_magics(): |
|
628 | def test_cell_magics(): | |
614 | from IPython.core import magic |
|
629 | from IPython.core import magic | |
615 |
|
630 |
General Comments 0
You need to be logged in to leave comments.
Login now