class Utils::Finder

finder.search
finder = Utils::Finder.new(args: { l: true }, roots: [‘.’])
@example
file sets.
optimize performance when dealing with large codebases or frequently accessed
pattern matching. It supports both indexed and direct search approaches to
based on various criteria including file extensions, directory pruning, and
This class provides functionality for traversing file systems to locate files
filters.
A class for finding and searching files with configurable patterns and

def build_paths

Returns:
  • (Array) - an array of file system path strings, with directories
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

def create_paths

Returns:
  • (Array) - an array containing the paths that were built and written
def create_paths
  paths = build_paths
  File.secure_write(index_path) do |output|
    output.puts paths
  end
  paths
end

def discover_roots(roots)

Returns:
  • (Array) - an array of expanded directory paths that match

Parameters:
  • roots (Array, nil) -- an array of root patterns or nil
def discover_roots(roots)
  roots ||= []
  roots.inject([]) { |rs, r| rs.concat Dir[r] }
end

def index_expired?(path)

Returns:
  • (TrueClass, FalseClass) - true if the index file has expired, false otherwise

Parameters:
  • path (String) -- the filesystem path to the index file being checked
def index_expired?(path)
  if duration = @config.discover.index_expire_after
    Time.now - duration >= File.mtime(path)
  else
    false
  end
rescue Errno::ENOENT
  false
end

def index_path

Returns:
  • (String) - the full file path where finder results should be stored
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

def initialize(opts = {})

Options Hash: (**opts)
  • :config (Utils::ConfigFile) -- the configuration file object
  • :roots (Array) -- the root directories to search in
  • :args (Hash) -- the argument options for the finder

Parameters:
  • opts (Hash) -- the options hash containing configuration settings
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

def load_paths

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

def reset_index

Returns:
  • (Utils::Finder) - returns self to allow for method chaining
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

def search_directly

Returns:
  • (Object) - the result of the search operation performed on the built paths
def search_directly
  search_paths build_paths
end

def search_index

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

paths.
The search_index method performs a pattern search across previously loaded
def search_index
  search_paths load_paths
end

def search_paths(paths)

Returns:
  • (Utils::Finder) - returns self to allow for method chaining

Parameters:
  • paths (Array) -- the collection of file paths to be processed
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