##// END OF EJS Templates
Merge branch 'fp-newkernel' into newkernel
Fernando Perez -
r2859:6b93afaa merge
parent child Browse files
Show More
@@ -61,6 +61,7 b' used, and this module (and the readline module) are silently inactive.'
61 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 67 # Imports
@@ -79,7 +80,7 b' import sys'
79 80
80 81 from IPython.core.error import TryNext
81 82 from IPython.core.prefilter import ESC_MAGIC
82 from IPython.utils import generics
83 from IPython.utils import generics, io
83 84 from IPython.utils.frame import debugx
84 85 from IPython.utils.dir2 import dir2
85 86
@@ -138,9 +139,60 b' def single_dir_expand(matches):'
138 139 else:
139 140 return matches
140 141
141 class Bunch: pass
142 142
143 class Completer:
143 class Bunch(object): pass
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):
144 196 def __init__(self,namespace=None,global_namespace=None):
145 197 """Create a new completer for the command line.
146 198
@@ -295,6 +347,8 b' class IPCompleter(Completer):'
295 347
296 348 self.magic_escape = ESC_MAGIC
297 349
350 self.splitter = CompletionSplitter()
351
298 352 # Readline-dependent code
299 353 self.use_readline = use_readline
300 354 if use_readline:
@@ -610,16 +664,20 b' class IPCompleter(Completer):'
610 664
611 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 668 """Return the state-th possible completion for 'text'.
615 669
616 670 This is called successively with state == 0, 1, 2, ... until it
617 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 676 Parameters
620 677 ----------
621 text : string
622 Text to perform the completion on.
678 text : string, optional
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 682 line_buffer : string, optional
625 683 If not given, the completer attempts to obtain the current line
@@ -631,6 +689,20 b' class IPCompleter(Completer):'
631 689 Index of the cursor in the full line buffer. Should be provided by
632 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)
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
634 706
635 707 magic_escape = self.magic_escape
636 708 self.full_lbuf = line_buffer
@@ -639,6 +711,8 b' class IPCompleter(Completer):'
639 711 if text.startswith('~'):
640 712 text = os.path.expanduser(text)
641 713
714 #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
715
642 716 # Start with a clean slate of completions
643 717 self.matches[:] = []
644 718 custom_res = self.dispatch_custom_completer(text)
@@ -663,8 +737,8 b' class IPCompleter(Completer):'
663 737 # simply collapse the dict into a list for readline, but we'd have
664 738 # richer completion semantics in other evironments.
665 739 self.matches = sorted(set(self.matches))
666 #from IPython.utils.io import rprint; rprint(self.matches) # dbg
667 return self.matches
740 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
741 return text, self.matches
668 742
669 743 def rlcomplete(self, text, state):
670 744 """Return the state-th possible completion for 'text'.
@@ -679,15 +753,15 b' class IPCompleter(Completer):'
679 753
680 754 state : int
681 755 Counter used by readline.
682
683 756 """
684
685 #print "rlcomplete! '%s' %s" % (text, state) # dbg
686
687 757 if state==0:
758
688 759 self.full_lbuf = line_buffer = self.get_line_buffer()
689 760 cursor_pos = self.get_endidx()
690 761
762 #io.rprint("\nRLCOMPLETE: %r %r %r" %
763 # (text, line_buffer, cursor_pos) ) # dbg
764
691 765 # if there is only a tab on a line with only whitespace, instead of
692 766 # the mostly useless 'do you want to see all million completions'
693 767 # message, just do the right thing and give the user his tab!
@@ -699,7 +773,7 b' class IPCompleter(Completer):'
699 773
700 774 # don't apply this on 'dumb' terminals, such as emacs buffers, so
701 775 # we don't interfere with their own tab-completion mechanism.
702 if not (self.dumb_terminal or self.full_lbuf.strip()):
776 if not (self.dumb_terminal or line_buffer.strip()):
703 777 self.readline.insert_text('\t')
704 778 sys.stdout.flush()
705 779 return None
@@ -719,4 +793,3 b' class IPCompleter(Completer):'
719 793 return self.matches[state]
720 794 except IndexError:
721 795 return None
722
@@ -1370,13 +1370,15 b' class InteractiveShell(Configurable, Magic):'
1370 1370 #-------------------------------------------------------------------------
1371 1371
1372 1372 def complete(self, text, line=None, cursor_pos=None):
1373 """Return a sorted list of all possible completions on text.
1373 """Return the completed text and a list of completions.
1374 1374
1375 1375 Parameters
1376 1376 ----------
1377 1377
1378 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 1383 line : string, optional
1382 1384 The complete line that text is part of.
@@ -1384,6 +1386,14 b' class InteractiveShell(Configurable, Magic):'
1384 1386 cursor_pos : int, optional
1385 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 1397 The optional arguments allow the completion to take more context into
1388 1398 account, and are part of the low-level completion API.
1389 1399
@@ -1394,21 +1404,15 b' class InteractiveShell(Configurable, Magic):'
1394 1404
1395 1405 Simple usage example:
1396 1406
1397 In [7]: x = 'hello'
1398
1399 In [8]: x
1400 Out[8]: 'hello'
1401
1402 In [9]: print x
1403 hello
1407 In [1]: x = 'hello'
1404 1408
1405 In [10]: _ip.complete('x.l')
1406 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1409 In [2]: _ip.complete('x.l')
1410 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
1407 1411 """
1408 1412
1409 1413 # Inject names into __builtin__ so we can complete on the added names.
1410 1414 with self.builtin_trap:
1411 return self.Completer.complete(text,line_buffer=text)
1415 return self.Completer.complete(text, line, cursor_pos)
1412 1416
1413 1417 def set_custom_completer(self,completer,pos=0):
1414 1418 """Adds a new custom completer function.
@@ -6,6 +6,7 b''
6 6
7 7 # stdlib
8 8 import sys
9 import unittest
9 10
10 11 # third party
11 12 import nose.tools as nt
@@ -33,3 +34,50 b' def test_protect_filename():'
33 34 for s1, s2 in pairs:
34 35 s1p = completer.protect_filename(s1)
35 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 378 def reset_font(self):
379 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 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 389 name = 'Courier'
383 390 elif sys.platform == 'darwin':
384 391 name = 'Monaco'
@@ -197,7 +197,10 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
197 197 cursor = self._get_cursor()
198 198 if rep['parent_header']['msg_id'] == self._complete_id and \
199 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 204 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
202 205 self._complete_with_items(cursor, rep['content']['matches'])
203 206
@@ -310,14 +313,22 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
310 313 """ Performs completion at the current cursor location.
311 314 """
312 315 # Decide if it makes sense to do completion
313 context = self._get_context()
314 if not context:
316
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 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 328 # Send the completion request to the kernel
318 329 self._complete_id = self.kernel_manager.xreq_channel.complete(
319 '.'.join(context), # text
320 self._get_input_buffer_cursor_line(), # line
330 text, # text
331 line, # line
321 332 self._get_input_buffer_cursor_column(), # cursor_pos
322 333 self.input_buffer) # block
323 334 self._complete_pos = self._get_cursor().position()
@@ -9,6 +9,7 b' IO related utilities.'
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
12 13
13 14 #-----------------------------------------------------------------------------
14 15 # Imports
@@ -38,13 +39,13 b' class IOStream:'
38 39 except:
39 40 try:
40 41 # print handles some unicode issues which may trip a plain
41 # write() call. Attempt to emulate write() by using a
42 # trailing comma
43 print >> self.stream, data,
42 # write() call. Emulate write() by using an empty end
43 # argument.
44 print(data, end='', file=self.stream)
44 45 except:
45 46 # if we get here, something is seriously broken.
46 print >> sys.stderr, \
47 'ERROR - failed to write data to stream:', self.stream
47 print('ERROR - failed to write data to stream:', self.stream,
48 file=sys.stderr)
48 49
49 50 # This class used to have a writeln method, but regular files and streams
50 51 # in Python don't have this method. We need to keep this completely
@@ -240,7 +241,7 b' class NLprinter:'
240 241 start = kw['start']; del kw['start']
241 242 stop = kw['stop']; del kw['stop']
242 243 if self.depth == 0 and 'header' in kw.keys():
243 print kw['header']
244 print(kw['header'])
244 245
245 246 for idx in range(start,stop):
246 247 elem = lst[idx]
@@ -277,10 +278,17 b" def temp_pyfile(src, ext='.py'):"
277 278 return fname, f
278 279
279 280
280 def rprint(*info):
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 290 """Raw print to sys.__stderr__"""
282 291
283 for item in info:
284 print >> sys.__stderr__, item,
285 print >> sys.__stderr__
292 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
293 file=sys.__stderr__)
286 294 sys.__stderr__.flush()
@@ -13,6 +13,7 b' Things to do:'
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 17
17 18 # Standard library imports.
18 19 import __builtin__
@@ -25,6 +26,7 b' import zmq'
25 26
26 27 # Local imports.
27 28 from IPython.config.configurable import Configurable
29 from IPython.utils import io
28 30 from IPython.utils.traitlets import Instance
29 31 from completer import KernelCompleter
30 32 from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \
@@ -126,11 +128,10 b' class Kernel(Configurable):'
126 128 assert self.reply_socket.rcvmore(), "Missing message part."
127 129 msg = self.reply_socket.recv_json()
128 130 omsg = Message(msg)
129 print>>sys.__stdout__
130 print>>sys.__stdout__, omsg
131 io.rprint('\n', omsg)
131 132 handler = self.handlers.get(omsg.msg_type, None)
132 133 if handler is None:
133 print >> sys.__stderr__, "UNKNOWN MESSAGE TYPE:", omsg
134 io.rprinte("UNKNOWN MESSAGE TYPE:", omsg)
134 135 else:
135 136 handler(ident, omsg)
136 137
@@ -142,8 +143,8 b' class Kernel(Configurable):'
142 143 try:
143 144 code = parent[u'content'][u'code']
144 145 except:
145 print>>sys.__stderr__, "Got bad msg: "
146 print>>sys.__stderr__, Message(parent)
146 io.rprinte("Got bad msg: ")
147 io.rprinte(Message(parent))
147 148 return
148 149 pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
149 150 self.pub_socket.send_json(pyin_msg)
@@ -200,25 +201,27 b' class Kernel(Configurable):'
200 201
201 202 # Send the reply.
202 203 reply_msg = self.session.msg(u'execute_reply', reply_content, parent)
203 print>>sys.__stdout__, Message(reply_msg)
204 io.rprint(Message(reply_msg))
204 205 self.reply_socket.send(ident, zmq.SNDMORE)
205 206 self.reply_socket.send_json(reply_msg)
206 207 if reply_msg['content']['status'] == u'error':
207 208 self._abort_queue()
208 209
209 210 def complete_request(self, ident, parent):
210 matches = {'matches' : self._complete(parent),
211 txt, matches = self._complete(parent)
212 matches = {'matches' : matches,
213 'matched_text' : txt,
211 214 'status' : 'ok'}
212 215 completion_msg = self.session.send(self.reply_socket, 'complete_reply',
213 216 matches, parent, ident)
214 print >> sys.__stdout__, completion_msg
217 io.rprint(completion_msg)
215 218
216 219 def object_info_request(self, ident, parent):
217 220 context = parent['content']['oname'].split('.')
218 221 object_info = self._object_info(context)
219 222 msg = self.session.send(self.reply_socket, 'object_info_reply',
220 223 object_info, parent, ident)
221 print >> sys.__stdout__, msg
224 io.rprint(msg)
222 225
223 226 def prompt_request(self, ident, parent):
224 227 prompt_number = self.shell.displayhook.prompt_count
@@ -228,7 +231,7 b' class Kernel(Configurable):'
228 231 'input_sep' : self.shell.displayhook.input_sep}
229 232 msg = self.session.send(self.reply_socket, 'prompt_reply',
230 233 content, parent, ident)
231 print >> sys.__stdout__, msg
234 io.rprint(msg)
232 235
233 236 def history_request(self, ident, parent):
234 237 output = parent['content']['output']
@@ -238,7 +241,7 b' class Kernel(Configurable):'
238 241 content = {'history' : hist}
239 242 msg = self.session.send(self.reply_socket, 'history_reply',
240 243 content, parent, ident)
241 print >> sys.__stdout__, msg
244 io.rprint(msg)
242 245
243 246 #---------------------------------------------------------------------------
244 247 # Protected interface
@@ -254,12 +257,11 b' class Kernel(Configurable):'
254 257 else:
255 258 assert self.reply_socket.rcvmore(), "Unexpected missing message part."
256 259 msg = self.reply_socket.recv_json()
257 print>>sys.__stdout__, "Aborting:"
258 print>>sys.__stdout__, Message(msg)
260 io.rprint("Aborting:\n", Message(msg))
259 261 msg_type = msg['msg_type']
260 262 reply_type = msg_type.split('_')[0] + '_reply'
261 263 reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg)
262 print>>sys.__stdout__, Message(reply_msg)
264 io.rprint(Message(reply_msg))
263 265 self.reply_socket.send(ident,zmq.SNDMORE)
264 266 self.reply_socket.send_json(reply_msg)
265 267 # We need to wait a bit for requests to come in. This can probably
@@ -281,23 +283,22 b' class Kernel(Configurable):'
281 283 try:
282 284 value = reply['content']['value']
283 285 except:
284 print>>sys.__stderr__, "Got bad raw_input reply: "
285 print>>sys.__stderr__, Message(parent)
286 io.rprinte("Got bad raw_input reply: ")
287 io.rprinte(Message(parent))
286 288 value = ''
287 289 return value
288 290
289 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 292 c = msg['content']
294 293 try:
295 294 cpos = int(c['cursor_pos'])
296 295 except:
297 296 # If we don't get something that we can convert to an integer, at
298 # leasat attempt the completion guessing the cursor is at the end
299 # of the text
297 # least attempt the completion guessing the cursor is at the end of
298 # the text, if there's any, and otherwise of the line
300 299 cpos = len(c['text'])
300 if cpos==0:
301 cpos = len(c['line'])
301 302 return self.shell.complete(c['text'], c['line'], cpos)
302 303
303 304 def _object_info(self, context):
General Comments 0
You need to be logged in to leave comments. Login now