[IPython-User] Problem: Custom Tab-Completion through Pyreadline

Ville M. Vainio vivainio@gmail....
Thu Jul 1 05:58:26 CDT 2010


Did you try using the completer customization mechanisms that already exist in ipython?
--
Sent from my Nokia N900

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.scipy.org/pipermail/ipython-user/attachments/20100701/8b05576c/attachment.html 


More information about the IPython-User mailing list