redwood 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +86 -13
- data/Rakefile +10 -0
- data/bin/redwood +120 -0
- data/lib/redwood.rb +60 -34
- data/lib/redwood/filenode.rb +46 -0
- data/lib/redwood/node.rb +12 -0
- data/man/redwood.1 +86 -0
- data/man/redwood.1.html +128 -0
- data/man/redwood.1.ronn +64 -0
- data/redwood.gemspec +62 -0
- data/test/test_redwood.rb +74 -7
- metadata +12 -6
data/README.md
CHANGED
@@ -1,17 +1,90 @@
|
|
1
|
-
|
1
|
+
# redwood
|
2
2
|
|
3
|
-
|
3
|
+
Simple Ruby trees. Redwood is a simple implementation of a tree data structure in pure Ruby. It provides a few things:
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
* Add tests for it. This is important so I don't break it in a
|
10
|
-
future version unintentionally.
|
11
|
-
* Commit, do not mess with rakefile, version, or history.
|
12
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
-
* Send me a pull request. Bonus points for topic branches.
|
5
|
+
+ The `redwood` command-line tool: like the Unix [`tree`](http://mama.indstate.edu/users/ice/tree/) tool, but in Ruby!
|
6
|
+
+ The Redwood module for basic tree-esqueness.
|
7
|
+
+ Redwood::Node class for basic tree-nodiness
|
8
|
+
+ Redwood::FileNode class for representing Directories and Files in a tree-like way.
|
14
9
|
|
15
|
-
|
10
|
+
[RDoc](http://rdoc.info/projects/mwunsch/redwood) | [Gem](http://rubygems.org/gems/redwood)
|
16
11
|
|
17
|
-
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
gem install redwood
|
15
|
+
|
16
|
+
## `redwood`
|
17
|
+
|
18
|
+
The `redwood` command-line tool attempts a pure Ruby implementation of [tree](http://man.cx/tree).
|
19
|
+
|
20
|
+
USAGE: redwood [ OPTIONS ] [ DIRECTORY ]
|
21
|
+
|
22
|
+
Looks a bit like this:
|
23
|
+
|
24
|
+
Redwood
|
25
|
+
|-- bin
|
26
|
+
| `-- redwood
|
27
|
+
|-- Gemfile
|
28
|
+
|-- lib
|
29
|
+
| |-- redwood
|
30
|
+
| | |-- filenode.rb
|
31
|
+
| | `-- node.rb
|
32
|
+
| `-- redwood.rb
|
33
|
+
|-- LICENSE
|
34
|
+
|-- pkg
|
35
|
+
| `-- redwood-0.0.1.gem
|
36
|
+
|-- Rakefile
|
37
|
+
|-- README.md
|
38
|
+
|-- redwood.gemspec
|
39
|
+
`-- test
|
40
|
+
|-- helper.rb
|
41
|
+
`-- test_redwood.rb
|
42
|
+
|
43
|
+
5 directories, 12 files
|
44
|
+
|
45
|
+
Help is a `redwood --help` away. See also: [redwood(1)](http://mwunsch.github.com/redwood/)
|
46
|
+
|
47
|
+
## `Redwood`
|
48
|
+
|
49
|
+
The Redwood module is a module for including/extending tree-like features on your objects. It stores nodes in an Array. The only requirement for children is that they too include/extend tree-like features.
|
50
|
+
|
51
|
+
Methods include:
|
52
|
+
|
53
|
+
root? ## Is this a root node? Meaning, it has no parent.
|
54
|
+
leaf? ## Is this a leaf node? Meaning, is it without children?
|
55
|
+
root ## Get the root node in this tree.
|
56
|
+
children ## Get the children of this node.
|
57
|
+
siblings ## Get this nodes siblings.
|
58
|
+
only_child? ## Is this node without siblings?
|
59
|
+
has_children? ## Does this node have children?
|
60
|
+
ancestors ## All of the parent nodes of this node.
|
61
|
+
descendants ## All of the descendant nodes of this node.
|
62
|
+
depth ## Integer representing how deep this node is in the tree.
|
63
|
+
## A root node has a depth of 1, its children: 2, etc.
|
64
|
+
unlink ## Detach this node from its parent.
|
65
|
+
prune ## Unlink all of this node's chidren.
|
66
|
+
walk ## Recursively yield every node in this tree to a block
|
67
|
+
view ## Make a fancy string representation of the tree
|
68
|
+
## as seen in the command-line tool
|
69
|
+
|
70
|
+
### Redwood::Node
|
71
|
+
|
72
|
+
The Redwood::Node class is a simple implementation of the Redwood module. It is a good starting point for other trees. It adds new methods:
|
73
|
+
|
74
|
+
add_child(name) ## Add a child node. Nodes can have a #name.
|
75
|
+
[](name) ## Lookup children node by their #name.
|
76
|
+
<<(node) ## Add a node to this node's children.
|
77
|
+
|
78
|
+
#### Redwood::FileNode
|
79
|
+
|
80
|
+
The Redwood::FileNode class is an example use-case for Redwood, and it powers the `redwood` CLI. It stores a directory tree in a Redwood-backed structure. It has one primary method that does the magic:
|
81
|
+
|
82
|
+
dir = Redwood::FileNode.scandir '~/Projects/Redwood'
|
83
|
+
|
84
|
+
That will go through the directory and build a Redwood tree. Redwood::FileNode objects have methods that correspond to the `File` class. So you can do things like `dir.directory?` or `dir.chmod`.
|
85
|
+
|
86
|
+
Now go forth and grow some Ruby-flavored trees.
|
87
|
+
|
88
|
+
## Copyright
|
89
|
+
|
90
|
+
Redwood is Copyright (c) 2010 Mark Wunsch and is licensed under the [MIT License](http://creativecommons.org/licenses/MIT/).
|
data/Rakefile
CHANGED
@@ -46,3 +46,13 @@ desc "Open an irb session preloaded with this library"
|
|
46
46
|
task :console do
|
47
47
|
sh "irb -rubygems -I lib -r redwood"
|
48
48
|
end
|
49
|
+
|
50
|
+
desc "Build the manual"
|
51
|
+
task :build_man do
|
52
|
+
sh "ronn -br5 --organization='Mark Wunsch' --manual='Redwood Manual' man/*.ronn"
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Show the manual"
|
56
|
+
task :man => :build_man do
|
57
|
+
exec "man man/redwood.1"
|
58
|
+
end
|
data/bin/redwood
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
## Redwood is an implementation of `tree` in Ruby
|
3
|
+
##
|
4
|
+
## Usage: redwood [ OPTIONS ] [ DIRECTORY ]
|
5
|
+
##
|
6
|
+
## Learn more about the original at:
|
7
|
+
## http://mama.indstate.edu/users/ice/tree/
|
8
|
+
##
|
9
|
+
##
|
10
|
+
|
11
|
+
require 'optparse'
|
12
|
+
|
13
|
+
def usage
|
14
|
+
File.readlines(__FILE__).
|
15
|
+
grep(/^##.*/).
|
16
|
+
map { |line| line.chomp[3..-1] }.
|
17
|
+
join("\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
begin
|
21
|
+
require 'redwood'
|
22
|
+
rescue LoadError
|
23
|
+
raise if $!.to_s !~ /redwood/
|
24
|
+
libdir = File.expand_path("../../lib", __FILE__).sub(/^#{Dir.pwd}/, '.')
|
25
|
+
if !$:.include?(libdir)
|
26
|
+
$:.unshift libdir
|
27
|
+
retry
|
28
|
+
end
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
|
32
|
+
options = {
|
33
|
+
:follow_symlinks => false,
|
34
|
+
:show_hidden_files => false
|
35
|
+
}
|
36
|
+
ARGV.options do |option|
|
37
|
+
option.banner = usage
|
38
|
+
option.separator "Options"
|
39
|
+
option.on('-a','All files are listed.') { options[:show_hidden_files] = true }
|
40
|
+
option.on('-d','List directories only.') { options[:only_directories] = true }
|
41
|
+
option.on('-l','Follow symbolic links like directories.') { options[:follow_symlinks] = true }
|
42
|
+
option.on('-f','Print the full path prefix for each file.') { options[:full_path] = true }
|
43
|
+
option.on('-s','Print the size in bytes of each file.') { options[:size] = true }
|
44
|
+
option.on('-D','Print the date of last modification.') { options[:date] = :mtime }
|
45
|
+
option.on('-F',"Appends '/', '@', '=', '*', or '|' as per ls -F.") { options[:ftype] = true }
|
46
|
+
option.on('-L level','Descend only level directories deep.') { |depth| options[:depth] = depth.to_i + 1}
|
47
|
+
option.separator ""
|
48
|
+
option.on_tail('--version','Prints version and exits.') { puts Redwood::VERSION ; exit }
|
49
|
+
option.on_tail('--help','Prints this help screen.') { puts option ; exit }
|
50
|
+
option.parse!
|
51
|
+
end
|
52
|
+
|
53
|
+
def statement(tree)
|
54
|
+
directories = 0
|
55
|
+
files = 0
|
56
|
+
tree.descendants.each do |f|
|
57
|
+
if f.directory?
|
58
|
+
directories += 1
|
59
|
+
else
|
60
|
+
files += 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
d = directories.eql?(1) ? 'directory' : 'directories'
|
64
|
+
f = files.eql?(1) ? 'file' : 'files'
|
65
|
+
"#{directories} #{d}, #{files} #{f}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def setup_tree(tree, options)
|
69
|
+
if options[:depth]
|
70
|
+
abort 'Invalid level, must be greater than 0' if options[:depth] <= 1
|
71
|
+
tree.descendants.each {|f| f.unlink if f.depth > options[:depth] }
|
72
|
+
end
|
73
|
+
if !options[:follow_symlinks]
|
74
|
+
tree.descendants.each do |f|
|
75
|
+
if f.symlink?
|
76
|
+
f.value << " -> #{f.readlink}"
|
77
|
+
end
|
78
|
+
f.unlink if f.parent.symlink?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
if options[:only_directories]
|
82
|
+
tree.descendants.each {|f| f.unlink if !f.directory? }
|
83
|
+
end
|
84
|
+
if !options[:show_hidden_files]
|
85
|
+
tree.descendants.each do |f|
|
86
|
+
f.unlink if f.basename.index('.').eql?(0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
tree.walk {|f| f.value = f.path } if options[:full_path]
|
90
|
+
|
91
|
+
if options[:date]
|
92
|
+
tree.descendants.each {|f| f.value.insert(0,"[#{f.send(options[:date]).strftime('%b %d %H:%M')}] ") }
|
93
|
+
end
|
94
|
+
if options[:size]
|
95
|
+
tree.descendants.each {|f| f.value.insert(0,"[#{f.size}] ") if f.size? }
|
96
|
+
end
|
97
|
+
if options[:ftype]
|
98
|
+
tree.descendants.each do |f|
|
99
|
+
f.value << "|" if f.ftype == 'fifo'
|
100
|
+
if f.symlink?
|
101
|
+
f.value << "@"
|
102
|
+
elsif f.directory?
|
103
|
+
f.value << "/"
|
104
|
+
end
|
105
|
+
f.value << "*" if f.executable? && f.file?
|
106
|
+
f.value << "=" if f.socket?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
tree
|
110
|
+
end
|
111
|
+
|
112
|
+
dir = ARGV.empty? ? '.' : ARGV.first
|
113
|
+
abort %Q{"#{dir}" is not a directory.} if !File.directory?(dir)
|
114
|
+
|
115
|
+
tree = setup_tree Redwood::FileNode.scandir(dir), options
|
116
|
+
puts tree.view(:value)
|
117
|
+
puts "\n"
|
118
|
+
puts statement(tree)
|
119
|
+
exit
|
120
|
+
|
data/lib/redwood.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
|
-
# The
|
1
|
+
# The Redwood module can be mixed in to give tree-like methods to an object.
|
2
2
|
# Its primary implementation is the Redwood::Node class. Its only requirement
|
3
3
|
# is that the tree-infused-object's children and parent is an object that
|
4
|
-
# also mixes in
|
4
|
+
# also mixes in tree-like methods. See Redwood::Node for the canononical representation.
|
5
5
|
|
6
6
|
module Redwood
|
7
|
-
VERSION = "0.0
|
7
|
+
VERSION = "0.1.0"
|
8
8
|
|
9
|
+
# This node's parent.
|
9
10
|
def parent
|
10
11
|
@parent
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
def value
|
17
|
-
end
|
18
|
-
|
14
|
+
# Is this node the root of the tree?
|
19
15
|
def root?
|
20
16
|
parent.nil?
|
21
17
|
end
|
22
18
|
|
19
|
+
# Is this node a leaf node? Is this node childless?
|
23
20
|
def leaf?
|
24
|
-
children.empty?
|
21
|
+
children.nil? || children.empty?
|
25
22
|
end
|
26
23
|
|
24
|
+
# Get the root node in this tree.
|
27
25
|
def root
|
28
26
|
if root?
|
29
27
|
self
|
@@ -31,56 +29,84 @@ module Redwood
|
|
31
29
|
parent.root
|
32
30
|
end
|
33
31
|
end
|
34
|
-
|
32
|
+
|
33
|
+
# Get the children of this node.
|
35
34
|
def children
|
36
35
|
@children ||= []
|
37
36
|
end
|
38
37
|
|
38
|
+
# Get the siblings of this node. The other children belonging to this node's parent.
|
39
39
|
def siblings
|
40
40
|
if parent
|
41
41
|
parent.children.reject {|child| child == self }
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
# Is this node the only child of its parent. Does it have any siblings?
|
45
46
|
def only_child?
|
46
47
|
if parent
|
47
48
|
siblings.empty?
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
|
52
|
-
children.nil? || children.empty?
|
53
|
-
end
|
54
|
-
|
52
|
+
# Does this node have children? Is it not a leaf node?
|
55
53
|
def has_children?
|
56
|
-
!
|
54
|
+
!leaf?
|
57
55
|
end
|
58
|
-
|
56
|
+
|
57
|
+
# Get all of the ancestors for this node.
|
59
58
|
def ancestors
|
60
|
-
|
61
|
-
@ancestors = []
|
59
|
+
ancestors = []
|
62
60
|
if parent
|
63
|
-
|
64
|
-
parent.ancestors.each {|ancestor|
|
61
|
+
ancestors << parent
|
62
|
+
parent.ancestors.each {|ancestor| ancestors << ancestor }
|
65
63
|
end
|
66
|
-
|
64
|
+
ancestors
|
67
65
|
end
|
68
|
-
|
66
|
+
|
67
|
+
# Get all of the descendants of this node.
|
68
|
+
# All of its children, and its childrens' children, and its childrens' childrens' children...
|
69
69
|
def descendants
|
70
|
-
|
71
|
-
@descendants = []
|
70
|
+
descendants = []
|
72
71
|
if !children.empty?
|
73
|
-
(
|
74
|
-
children.each {|descendant|
|
75
|
-
|
72
|
+
(descendants << children).flatten!
|
73
|
+
children.each {|descendant| descendants << descendant.descendants }
|
74
|
+
descendants.flatten!
|
76
75
|
end
|
77
|
-
|
76
|
+
descendants
|
78
77
|
end
|
79
|
-
|
78
|
+
|
79
|
+
# An integer representation of how deep in the tree this node is.
|
80
|
+
# The root node has a depth of 1, its children have a depth of 2, etc.
|
80
81
|
def depth
|
81
82
|
ancestors.size + 1
|
82
83
|
end
|
83
84
|
|
85
|
+
# Orphan this node. Remove it from its parent node.
|
86
|
+
def unlink
|
87
|
+
if parent
|
88
|
+
parent.children.delete(self)
|
89
|
+
self.instance_variable_set(:@parent, nil)
|
90
|
+
return self
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Abandon all of this node's children.
|
95
|
+
def prune
|
96
|
+
if children
|
97
|
+
children.each {|child| child.unlink }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Recursively yield every node in the tree.
|
102
|
+
def walk(&block)
|
103
|
+
if block_given?
|
104
|
+
yield self
|
105
|
+
children.each {|child| child.walk(&block) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Makes a pretty string representation of the tree.
|
84
110
|
def view(content = :name)
|
85
111
|
treeview = ''
|
86
112
|
if parent
|
@@ -88,7 +114,7 @@ module Redwood
|
|
88
114
|
treeview << "--\s"
|
89
115
|
end
|
90
116
|
treeview << "#{self.send(content)}"
|
91
|
-
if
|
117
|
+
if has_children?
|
92
118
|
treeview << "\n"
|
93
119
|
children.each do |child|
|
94
120
|
if parent
|
@@ -109,6 +135,6 @@ module Redwood
|
|
109
135
|
treeview
|
110
136
|
end
|
111
137
|
|
112
|
-
|
113
|
-
|
114
|
-
|
138
|
+
autoload :FileNode, 'redwood/filenode'
|
139
|
+
autoload :Node, 'redwood/node'
|
140
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Redwood::FileNode stores a Directory tree in a Redwood structure.
|
2
|
+
# FileNodes respond to methods of the File class.
|
3
|
+
# eg. FileNode#chmod, FileNode#stat, etc.
|
4
|
+
|
5
|
+
module Redwood
|
6
|
+
class FileNode < Node
|
7
|
+
|
8
|
+
# Takes a path and scans the directory, creating a Redwood tree.
|
9
|
+
def self.scandir(dir = Dir.pwd, tree=nil)
|
10
|
+
node = tree ? tree : self.new(dir)
|
11
|
+
if File.directory?(dir)
|
12
|
+
Dir.foreach(dir) do |d|
|
13
|
+
if File.directory?("#{dir}/#{d}")
|
14
|
+
node << scandir("#{dir}/#{d}",tree) unless (d.eql?('..') || d.eql?('.'))
|
15
|
+
else
|
16
|
+
node.add_child("#{dir}/#{d}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
node.add_child(dir)
|
21
|
+
end
|
22
|
+
node
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :path
|
26
|
+
|
27
|
+
def initialize(name, parent=nil)
|
28
|
+
super
|
29
|
+
@path = File.expand_path(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Some information to store in the node. Defaults to the basename of the file/directory
|
33
|
+
def value
|
34
|
+
@value ||= basename
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(method, *args, &block)
|
38
|
+
if File.respond_to?(method)
|
39
|
+
File.send method, path
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/redwood/node.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# A basic representation of a Redwood tree.
|
2
|
+
|
1
3
|
module Redwood
|
2
4
|
class Node
|
3
5
|
include Redwood
|
4
6
|
|
5
7
|
attr_reader :name
|
8
|
+
attr_accessor :value
|
6
9
|
|
7
10
|
def initialize(name=nil, parent=nil)
|
8
11
|
@name = name
|
@@ -12,10 +15,19 @@ module Redwood
|
|
12
15
|
# Creates a child, adds it to children, and returns the child
|
13
16
|
def add_child(name)
|
14
17
|
child = self.class.new(name, self)
|
18
|
+
yield child if block_given?
|
15
19
|
children << child
|
16
20
|
child
|
17
21
|
end
|
18
22
|
|
23
|
+
# Add a node to this nodes children, and return the child
|
24
|
+
def <<(child)
|
25
|
+
child.instance_variable_set(:@parent, self)
|
26
|
+
children << child
|
27
|
+
child
|
28
|
+
end
|
29
|
+
|
30
|
+
# Lookup a child node by its name
|
19
31
|
def [](key)
|
20
32
|
selected_child = children.select {|child| child.name == key }
|
21
33
|
selected_child.size.eql?(1) ? selected_child.first : selected_child
|
data/man/redwood.1
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
.\" generated with Ronn/v0.5
|
2
|
+
.\" http://github.com/rtomayko/ronn/
|
3
|
+
.
|
4
|
+
.TH "REDWOOD" "1" "April 2010" "Mark Wunsch" "Redwood Manual"
|
5
|
+
.
|
6
|
+
.SH "NAME"
|
7
|
+
\fBredwood\fR \-\- Ruby\-flavored tree
|
8
|
+
.
|
9
|
+
.SH "SYNOPSIS"
|
10
|
+
\fBredwood\fR [\fIOPTIONS\fR] \fIDIRECTORY\fR
|
11
|
+
.
|
12
|
+
.SH "DESCRIPTION"
|
13
|
+
\fBredwood\fR is an implementation of \fBtree\fR in Ruby. Like the original \fBTree\fR, \fBRedwood\fR is a recursive directory listing program, producing a pretty\-looking depth indented listing of directory contents. Without arguments, \fBredwood\fR lists the files in the current directory. Like \fBtree\fR, after listing, \fBredwood\fR prints a summary of the total number of files and/or directories listed.
|
14
|
+
.
|
15
|
+
.P
|
16
|
+
And, again like the original \fBtree\fR, symbolic links are not followed and hidden files (those beginning with a '.') remain unseen by default. You can reveal them with options. File system constructs, the current directory as '.' and the parent directory as '..', are never printed.
|
17
|
+
.
|
18
|
+
.P
|
19
|
+
Learn more about the original \fBtree\fR with tree(1) and at http://mama.indstate.edu/users/ice/tree/
|
20
|
+
.
|
21
|
+
.P
|
22
|
+
This is a proof\-of\-concept. It's written in Ruby. It does half of what \fBtree\fR does pretty well. You should probably just use \fBtree\fR.
|
23
|
+
.
|
24
|
+
.SH "OPTIONS"
|
25
|
+
.
|
26
|
+
.TP
|
27
|
+
\fB\-a\fR
|
28
|
+
Print all files, even hidden ones (that begin with a '.').
|
29
|
+
.
|
30
|
+
.TP
|
31
|
+
\fB\-d\fR
|
32
|
+
Only list directories.
|
33
|
+
.
|
34
|
+
.TP
|
35
|
+
\fB\-l\fR
|
36
|
+
Follow symbolic links (that point to directories), as though they were directories. There is no protection from recursion, so don't do that.
|
37
|
+
.
|
38
|
+
.TP
|
39
|
+
\fB\-f\fR
|
40
|
+
Print the full path prefix for each file.
|
41
|
+
.
|
42
|
+
.TP
|
43
|
+
\fB\-s\fR
|
44
|
+
Print the size of each file in bytes.
|
45
|
+
.
|
46
|
+
.TP
|
47
|
+
\fB\-D\fR
|
48
|
+
Print the date of last modification for the file, in the format like: 'Aug 25 14:92'
|
49
|
+
.
|
50
|
+
.TP
|
51
|
+
\fB\-F\fR
|
52
|
+
Appends '/' to directories, '@' to symlinks, '=' to sockets, '*' to executables, and '|' to FIFO's, as per ls \-F.
|
53
|
+
.
|
54
|
+
.TP
|
55
|
+
\fB\-L\fR \fIlevel\fR
|
56
|
+
Max display depth of the directory tree. Has got to be greater than 0.
|
57
|
+
.
|
58
|
+
.P
|
59
|
+
Other:
|
60
|
+
.
|
61
|
+
.TP
|
62
|
+
\fB\-\-help\fR
|
63
|
+
Print the help message and quit.
|
64
|
+
.
|
65
|
+
.TP
|
66
|
+
\fB\-\-version\fR
|
67
|
+
Print the \fBredwood\fR version and quit.
|
68
|
+
.
|
69
|
+
.SH "INSTALLATION"
|
70
|
+
If you have RubyGems installed:
|
71
|
+
.
|
72
|
+
.IP "" 4
|
73
|
+
.
|
74
|
+
.nf
|
75
|
+
|
76
|
+
gem install redwood
|
77
|
+
.
|
78
|
+
.fi
|
79
|
+
.
|
80
|
+
.IP "" 0
|
81
|
+
.
|
82
|
+
.SH "COPYRIGHT"
|
83
|
+
Redwood is Copyright (C) 2010 Mark Wunsch
|
84
|
+
.
|
85
|
+
.SH "SEE ALSO"
|
86
|
+
tree(1), ls(1)
|
data/man/redwood.1.html
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv='content-type' value='text/html;charset=utf8'>
|
5
|
+
<meta name='generator' value='Ronn/v0.5'>
|
6
|
+
<title>redwood(1) -- Ruby-flavored tree</title>
|
7
|
+
<style type='text/css'>
|
8
|
+
body {margin:0}
|
9
|
+
#man, #man code, #man pre, #man tt, #man kbd, #man samp {
|
10
|
+
font-family:consolas,monospace;
|
11
|
+
font-size:16px;
|
12
|
+
line-height:1.3;
|
13
|
+
color:#343331;
|
14
|
+
background:#fff; }
|
15
|
+
#man { max-width:89ex; text-align:justify; margin:0 25px 25px 25px }
|
16
|
+
#man h1, #man h2, #man h3 { color:#232221;clear:left }
|
17
|
+
#man h1 { font-size:28px; margin:15px 0 30px 0; text-align:center }
|
18
|
+
#man h2 { font-size:18px; margin-bottom:0; margin-top:10px; line-height:1.3; }
|
19
|
+
#man h3 { font-size:16px; margin:0 0 0 4ex; }
|
20
|
+
#man p, #man ul, #man ol, #man dl, #man pre { margin:0 0 18px 0; }
|
21
|
+
#man pre {
|
22
|
+
color:#333231;
|
23
|
+
background:#edeceb;
|
24
|
+
padding:5px 7px;
|
25
|
+
margin:0px 0 20px 0;
|
26
|
+
border-left:2ex solid #ddd}
|
27
|
+
#man pre + h2, #man pre + h3 {
|
28
|
+
margin-top:22px;
|
29
|
+
}
|
30
|
+
#man h2 + pre, #man h3 + pre {
|
31
|
+
margin-top:5px;
|
32
|
+
}
|
33
|
+
#man > p, #man > ul, #man > ol, #man > dl, #man > pre { margin-left:8ex; }
|
34
|
+
#man dt { margin:0; clear:left }
|
35
|
+
#man dt.flush { float:left; width:8ex }
|
36
|
+
#man dd { margin:0 0 0 9ex }
|
37
|
+
#man code, #man strong, #man b { font-weight:bold; color:#131211; }
|
38
|
+
#man pre code { font-weight:normal; color:#232221; background:inherit }
|
39
|
+
#man em, var, u {
|
40
|
+
font-style:normal; color:#333231; border-bottom:1px solid #999; }
|
41
|
+
#man h1.man-title { display:none; }
|
42
|
+
#man ol.man, #man ol.man li { margin:2px 0 10px 0; padding:0;
|
43
|
+
float:left; width:33%; list-style-type:none;
|
44
|
+
text-transform:uppercase; font-size:18px; color:#999;
|
45
|
+
letter-spacing:1px;}
|
46
|
+
#man ol.man { width:100%; }
|
47
|
+
#man ol.man li.tl { text-align:left }
|
48
|
+
#man ol.man li.tc { text-align:center;letter-spacing:4px }
|
49
|
+
#man ol.man li.tr { text-align:right }
|
50
|
+
#man ol.man a { color:#999 }
|
51
|
+
#man ol.man a:hover { color:#333231 }
|
52
|
+
</style>
|
53
|
+
</head>
|
54
|
+
<body>
|
55
|
+
<div id='man'>
|
56
|
+
|
57
|
+
<h1 class='man-title'>redwood(1)</h1>
|
58
|
+
|
59
|
+
<ol class='head man'>
|
60
|
+
<li class='tl'>redwood(1)</li>
|
61
|
+
<li class='tc'>Redwood Manual</li>
|
62
|
+
<li class='tr'>redwood(1)</li>
|
63
|
+
</ol>
|
64
|
+
|
65
|
+
<h2 id='NAME'>NAME</h2>
|
66
|
+
<p><code>redwood</code> -- Ruby-flavored tree</p>
|
67
|
+
|
68
|
+
<h2>SYNOPSIS</h2>
|
69
|
+
|
70
|
+
<p><code>redwood</code> [<var>OPTIONS</var>] <var>DIRECTORY</var></p>
|
71
|
+
|
72
|
+
<h2>DESCRIPTION</h2>
|
73
|
+
|
74
|
+
<p><code>redwood</code> is an implementation of <code>tree</code> in Ruby. Like the original <code>Tree</code>, <code>Redwood</code> is a recursive directory listing program, producing a pretty-looking depth indented listing of directory contents. Without arguments, <code>redwood</code> lists the files in the current directory. Like <code>tree</code>, after listing, <code>redwood</code> prints a summary of the total number of files and/or directories listed.</p>
|
75
|
+
|
76
|
+
<p>And, again like the original <code>tree</code>, symbolic links are not followed and hidden files (those beginning with a '.') remain unseen by default. You can reveal them with options. File system constructs, the current directory as '.' and the parent directory as '..', are never printed.</p>
|
77
|
+
|
78
|
+
<p>Learn more about the original <code>tree</code> with tree(1) and at http://mama.indstate.edu/users/ice/tree/</p>
|
79
|
+
|
80
|
+
<p>This is a proof-of-concept. It's written in Ruby. It does half of what <code>tree</code> does pretty well. You should probably just use <code>tree</code>.</p>
|
81
|
+
|
82
|
+
<h2>OPTIONS</h2>
|
83
|
+
|
84
|
+
<dl>
|
85
|
+
<dt class="flush"><code>-a</code></dt><dd><p> Print all files, even hidden ones (that begin with a '.').</p></dd>
|
86
|
+
<dt class="flush"><code>-d</code></dt><dd><p> Only list directories.</p></dd>
|
87
|
+
<dt class="flush"><code>-l</code></dt><dd><p> Follow symbolic links (that point to directories), as though they were directories. There is no protection from recursion, so don't do that.</p></dd>
|
88
|
+
<dt class="flush"><code>-f</code></dt><dd><p> Print the full path prefix for each file.</p></dd>
|
89
|
+
<dt class="flush"><code>-s</code></dt><dd><p> Print the size of each file in bytes.</p></dd>
|
90
|
+
<dt class="flush"><code>-D</code></dt><dd><p> Print the date of last modification for the file, in the format like: 'Aug 25 14:92'</p></dd>
|
91
|
+
<dt class="flush"><code>-F</code></dt><dd><p> Appends '/' to directories, '@' to symlinks, '=' to sockets, '*' to executables, and '|' to FIFO's, as per ls -F.</p></dd>
|
92
|
+
<dt><code>-L</code> <em>level</em></dt><dd><p> Max display depth of the directory tree. Has got to be greater than 0.</p></dd>
|
93
|
+
</dl>
|
94
|
+
|
95
|
+
|
96
|
+
<p>Other:</p>
|
97
|
+
|
98
|
+
<dl>
|
99
|
+
<dt class="flush"><code>--help</code></dt><dd><p> Print the help message and quit.</p></dd>
|
100
|
+
<dt><code>--version</code></dt><dd><p> Print the <code>redwood</code> version and quit.</p></dd>
|
101
|
+
</dl>
|
102
|
+
|
103
|
+
|
104
|
+
<h2>INSTALLATION</h2>
|
105
|
+
|
106
|
+
<p>If you have RubyGems installed:</p>
|
107
|
+
|
108
|
+
<pre><code>gem install redwood
|
109
|
+
</code></pre>
|
110
|
+
|
111
|
+
<h2>COPYRIGHT</h2>
|
112
|
+
|
113
|
+
<p>Redwood is Copyright (C) 2010 Mark Wunsch</p>
|
114
|
+
|
115
|
+
<h2>SEE ALSO</h2>
|
116
|
+
|
117
|
+
<p>tree(1), ls(1)</p>
|
118
|
+
|
119
|
+
|
120
|
+
<ol class='foot man'>
|
121
|
+
<li class='tl'>Mark Wunsch</li>
|
122
|
+
<li class='tc'>April 2010</li>
|
123
|
+
<li class='tr'>redwood(1)</li>
|
124
|
+
</ol>
|
125
|
+
|
126
|
+
</div>
|
127
|
+
</body>
|
128
|
+
</html>
|
data/man/redwood.1.ronn
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
redwood(1) -- Ruby-flavored tree
|
2
|
+
===================================
|
3
|
+
|
4
|
+
## SYNOPSIS
|
5
|
+
|
6
|
+
`redwood` [<OPTIONS>] <DIRECTORY>
|
7
|
+
|
8
|
+
## DESCRIPTION
|
9
|
+
|
10
|
+
`redwood` is an implementation of `tree` in Ruby. Like the original `Tree`, `Redwood` is a recursive directory listing program, producing a pretty-looking depth indented listing of directory contents. Without arguments, `redwood` lists the files in the current directory. Like `tree`, after listing, `redwood` prints a summary of the total number of files and/or directories listed.
|
11
|
+
|
12
|
+
And, again like the original `tree`, symbolic links are not followed and hidden files (those beginning with a '.') remain unseen by default. You can reveal them with options. File system constructs, the current directory as '.' and the parent directory as '..', are never printed.
|
13
|
+
|
14
|
+
Learn more about the original `tree` with tree(1) and at http://mama.indstate.edu/users/ice/tree/
|
15
|
+
|
16
|
+
This is a proof-of-concept. It's written in Ruby. It does half of what `tree` does pretty well. You should probably just use `tree`.
|
17
|
+
|
18
|
+
## OPTIONS
|
19
|
+
|
20
|
+
* `-a`:
|
21
|
+
Print all files, even hidden ones (that begin with a '.').
|
22
|
+
|
23
|
+
* `-d`:
|
24
|
+
Only list directories.
|
25
|
+
|
26
|
+
* `-l`:
|
27
|
+
Follow symbolic links (that point to directories), as though they were directories. There is no protection from recursion, so don't do that.
|
28
|
+
|
29
|
+
* `-f`:
|
30
|
+
Print the full path prefix for each file.
|
31
|
+
|
32
|
+
* `-s`:
|
33
|
+
Print the size of each file in bytes.
|
34
|
+
|
35
|
+
* `-D`:
|
36
|
+
Print the date of last modification for the file, in the format like: 'Aug 25 14:92'
|
37
|
+
|
38
|
+
* `-F`:
|
39
|
+
Appends '/' to directories, '@' to symlinks, '=' to sockets, '*' to executables, and '|' to FIFO's, as per ls -F.
|
40
|
+
|
41
|
+
* `-L` _level_:
|
42
|
+
Max display depth of the directory tree. Has got to be greater than 0.
|
43
|
+
|
44
|
+
Other:
|
45
|
+
|
46
|
+
* `--help`:
|
47
|
+
Print the help message and quit.
|
48
|
+
|
49
|
+
* `--version`:
|
50
|
+
Print the `redwood` version and quit.
|
51
|
+
|
52
|
+
## INSTALLATION
|
53
|
+
|
54
|
+
If you have RubyGems installed:
|
55
|
+
|
56
|
+
gem install redwood
|
57
|
+
|
58
|
+
## COPYRIGHT
|
59
|
+
|
60
|
+
Redwood is Copyright (C) 2010 Mark Wunsch
|
61
|
+
|
62
|
+
## SEE ALSO
|
63
|
+
|
64
|
+
tree(1), ls(1)
|
data/redwood.gemspec
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{redwood}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Mark Wunsch"]
|
12
|
+
s.date = %q{2010-04-10}
|
13
|
+
s.default_executable = %q{redwood}
|
14
|
+
s.description = %q{A simple library to create and manage basic tree-esque structures.}
|
15
|
+
s.email = ["mark@markwunsch.com"]
|
16
|
+
s.executables = ["redwood"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.md"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
".gitignore",
|
24
|
+
"Gemfile",
|
25
|
+
"LICENSE",
|
26
|
+
"README.md",
|
27
|
+
"Rakefile",
|
28
|
+
"bin/redwood",
|
29
|
+
"lib/redwood.rb",
|
30
|
+
"lib/redwood/filenode.rb",
|
31
|
+
"lib/redwood/node.rb",
|
32
|
+
"man/redwood.1",
|
33
|
+
"man/redwood.1.html",
|
34
|
+
"man/redwood.1.ronn",
|
35
|
+
"redwood.gemspec",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_redwood.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/mwunsch/redwood}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.6}
|
43
|
+
s.summary = %q{Ruby trees}
|
44
|
+
s.test_files = [
|
45
|
+
"test/helper.rb",
|
46
|
+
"test/test_redwood.rb"
|
47
|
+
]
|
48
|
+
|
49
|
+
if s.respond_to? :specification_version then
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_development_dependency(%q<bundler>, [">= 0.9.7"])
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<bundler>, [">= 0.9.7"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<bundler>, [">= 0.9.7"])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
data/test/test_redwood.rb
CHANGED
@@ -7,12 +7,6 @@ class TestRedwood < Test::Unit::TestCase
|
|
7
7
|
assert_equal :test, node.name
|
8
8
|
end
|
9
9
|
|
10
|
-
test 'can be without children' do
|
11
|
-
node = Redwood::Node.new
|
12
|
-
assert node.childless?
|
13
|
-
assert !node.has_children?
|
14
|
-
end
|
15
|
-
|
16
10
|
test 'can be a root element' do
|
17
11
|
node = Redwood::Node.new
|
18
12
|
assert node.root?
|
@@ -126,6 +120,79 @@ class TestRedwood < Test::Unit::TestCase
|
|
126
120
|
assert_respond_to node, :view
|
127
121
|
assert_equal String, node.view.class
|
128
122
|
end
|
129
|
-
|
123
|
+
|
124
|
+
test 'is a leaf node' do
|
125
|
+
node = Redwood::Node.new(:parent)
|
126
|
+
child = node.add_child(:child)
|
127
|
+
|
128
|
+
assert !node.leaf?
|
129
|
+
assert child.leaf?
|
130
|
+
end
|
131
|
+
|
132
|
+
test 'walks the tree' do
|
133
|
+
node = Redwood::Node.new(:parent)
|
134
|
+
dog = node.add_child(:dog)
|
135
|
+
puppy = dog.add_child(:puppy)
|
136
|
+
son = node.add_child(:son)
|
137
|
+
daughter = node.add_child(:daughter)
|
138
|
+
grandson = son.add_child(:grandson)
|
139
|
+
counter = 0
|
140
|
+
node.walk {|n| counter += 1 }
|
141
|
+
assert_equal 6, counter
|
142
|
+
end
|
143
|
+
|
144
|
+
test 'add a child with the << method' do
|
145
|
+
node = Redwood::Node.new(:parent)
|
146
|
+
dog = Redwood::Node.new(:dog)
|
147
|
+
|
148
|
+
node << dog
|
149
|
+
assert_equal node, dog.parent
|
150
|
+
assert node.children.include?(dog)
|
151
|
+
assert !dog.root?
|
152
|
+
assert !node.leaf?
|
153
|
+
end
|
154
|
+
|
155
|
+
test 'has an optional arbitrary value' do
|
156
|
+
node = Redwood::Node.new(:parent)
|
157
|
+
node.value = "hello world"
|
158
|
+
assert_equal "hello world", node.value
|
159
|
+
end
|
160
|
+
|
161
|
+
test 'unlinks a node from its parent' do
|
162
|
+
node = Redwood::Node.new(:parent)
|
163
|
+
dog = node.add_child :dog
|
164
|
+
|
165
|
+
dog.unlink
|
166
|
+
assert node.leaf?
|
167
|
+
assert !node.children.include?(dog)
|
168
|
+
assert dog.root?
|
169
|
+
end
|
170
|
+
|
171
|
+
test 'prunes its children' do
|
172
|
+
node = Redwood::Node.new(:parent)
|
173
|
+
dog = node.add_child :dog
|
174
|
+
|
175
|
+
node.prune
|
176
|
+
assert node.children.empty?
|
177
|
+
assert node.leaf?
|
178
|
+
assert !dog.parent
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe 'FileNode' do
|
183
|
+
test 'scan a directory' do
|
184
|
+
dir = Redwood::FileNode.scandir
|
185
|
+
assert_equal Dir.pwd, dir.name
|
186
|
+
end
|
187
|
+
|
188
|
+
test 'implements File methods on the Node' do
|
189
|
+
dir = Redwood::FileNode.scandir
|
190
|
+
assert dir.directory?
|
191
|
+
end
|
192
|
+
|
193
|
+
test 'has a full path' do
|
194
|
+
dir = Redwood::FileNode.scandir('.')
|
195
|
+
assert_equal File.expand_path('.'), dir.path
|
196
|
+
end
|
130
197
|
end
|
131
198
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 0
|
8
7
|
- 1
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mark Wunsch
|
@@ -14,8 +14,8 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
18
|
-
default_executable:
|
17
|
+
date: 2010-04-10 00:00:00 -04:00
|
18
|
+
default_executable: redwood
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: bundler
|
@@ -34,8 +34,8 @@ dependencies:
|
|
34
34
|
description: A simple library to create and manage basic tree-esque structures.
|
35
35
|
email:
|
36
36
|
- mark@markwunsch.com
|
37
|
-
executables:
|
38
|
-
|
37
|
+
executables:
|
38
|
+
- redwood
|
39
39
|
extensions: []
|
40
40
|
|
41
41
|
extra_rdoc_files:
|
@@ -48,8 +48,14 @@ files:
|
|
48
48
|
- LICENSE
|
49
49
|
- README.md
|
50
50
|
- Rakefile
|
51
|
+
- bin/redwood
|
51
52
|
- lib/redwood.rb
|
53
|
+
- lib/redwood/filenode.rb
|
52
54
|
- lib/redwood/node.rb
|
55
|
+
- man/redwood.1
|
56
|
+
- man/redwood.1.html
|
57
|
+
- man/redwood.1.ronn
|
58
|
+
- redwood.gemspec
|
53
59
|
- test/helper.rb
|
54
60
|
- test/test_redwood.rb
|
55
61
|
has_rdoc: true
|