<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="generator" content="Osso Notes">
    <title></title></head>
<body>
<p>Did you try using the completer customization mechanisms that already exist in ipython?
<br><font color="#999999">--</font>
<br><font color="#999999">Sent from my Nokia N900</font>
<br>
<br>----- Original message -----
<br>&gt; Hello,
<br>&gt; 
<br>&gt; I'm helping build a cross-platform custom tab completer for a Python
<br>&gt; research project, and I'm using Pyreadline to substitute for the the
<br>&gt; lack of readline on Windows. However, upon installation, despite trying
<br>&gt; to set-up the custom tab completion through the use of readline's
<br>&gt; set_completer function, pyreadline automatically uses the completer
<br>&gt; under basemode.py, shown when it printed out a list of files in the
<br>&gt; directory when I tabbed despite changing the custom tab complete
<br>&gt; function to raise an exception instead. When I ran through the code
<br>&gt; using the Python Debugger, I saw that set_completer(completer.complete)
<br>&gt; was clearly called under rlmain.py, yet the custom tab complete function
<br>&gt; wasn't implemented in the readline somehow.
<br>&gt; 
<br>&gt; I'm using version 1.5 of Pyreadline, installed under a custom directory
<br>&gt; of the research project that essentially uses Python 2.5. I'm testing
<br>&gt; all this through Windows command prompt. I might have overlooked some
<br>&gt; details since I'm still fairly new to Python, but any help would be much
<br>&gt; appreciated.
<br>&gt; 
<br>&gt; For reference, I didn't write the TabCompleter code, and it works when
<br>&gt; used in a Unix system with their GNU Readline.
<br>&gt; 
<br>&gt; Thanks,
<br>&gt; Alan Loh
<br>&gt; 
<br>&gt; 
<br>&gt; 
<br>&gt; This is the code for the custom tab completion part of the project:
<br>&gt; 
<br>&gt; tabcompletion = True
<br>&gt; try:
<br>&gt;&nbsp; &nbsp; &#32;import readline
<br>&gt; except ImportError:
<br>&gt;&nbsp; &nbsp; &#32;print "Auto tab completion is off, because it is not available on your
<br>&gt; operating system."&nbsp; &#32;tabcompletion = False
<br>&gt; .
<br>&gt; .
<br>&gt; .
<br>&gt;&nbsp; &nbsp; &#32;# Set up the tab completion environment
<br>&gt;&nbsp; &nbsp; &#32;if tabcompletion:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;completer = TabCompleter()
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;readline.parse_and_bind("tab: complete")
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;readline.set_completer_delims(" ")
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;readline.set_completer(completer.complete)
<br>&gt; 
<br>&gt; 
<br>&gt; 
<br>&gt; ...and this is the TabCompleter class I'm trying to help implement.
<br>&gt; 
<br>&gt; 
<br>&gt; 
<br>&gt; class TabCompleter:
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &#32;# Constructor that initializes all the private variables
<br>&gt;&nbsp; &nbsp; &#32;def __init__(self):
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# list of files that match the directory of the given prefix
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;self._words = []
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# list of files that match the given prefix
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;self._matching_words = []
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;self._prefix = None
<br>&gt; 
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &#32;# Returns the path from a given prefix, by extracting the string up to
<br>&gt; the&nbsp; &#32;# last forward slash in the prefix. If no forward slash is found,
<br>&gt; returns an&nbsp; &#32;# empty string.
<br>&gt;&nbsp; &nbsp; &#32;def _getpath(self, prefix):
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;slashpos = prefix.rfind("/")
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;currentpath = ""
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;if slashpos &gt; -1:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;currentpath = prefix[0 : slashpos+1]
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;return currentpath
<br>&gt; 
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &#32;# Returns the file name, or a part of the file name, from a given
<br>&gt; prefix, by&nbsp; &#32;# extracting the string after the last forward slash in the
<br>&gt; prefix. If no&nbsp; &#32;# forward slash is found, returns an empty string.
<br>&gt;&nbsp; &nbsp; &#32;def _getfilename(self, prefix):
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# Find the last occurrence of the slash (if any), as it separates
<br>&gt; the path&nbsp; &nbsp; &nbsp; &#32;# and the file name.
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;slashpos = prefix.rfind("/")
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;filename = ""
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# If slash exists and there are characters after the last slash,
<br>&gt; then the&nbsp; &nbsp; &nbsp; &#32;# file name is whatever that follows the last slash.
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;if slashpos &gt; -1 and slashpos+1 &lt;= len(prefix)-1:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;filename = prefix[slashpos+1:]
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# If no slash is found, then we assume that the entire user input is
<br>&gt; the&nbsp; &nbsp; &nbsp; &#32;# prefix of a file name because it does not contain a directory
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;elif slashpos == -1:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;filename = prefix
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# If both cases fail, then the entire user input is the name of a
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# directory. Thus, we return the file name as an empty string.
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;return filename
<br>&gt; 
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &#32;# Returns a list of file names that start with the given prefix.
<br>&gt;&nbsp; &nbsp; &#32;def _listfiles(self, prefix):
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# Find the directory specified by the prefix
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;currentpath = self._getpath(prefix)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;if not currentpath:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;currentpath = "./"
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;filelist = []
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# Attempt to list files from the directory
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;try:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;currentpath = os.path.expanduser(currentpath)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;filelist = os.listdir(currentpath)
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;except:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;# We are silently dropping all exceptions because the directory
<br>&gt; specified&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;# by the prefix may be incorrect. In this case, we're
<br>&gt; returning an empty&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;# list, similar to what you would get when you
<br>&gt; TAB a wrong name in the&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;# Unix shell.
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;pass
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;finally:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;return filelist
<br>&gt; 
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &#32;# The completer function required as a callback by the readline
<br>&gt; module. See&nbsp; &#32;# also
<br>&gt; <a href="http://docs.python.org/library/readline.html#readline.set_completer&nbsp">http://docs.python.org/library/readline.html#readline.set_completer&nbsp</a>; &#32;def
<br>&gt; complete(self, prefix, index):
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;# If the user updates the prefix, then we list files that start with
<br>&gt; the&nbsp; &nbsp; &nbsp; &#32;# prefix.
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;if prefix != self._prefix:
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;self._words = self._listfiles(prefix)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;fn = self._getfilename(prefix)
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;# Find the files that match the prefix
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;self._matching_words = []
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;for word in self._words:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;if word.startswith(fn):
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;self._matching_words.append(word)
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;self._prefix = prefix
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;try:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;return self._getpath(prefix) + self._matching_words[index]
<br>&gt; 
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &#32;except IndexError:
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;return None
<br>&gt; 
<br><br></p>
</body>
</html>