Permalink
Browse files

Merge pull request #3 from mrjbq7/master

Faster initialization by using length of shared prefix.
  • Loading branch information...
2 parents 23fe7a6 + 56491bd commit 0b118817cabc74d3fafd4c8fb69369c7a3a3b5ac @sethbc committed Nov 15, 2011
Showing with 82 additions and 12 deletions.
  1. +81 −11 plugin/fuzzy_file_finder.rb
  2. +1 −1 plugin/fuzzyfinder_textmate.vim
View
92 plugin/fuzzy_file_finder.rb
@@ -116,14 +116,22 @@ def initialize(directories=['.'], ceiling=10_000, ignores=nil, highlighter=Chara
# expand any paths with ~
@roots = directories.map { |d| File.expand_path(d) }.select { |d| File.directory?(d) }.uniq
- @shared_prefix = determine_shared_prefix
- @shared_prefix_re = Regexp.new("^#{Regexp.escape(shared_prefix)}" + (shared_prefix.empty? ? "" : "/"))
+ @shared_prefix = determine_shared_prefix.length
+ if @shared_prefix > 0
+ @shared_prefix += 1
+ end
@files = []
@cache = {}
@ceiling = ceiling
- @ignores = Array(ignores)
+ # change ignores to a regexp
+ if ignores != nil
+ globs = split_globs(ignores)
+ @ignores = Regexp.union(globs.map {|s| glob_to_pattern(s)})
+ else
+ @ignores = /.*/
+ end
@highlighted_match_class = highlighter
@@ -229,19 +237,13 @@ def follow_tree(directory)
if File.directory?(full) && File.readable?(full)
follow_tree(full)
- elsif !ignore?(full.sub(@shared_prefix_re, ""))
+ elsif !@ignores.match(full[@shared_prefix..-1])
files.push(FileSystemEntry.new(directory, entry, full))
raise TooManyEntries if files.length > ceiling
end
end
end
- # Returns +true+ if the given name matches any of the ignore
- # patterns.
- def ignore?(name)
- ignores.any? { |pattern| File.fnmatch(pattern, name) }
- end
-
# Takes the given pattern string "foo" and converts it to a new
# string "(f)([^/]*?)(o)([^/]*?)(o)" that can be used to create
# a regular expression.
@@ -255,6 +257,74 @@ def make_pattern(pattern)
end
end
+ # Takes a string of globs and splits them into an array
+ def split_globs(s)
+ globs = []
+ start = 0
+ offset = 0
+ braces = 0
+ loop {
+ i = s.index(/[:,{}]/, offset)
+
+ if i == nil
+ globs.push(s[start..-1])
+ break
+ end
+
+ if s[i].ord == '{'[0].ord
+ braces += 1
+ elsif s[i].ord == '}'[0].ord
+ braces -= 1
+ end
+
+ offset = i + 1
+
+ if braces == 0 &&
+ (s[i].ord == ":"[0].ord || s[i].ord == ","[0].ord)
+
+ if start < (i-1)
+ globs.push(s[start..i-1])
+ end
+
+ start = offset
+ end
+ }
+ globs
+ end
+
+ # Takes a glob and turns it into a regexp pattern.
+ def glob_to_pattern(s)
+ r = ['^']
+ curlies = 0
+ escaped = false
+ s.each_char {|c|
+ if ".()|+^$@%".include?(c)
+ r.push("\\#{c}")
+ elsif c == '*'
+ r.push(escaped ? "\\*" : ".*")
+ elsif c == '?'
+ r.push(escaped ? "\\." : ".")
+ elsif c == '{'
+ r.push(escaped ? "\\{" : "(")
+ curlies += 1 unless escaped
+ elsif c == '}' && curlies > 0
+ r.push(escaped ? "\\}" : ")")
+ curlies -= 1 unless escaped
+ elsif c == ',' && curlies > 0
+ r.push(escaped ? "," : "|")
+ elsif c == '\\'
+ r.push("\\\\") if escaped
+ escaped = !escaped
+ next
+ else
+ r.push(c)
+ end
+ escaped = false
+ }
+ r.push('$')
+ Regexp.new(r * "")
+ end
+
# Given a MatchData object +match+ and a number of "inside"
# segments to support, compute both the match score and the
# highlighted match string. The "inside segments" refers to how
@@ -310,7 +380,7 @@ def match_path(path, path_matches, path_regex, path_segments)
return path_matches[path] if path_matches.key?(path)
name_with_slash = path + "/" # add a trailing slash for matching the prefix
- matchable_name = name_with_slash.sub(@shared_prefix_re, "")
+ matchable_name = name_with_slash[@shared_prefix..-1]
matchable_name.chop! # kill the trailing slash
if path_regex
View
2 plugin/fuzzyfinder_textmate.vim
@@ -76,7 +76,7 @@ ruby << RUBY
fuzzy_roots = VIM.evaluate("g:fuzzy_roots")
roots = fuzzy_roots.respond_to?(:split) ? fuzzy_roots.split("\n") : fuzzy_roots
ceiling = VIM.evaluate("g:fuzzy_ceiling").to_i
- ignore = VIM.evaluate("g:fuzzy_ignore").split(/[;,]/)
+ ignore = VIM.evaluate("g:fuzzy_ignore")
FuzzyFileFinder.new(roots, ceiling, ignore)
end
end

0 comments on commit 0b11881

Please sign in to comment.