##// END OF EJS Templates
Multiple improvements to tab completion....
Fernando Perez -
Show More
@@ -82,7 +82,6 b' from IPython.core.prefilter import ESC_MAGIC'
82 82 from IPython.utils import generics
83 83 from IPython.utils.frame import debugx
84 84 from IPython.utils.dir2 import dir2
85 import IPython.utils.rlineimpl as readline
86 85
87 86 #-----------------------------------------------------------------------------
88 87 # Globals
@@ -107,6 +106,18 b' def protect_filename(s):'
107 106 for ch in s])
108 107
109 108
109 def mark_dirs(matches):
110 """Mark directories in input list by appending '/' to their names."""
111 out = []
112 isdir = os.path.isdir
113 for x in matches:
114 if isdir(x):
115 out.append(x+'/')
116 else:
117 out.append(x)
118 return out
119
120
110 121 def single_dir_expand(matches):
111 122 "Recursively expand match lists containing a single dir."
112 123
@@ -250,7 +261,7 b' class IPCompleter(Completer):'
250 261 """Extension of the completer class with IPython-specific features"""
251 262
252 263 def __init__(self,shell,namespace=None,global_namespace=None,
253 omit__names=0,alias_table=None):
264 omit__names=0, alias_table=None, use_readline=True):
254 265 """IPCompleter() -> completer
255 266
256 267 Return a completer object suitable for use by the readline library
@@ -273,17 +284,31 b' class IPCompleter(Completer):'
273 284 to be completed explicitly starts with one or more underscores.
274 285
275 286 - If alias_table is supplied, it should be a dictionary of aliases
276 to complete. """
287 to complete.
288
289 use_readline : bool, optional
290 If true, use the readline library. This completer can still function
291 without readline, though in that case callers must provide some extra
292 information on each call about the current line."""
277 293
278 294 Completer.__init__(self,namespace,global_namespace)
279 295
280 296 self.magic_escape = ESC_MAGIC
297
298 # Readline-dependent code
299 self.use_readline = use_readline
300 if use_readline:
301 import IPython.utils.rlineimpl as readline
281 302 self.readline = readline
282 303 delims = self.readline.get_completer_delims()
283 304 delims = delims.replace(self.magic_escape,'')
284 305 self.readline.set_completer_delims(delims)
285 306 self.get_line_buffer = self.readline.get_line_buffer
286 307 self.get_endidx = self.readline.get_endidx
308 # /end readline-dependent code
309
310 # List where completion matches will be stored
311 self.matches = []
287 312 self.omit__names = omit__names
288 313 self.merge_completions = shell.readline_merge_completions
289 314 self.shell = shell.shell
@@ -311,7 +336,8 b' class IPCompleter(Completer):'
311 336 self.file_matches,
312 337 self.magic_matches,
313 338 self.alias_matches,
314 self.python_func_kw_matches]
339 self.python_func_kw_matches,
340 ]
315 341
316 342 # Code contributed by Alex Schmolck, for ipython/emacs integration
317 343 def all_completions(self, text):
@@ -414,7 +440,8 b' class IPCompleter(Completer):'
414 440 protect_filename(f) for f in m0]
415 441
416 442 #print 'mm',matches # dbg
417 return single_dir_expand(matches)
443 #return single_dir_expand(matches)
444 return mark_dirs(matches)
418 445
419 446 def magic_matches(self, text):
420 447 """Match magics"""
@@ -583,50 +610,37 b' class IPCompleter(Completer):'
583 610
584 611 return None
585 612
586 def complete(self, text, state, line_buffer=None):
587 """Return the next possible completion for 'text'.
613 def complete(self, text, line_buffer, cursor_pos=None):
614 """Return the state-th possible completion for 'text'.
588 615
589 616 This is called successively with state == 0, 1, 2, ... until it
590 617 returns None. The completion should begin with 'text'.
591 618
592 :Keywords:
593 - line_buffer: string
594 If not given, the completer attempts to obtain the current line buffer
595 via readline. This keyword allows clients which are requesting for
596 text completions in non-readline contexts to inform the completer of
597 the entire text.
598 """
599
600 #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg
619 Parameters
620 ----------
621 text : string
622 Text to perform the completion on.
601 623
602 # if there is only a tab on a line with only whitespace, instead
603 # of the mostly useless 'do you want to see all million
604 # completions' message, just do the right thing and give the user
605 # his tab! Incidentally, this enables pasting of tabbed text from
606 # an editor (as long as autoindent is off).
624 line_buffer : string, optional
625 If not given, the completer attempts to obtain the current line
626 buffer via readline. This keyword allows clients which are
627 requesting for text completions in non-readline contexts to inform
628 the completer of the entire text.
607 629
608 # It should be noted that at least pyreadline still shows
609 # file completions - is there a way around it?
610
611 # don't apply this on 'dumb' terminals, such as emacs buffers, so we
612 # don't interfere with their own tab-completion mechanism.
613 if line_buffer is None:
614 self.full_lbuf = self.get_line_buffer()
615 else:
616 self.full_lbuf = line_buffer
617
618 if not (self.dumb_terminal or self.full_lbuf.strip()):
619 self.readline.insert_text('\t')
620 return None
630 cursor_pos : int, optional
631 Index of the cursor in the full line buffer. Should be provided by
632 remote frontends where kernel has no access to frontend state.
633 """
621 634
622 635 magic_escape = self.magic_escape
636 self.full_lbuf = line_buffer
637 self.lbuf = self.full_lbuf[:cursor_pos]
623 638
624 self.lbuf = self.full_lbuf[:self.get_endidx()]
625
626 try:
627 639 if text.startswith('~'):
628 640 text = os.path.expanduser(text)
629 if state == 0:
641
642 # Start with a clean slate of completions
643 self.matches[:] = []
630 644 custom_res = self.dispatch_custom_completer(text)
631 645 if custom_res is not None:
632 646 # did custom completers produce something?
@@ -644,15 +658,65 b' class IPCompleter(Completer):'
644 658 self.matches = matcher(text)
645 659 if self.matches:
646 660 break
647 self.matches = list(set(self.matches))
661 # FIXME: we should extend our api to return a dict with completions for
662 # different types of objects. The rlcomplete() method could then
663 # simply collapse the dict into a list for readline, but we'd have
664 # richer completion semantics in other evironments.
665 self.matches = sorted(set(self.matches))
666 #from IPython.utils.io import rprint; rprint(self.matches) # dbg
667 return self.matches
668
669 def rlcomplete(self, text, state):
670 """Return the state-th possible completion for 'text'.
671
672 This is called successively with state == 0, 1, 2, ... until it
673 returns None. The completion should begin with 'text'.
674
675 Parameters
676 ----------
677 text : string
678 Text to perform the completion on.
679
680 state : int
681 Counter used by readline.
682
683 """
684
685 #print "rlcomplete! '%s' %s" % (text, state) # dbg
686
687 if state==0:
688 self.full_lbuf = line_buffer = self.get_line_buffer()
689 cursor_pos = self.get_endidx()
690
691 # 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'
693 # message, just do the right thing and give the user his tab!
694 # Incidentally, this enables pasting of tabbed text from an editor
695 # (as long as autoindent is off).
696
697 # It should be noted that at least pyreadline still shows file
698 # completions - is there a way around it?
699
700 # don't apply this on 'dumb' terminals, such as emacs buffers, so
701 # we don't interfere with their own tab-completion mechanism.
702 if not (self.dumb_terminal or self.full_lbuf.strip()):
703 self.readline.insert_text('\t')
704 sys.stdout.flush()
705 return None
706
707 # This method computes the self.matches array
708 self.complete(text, line_buffer, cursor_pos)
709
710 # Debug version, since readline silences all exceptions making it
711 # impossible to debug any problem in the above code
712
713 ## try:
714 ## self.complete(text, line_buffer, cursor_pos)
715 ## except:
716 ## import traceback; traceback.print_exc()
717
648 718 try:
649 #print "MATCH: %r" % self.matches[state] # dbg
650 719 return self.matches[state]
651 720 except IndexError:
652 721 return None
653 except:
654 #from IPython.core.ultratb import AutoFormattedTB; # dbg
655 #tb=AutoFormattedTB('Verbose');tb() #dbg
656 722
657 # If completion fails, don't annoy the user.
658 return None
@@ -1303,7 +1303,7 b' class InteractiveShell(Configurable, Magic):'
1303 1303 else:
1304 1304 if exception_only:
1305 1305 stb = ['An exception has occurred, use %tb to see '
1306 'the full traceback.']
1306 'the full traceback.\n']
1307 1307 stb.extend(self.InteractiveTB.get_exception_only(etype,
1308 1308 value))
1309 1309 else:
@@ -1327,7 +1327,9 b' class InteractiveShell(Configurable, Magic):'
1327 1327 Subclasses may override this method to put the traceback on a different
1328 1328 place, like a side channel.
1329 1329 """
1330 self.write_err('\n'.join(stb))
1330 # FIXME: this should use the proper write channels, but our test suite
1331 # relies on it coming out of stdout...
1332 print >> sys.stdout, self.InteractiveTB.stb2text(stb)
1331 1333
1332 1334 def showsyntaxerror(self, filename=None):
1333 1335 """Display the syntax error that just occurred.
@@ -1367,12 +1369,23 b' class InteractiveShell(Configurable, Magic):'
1367 1369 # Things related to tab completion
1368 1370 #-------------------------------------------------------------------------
1369 1371
1370 def complete(self, text):
1372 def complete(self, text, line=None, cursor_pos=None):
1371 1373 """Return a sorted list of all possible completions on text.
1372 1374
1373 Inputs:
1375 Parameters
1376 ----------
1377
1378 text : string
1379 A string of text to be completed on.
1374 1380
1375 - text: a string of text to be completed on.
1381 line : string, optional
1382 The complete line that text is part of.
1383
1384 cursor_pos : int, optional
1385 The position of the cursor on the input line.
1386
1387 The optional arguments allow the completion to take more context into
1388 account, and are part of the low-level completion API.
1376 1389
1377 1390 This is a wrapper around the completion mechanism, similar to what
1378 1391 readline does at the command line when the TAB key is hit. By
@@ -1395,23 +1408,7 b' class InteractiveShell(Configurable, Magic):'
1395 1408
1396 1409 # Inject names into __builtin__ so we can complete on the added names.
1397 1410 with self.builtin_trap:
1398 complete = self.Completer.complete
1399 state = 0
1400 # use a dict so we get unique keys, since ipyhton's multiple
1401 # completers can return duplicates. When we make 2.4 a requirement,
1402 # start using sets instead, which are faster.
1403 comps = {}
1404 while True:
1405 newcomp = complete(text,state,line_buffer=text)
1406 if newcomp is None:
1407 break
1408 comps[newcomp] = 1
1409 state += 1
1410 outcomps = comps.keys()
1411 outcomps.sort()
1412 #print "T:",text,"OC:",outcomps # dbg
1413 #print "vars:",self.user_ns.keys()
1414 return outcomps
1411 return self.Completer.complete(text,line_buffer=text)
1415 1412
1416 1413 def set_custom_completer(self,completer,pos=0):
1417 1414 """Adds a new custom completer function.
@@ -1425,7 +1422,7 b' class InteractiveShell(Configurable, Magic):'
1425 1422
1426 1423 def set_completer(self):
1427 1424 """Reset readline's completer to be our own."""
1428 self.readline.set_completer(self.Completer.complete)
1425 self.readline.set_completer(self.Completer.rlcomplete)
1429 1426
1430 1427 def set_completer_frame(self, frame=None):
1431 1428 """Set the frame of the completer."""
@@ -1497,7 +1494,7 b' class InteractiveShell(Configurable, Magic):'
1497 1494 % inputrc_name)
1498 1495
1499 1496 # save this in sys so embedded copies can restore it properly
1500 sys.ipcompleter = self.Completer.complete
1497 sys.ipcompleter = self.Completer.rlcomplete
1501 1498 self.set_completer()
1502 1499
1503 1500 # Configure readline according to user's prefs
@@ -360,6 +360,10 b' class TBTools(object):'
360 360 self.color_scheme_table.set_active_scheme('NoColor')
361 361 self.Colors = self.color_scheme_table.active_colors
362 362
363 def stb2text(self, stb):
364 """Convert a structured traceback (a list) to a string."""
365 return '\n'.join(stb)
366
363 367 def text(self, etype, value, tb, tb_offset=None, context=5):
364 368 """Return formatted traceback.
365 369
@@ -367,7 +371,7 b' class TBTools(object):'
367 371 """
368 372 tb_list = self.structured_traceback(etype, value, tb,
369 373 tb_offset, context)
370 return '\n'.join(tb_list)
374 return self.stb2text(tb_list)
371 375
372 376 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
373 377 context=5, mode=None):
@@ -1008,6 +1012,11 b' class FormattedTB(VerboseTB, ListTB):'
1008 1012
1009 1013 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
1010 1014 call_pdb=call_pdb,include_vars=include_vars)
1015
1016 # Different types of tracebacks are joined with different separators to
1017 # form a single string. They are taken from this dict
1018 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1019 # set_mode also sets the tb_join_char attribute
1011 1020 self.set_mode(mode)
1012 1021
1013 1022 def _extract_tb(self,tb):
@@ -1016,10 +1025,9 b' class FormattedTB(VerboseTB, ListTB):'
1016 1025 else:
1017 1026 return None
1018 1027
1019 def structured_traceback(self, etype, value, tb, tb_offset=None,
1020 context=5, mode=None):
1028 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1021 1029 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1022 mode = self.mode if mode is None else mode
1030 mode = self.mode
1023 1031 if mode in self.verbose_modes:
1024 1032 # Verbose modes need a full traceback
1025 1033 return VerboseTB.structured_traceback(
@@ -1035,16 +1043,9 b' class FormattedTB(VerboseTB, ListTB):'
1035 1043 self, etype, value, elist, tb_offset, context
1036 1044 )
1037 1045
1038 def text(self, etype, value, tb, tb_offset=None, context=5, mode=None):
1039 """Return formatted traceback.
1040
1041 If the optional mode parameter is given, it overrides the current
1042 mode."""
1043
1044 mode = self.mode if mode is None else mode
1045 tb_list = self.structured_traceback(etype, value, tb, tb_offset,
1046 context, mode)
1047 return '\n'.join(tb_list)
1046 def stb2text(self, stb):
1047 """Convert a structured traceback (a list) to a string."""
1048 return self.tb_join_char.join(stb)
1048 1049
1049 1050
1050 1051 def set_mode(self,mode=None):
@@ -1063,6 +1064,8 b' class FormattedTB(VerboseTB, ListTB):'
1063 1064 self.mode = mode
1064 1065 # include variable details only in 'Verbose' mode
1065 1066 self.include_vars = (self.mode == self.valid_modes[2])
1067 # Set the join character for generating text tracebacks
1068 self.tb_join_char = self._join_chars[mode]
1066 1069
1067 1070 # some convenient shorcuts
1068 1071 def plain(self):
@@ -1117,12 +1120,12 b' class AutoFormattedTB(FormattedTB):'
1117 1120 print "\nKeyboardInterrupt"
1118 1121
1119 1122 def structured_traceback(self, etype=None, value=None, tb=None,
1120 tb_offset=None, context=5, mode=None):
1123 tb_offset=None, context=5):
1121 1124 if etype is None:
1122 1125 etype,value,tb = sys.exc_info()
1123 1126 self.tb = tb
1124 1127 return FormattedTB.structured_traceback(
1125 self, etype, value, tb, tb_offset, context, mode )
1128 self, etype, value, tb, tb_offset, context)
1126 1129
1127 1130 #---------------------------------------------------------------------------
1128 1131
@@ -1151,14 +1154,10 b' class SyntaxTB(ListTB):'
1151 1154 self.last_syntax_error = None
1152 1155 return e
1153 1156
1154 def text(self, etype, value, tb, tb_offset=None, context=5):
1155 """Return formatted traceback.
1157 def stb2text(self, stb):
1158 """Convert a structured traceback (a list) to a string."""
1159 return ''.join(stb)
1156 1160
1157 Subclasses may override this if they add extra arguments.
1158 """
1159 tb_list = self.structured_traceback(etype, value, tb,
1160 tb_offset, context)
1161 return ''.join(tb_list)
1162 1161
1163 1162 #----------------------------------------------------------------------------
1164 1163 # module testing (minimal)
@@ -293,8 +293,15 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
293 293
294 294 # Send the completion request to the kernel
295 295 text = '.'.join(context)
296
297 # FIXME - Evan: we need the position of the cursor in the current input
298 # buffer. I tried this line below but the numbers I get are bogus. -
299 # Not sure what to do. fperez.
300 cursor_pos = self._get_cursor().position()
301
296 302 self._complete_id = self.kernel_manager.xreq_channel.complete(
297 text, self._get_input_buffer_cursor_line(), self.input_buffer)
303 text, self._get_input_buffer_cursor_line(), cursor_pos,
304 self.input_buffer)
298 305 self._complete_pos = self._get_cursor().position()
299 306 return True
300 307
@@ -286,7 +286,18 b' class Kernel(Configurable):'
286 286 return value
287 287
288 288 def _complete(self, msg):
289 return self.shell.complete(msg.content.line)
289 #from IPython.utils.io import rprint # dbg
290 #rprint('\n\n**MSG**\n\n', msg) # dbg
291 #import traceback; rprint(''.join(traceback.format_stack())) # dbg
292 c = msg['content']
293 try:
294 cpos = int(c['cursor_pos'])
295 except:
296 # If we don't get something that we can convert to an integer, at
297 # leasat attempt the completion guessing the cursor is at the end
298 # of the text
299 cpos = len(c['text'])
300 return self.shell.complete(c['text'], c['line'], cpos)
290 301
291 302 def _object_info(self, context):
292 303 symbol, leftover = self._symbol_from_context(context)
@@ -182,7 +182,7 b' class XReqSocketChannel(ZmqSocketChannel):'
182 182 self._queue_request(msg)
183 183 return msg['header']['msg_id']
184 184
185 def complete(self, text, line, block=None):
185 def complete(self, text, line, cursor_pos, block=None):
186 186 """Tab complete text, line, block in the kernel's namespace.
187 187
188 188 Parameters
@@ -199,7 +199,7 b' class XReqSocketChannel(ZmqSocketChannel):'
199 199 -------
200 200 The msg_id of the message sent.
201 201 """
202 content = dict(text=text, line=line)
202 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
203 203 msg = self.session.msg('complete_request', content)
204 204 self._queue_request(msg)
205 205 return msg['header']['msg_id']
General Comments 0
You need to be logged in to leave comments. Login now