Class: Utils::Finder

Inherits:
Object show all
Includes:
Term::ANSIColor, Tins::Find, Patterns
Defined in:
lib/utils/finder.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Patterns

#choose

Constructor Details

#initialize(opts = {}) ⇒ Finder

The initialize method sets up the finder instance with the provided options.

This method configures the finder by processing the input options, including arguments, root directories, and pattern settings. It initializes the pattern matcher based on the specified options and prepares the index for searching.

Options Hash (opts):

  • :args (Hash)

    the argument options for the finder

  • :roots (Array)

    the root directories to search in

  • :config (Utils::ConfigFile)

    the configuration file object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/utils/finder.rb', line 23

def initialize(opts = {})
  @args  = opts[:args] || {}
  @roots = discover_roots(opts[:roots])
  @config = opts[:config] || Utils::ConfigFile.new
  if @args[?l] || @args[?L]
    @pattern = nil
  else
    pattern_opts = opts.subhash(:pattern) | {
      :cset  => @args[?a],
      :icase => @args[?i] != ?n,
    }
    @pattern = choose(@args[?p], pattern_opts)
  end
  @paths  = []
  reset_index
end

Instance Attribute Details

#outputObject (readonly)

The output reader method provides access to the output value.



53
54
55
# File 'lib/utils/finder.rb', line 53

def output
  @output
end

#pathsArray<String> (readonly)

The paths reader method provides access to the array of file paths that have been processed or collected.

This method returns the internal array containing the file paths, allowing external code to read the current set of paths without modifying the original collection.



48
49
50
# File 'lib/utils/finder.rb', line 48

def paths
  @paths
end

Instance Method Details

#build_pathsArray

The build_paths method constructs a list of file system paths by traversing the configured root directories.

This method iterates through the specified root directories and collects all file system entries, applying filtering logic to exclude certain directories and files based on configuration settings. It handles both regular files and directories, ensuring that directory entries are properly marked with a trailing slash for distinction. The resulting paths are deduplicated before being returned.

marked by a trailing slash



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/utils/finder.rb', line 67

def build_paths
  paths = []

  visit = -> filename {
    s  = filename.stat
    bn = filename.pathname.basename
    if !s ||
        s.directory? && @config.discover.prune?(bn) ||
        s.file? && @config.discover.skip?(bn)
    then
      @args[?v] and warn "Pruning #{filename.inspect}."
      prune
    end
    true
  }
  find(*@roots, visit: visit) do |filename|
    filename.stat.directory? and filename << ?/
    paths << filename
  end
  paths.uniq!
  paths
end

#create_pathsArray

The create_paths method generates and stores path information by building a list of paths, writing them to a secure file, and then returning the list of paths.

to the index file



114
115
116
117
118
119
120
# File 'lib/utils/finder.rb', line 114

def create_paths
  paths = build_paths
  File.secure_write(index_path) do |output|
    output.puts paths
  end
  paths
end

#index_pathString

The index_path method generates a unique file path for storing finder results.

This method creates a standardized location in the temporary directory for caching finder path data based on the root directories being processed. It ensures uniqueness by hashing the sorted root paths and uses the current script name as part of the directory structure.



99
100
101
102
103
104
105
106
# File 'lib/utils/finder.rb', line 99

def index_path
  roots = @roots.map { |r| File.expand_path(r) }.uniq.sort
  filename = "finder-paths-" +
    Digest::MD5.new.update(roots.inspect).hexdigest
  dirname = File.join(Dir.tmpdir, File.basename($0))
  FileUtils.mkdir_p dirname
  File.join(dirname, filename)
end

#load_pathsArray<String>

The load_paths method reads and processes indexed file paths from disk.

This method loads lines from the index file path, removes trailing whitespace, and filters out directory entries if the debug flag is not set. It returns create_paths if the index file is empty or missing, otherwise it returns the processed list of file paths.



130
131
132
133
134
135
136
137
138
139
# File 'lib/utils/finder.rb', line 130

memoize method:
def load_paths
  lines = File.readlines(index_path)
  @args[?v] and warn "Loaded index #{index_path.inspect}."
  lines.empty? and raise Errno::ENOENT
  @args[?d] or lines = lines.grep_v(%r{/$})
  lines.map(&:chomp!)
rescue Errno::ENOENT
  return create_paths
end

#reset_indexUtils::Finder

The reset_index method resets the index file by removing it if the reset flag is set or if the index has expired.

This method checks whether the reset argument flag is set or if the index file has expired based on its modification time. If either condition is true, it removes the index file from the filesystem and clears the mize cache. The method then returns the instance itself to allow for method chaining.



151
152
153
154
155
156
157
158
159
# File 'lib/utils/finder.rb', line 151

def reset_index
  path = index_path
  if @args[?r] || index_expired?(path)
    @args[?v] and warn "Resetting index #{path.inspect}."
    FileUtils.rm_f path
    mize_cache_clear
  end
  self
end

#search_directlyObject

The search_directly method performs a direct search by building paths and then searching through them.

This method first constructs the list of paths to be searched and then executes the search operation on those paths, returning the results of the search.



222
223
224
# File 'lib/utils/finder.rb', line 222

def search_directly
  search_paths build_paths
end

#search_indexObject Also known as: search

The search_index method performs a pattern search across previously loaded paths.

This method utilizes the loaded paths from the internal storage to execute a search operation, applying the configured pattern matching criteria to filter and return relevant results based on the current search configuration.



233
234
235
# File 'lib/utils/finder.rb', line 233

def search_index
  search_paths load_paths
end

#search_paths(paths) ⇒ Utils::Finder

The search_paths method processes and filters a collection of file paths based on specified criteria.

This method takes an array of paths and applies filtering based on file extensions and patterns. It handles both fuzzy and regular expression pattern matching, and returns formatted results with optional sorting and limiting of results.



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/utils/finder.rb', line 172

def search_paths(paths)
  suffixes = Array(@args[?I])
  suffixes.full? do |s|
    paths.select! { |path| s.include?(File.extname(path)[1..-1]) }
  end
  paths = paths.map! do |path|
    if @pattern.nil?
      [ [ path.count(?/), path ], path, path ]
    elsif match = @pattern.match(path)
      if FuzzyPattern === @pattern
        current = 0
        marked_path = ''
        score, e = path.size, nil
        for i in 1...match.size
          match[i] or next
          b = match.begin(i)
          e ||= b
          marked_path << path[current...b]
          marked_path << red(path[b, 1])
          score += (b - e) * (path.size - b)
          e = match.end(i)
          current = b + 1
        end
        marked_path << match.post_match
        [ score, path, marked_path ]
      else
        marked_path = path[0...match.begin(0)] <<
          red(path[match.begin(0)...match.end(0)]) <<
          path[match.end(0)..-1]
        [ 0, path, marked_path ]
      end
    end
  end
  paths.compact!
  @paths, @output = paths.sort.transpose.values_at(-2, -1)
  if n = @args[?n]&.to_i
    @paths = @paths&.first(n) || []
    @output = @output&.first(n) || []
  end
  self
end