Skip to content

Instantly share code, notes, and snippets.

@ralphbean
Created November 12, 2012 18:28
Show Gist options
  • Save ralphbean/4061003 to your computer and use it in GitHub Desktop.
Save ralphbean/4061003 to your computer and use it in GitHub Desktop.
Half-working filename tab-completer. Play with it--it mostly works, but you have to help it along more than you're used to at the command line.
#!/usr/bin/env python
import readline
import os
import re
# This will tab-complete from the working directory, starting from /, and going
# through the sub-directories, but it doesn't behave quite the way you expect.
# For instance, it chooses for you if there are two partial matches.
# The readline call to def complete_path does not pass a leading "/" in the "text"
# variable, so I had to start using get_line_buffer and really don't find much
# use for the variables "text" and "state".
#RE_SPACE = re.compile(".*\s+$", re.M) # Not sure what this does.
possible_completions = os.listdir(".")
# This will be changed to a class, so that the list possible_completions can be saved
# between calls, rather than using a global definition.
def complete_path(text, state):
# NOTE THAT THE LEADING / WILL NOT COME THROUGH IN text. This is why only
# the line buffer is used below, not the "text" field passed from readline.
# Changed the type of "line" to a string. (It was a list in the last
# version.)
line = readline.get_line_buffer()
print "\n" + str(line) + "\n"
try:
if line == "":
# Nothing has been typed yet, so the default starting path is the
# working directory.
possible_completions = os.listdir(".")
elif not "/" in line:
# The line is not empty, but does not contain a "/". This must be
# a partial file name in the working directory.
temporary_completion_list = os.listdir(".")
# Keep only the entries where the last sub-string after
# the last "/" matches partial_file_name.
possible_completions = []
for one_item in temporary_completion_list:
this_partial_file_name = one_item.rsplit("/",1)[1]
if this_partial_file_name == line:
possible_completions.append(one_item)
else:
# Need to treat a path that refers to a directory, as well as one
# that refers to a file or partial file name.
try:
# Assume that the line typed so far is a directory, and try to
# get a listing of its contents. This will handle either e.g.
# /home/jenny/mydir/ or /home/jenny/mydir
possible_completions = os.listdir(line)
except:
# In the final version, examine the exception--error 20 from os
# is "Not a directory" and will elucidate the problem.
# See if the path is a directory followed by a file name or
# partial file name. e.g. "/home/jenny/mydir/blah": if the
# path does not end in "/", strip off everything to the right
# of the last "/", and see if that is a valid directory.
if not line.endswith("/"):
# If it ends with "/", then it must be a directory name
# (valid or not).
try:
# Strip off the last word.
# Example: /home/jenny/mydir/blah --> /home/jenny/mydir/
path, partial_file_name = line.rsplit("/",1)
temporary_completion_list = os.listdir(path)
# Keep only the entries where the last sub-string after
# the last "/" matches partial_file_name.
possible_completions = []
for one_item in temporary_completion_list:
this_partial_file_name = one_item.rsplit("/",1)[1]
if this_partial_file_name == partial_file_name:
possible_completions.append(one_item)
### This is repeated code and can be moved to another
### method.
except:
# /home/jenny/mydir/ was not a valid directory.
try:
# See if the line refers to a directory followed by a
# If nothing works, don't try any more completion. The
# user will have to fix the path.
pass
except:
pass
for one_file in possible_completions:
if one_file.startswith(text) and state == 0:
return one_file
else:
state -= 1
print os.listdir("/home/hayes/testing.py")
readline.parse_and_bind("tab: complete")
readline.set_completer(complete_path)
while True:
file_name = raw_input("Enter file name: ")
print file_name
Copy link

ghost commented Nov 12, 2012

There's a new working version in good shape on gist https://gist.github.com/4040404/ with credits in the comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment