##// END OF EJS Templates
Multiple improvements to tab completion....
Fernando Perez -
r2839:8cff4913
parent child
Show More
@@ -82,7 +82,6 from IPython.core.prefilter import ESC_MAGIC
82 from IPython.utils import generics
82 from IPython.utils import generics
83 from IPython.utils.frame import debugx
83 from IPython.utils.frame import debugx
84 from IPython.utils.dir2 import dir2
84 from IPython.utils.dir2 import dir2
85 import IPython.utils.rlineimpl as readline
86
85
87 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
88 # Globals
87 # Globals
@@ -107,6 +106,18 def protect_filename(s):
107 for ch in s])
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 def single_dir_expand(matches):
121 def single_dir_expand(matches):
111 "Recursively expand match lists containing a single dir."
122 "Recursively expand match lists containing a single dir."
112
123
@@ -249,8 +260,8 class Completer:
249 class IPCompleter(Completer):
260 class IPCompleter(Completer):
250 """Extension of the completer class with IPython-specific features"""
261 """Extension of the completer class with IPython-specific features"""
251
262
252 def __init__(self,shell,namespace=None,global_namespace=None,
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 """IPCompleter() -> completer
265 """IPCompleter() -> completer
255
266
256 Return a completer object suitable for use by the readline library
267 Return a completer object suitable for use by the readline library
@@ -273,17 +284,31 class IPCompleter(Completer):
273 to be completed explicitly starts with one or more underscores.
284 to be completed explicitly starts with one or more underscores.
274
285
275 - If alias_table is supplied, it should be a dictionary of aliases
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 Completer.__init__(self,namespace,global_namespace)
294 Completer.__init__(self,namespace,global_namespace)
279
295
280 self.magic_escape = ESC_MAGIC
296 self.magic_escape = ESC_MAGIC
281 self.readline = readline
297
282 delims = self.readline.get_completer_delims()
298 # Readline-dependent code
283 delims = delims.replace(self.magic_escape,'')
299 self.use_readline = use_readline
284 self.readline.set_completer_delims(delims)
300 if use_readline:
285 self.get_line_buffer = self.readline.get_line_buffer
301 import IPython.utils.rlineimpl as readline
286 self.get_endidx = self.readline.get_endidx
302 self.readline = readline
303 delims = self.readline.get_completer_delims()
304 delims = delims.replace(self.magic_escape,'')
305 self.readline.set_completer_delims(delims)
306 self.get_line_buffer = self.readline.get_line_buffer
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 self.omit__names = omit__names
312 self.omit__names = omit__names
288 self.merge_completions = shell.readline_merge_completions
313 self.merge_completions = shell.readline_merge_completions
289 self.shell = shell.shell
314 self.shell = shell.shell
@@ -311,7 +336,8 class IPCompleter(Completer):
311 self.file_matches,
336 self.file_matches,
312 self.magic_matches,
337 self.magic_matches,
313 self.alias_matches,
338 self.alias_matches,
314 self.python_func_kw_matches]
339 self.python_func_kw_matches,
340 ]
315
341
316 # Code contributed by Alex Schmolck, for ipython/emacs integration
342 # Code contributed by Alex Schmolck, for ipython/emacs integration
317 def all_completions(self, text):
343 def all_completions(self, text):
@@ -414,7 +440,8 class IPCompleter(Completer):
414 protect_filename(f) for f in m0]
440 protect_filename(f) for f in m0]
415
441
416 #print 'mm',matches # dbg
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 def magic_matches(self, text):
446 def magic_matches(self, text):
420 """Match magics"""
447 """Match magics"""
@@ -583,76 +610,113 class IPCompleter(Completer):
583
610
584 return None
611 return None
585
612
586 def complete(self, text, state, line_buffer=None):
613 def complete(self, text, line_buffer, cursor_pos=None):
587 """Return the next possible completion for 'text'.
614 """Return the state-th possible completion for 'text'.
588
615
589 This is called successively with state == 0, 1, 2, ... until it
616 This is called successively with state == 0, 1, 2, ... until it
590 returns None. The completion should begin with 'text'.
617 returns None. The completion should begin with 'text'.
591
618
592 :Keywords:
619 Parameters
593 - line_buffer: string
620 ----------
594 If not given, the completer attempts to obtain the current line buffer
621 text : string
595 via readline. This keyword allows clients which are requesting for
622 Text to perform the completion on.
596 text completions in non-readline contexts to inform the completer of
623
597 the entire text.
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.
629
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.
598 """
633 """
599
634
600 #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg
635 magic_escape = self.magic_escape
636 self.full_lbuf = line_buffer
637 self.lbuf = self.full_lbuf[:cursor_pos]
601
638
602 # if there is only a tab on a line with only whitespace, instead
639 if text.startswith('~'):
603 # of the mostly useless 'do you want to see all million
640 text = os.path.expanduser(text)
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).
607
641
608 # It should be noted that at least pyreadline still shows
642 # Start with a clean slate of completions
609 # file completions - is there a way around it?
643 self.matches[:] = []
610
644 custom_res = self.dispatch_custom_completer(text)
611 # don't apply this on 'dumb' terminals, such as emacs buffers, so we
645 if custom_res is not None:
612 # don't interfere with their own tab-completion mechanism.
646 # did custom completers produce something?
613 if line_buffer is None:
647 self.matches = custom_res
614 self.full_lbuf = self.get_line_buffer()
615 else:
648 else:
616 self.full_lbuf = line_buffer
649 # Extend the list of completions with the results of each
617
650 # matcher, so we return results to the user from all
618 if not (self.dumb_terminal or self.full_lbuf.strip()):
651 # namespaces.
619 self.readline.insert_text('\t')
652 if self.merge_completions:
620 return None
653 self.matches = []
621
654 for matcher in self.matchers:
622 magic_escape = self.magic_escape
655 self.matches.extend(matcher(text))
656 else:
657 for matcher in self.matchers:
658 self.matches = matcher(text)
659 if self.matches:
660 break
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'.
623
671
624 self.lbuf = self.full_lbuf[:self.get_endidx()]
672 This is called successively with state == 0, 1, 2, ... until it
673 returns None. The completion should begin with 'text'.
625
674
626 try:
675 Parameters
627 if text.startswith('~'):
676 ----------
628 text = os.path.expanduser(text)
677 text : string
629 if state == 0:
678 Text to perform the completion on.
630 custom_res = self.dispatch_custom_completer(text)
679
631 if custom_res is not None:
680 state : int
632 # did custom completers produce something?
681 Counter used by readline.
633 self.matches = custom_res
682
634 else:
683 """
635 # Extend the list of completions with the results of each
684
636 # matcher, so we return results to the user from all
685 #print "rlcomplete! '%s' %s" % (text, state) # dbg
637 # namespaces.
686
638 if self.merge_completions:
687 if state==0:
639 self.matches = []
688 self.full_lbuf = line_buffer = self.get_line_buffer()
640 for matcher in self.matchers:
689 cursor_pos = self.get_endidx()
641 self.matches.extend(matcher(text))
690
642 else:
691 # if there is only a tab on a line with only whitespace, instead of
643 for matcher in self.matchers:
692 # the mostly useless 'do you want to see all million completions'
644 self.matches = matcher(text)
693 # message, just do the right thing and give the user his tab!
645 if self.matches:
694 # Incidentally, this enables pasting of tabbed text from an editor
646 break
695 # (as long as autoindent is off).
647 self.matches = list(set(self.matches))
696
648 try:
697 # It should be noted that at least pyreadline still shows file
649 #print "MATCH: %r" % self.matches[state] # dbg
698 # completions - is there a way around it?
650 return self.matches[state]
699
651 except IndexError:
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()
652 return None
705 return None
653 except:
706
654 #from IPython.core.ultratb import AutoFormattedTB; # dbg
707 # This method computes the self.matches array
655 #tb=AutoFormattedTB('Verbose');tb() #dbg
708 self.complete(text, line_buffer, cursor_pos)
656
709
657 # If completion fails, don't annoy the user.
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
718 try:
719 return self.matches[state]
720 except IndexError:
658 return None
721 return None
722
@@ -1303,7 +1303,7 class InteractiveShell(Configurable, Magic):
1303 else:
1303 else:
1304 if exception_only:
1304 if exception_only:
1305 stb = ['An exception has occurred, use %tb to see '
1305 stb = ['An exception has occurred, use %tb to see '
1306 'the full traceback.']
1306 'the full traceback.\n']
1307 stb.extend(self.InteractiveTB.get_exception_only(etype,
1307 stb.extend(self.InteractiveTB.get_exception_only(etype,
1308 value))
1308 value))
1309 else:
1309 else:
@@ -1327,7 +1327,9 class InteractiveShell(Configurable, Magic):
1327 Subclasses may override this method to put the traceback on a different
1327 Subclasses may override this method to put the traceback on a different
1328 place, like a side channel.
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 def showsyntaxerror(self, filename=None):
1334 def showsyntaxerror(self, filename=None):
1333 """Display the syntax error that just occurred.
1335 """Display the syntax error that just occurred.
@@ -1367,13 +1369,24 class InteractiveShell(Configurable, Magic):
1367 # Things related to tab completion
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 """Return a sorted list of all possible completions on text.
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.
1376
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.
1389
1377 This is a wrapper around the completion mechanism, similar to what
1390 This is a wrapper around the completion mechanism, similar to what
1378 readline does at the command line when the TAB key is hit. By
1391 readline does at the command line when the TAB key is hit. By
1379 exposing it as a method, it can be used by other non-readline
1392 exposing it as a method, it can be used by other non-readline
@@ -1395,23 +1408,7 class InteractiveShell(Configurable, Magic):
1395
1408
1396 # Inject names into __builtin__ so we can complete on the added names.
1409 # Inject names into __builtin__ so we can complete on the added names.
1397 with self.builtin_trap:
1410 with self.builtin_trap:
1398 complete = self.Completer.complete
1411 return self.Completer.complete(text,line_buffer=text)
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
1415
1412
1416 def set_custom_completer(self,completer,pos=0):
1413 def set_custom_completer(self,completer,pos=0):
1417 """Adds a new custom completer function.
1414 """Adds a new custom completer function.
@@ -1425,7 +1422,7 class InteractiveShell(Configurable, Magic):
1425
1422
1426 def set_completer(self):
1423 def set_completer(self):
1427 """Reset readline's completer to be our own."""
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 def set_completer_frame(self, frame=None):
1427 def set_completer_frame(self, frame=None):
1431 """Set the frame of the completer."""
1428 """Set the frame of the completer."""
@@ -1497,7 +1494,7 class InteractiveShell(Configurable, Magic):
1497 % inputrc_name)
1494 % inputrc_name)
1498
1495
1499 # save this in sys so embedded copies can restore it properly
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 self.set_completer()
1498 self.set_completer()
1502
1499
1503 # Configure readline according to user's prefs
1500 # Configure readline according to user's prefs
@@ -360,6 +360,10 class TBTools(object):
360 self.color_scheme_table.set_active_scheme('NoColor')
360 self.color_scheme_table.set_active_scheme('NoColor')
361 self.Colors = self.color_scheme_table.active_colors
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 def text(self, etype, value, tb, tb_offset=None, context=5):
367 def text(self, etype, value, tb, tb_offset=None, context=5):
364 """Return formatted traceback.
368 """Return formatted traceback.
365
369
@@ -367,7 +371,7 class TBTools(object):
367 """
371 """
368 tb_list = self.structured_traceback(etype, value, tb,
372 tb_list = self.structured_traceback(etype, value, tb,
369 tb_offset, context)
373 tb_offset, context)
370 return '\n'.join(tb_list)
374 return self.stb2text(tb_list)
371
375
372 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
376 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
373 context=5, mode=None):
377 context=5, mode=None):
@@ -1008,6 +1012,11 class FormattedTB(VerboseTB, ListTB):
1008
1012
1009 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
1013 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
1010 call_pdb=call_pdb,include_vars=include_vars)
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 self.set_mode(mode)
1020 self.set_mode(mode)
1012
1021
1013 def _extract_tb(self,tb):
1022 def _extract_tb(self,tb):
@@ -1016,10 +1025,9 class FormattedTB(VerboseTB, ListTB):
1016 else:
1025 else:
1017 return None
1026 return None
1018
1027
1019 def structured_traceback(self, etype, value, tb, tb_offset=None,
1028 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1020 context=5, mode=None):
1021 tb_offset = self.tb_offset if tb_offset is None else tb_offset
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 if mode in self.verbose_modes:
1031 if mode in self.verbose_modes:
1024 # Verbose modes need a full traceback
1032 # Verbose modes need a full traceback
1025 return VerboseTB.structured_traceback(
1033 return VerboseTB.structured_traceback(
@@ -1035,16 +1043,9 class FormattedTB(VerboseTB, ListTB):
1035 self, etype, value, elist, tb_offset, context
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):
1046 def stb2text(self, stb):
1039 """Return formatted traceback.
1047 """Convert a structured traceback (a list) to a string."""
1040
1048 return self.tb_join_char.join(stb)
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)
1048
1049
1049
1050
1050 def set_mode(self,mode=None):
1051 def set_mode(self,mode=None):
@@ -1063,6 +1064,8 class FormattedTB(VerboseTB, ListTB):
1063 self.mode = mode
1064 self.mode = mode
1064 # include variable details only in 'Verbose' mode
1065 # include variable details only in 'Verbose' mode
1065 self.include_vars = (self.mode == self.valid_modes[2])
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 # some convenient shorcuts
1070 # some convenient shorcuts
1068 def plain(self):
1071 def plain(self):
@@ -1117,12 +1120,12 class AutoFormattedTB(FormattedTB):
1117 print "\nKeyboardInterrupt"
1120 print "\nKeyboardInterrupt"
1118
1121
1119 def structured_traceback(self, etype=None, value=None, tb=None,
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 if etype is None:
1124 if etype is None:
1122 etype,value,tb = sys.exc_info()
1125 etype,value,tb = sys.exc_info()
1123 self.tb = tb
1126 self.tb = tb
1124 return FormattedTB.structured_traceback(
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 class SyntaxTB(ListTB):
1151 self.last_syntax_error = None
1154 self.last_syntax_error = None
1152 return e
1155 return e
1153
1156
1154 def text(self, etype, value, tb, tb_offset=None, context=5):
1157 def stb2text(self, stb):
1155 """Return formatted traceback.
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 # module testing (minimal)
1163 # module testing (minimal)
@@ -293,8 +293,15 class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
293
293
294 # Send the completion request to the kernel
294 # Send the completion request to the kernel
295 text = '.'.join(context)
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 self._complete_id = self.kernel_manager.xreq_channel.complete(
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 self._complete_pos = self._get_cursor().position()
305 self._complete_pos = self._get_cursor().position()
299 return True
306 return True
300
307
@@ -286,7 +286,18 class Kernel(Configurable):
286 return value
286 return value
287
287
288 def _complete(self, msg):
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 def _object_info(self, context):
302 def _object_info(self, context):
292 symbol, leftover = self._symbol_from_context(context)
303 symbol, leftover = self._symbol_from_context(context)
@@ -182,7 +182,7 class XReqSocketChannel(ZmqSocketChannel):
182 self._queue_request(msg)
182 self._queue_request(msg)
183 return msg['header']['msg_id']
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 """Tab complete text, line, block in the kernel's namespace.
186 """Tab complete text, line, block in the kernel's namespace.
187
187
188 Parameters
188 Parameters
@@ -199,7 +199,7 class XReqSocketChannel(ZmqSocketChannel):
199 -------
199 -------
200 The msg_id of the message sent.
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 msg = self.session.msg('complete_request', content)
203 msg = self.session.msg('complete_request', content)
204 self._queue_request(msg)
204 self._queue_request(msg)
205 return msg['header']['msg_id']
205 return msg['header']['msg_id']
General Comments 0
You need to be logged in to leave comments. Login now