From e11dd706a298c2d2eb95bf2537b76cf7e846de2b 2008-07-17 08:04:52 From: Gael Varoquaux Date: 2008-07-17 08:04:52 Subject: [PATCH] Proper tab completion that actually completes. --- diff --git a/IPython/frontend/linefrontendbase.py b/IPython/frontend/linefrontendbase.py index 462c170..2c634f0 100644 --- a/IPython/frontend/linefrontendbase.py +++ b/IPython/frontend/linefrontendbase.py @@ -23,6 +23,19 @@ import IPython from frontendbase import FrontEndBase from IPython.kernel.core.interpreter import Interpreter + +def common_prefix(strings): + ref = strings[0] + prefix = '' + for size in range(len(ref)): + test_prefix = ref[:size+1] + for string in strings[1:]: + if not string.startswith(test_prefix): + return prefix + prefix = test_prefix + + return prefix + #------------------------------------------------------------------------------- # Base class for the line-oriented front ends #------------------------------------------------------------------------------- @@ -49,20 +62,24 @@ class LineFrontEndBase(FrontEndBase): % IPython.__version__ - def complete(self, token): - """Complete token in engine's user_ns + def complete(self, line): + """Complete line in engine's user_ns Parameters ---------- - token : string + line : string Result ------ - Deferred result of - IPython.kernel.engineservice.IEngineBase.complete + The replacement for the line and the list of possible completions. """ - - return self.shell.complete(token) + completions = self.shell.complete(line) + complete_sep = re.compile('[\s\{\}\[\]\(\)\=]') + if completions: + prefix = common_prefix(completions) + residual = complete_sep.split(line)[:-1] + line = line[:-len(residual)] + prefix + return line, completions def render_result(self, result): diff --git a/IPython/frontend/wx/console_widget.py b/IPython/frontend/wx/console_widget.py index 1d4e29e..db69dfc 100644 --- a/IPython/frontend/wx/console_widget.py +++ b/IPython/frontend/wx/console_widget.py @@ -280,14 +280,30 @@ class ConsoleWidget(editwindow.EditWindow): def write_completion(self, possibilities, mode=None): if mode=='text' or self.autocomplete_mode == 'text': - max_len = len(max(possibilities, key=len)) + # FIXME: This is non Wx specific and needs to be moved into + # the base class. current_buffer = self.get_current_edit_buffer() self.write('\n') + max_len = len(max(possibilities, key=len)) + + #now we check how much symbol we can put on a line... + chars_per_line = self.GetSize()[0]/self.GetCharWidth() + symbols_per_line = max(1, chars_per_line/max_len) + + pos = 1 + buf = [] for symbol in possibilities: - self.write(symbol.ljust(max_len)) + if pos < symbols_per_line: + buf.append(symbol.ljust(max_len)) + pos += 1 + else: + buf.append(symbol.rstrip() +'\n') + pos = 1 + self.write(''.join(buf)) self.new_prompt(self.prompt % (self.last_result['number'] + 1)) self.replace_current_edit_buffer(current_buffer) + else: self.AutoCompSetIgnoreCase(False) self.AutoCompSetAutoHide(False) diff --git a/IPython/frontend/wx/wx_frontend.py b/IPython/frontend/wx/wx_frontend.py index 20fccaa..9da5747 100644 --- a/IPython/frontend/wx/wx_frontend.py +++ b/IPython/frontend/wx/wx_frontend.py @@ -69,13 +69,13 @@ class IPythonWxController(PrefilterFrontEnd, ConsoleWidget): mode can be 'text', 'popup' or 'none' to use default. """ line = self.get_current_edit_buffer() - completions = self.complete(line) - if len(completions)>0: + new_line, completions = self.complete(line) + if len(completions)>1: self.write_completion(completions, mode=mode) + self.replace_current_edit_buffer(new_line) def do_calltip(self): - # compute the length ot the last word separators = [' ', '(', '[', '{', '\n', '\t'] symbol = self.get_current_edit_buffer() for separator in separators: @@ -93,6 +93,7 @@ class IPythonWxController(PrefilterFrontEnd, ConsoleWidget): symbol = getattr(symbol, name) self.CallTipShow(self.GetCurrentPos(), symbol) + def update_completion(self): line = self.get_current_edit_buffer() if self.AutoCompActive() and not line[-1] == '.':