Skip to content

Instantly share code, notes, and snippets.

@sri
Created August 4, 2014 05:35
Show Gist options
  • Save sri/0ad8fd2d49712f1df854 to your computer and use it in GitHub Desktop.
Save sri/0ad8fd2d49712f1df854 to your computer and use it in GitHub Desktop.
tree command in Ruby
#! /usr/bin/env ruby
# sri, Sun Aug 3 22:28:22 PDT 2014
# The tree command in Ruby.
# Mimics the output of tree.
module Tree
class Directory
attr_reader :pathname
def initialize(pathname)
@pathname = pathname
@state = nil
@given_last = nil
ancestors = @pathname.ancestors + [self]
entries = Dir.entries(@pathname.abs_path).sort_by(&:downcase)
entries -= %w{. ..}
@entries = entries.map do |e|
full = File.join(@pathname.abs_path, e)
Pathname.new(full, ancestors)
end
@entries.reverse!
end
# When next_entry is called, we update the state.
def next_entry
p = @entries.pop
if @state == :last
@state = :beyond_last
elsif @entries.empty?
@state = :last
end
p
end
# When dir_prefix is called, we update the state.
# If state is last, "`" is given to the client
# only once.
def dir_prefix
if @state == :last
result = @given_last ? " " : "`"
@given_last = true
result
else
"|"
end
end
end
class Pathname
attr_reader :abs_path, :ancestors
def initialize(abs_path, ancestors = [])
@abs_path = abs_path
@ancestors = ancestors
end
def directory?
File.directory?(abs_path)
end
def as_directory
Directory.new(self)
end
def basename
File.basename(abs_path)
end
def line
result = [ancestors.first.dir_prefix]
parents = ancestors[1..-1]
while !parents.empty?
result << " " << parents.shift.dir_prefix
end
result << "-- " << basename
result.join
end
end
def self.tree(d)
f = d.next_entry
return if f.nil?
puts f.line
tree(f.as_directory) if f.directory?
tree(d)
end
def self.from_cmdline
arg = ARGV[0] || "."
p = Tree::Pathname.new(arg)
puts arg
tree(p.as_directory)
end
end
if $0 == __FILE__
Tree.from_cmdline
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment