Show More
@@ -61,6 +61,7 b' used, and this module (and the readline module) are silently inactive.' | |||||
61 | # the file COPYING, distributed as part of this software. |
|
61 | # the file COPYING, distributed as part of this software. | |
62 | # |
|
62 | # | |
63 | #***************************************************************************** |
|
63 | #***************************************************************************** | |
|
64 | from __future__ import print_function | |||
64 |
|
65 | |||
65 | #----------------------------------------------------------------------------- |
|
66 | #----------------------------------------------------------------------------- | |
66 | # Imports |
|
67 | # Imports | |
@@ -79,7 +80,7 b' import sys' | |||||
79 |
|
80 | |||
80 | from IPython.core.error import TryNext |
|
81 | from IPython.core.error import TryNext | |
81 | from IPython.core.prefilter import ESC_MAGIC |
|
82 | from IPython.core.prefilter import ESC_MAGIC | |
82 | from IPython.utils import generics |
|
83 | from IPython.utils import generics, io | |
83 | from IPython.utils.frame import debugx |
|
84 | from IPython.utils.frame import debugx | |
84 | from IPython.utils.dir2 import dir2 |
|
85 | from IPython.utils.dir2 import dir2 | |
85 |
|
86 | |||
@@ -138,10 +139,61 b' def single_dir_expand(matches):' | |||||
138 | else: |
|
139 | else: | |
139 | return matches |
|
140 | return matches | |
140 |
|
141 | |||
141 | class Bunch: pass |
|
|||
142 |
|
142 | |||
143 | class Completer: |
|
143 | class Bunch(object): pass | |
144 | def __init__(self,namespace=None,global_namespace=None): |
|
144 | ||
|
145 | ||||
|
146 | class CompletionSplitter(object): | |||
|
147 | """An object to split an input line in a manner similar to readline. | |||
|
148 | ||||
|
149 | By having our own implementation, we can expose readline-like completion in | |||
|
150 | a uniform manner to all frontends. This object only needs to be given the | |||
|
151 | line of text to be split and the cursor position on said line, and it | |||
|
152 | returns the 'word' to be completed on at the cursor after splitting the | |||
|
153 | entire line. | |||
|
154 | ||||
|
155 | What characters are used as splitting delimiters can be controlled by | |||
|
156 | setting the `delims` attribute (this is a property that internally | |||
|
157 | automatically builds the necessary """ | |||
|
158 | ||||
|
159 | # Private interface | |||
|
160 | ||||
|
161 | # A string of delimiter characters. The default value makes sense for | |||
|
162 | # IPython's most typical usage patterns. | |||
|
163 | _delims = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' | |||
|
164 | ||||
|
165 | # The expression (a normal string) to be compiled into a regular expression | |||
|
166 | # for actual splitting. We store it as an attribute mostly for ease of | |||
|
167 | # debugging, since this type of code can be so tricky to debug. | |||
|
168 | _delim_expr = None | |||
|
169 | ||||
|
170 | # The regular expression that does the actual splitting | |||
|
171 | _delim_re = None | |||
|
172 | ||||
|
173 | def __init__(self, delims=None): | |||
|
174 | delims = CompletionSplitter._delims if delims is None else delims | |||
|
175 | self.set_delims(delims) | |||
|
176 | ||||
|
177 | def set_delims(self, delims): | |||
|
178 | """Set the delimiters for line splitting.""" | |||
|
179 | expr = '[' + ''.join('\\'+ c for c in delims) + ']' | |||
|
180 | self._delim_re = re.compile(expr) | |||
|
181 | self._delims = delims | |||
|
182 | self._delim_expr = expr | |||
|
183 | ||||
|
184 | def get_delims(self): | |||
|
185 | """Return the string of delimiter characters.""" | |||
|
186 | return self._delims | |||
|
187 | ||||
|
188 | def split_line(self, line, cursor_pos=None): | |||
|
189 | """Split a line of text with a cursor at the given position. | |||
|
190 | """ | |||
|
191 | l = line if cursor_pos is None else line[:cursor_pos] | |||
|
192 | return self._delim_re.split(l)[-1] | |||
|
193 | ||||
|
194 | ||||
|
195 | class Completer(object): | |||
|
196 | def __init__(self, namespace=None, global_namespace=None): | |||
145 | """Create a new completer for the command line. |
|
197 | """Create a new completer for the command line. | |
146 |
|
198 | |||
147 | Completer([namespace,global_namespace]) -> completer instance. |
|
199 | Completer([namespace,global_namespace]) -> completer instance. | |
@@ -291,10 +343,12 b' class IPCompleter(Completer):' | |||||
291 | without readline, though in that case callers must provide some extra |
|
343 | without readline, though in that case callers must provide some extra | |
292 | information on each call about the current line.""" |
|
344 | information on each call about the current line.""" | |
293 |
|
345 | |||
294 | Completer.__init__(self,namespace,global_namespace) |
|
346 | Completer.__init__(self, namespace, global_namespace) | |
295 |
|
347 | |||
296 | self.magic_escape = ESC_MAGIC |
|
348 | self.magic_escape = ESC_MAGIC | |
297 |
|
349 | |||
|
350 | self.splitter = CompletionSplitter() | |||
|
351 | ||||
298 | # Readline-dependent code |
|
352 | # Readline-dependent code | |
299 | self.use_readline = use_readline |
|
353 | self.use_readline = use_readline | |
300 | if use_readline: |
|
354 | if use_readline: | |
@@ -610,16 +664,20 b' class IPCompleter(Completer):' | |||||
610 |
|
664 | |||
611 | return None |
|
665 | return None | |
612 |
|
666 | |||
613 | def complete(self, text, line_buffer, cursor_pos=None): |
|
667 | def complete(self, text=None, line_buffer=None, cursor_pos=None): | |
614 | """Return the state-th possible completion for 'text'. |
|
668 | """Return the state-th possible completion for 'text'. | |
615 |
|
669 | |||
616 | This is called successively with state == 0, 1, 2, ... until it |
|
670 | This is called successively with state == 0, 1, 2, ... until it | |
617 | returns None. The completion should begin with 'text'. |
|
671 | returns None. The completion should begin with 'text'. | |
618 |
|
672 | |||
|
673 | Note that both the text and the line_buffer are optional, but at least | |||
|
674 | one of them must be given. | |||
|
675 | ||||
619 | Parameters |
|
676 | Parameters | |
620 | ---------- |
|
677 | ---------- | |
621 | text : string |
|
678 | text : string, optional | |
622 | Text to perform the completion on. |
|
679 | Text to perform the completion on. If not given, the line buffer | |
|
680 | is split using the instance's CompletionSplitter object. | |||
623 |
|
681 | |||
624 | line_buffer : string, optional |
|
682 | line_buffer : string, optional | |
625 | If not given, the completer attempts to obtain the current line |
|
683 | If not given, the completer attempts to obtain the current line | |
@@ -631,7 +689,21 b' class IPCompleter(Completer):' | |||||
631 | Index of the cursor in the full line buffer. Should be provided by |
|
689 | Index of the cursor in the full line buffer. Should be provided by | |
632 | remote frontends where kernel has no access to frontend state. |
|
690 | remote frontends where kernel has no access to frontend state. | |
633 | """ |
|
691 | """ | |
|
692 | #io.rprint('COMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg | |||
|
693 | ||||
|
694 | # if the cursor position isn't given, the only sane assumption we can | |||
|
695 | # make is that it's at the end of the line (the common case) | |||
|
696 | if cursor_pos is None: | |||
|
697 | cursor_pos = len(line_buffer) if text is None else len(text) | |||
|
698 | ||||
|
699 | # if text is either None or an empty string, rely on the line buffer | |||
|
700 | if not text: | |||
|
701 | text = self.splitter.split_line(line_buffer, cursor_pos) | |||
634 |
|
702 | |||
|
703 | # If no line buffer is given, assume the input text is all there was | |||
|
704 | if line_buffer is None: | |||
|
705 | line_buffer = text | |||
|
706 | ||||
635 | magic_escape = self.magic_escape |
|
707 | magic_escape = self.magic_escape | |
636 | self.full_lbuf = line_buffer |
|
708 | self.full_lbuf = line_buffer | |
637 | self.lbuf = self.full_lbuf[:cursor_pos] |
|
709 | self.lbuf = self.full_lbuf[:cursor_pos] | |
@@ -639,6 +711,8 b' class IPCompleter(Completer):' | |||||
639 | if text.startswith('~'): |
|
711 | if text.startswith('~'): | |
640 | text = os.path.expanduser(text) |
|
712 | text = os.path.expanduser(text) | |
641 |
|
713 | |||
|
714 | #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg | |||
|
715 | ||||
642 | # Start with a clean slate of completions |
|
716 | # Start with a clean slate of completions | |
643 | self.matches[:] = [] |
|
717 | self.matches[:] = [] | |
644 | custom_res = self.dispatch_custom_completer(text) |
|
718 | custom_res = self.dispatch_custom_completer(text) | |
@@ -663,8 +737,8 b' class IPCompleter(Completer):' | |||||
663 | # simply collapse the dict into a list for readline, but we'd have |
|
737 | # simply collapse the dict into a list for readline, but we'd have | |
664 | # richer completion semantics in other evironments. |
|
738 | # richer completion semantics in other evironments. | |
665 | self.matches = sorted(set(self.matches)) |
|
739 | self.matches = sorted(set(self.matches)) | |
666 | #from IPython.utils.io import rprint; rprint(self.matches) # dbg |
|
740 | #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg | |
667 | return self.matches |
|
741 | return text, self.matches | |
668 |
|
742 | |||
669 | def rlcomplete(self, text, state): |
|
743 | def rlcomplete(self, text, state): | |
670 | """Return the state-th possible completion for 'text'. |
|
744 | """Return the state-th possible completion for 'text'. | |
@@ -679,15 +753,15 b' class IPCompleter(Completer):' | |||||
679 |
|
753 | |||
680 | state : int |
|
754 | state : int | |
681 | Counter used by readline. |
|
755 | Counter used by readline. | |
682 |
|
||||
683 | """ |
|
756 | """ | |
684 |
|
||||
685 | #print "rlcomplete! '%s' %s" % (text, state) # dbg |
|
|||
686 |
|
||||
687 | if state==0: |
|
757 | if state==0: | |
|
758 | ||||
688 | self.full_lbuf = line_buffer = self.get_line_buffer() |
|
759 | self.full_lbuf = line_buffer = self.get_line_buffer() | |
689 | cursor_pos = self.get_endidx() |
|
760 | cursor_pos = self.get_endidx() | |
690 |
|
761 | |||
|
762 | #io.rprint("\nRLCOMPLETE: %r %r %r" % | |||
|
763 | # (text, line_buffer, cursor_pos) ) # dbg | |||
|
764 | ||||
691 | # if there is only a tab on a line with only whitespace, instead of |
|
765 | # if there is only a tab on a line with only whitespace, instead of | |
692 | # the mostly useless 'do you want to see all million completions' |
|
766 | # the mostly useless 'do you want to see all million completions' | |
693 | # message, just do the right thing and give the user his tab! |
|
767 | # message, just do the right thing and give the user his tab! | |
@@ -699,7 +773,7 b' class IPCompleter(Completer):' | |||||
699 |
|
773 | |||
700 | # don't apply this on 'dumb' terminals, such as emacs buffers, so |
|
774 | # don't apply this on 'dumb' terminals, such as emacs buffers, so | |
701 | # we don't interfere with their own tab-completion mechanism. |
|
775 | # we don't interfere with their own tab-completion mechanism. | |
702 |
if not (self.dumb_terminal or |
|
776 | if not (self.dumb_terminal or line_buffer.strip()): | |
703 | self.readline.insert_text('\t') |
|
777 | self.readline.insert_text('\t') | |
704 | sys.stdout.flush() |
|
778 | sys.stdout.flush() | |
705 | return None |
|
779 | return None | |
@@ -719,4 +793,3 b' class IPCompleter(Completer):' | |||||
719 | return self.matches[state] |
|
793 | return self.matches[state] | |
720 | except IndexError: |
|
794 | except IndexError: | |
721 | return None |
|
795 | return None | |
722 |
|
@@ -1370,13 +1370,15 b' class InteractiveShell(Configurable, Magic):' | |||||
1370 | #------------------------------------------------------------------------- |
|
1370 | #------------------------------------------------------------------------- | |
1371 |
|
1371 | |||
1372 | def complete(self, text, line=None, cursor_pos=None): |
|
1372 | def complete(self, text, line=None, cursor_pos=None): | |
1373 |
"""Return |
|
1373 | """Return the completed text and a list of completions. | |
1374 |
|
1374 | |||
1375 | Parameters |
|
1375 | Parameters | |
1376 | ---------- |
|
1376 | ---------- | |
1377 |
|
1377 | |||
1378 | text : string |
|
1378 | text : string | |
1379 | A string of text to be completed on. |
|
1379 | A string of text to be completed on. It can be given as empty and | |
|
1380 | instead a line/position pair are given. In this case, the | |||
|
1381 | completer itself will split the line like readline does. | |||
1380 |
|
1382 | |||
1381 | line : string, optional |
|
1383 | line : string, optional | |
1382 | The complete line that text is part of. |
|
1384 | The complete line that text is part of. | |
@@ -1384,6 +1386,14 b' class InteractiveShell(Configurable, Magic):' | |||||
1384 | cursor_pos : int, optional |
|
1386 | cursor_pos : int, optional | |
1385 | The position of the cursor on the input line. |
|
1387 | The position of the cursor on the input line. | |
1386 |
|
1388 | |||
|
1389 | Returns | |||
|
1390 | ------- | |||
|
1391 | text : string | |||
|
1392 | The actual text that was completed. | |||
|
1393 | ||||
|
1394 | matches : list | |||
|
1395 | A sorted list with all possible completions. | |||
|
1396 | ||||
1387 | The optional arguments allow the completion to take more context into |
|
1397 | The optional arguments allow the completion to take more context into | |
1388 | account, and are part of the low-level completion API. |
|
1398 | account, and are part of the low-level completion API. | |
1389 |
|
1399 | |||
@@ -1394,23 +1404,17 b' class InteractiveShell(Configurable, Magic):' | |||||
1394 |
|
1404 | |||
1395 | Simple usage example: |
|
1405 | Simple usage example: | |
1396 |
|
1406 | |||
1397 |
In [ |
|
1407 | In [1]: x = 'hello' | |
1398 |
|
||||
1399 | In [8]: x |
|
|||
1400 | Out[8]: 'hello' |
|
|||
1401 |
|
||||
1402 | In [9]: print x |
|
|||
1403 | hello |
|
|||
1404 |
|
1408 | |||
1405 |
In [ |
|
1409 | In [2]: _ip.complete('x.l') | |
1406 |
Out[ |
|
1410 | Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip']) | |
1407 | """ |
|
1411 | """ | |
1408 |
|
1412 | |||
1409 | # Inject names into __builtin__ so we can complete on the added names. |
|
1413 | # Inject names into __builtin__ so we can complete on the added names. | |
1410 | with self.builtin_trap: |
|
1414 | with self.builtin_trap: | |
1411 |
return self.Completer.complete(text, |
|
1415 | return self.Completer.complete(text, line, cursor_pos) | |
1412 |
|
1416 | |||
1413 | def set_custom_completer(self,completer,pos=0): |
|
1417 | def set_custom_completer(self, completer, pos=0): | |
1414 | """Adds a new custom completer function. |
|
1418 | """Adds a new custom completer function. | |
1415 |
|
1419 | |||
1416 | The position argument (defaults to 0) is the index in the completers |
|
1420 | The position argument (defaults to 0) is the index in the completers |
@@ -6,6 +6,7 b'' | |||||
6 |
|
6 | |||
7 | # stdlib |
|
7 | # stdlib | |
8 | import sys |
|
8 | import sys | |
|
9 | import unittest | |||
9 |
|
10 | |||
10 | # third party |
|
11 | # third party | |
11 | import nose.tools as nt |
|
12 | import nose.tools as nt | |
@@ -33,3 +34,50 b' def test_protect_filename():' | |||||
33 | for s1, s2 in pairs: |
|
34 | for s1, s2 in pairs: | |
34 | s1p = completer.protect_filename(s1) |
|
35 | s1p = completer.protect_filename(s1) | |
35 | nt.assert_equals(s1p, s2) |
|
36 | nt.assert_equals(s1p, s2) | |
|
37 | ||||
|
38 | ||||
|
39 | def check_line_split(splitter, test_specs): | |||
|
40 | for part1, part2, split in test_specs: | |||
|
41 | cursor_pos = len(part1) | |||
|
42 | line = part1+part2 | |||
|
43 | out = splitter.split_line(line, cursor_pos) | |||
|
44 | nt.assert_equal(out, split) | |||
|
45 | ||||
|
46 | ||||
|
47 | def test_line_split(): | |||
|
48 | """Basice line splitter test with default specs.""" | |||
|
49 | sp = completer.CompletionSplitter() | |||
|
50 | # The format of the test specs is: part1, part2, expected answer. Parts 1 | |||
|
51 | # and 2 are joined into the 'line' sent to the splitter, as if the cursor | |||
|
52 | # was at the end of part1. So an empty part2 represents someone hitting | |||
|
53 | # tab at the end of the line, the most common case. | |||
|
54 | t = [('run some/scrip', '', 'some/scrip'), | |||
|
55 | ('run scripts/er', 'ror.py foo', 'scripts/er'), | |||
|
56 | ('echo $HOM', '', 'HOM'), | |||
|
57 | ('print sys.pa', '', 'sys.pa'), | |||
|
58 | ('print(sys.pa', '', 'sys.pa'), | |||
|
59 | ("execfile('scripts/er", '', 'scripts/er'), | |||
|
60 | ('a[x.', '', 'x.'), | |||
|
61 | ('a[x.', 'y', 'x.'), | |||
|
62 | ('cd "some_file/', '', 'some_file/'), | |||
|
63 | ] | |||
|
64 | check_line_split(sp, t) | |||
|
65 | ||||
|
66 | ||||
|
67 | class CompletionSplitterTestCase(unittest.TestCase): | |||
|
68 | def setUp(self): | |||
|
69 | self.sp = completer.CompletionSplitter() | |||
|
70 | ||||
|
71 | def test_delim_setting(self): | |||
|
72 | self.sp.set_delims(' ') | |||
|
73 | nt.assert_equal(self.sp.get_delims(), ' ') | |||
|
74 | nt.assert_equal(self.sp._delim_expr, '[\ ]') | |||
|
75 | ||||
|
76 | def test_spaces(self): | |||
|
77 | """Test with only spaces as split chars.""" | |||
|
78 | self.sp.delims = ' ' | |||
|
79 | t = [('foo', '', 'foo'), | |||
|
80 | ('run foo', '', 'foo'), | |||
|
81 | ('run foo', 'bar', 'foo'), | |||
|
82 | ] | |||
|
83 | check_line_split(self.sp, t) |
@@ -378,7 +378,14 b' class ConsoleWidget(QtGui.QWidget):' | |||||
378 | def reset_font(self): |
|
378 | def reset_font(self): | |
379 | """ Sets the font to the default fixed-width font for this platform. |
|
379 | """ Sets the font to the default fixed-width font for this platform. | |
380 | """ |
|
380 | """ | |
|
381 | # FIXME: font family and size should be configurable by the user. | |||
|
382 | ||||
381 | if sys.platform == 'win32': |
|
383 | if sys.platform == 'win32': | |
|
384 | # Fixme: we should test whether Consolas is available and use it | |||
|
385 | # first if it is. Consolas ships by default from Vista onwards, | |||
|
386 | # it's *vastly* more readable and prettier than Courier, and is | |||
|
387 | # often installed even on XP systems. So we should first check for | |||
|
388 | # it, and only fallback to Courier if absolutely necessary. | |||
382 | name = 'Courier' |
|
389 | name = 'Courier' | |
383 | elif sys.platform == 'darwin': |
|
390 | elif sys.platform == 'darwin': | |
384 | name = 'Monaco' |
|
391 | name = 'Monaco' |
@@ -197,7 +197,10 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
197 | cursor = self._get_cursor() |
|
197 | cursor = self._get_cursor() | |
198 | if rep['parent_header']['msg_id'] == self._complete_id and \ |
|
198 | if rep['parent_header']['msg_id'] == self._complete_id and \ | |
199 | cursor.position() == self._complete_pos: |
|
199 | cursor.position() == self._complete_pos: | |
200 | text = '.'.join(self._get_context()) |
|
200 | # The completer tells us what text was actually used for the | |
|
201 | # matching, so we must move that many characters left to apply the | |||
|
202 | # completions. | |||
|
203 | text = rep['content']['matched_text'] | |||
201 | cursor.movePosition(QtGui.QTextCursor.Left, n=len(text)) |
|
204 | cursor.movePosition(QtGui.QTextCursor.Left, n=len(text)) | |
202 | self._complete_with_items(cursor, rep['content']['matches']) |
|
205 | self._complete_with_items(cursor, rep['content']['matches']) | |
203 |
|
206 | |||
@@ -310,14 +313,22 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||||
310 | """ Performs completion at the current cursor location. |
|
313 | """ Performs completion at the current cursor location. | |
311 | """ |
|
314 | """ | |
312 | # Decide if it makes sense to do completion |
|
315 | # Decide if it makes sense to do completion | |
313 | context = self._get_context() |
|
316 | ||
314 | if not context: |
|
317 | # We should return only if the line is empty. Otherwise, let the | |
|
318 | # kernel split the line up. | |||
|
319 | line = self._get_input_buffer_cursor_line() | |||
|
320 | if not line: | |||
315 | return False |
|
321 | return False | |
316 |
|
322 | |||
|
323 | # We let the kernel split the input line, so we *always* send an empty | |||
|
324 | # text field. Readline-based frontends do get a real text field which | |||
|
325 | # they can use. | |||
|
326 | text = '' | |||
|
327 | ||||
317 | # Send the completion request to the kernel |
|
328 | # Send the completion request to the kernel | |
318 | self._complete_id = self.kernel_manager.xreq_channel.complete( |
|
329 | self._complete_id = self.kernel_manager.xreq_channel.complete( | |
319 |
|
|
330 | text, # text | |
320 | self._get_input_buffer_cursor_line(), # line |
|
331 | line, # line | |
321 | self._get_input_buffer_cursor_column(), # cursor_pos |
|
332 | self._get_input_buffer_cursor_column(), # cursor_pos | |
322 | self.input_buffer) # block |
|
333 | self.input_buffer) # block | |
323 | self._complete_pos = self._get_cursor().position() |
|
334 | self._complete_pos = self._get_cursor().position() |
@@ -9,6 +9,7 b' IO related utilities.' | |||||
9 | # Distributed under the terms of the BSD License. The full license is in |
|
9 | # Distributed under the terms of the BSD License. The full license is in | |
10 | # the file COPYING, distributed as part of this software. |
|
10 | # the file COPYING, distributed as part of this software. | |
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
|
12 | from __future__ import print_function | |||
12 |
|
13 | |||
13 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
14 | # Imports |
|
15 | # Imports | |
@@ -38,13 +39,13 b' class IOStream:' | |||||
38 | except: |
|
39 | except: | |
39 | try: |
|
40 | try: | |
40 | # print handles some unicode issues which may trip a plain |
|
41 | # print handles some unicode issues which may trip a plain | |
41 |
# write() call. |
|
42 | # write() call. Emulate write() by using an empty end | |
42 |
# |
|
43 | # argument. | |
43 |
print |
|
44 | print(data, end='', file=self.stream) | |
44 | except: |
|
45 | except: | |
45 | # if we get here, something is seriously broken. |
|
46 | # if we get here, something is seriously broken. | |
46 | print >> sys.stderr, \ |
|
47 | print('ERROR - failed to write data to stream:', self.stream, | |
47 | 'ERROR - failed to write data to stream:', self.stream |
|
48 | file=sys.stderr) | |
48 |
|
49 | |||
49 | # This class used to have a writeln method, but regular files and streams |
|
50 | # This class used to have a writeln method, but regular files and streams | |
50 | # in Python don't have this method. We need to keep this completely |
|
51 | # in Python don't have this method. We need to keep this completely | |
@@ -240,7 +241,7 b' class NLprinter:' | |||||
240 | start = kw['start']; del kw['start'] |
|
241 | start = kw['start']; del kw['start'] | |
241 | stop = kw['stop']; del kw['stop'] |
|
242 | stop = kw['stop']; del kw['stop'] | |
242 | if self.depth == 0 and 'header' in kw.keys(): |
|
243 | if self.depth == 0 and 'header' in kw.keys(): | |
243 |
print |
|
244 | print(kw['header']) | |
244 |
|
245 | |||
245 | for idx in range(start,stop): |
|
246 | for idx in range(start,stop): | |
246 | elem = lst[idx] |
|
247 | elem = lst[idx] | |
@@ -277,10 +278,17 b" def temp_pyfile(src, ext='.py'):" | |||||
277 | return fname, f |
|
278 | return fname, f | |
278 |
|
279 | |||
279 |
|
280 | |||
280 |
def rprint(* |
|
281 | def rprint(*args, **kw): | |
|
282 | """Raw print to sys.__stdout__""" | |||
|
283 | ||||
|
284 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), | |||
|
285 | file=sys.__stdout__) | |||
|
286 | sys.__stdout__.flush() | |||
|
287 | ||||
|
288 | ||||
|
289 | def rprinte(*args, **kw): | |||
281 | """Raw print to sys.__stderr__""" |
|
290 | """Raw print to sys.__stderr__""" | |
282 |
|
291 | |||
283 | for item in info: |
|
292 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), | |
284 |
|
|
293 | file=sys.__stderr__) | |
285 | print >> sys.__stderr__ |
|
|||
286 | sys.__stderr__.flush() |
|
294 | sys.__stderr__.flush() |
@@ -13,6 +13,7 b' Things to do:' | |||||
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
|
16 | from __future__ import print_function | |||
16 |
|
17 | |||
17 | # Standard library imports. |
|
18 | # Standard library imports. | |
18 | import __builtin__ |
|
19 | import __builtin__ | |
@@ -25,6 +26,7 b' import zmq' | |||||
25 |
|
26 | |||
26 | # Local imports. |
|
27 | # Local imports. | |
27 | from IPython.config.configurable import Configurable |
|
28 | from IPython.config.configurable import Configurable | |
|
29 | from IPython.utils import io | |||
28 | from IPython.utils.traitlets import Instance |
|
30 | from IPython.utils.traitlets import Instance | |
29 | from completer import KernelCompleter |
|
31 | from completer import KernelCompleter | |
30 | from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \ |
|
32 | from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \ | |
@@ -126,11 +128,10 b' class Kernel(Configurable):' | |||||
126 | assert self.reply_socket.rcvmore(), "Missing message part." |
|
128 | assert self.reply_socket.rcvmore(), "Missing message part." | |
127 | msg = self.reply_socket.recv_json() |
|
129 | msg = self.reply_socket.recv_json() | |
128 | omsg = Message(msg) |
|
130 | omsg = Message(msg) | |
129 | print>>sys.__stdout__ |
|
131 | io.rprint('\n', omsg) | |
130 | print>>sys.__stdout__, omsg |
|
|||
131 | handler = self.handlers.get(omsg.msg_type, None) |
|
132 | handler = self.handlers.get(omsg.msg_type, None) | |
132 | if handler is None: |
|
133 | if handler is None: | |
133 |
|
|
134 | io.rprinte("UNKNOWN MESSAGE TYPE:", omsg) | |
134 | else: |
|
135 | else: | |
135 | handler(ident, omsg) |
|
136 | handler(ident, omsg) | |
136 |
|
137 | |||
@@ -142,8 +143,8 b' class Kernel(Configurable):' | |||||
142 | try: |
|
143 | try: | |
143 | code = parent[u'content'][u'code'] |
|
144 | code = parent[u'content'][u'code'] | |
144 | except: |
|
145 | except: | |
145 |
|
|
146 | io.rprinte("Got bad msg: ") | |
146 |
|
|
147 | io.rprinte(Message(parent)) | |
147 | return |
|
148 | return | |
148 | pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent) |
|
149 | pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent) | |
149 | self.pub_socket.send_json(pyin_msg) |
|
150 | self.pub_socket.send_json(pyin_msg) | |
@@ -200,25 +201,27 b' class Kernel(Configurable):' | |||||
200 |
|
201 | |||
201 | # Send the reply. |
|
202 | # Send the reply. | |
202 | reply_msg = self.session.msg(u'execute_reply', reply_content, parent) |
|
203 | reply_msg = self.session.msg(u'execute_reply', reply_content, parent) | |
203 |
|
|
204 | io.rprint(Message(reply_msg)) | |
204 | self.reply_socket.send(ident, zmq.SNDMORE) |
|
205 | self.reply_socket.send(ident, zmq.SNDMORE) | |
205 | self.reply_socket.send_json(reply_msg) |
|
206 | self.reply_socket.send_json(reply_msg) | |
206 | if reply_msg['content']['status'] == u'error': |
|
207 | if reply_msg['content']['status'] == u'error': | |
207 | self._abort_queue() |
|
208 | self._abort_queue() | |
208 |
|
209 | |||
209 | def complete_request(self, ident, parent): |
|
210 | def complete_request(self, ident, parent): | |
210 |
matches = |
|
211 | txt, matches = self._complete(parent) | |
|
212 | matches = {'matches' : matches, | |||
|
213 | 'matched_text' : txt, | |||
211 | 'status' : 'ok'} |
|
214 | 'status' : 'ok'} | |
212 | completion_msg = self.session.send(self.reply_socket, 'complete_reply', |
|
215 | completion_msg = self.session.send(self.reply_socket, 'complete_reply', | |
213 | matches, parent, ident) |
|
216 | matches, parent, ident) | |
214 |
|
|
217 | io.rprint(completion_msg) | |
215 |
|
218 | |||
216 | def object_info_request(self, ident, parent): |
|
219 | def object_info_request(self, ident, parent): | |
217 | context = parent['content']['oname'].split('.') |
|
220 | context = parent['content']['oname'].split('.') | |
218 | object_info = self._object_info(context) |
|
221 | object_info = self._object_info(context) | |
219 | msg = self.session.send(self.reply_socket, 'object_info_reply', |
|
222 | msg = self.session.send(self.reply_socket, 'object_info_reply', | |
220 | object_info, parent, ident) |
|
223 | object_info, parent, ident) | |
221 | print >> sys.__stdout__, msg |
|
224 | io.rprint(msg) | |
222 |
|
225 | |||
223 | def prompt_request(self, ident, parent): |
|
226 | def prompt_request(self, ident, parent): | |
224 | prompt_number = self.shell.displayhook.prompt_count |
|
227 | prompt_number = self.shell.displayhook.prompt_count | |
@@ -228,7 +231,7 b' class Kernel(Configurable):' | |||||
228 | 'input_sep' : self.shell.displayhook.input_sep} |
|
231 | 'input_sep' : self.shell.displayhook.input_sep} | |
229 | msg = self.session.send(self.reply_socket, 'prompt_reply', |
|
232 | msg = self.session.send(self.reply_socket, 'prompt_reply', | |
230 | content, parent, ident) |
|
233 | content, parent, ident) | |
231 | print >> sys.__stdout__, msg |
|
234 | io.rprint(msg) | |
232 |
|
235 | |||
233 | def history_request(self, ident, parent): |
|
236 | def history_request(self, ident, parent): | |
234 | output = parent['content']['output'] |
|
237 | output = parent['content']['output'] | |
@@ -238,7 +241,7 b' class Kernel(Configurable):' | |||||
238 | content = {'history' : hist} |
|
241 | content = {'history' : hist} | |
239 | msg = self.session.send(self.reply_socket, 'history_reply', |
|
242 | msg = self.session.send(self.reply_socket, 'history_reply', | |
240 | content, parent, ident) |
|
243 | content, parent, ident) | |
241 | print >> sys.__stdout__, msg |
|
244 | io.rprint(msg) | |
242 |
|
245 | |||
243 | #--------------------------------------------------------------------------- |
|
246 | #--------------------------------------------------------------------------- | |
244 | # Protected interface |
|
247 | # Protected interface | |
@@ -254,12 +257,11 b' class Kernel(Configurable):' | |||||
254 | else: |
|
257 | else: | |
255 | assert self.reply_socket.rcvmore(), "Unexpected missing message part." |
|
258 | assert self.reply_socket.rcvmore(), "Unexpected missing message part." | |
256 | msg = self.reply_socket.recv_json() |
|
259 | msg = self.reply_socket.recv_json() | |
257 | print>>sys.__stdout__, "Aborting:" |
|
260 | io.rprint("Aborting:\n", Message(msg)) | |
258 | print>>sys.__stdout__, Message(msg) |
|
|||
259 | msg_type = msg['msg_type'] |
|
261 | msg_type = msg['msg_type'] | |
260 | reply_type = msg_type.split('_')[0] + '_reply' |
|
262 | reply_type = msg_type.split('_')[0] + '_reply' | |
261 | reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg) |
|
263 | reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg) | |
262 |
|
|
264 | io.rprint(Message(reply_msg)) | |
263 | self.reply_socket.send(ident,zmq.SNDMORE) |
|
265 | self.reply_socket.send(ident,zmq.SNDMORE) | |
264 | self.reply_socket.send_json(reply_msg) |
|
266 | self.reply_socket.send_json(reply_msg) | |
265 | # We need to wait a bit for requests to come in. This can probably |
|
267 | # We need to wait a bit for requests to come in. This can probably | |
@@ -281,23 +283,22 b' class Kernel(Configurable):' | |||||
281 | try: |
|
283 | try: | |
282 | value = reply['content']['value'] |
|
284 | value = reply['content']['value'] | |
283 | except: |
|
285 | except: | |
284 |
|
|
286 | io.rprinte("Got bad raw_input reply: ") | |
285 |
|
|
287 | io.rprinte(Message(parent)) | |
286 | value = '' |
|
288 | value = '' | |
287 | return value |
|
289 | return value | |
288 |
|
290 | |||
289 | def _complete(self, msg): |
|
291 | def _complete(self, msg): | |
290 | #from IPython.utils.io import rprint # dbg |
|
|||
291 | #rprint('\n\n**MSG**\n\n', msg) # dbg |
|
|||
292 | #import traceback; rprint(''.join(traceback.format_stack())) # dbg |
|
|||
293 | c = msg['content'] |
|
292 | c = msg['content'] | |
294 | try: |
|
293 | try: | |
295 | cpos = int(c['cursor_pos']) |
|
294 | cpos = int(c['cursor_pos']) | |
296 | except: |
|
295 | except: | |
297 | # If we don't get something that we can convert to an integer, at |
|
296 | # If we don't get something that we can convert to an integer, at | |
298 |
# leas |
|
297 | # least attempt the completion guessing the cursor is at the end of | |
299 | # of the text |
|
298 | # the text, if there's any, and otherwise of the line | |
300 | cpos = len(c['text']) |
|
299 | cpos = len(c['text']) | |
|
300 | if cpos==0: | |||
|
301 | cpos = len(c['line']) | |||
301 | return self.shell.complete(c['text'], c['line'], cpos) |
|
302 | return self.shell.complete(c['text'], c['line'], cpos) | |
302 |
|
303 | |||
303 | def _object_info(self, context): |
|
304 | def _object_info(self, context): |
General Comments 0
You need to be logged in to leave comments.
Login now