class Exa::Visitor

Public Class Methods

new(root) click to toggle source
# File lib/exa/visitor.rb, line 3
def initialize(root)
  @root = root
end

Public Instance Methods

gather_branches(branch=@root, depth: 10) click to toggle source
# File lib/exa/visitor.rb, line 18
def gather_branches(branch=@root, depth: 10)
  return [] if depth < 0
  if branch.children.any?
    [ branch ] + branch.children.flat_map do |child|
      gather_branches(child, depth: depth-1)
    end.uniq
  else # we are a leaf!
    [ ]
  end
end
gather_leaves(branch=@root, depth: 10) click to toggle source
# File lib/exa/visitor.rb, line 7
def gather_leaves(branch=@root, depth: 10)
  return [] if depth < 0
  if branch.children.any?
    branch.children.flat_map do |child|
      gather_leaves(child, depth: depth-1)
    end.uniq
  else # we are a leaf!
    [ branch ]
  end
end
query(path) click to toggle source
# File lib/exa/visitor.rb, line 48
def query(path)
  path = '/' + path unless path.start_with?('/')
  _root, next_segment, *remaining_segments = path.split('/')
  remaining_path = '/' + remaining_segments.join('/')
  current = @root
  return [current] unless next_segment
  if next_segment == '*'
    # need to multiplex remaining query across *all* children
    next_children = current.children
    if remaining_segments.any?
      next_children.flat_map do |child|
        child.query(remaining_path).uniq
      end
    else
      next_children
    end
  elsif next_segment == '**'
    # this is more subtle, and really points to:
    # do we need to be treating the path query as a regular expression?
    # and matching against *all* filenames?
    if remaining_segments.any?
      gather_branches(current).flat_map do |folder|
        folder.query(remaining_path).uniq
      end
    else
      gather_leaves(current)
    end
  elsif next_segment == '..'
    # need to back up...
    parent = current.parent
    if remaining_segments.any?
      parent.children.flat_map do |child|
        child.query(remaining_path).uniq
      end.uniq
    else
      [ parent ]
    end
  else
    # need to find just child matching *this* segment
    next_child = current.children.detect { |c| c.name == next_segment }
    if next_child
      if remaining_segments.any?
        next_child.query(remaining_path).uniq
      else
        [ next_child ]
      end
    else
      []
    end
  end
end
seek(path, create_missing: true) click to toggle source
# File lib/exa/visitor.rb, line 29
def seek(path, create_missing: true)
  path = '/' + path unless path.start_with?('/')
  _root, *path_segments = path.split('/')
  current = @root
  path_segments.each do |segment|
    next_child = current.children.detect do |child|
      child.name == segment
    end

    current = if next_child
      next_child
    else
      return nil unless create_missing
      current.create_child(child_name: segment)
    end
  end
  current
end