# HG changeset patch # User Steve Losh # Date 1348343657 14400 # Node ID d6c518c8ab395fda08ad3d3aa3661504b95d8f5a # Parent a8b6ed833a30a9069bdf3e31807909eba6b0f81f Implement type filtering. diff -r a8b6ed833a30 -r d6c518c8ab39 ffind --- a/ffind Sat Sep 22 15:40:00 2012 -0400 +++ b/ffind Sat Sep 22 15:54:17 2012 -0400 @@ -22,10 +22,30 @@ VCS_DIRS = ['.hg', '.git', '.svn'] +TYPE_FILE_REAL = 1 +TYPE_FILE_SYMLINK = 2 +TYPE_DIR_REAL = 3 +TYPE_DIR_SYMLINK = 4 + +TYPES_FILE_REAL = set([TYPE_FILE_REAL]) +TYPES_FILE_SYMLINK = set([TYPE_FILE_SYMLINK]) +TYPES_DIR_REAL = set([TYPE_DIR_REAL]) +TYPES_DIR_SYMLINK = set([TYPE_DIR_SYMLINK]) + +TYPES_FILE = TYPES_FILE_REAL | TYPES_FILE_SYMLINK +TYPES_DIR = TYPES_DIR_REAL | TYPES_DIR_SYMLINK + +TYPES_REAL = TYPES_FILE_REAL | TYPES_DIR_REAL +TYPES_SYMLINK = TYPES_FILE_SYMLINK | TYPES_DIR_SYMLINK + +TYPES_ALL = TYPES_FILE | TYPES_DIR + + # Global Options -------------------------------------------------------------- # (it's a prototype, shut up) options = None + # Output ---------------------------------------------------------------------- def out(s, line_ending='\n'): sys.stdout.write(s + line_ending) @@ -39,6 +59,19 @@ # Searching! ------------------------------------------------------------------ +def get_type(path): + link = os.path.islink(path) + dir = os.path.isdir(path) + + if link and dir: + return TYPE_DIR_SYMLINK + elif link and not dir: + return TYPE_FILE_SYMLINK + elif not link and dir: + return TYPE_DIR_REAL + elif not link and not dir: + return TYPE_FILE_REAL + def should_ignore(basename, path): if basename in VCS_DIRS: return True @@ -47,6 +80,10 @@ def match(query, path): def _match(): + if options.type != TYPES_ALL: + if get_type(path) not in options.type: + return False + if options.case == CASE_INSENSITIVE: return query.lower() in path.lower() else: @@ -126,13 +163,16 @@ help='ignore binary files') g.add_option('-r', '--restricted', action='store_true', default=False, - help="restricted search (skip VCS directories, parse all ignore files) (default)") + help="restricted search (skip VCS directories, " + "parse all ignore files) (default)") g.add_option('-q', '--semi-restricted', action='store_true', default=False, - help="semi-restricted search (don't parse VCS ignore files, but still skip VCS directories and parse .ffignore)") + help="semi-restricted search (don't parse VCS ignore files, " + "but still skip VCS directories and parse .ffignore)") g.add_option('-u', '--unrestricted', action='store_true', default=False, - help="unrestricted search (don't parse ignore files, but still skip VCS directories)") + help="unrestricted search (don't parse ignore files, but " + "still skip VCS directories)") g.add_option('-a', '--all', action='store_true', default=False, help="don't ignore anything (ALL files can match)") @@ -211,6 +251,30 @@ return p +def build_type_set(types): + if not types: + return TYPES_ALL + + result = set() + for c in types: + result = result | { + 'a': TYPES_ALL, + + 'e': TYPES_FILE_REAL, + 'x': TYPES_FILE_SYMLINK, + 'c': TYPES_DIR_REAL, + 'y': TYPES_DIR_SYMLINK, + + 'f': TYPES_FILE, + 'd': TYPES_DIR, + + 'r': TYPES_REAL, + 's': TYPES_SYMLINK, + }[c.lower()] + + return result + + def main(): global options @@ -243,6 +307,9 @@ else: options.case = CASE_INSENSITIVE + # --type + options.type = build_type_set(options.type) + # Go! search(query)