#!/usr/bin/python"""Utility to open a filename given a partial filename string.Searches recursively and provides a prompt for disambiguation.lib.util - Copyright (c) 2006-2007 James Harris, Erin Houston$Id$"""__revision__ = '$Revision$'__all__ = [ 'Opener' ] import cursesfrom sys import argv, exitfrom os import walk, getcwd, sep, systemfrom os.path import joinfrom raze.optparse_ import OptionParserfrom raze.property_ import cached_propertyclass Opener(object): """ Helper object for opening files. """ command = 'vi' includes = [ '.py', '.xml', '.sql' ] excludes = [ 'svn-base', '.pyc', '.swp', 'tags' ] ordering = '123456789abcdefghijklmnopqrstuvwxyz' def __init__(self, top, *argv): self.top = top self.options = OptionParser(*argv) try: print '(got %s)' % self.options.arguments self.tokens = self.options.arguments[1:] except IndexError: print 'Not enough arguments. (got %s)' % self.options.arguments exit() def execute(self): """ Run curses window and open requested file. """ result = curses.wrapper(lambda screen: self.display(screen)) if result == ord('q'): return result = self.ordering.find(str(result - 48)) if result == -1: result = 0 system('%s %s' % (self.command, self.files[result])) def display(self, screen): """ Curses display function. """ screen.addstr(0, 0, 'Press key to open file, or ''q'' to exit') y = 0 for match in self.files: screen.addstr(y + 2, 0, '%s: %s' % (self.ordering[y], match)) y = y + 1 if y == len(self.ordering): screen.addstr(y, 0, '< more files not shown >') break return screen.getch() @cached_property def files(self): matches = self.walk() matches = self.match_includes(matches) matches = self.strip_excludes(matches) return matches def walk(self): """ Find files recursively from top that match token. """ def contains_all(name, tokens): for t in tokens: if t not in name: return False return True results = [] files = walk(self.top) for path, dirs, files in files: for file in files: if self.tokens[0] in file: path_matched = True if len(self.tokens) > 1: if not contains_all(path, self.tokens[1:]): path_matched = False if path_matched: local_path = path[len(getcwd())+1:] results.append(join(local_path, file)) return results def match_includes(self, names): """ Select names matching include list. """ if 'include' in self.options.dict: includes = self.options.include.value.split(' ') else: includes = self.includes results = [] for include in includes: for name in names: if name.find(include) != -1: results.append(name) continue return results def strip_excludes(self, names): """ Strips names matching exclude list. """ if 'exclude' in self.options.dict: excludes = self.options.exclude.value.split(' ') else: excludes = self.excludes results = [] for name in names: excluded = False for exclude in excludes: if name.find(exclude) != -1: excluded = True if not excluded: results.append(name) return resultsif __name__ == '__main__': opener = Opener(getcwd(), argv) opener.execute()