From ad410584c9be8c0557a33729d8faa74ab1a41097 Mon Sep 17 00:00:00 2001 From: Bob Farrell Date: Tue, 24 Jun 2008 16:18:19 +0100 Subject: [PATCH] My homie Brendogg axed me for manual display of the completion window Now there's an option to require hitting tab to display the completion window instead of having it pop up automatically as you type. You need to edit the source at the moment (change OPTS.auto_display_list), the next commit should have config file support. --- bpython.py | 68 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/bpython.py b/bpython.py index 74f6b9d..dc76efd 100644 --- a/bpython.py +++ b/bpython.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# bpython 0.5.0::fancy curses interface to the Python repl::Bob Farrell 2008 +# bpython 0.5.1::fancy curses interface to the Python repl::Bob Farrell 2008 # # The MIT License # @@ -49,6 +49,8 @@ class Dummy( object ): pass OPTS = Dummy() +OPTS.auto_display_list = True + try: from pygments import highlight from pygments.lexers import PythonLexer @@ -70,6 +72,10 @@ import pydoc # TODO: # +# Keyboard interrupt needs to tidy up the screen afterwards. +# +# Ability to require a keypress (e.g. tab) to display autocomplete +# list. # # No config file yet. This will allow things like "indent depth" for requiring # the user to hit return n times to signify the end of a code block. @@ -210,6 +216,7 @@ class Repl( object ): self.argspec = None self.tablen = None self.s = '' + self.list_win_visible = False if not OPTS.argspec: @@ -334,10 +341,25 @@ class Repl( object ): return getargspec( func ) - def complete( self ): + def complete( self, tab=False ): + """Wrap the _complete method to determine the visibility of list_win + since there can be several reasons why it won't be displayed; this + makes it more manageable.""" + + if self.list_win_visible and not OPTS.auto_display_list: + self.scr.touchwin() + self.list_win_visible = False + return + + if OPTS.auto_display_list or tab: + self.list_win_visible = self._complete( tab ) + return + + def _complete( self, tab=False ): """Construct a full list of possible completions and construct and display them in a window. Also check if there's an available argspec - (via the inspect module) and bang that on top of the completions too.""" + (via the inspect module) and bang that on top of the completions too. + The return value is whether the list_win is visible or not.""" words = [] i = 0 @@ -349,7 +371,7 @@ class Repl( object ): if not (cw or self.argspec): self.scr.redrawwin() self.scr.refresh() - return None + return False if not cw: self.matches = [] @@ -365,12 +387,19 @@ class Repl( object ): if (e or not self.completer.matches) and not self.argspec: self.scr.redrawwin() - return + return False if not e and self.completer.matches: self.matches = sorted( set( self.completer.matches ) ) # remove duplicates and # restore order + + if len( self.matches ) == 1 and not OPTS.auto_display_list: + self.list_win_visible = True + self.tab() + return False + self.show_list( self.matches, self.argspec ) + return True def show_list( self, items, topline=None ): shared = Dummy() @@ -419,6 +448,7 @@ class Repl( object ): v_items.append( i[:max_w-3] ) if not lsize(): del v_items[-1] + v_items[-1] = '...' break rows = shared.rows @@ -454,14 +484,22 @@ class Repl( object ): for ix, i in enumerate(v_items): padding = (wl - len(i)) * ' ' self.list_win.addstr( i + padding, curses.color_pair( self._C["c"]+1 ) ) - if (cols == 1) or (ix and not ix % cols and ix < len(v_items)): + if ((cols == 1) or (ix and not ix % cols)) and ix+1 < len(v_items): self.list_win.addstr( '\n ' ) + +# XXX: After all the trouble I had with sizing the list box (I'm not very good +# at that type of thing) I decided to do this bit of tidying up here just to make +# sure there's no unnececessary blank lines, it makes things look nicer. :) + y = self.list_win.getyx()[0] + self.list_win.resize(y + 2, w ) self.statusbar.win.touchwin() self.statusbar.win.noutrefresh() self.list_win.border() self.scr.touchwin() + self.scr.cursyncup() self.scr.noutrefresh() + self.scr.move( *self.scr.getyx() ) self.list_win.refresh() @@ -996,12 +1034,20 @@ class Repl( object ): self.tablen = self.scr.getyx()[1] - x return True + if not OPTS.auto_display_list and not self.list_win_visible: + self.complete( tab=True ) + return True + cw = self.cw() - if cw: - b = self.strbase( self.matches ) - if b: - self.s += b[ len( cw ) : ] - self.print_line( self.s ) + if not cw: + return True + + b = self.strbase( self.matches ) + if b: + self.s += b[ len( cw ) : ] + self.print_line( self.s ) + if len( self.matches ) == 1 and OPTS.auto_display_list: + self.scr.touchwin() return True def strbase( self, l ):