]> git.r.bdr.sh - rbdr/dotfiles/blob - vim/tmp/command_t/ruby/command-t/scanner/file_scanner.rb
Relative line numbers for vim
[rbdr/dotfiles] / vim / tmp / command_t / ruby / command-t / scanner / file_scanner.rb
1 # Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are met:
5 #
6 # 1. Redistributions of source code must retain the above copyright notice,
7 # this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright notice,
9 # this list of conditions and the following disclaimer in the documentation
10 # and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
16 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22 # POSSIBILITY OF SUCH DAMAGE.
23
24 require 'command-t/vim'
25 require 'command-t/scanner'
26
27 module CommandT
28 # Reads the current directory recursively for the paths to all regular files.
29 class FileScanner < Scanner
30 class FileLimitExceeded < ::RuntimeError; end
31
32 def initialize path = Dir.pwd, options = {}
33 @path = path
34 @max_depth = options[:max_depth] || 15
35 @max_files = options[:max_files] || 10_000
36 @scan_dot_directories = options[:scan_dot_directories] || false
37 end
38
39 def paths
40 return @paths unless @paths.nil?
41 begin
42 @paths = []
43 @depth = 0
44 @files = 0
45 @prefix_len = @path.chomp('/').length
46 add_paths_for_directory @path, @paths
47 rescue FileLimitExceeded
48 end
49 @paths
50 end
51
52 def flush
53 @paths = nil
54 end
55
56 def path= str
57 if @path != str
58 @path = str
59 flush
60 end
61 end
62
63 private
64
65 def path_excluded? path
66 # first strip common prefix (@path) from path to match VIM's behavior
67 path = path[(@prefix_len + 1)..-1]
68 path = VIM::escape_for_single_quotes path
69 ::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
70 end
71
72 def add_paths_for_directory dir, accumulator
73 Dir.foreach(dir) do |entry|
74 next if ['.', '..'].include?(entry)
75 path = File.join(dir, entry)
76 unless path_excluded?(path)
77 if File.file?(path)
78 @files += 1
79 raise FileLimitExceeded if @files > @max_files
80 accumulator << path[@prefix_len + 1..-1]
81 elsif File.directory?(path)
82 next if @depth >= @max_depth
83 next if (entry.match(/\A\./) && !@scan_dot_directories)
84 @depth += 1
85 add_paths_for_directory path, accumulator
86 @depth -= 1
87 end
88 end
89 end
90 rescue Errno::EACCES
91 # skip over directories for which we don't have access
92 end
93 end # class FileScanner
94 end # module CommandT