treevisitor 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.rdoc +42 -0
- data/Rakefile +9 -0
- data/VERSION.yml +5 -0
- data/bin/tree.rb +9 -0
- data/examples/find_files.rb +17 -0
- data/examples/print_files.rb +15 -0
- data/lib/tree_visitor.rb +2 -0
- data/lib/treevisitor.rb +31 -0
- data/lib/treevisitor/abs_node.rb +146 -0
- data/lib/treevisitor/cli/cli_tree.rb +98 -0
- data/lib/treevisitor/dir_processor.rb +46 -0
- data/lib/treevisitor/dir_tree_walker.rb +164 -0
- data/lib/treevisitor/leaf_node.rb +33 -0
- data/lib/treevisitor/tree_node.rb +247 -0
- data/lib/treevisitor/tree_node_visitor.rb +29 -0
- data/lib/treevisitor/visitors/block_tree_node_visitor.rb +21 -0
- data/lib/treevisitor/visitors/build_dir_tree_visitor.rb +53 -0
- data/lib/treevisitor/visitors/callback_tree_node_visitor.rb +43 -0
- data/lib/treevisitor/visitors/callback_tree_node_visitor2.rb +61 -0
- data/lib/treevisitor/visitors/clone_tree_node_visitor.rb +39 -0
- data/lib/treevisitor/visitors/depth_tree_node_visitor.rb +27 -0
- data/lib/treevisitor/visitors/flat_print_tree_node_visitors.rb +20 -0
- data/lib/treevisitor/visitors/print_dir_tree_visitor.rb +21 -0
- data/lib/treevisitor/visitors/print_tree_node_visitor.rb +40 -0
- data/lib/treevisitor_cli.rb +7 -0
- data/spec/fixtures/test_dir/.dir_with_dot/dummy.txt +0 -0
- data/spec/fixtures/test_dir/dir.1/dir.1.2/file.1.2.1 +0 -0
- data/spec/fixtures/test_dir/dir.1/file.1.1 +0 -0
- data/spec/fixtures/test_dir/dir.2/file.2.1 +0 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/treevisitor/cli/cli_tree_spec.rb +58 -0
- data/spec/treevisitor/dir_processor_spec.rb +15 -0
- data/spec/treevisitor/dir_tree_walker_spec.rb +33 -0
- data/spec/treevisitor/tree_node_dsl_spec.rb +153 -0
- data/spec/treevisitor/tree_node_spec.rb +153 -0
- data/spec/treevisitor/tree_node_visitor_spec.rb +70 -0
- data/tasks/jeweler.rake +55 -0
- data/tasks/rspec.rake +34 -0
- data/tasks/rubyforge.rake +28 -0
- data/tasks/yard.rake +36 -0
- metadata +192 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009-2010 tokiro.oyama@gmail.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
= tree.rb / tree visitor library
|
2
|
+
|
3
|
+
+tree.rb+ is a 'clone' of tree unix command. It is based on tree visitor library.
|
4
|
+
Tree visitor is an implementation of visitor design pattern.
|
5
|
+
|
6
|
+
$ tree.rb lib
|
7
|
+
|
8
|
+
lib
|
9
|
+
|-- tree_visitor.rb
|
10
|
+
|-- treevisitor.rb
|
11
|
+
|-- treevisitor_cli.rb
|
12
|
+
`-- treevisitor
|
13
|
+
|-- abs_node.rb
|
14
|
+
|-- dir_processor.rb
|
15
|
+
|-- dir_tree_walker.rb
|
16
|
+
|-- leaf_node.rb
|
17
|
+
|-- tree_node.rb
|
18
|
+
|-- tree_node_visitor.rb
|
19
|
+
|-- cli
|
20
|
+
| `-- cli_tree.rb
|
21
|
+
`-- visitors
|
22
|
+
|-- block_tree_node_visitor.rb
|
23
|
+
|-- build_dir_tree_visitor.rb
|
24
|
+
|-- callback_tree_node_visitor.rb
|
25
|
+
|-- callback_tree_node_visitor2.rb
|
26
|
+
|-- clone_tree_node_visitor.rb
|
27
|
+
|-- depth_tree_node_visitor.rb
|
28
|
+
|-- flat_print_tree_node_visitors.rb
|
29
|
+
|-- print_dir_tree_visitor.rb
|
30
|
+
`-- print_tree_node_visitor.rb
|
31
|
+
|
32
|
+
== Documentation
|
33
|
+
|
34
|
+
http://rubydoc.info/gems/treevisitor
|
35
|
+
|
36
|
+
== INSTALL:
|
37
|
+
|
38
|
+
sudo gem install treevisitor
|
39
|
+
|
40
|
+
== Copyright
|
41
|
+
|
42
|
+
Copyright (c) 2009-2010 tokiro.oyama@gmail.com. See LICENSE for details.
|
data/Rakefile
ADDED
data/VERSION.yml
ADDED
data/bin/tree.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
cwd = File.expand_path( File.join( File.dirname(__FILE__), "..", "lib" ) )
|
2
|
+
$:.unshift(cwd) unless $:.include?(cwd)
|
3
|
+
require 'treevisitor'
|
4
|
+
|
5
|
+
include TreeVisitor
|
6
|
+
|
7
|
+
class MyVisitor < TreeNodeVisitor
|
8
|
+
def visit_leaf_node( pathname )
|
9
|
+
puts pathname
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
dtw = DirTreeWalker.new( ".." )
|
14
|
+
dtw.match "leaf_node.rb"
|
15
|
+
dtw.match "abs_node.rb"
|
16
|
+
dtw.run( MyVisitor.new )
|
17
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
cwd = File.expand_path( File.join( File.dirname(__FILE__), "..", "lib" ) )
|
2
|
+
$:.unshift(cwd) unless $:.include?(cwd)
|
3
|
+
require 'treevisitor'
|
4
|
+
|
5
|
+
include TreeVisitor
|
6
|
+
|
7
|
+
class MyVisitor < TreeNodeVisitor
|
8
|
+
def visit_leaf_node( pathname )
|
9
|
+
puts pathname
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
dtw = DirTreeWalker.new( ".." )
|
14
|
+
dtw.ignore ".git"
|
15
|
+
dtw.run( MyVisitor.new )
|
data/lib/tree_visitor.rb
ADDED
data/lib/treevisitor.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# rubygems
|
3
|
+
require "rubygems"
|
4
|
+
require "abstract"
|
5
|
+
require 'pathname'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module TreeVisitor
|
9
|
+
def self.version
|
10
|
+
cwd = Pathname(__FILE__).dirname.expand_path.to_s
|
11
|
+
yaml = YAML.load_file(cwd + '/../VERSION.yml')
|
12
|
+
major = (yaml['major'] || yaml[:major]).to_i
|
13
|
+
minor = (yaml['minor'] || yaml[:minor]).to_i
|
14
|
+
patch = (yaml['patch'] || yaml[:patch]).to_i
|
15
|
+
"#{major}.#{minor}.#{patch}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
require "treevisitor/abs_node"
|
21
|
+
require 'treevisitor/leaf_node'
|
22
|
+
require 'treevisitor/tree_node_visitor.rb'
|
23
|
+
|
24
|
+
require 'treevisitor/tree_node'
|
25
|
+
require 'treevisitor/dir_tree_walker'
|
26
|
+
require 'treevisitor/tree_node_visitor'
|
27
|
+
require 'treevisitor/dir_processor'
|
28
|
+
|
29
|
+
require 'treevisitor/visitors/block_tree_node_visitor.rb'
|
30
|
+
require 'treevisitor/visitors/build_dir_tree_visitor'
|
31
|
+
require 'treevisitor/visitors/print_dir_tree_visitor'
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TreeVisitor
|
3
|
+
|
4
|
+
#
|
5
|
+
# @abstract Subclass to implement a concrete Node (Leaf or Tree).
|
6
|
+
#
|
7
|
+
# Abstract Node
|
8
|
+
# Class hierarchy
|
9
|
+
#
|
10
|
+
# AbsNode has a name, a parent
|
11
|
+
# ^ and define a path i.e. concatenation ancestor names
|
12
|
+
# |
|
13
|
+
# |-- LeafNode
|
14
|
+
# |
|
15
|
+
# `-- TreeNode
|
16
|
+
#
|
17
|
+
# Object diagram
|
18
|
+
#
|
19
|
+
# TreeNode (parent: nil)
|
20
|
+
# |
|
21
|
+
# |--->[ LeafNode, LeafNode, LeafNode ]
|
22
|
+
# |
|
23
|
+
# |--->[ TreeNode, TreeNode ]
|
24
|
+
# |
|
25
|
+
# |--> [LeafNode]
|
26
|
+
# |
|
27
|
+
# `--> [TreeNode, TreeNode]
|
28
|
+
class AbsNode
|
29
|
+
|
30
|
+
class << self
|
31
|
+
attr_accessor :path_separator
|
32
|
+
end
|
33
|
+
self.path_separator = File::SEPARATOR
|
34
|
+
|
35
|
+
attr_reader :parent
|
36
|
+
attr_reader :content
|
37
|
+
|
38
|
+
attr_accessor :prev
|
39
|
+
attr_accessor :next
|
40
|
+
|
41
|
+
#
|
42
|
+
# Create a new AbsNode
|
43
|
+
#
|
44
|
+
# @param content of node
|
45
|
+
#
|
46
|
+
def initialize( content )
|
47
|
+
@parent = nil
|
48
|
+
@content = content
|
49
|
+
@prefix_path = nil
|
50
|
+
invalidate
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# invalidate cached path info
|
55
|
+
#
|
56
|
+
def invalidate
|
57
|
+
@path = nil
|
58
|
+
@path_with_prefix = nil
|
59
|
+
@depth = nil
|
60
|
+
@root = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Root node could have assigned a path
|
65
|
+
#
|
66
|
+
def prefix_path
|
67
|
+
if not @parent.nil?
|
68
|
+
raise "Not root!!"
|
69
|
+
end
|
70
|
+
@prefix_path
|
71
|
+
end
|
72
|
+
|
73
|
+
def prefix_path=( prefix )
|
74
|
+
if not @parent.nil?
|
75
|
+
raise "Not root!!"
|
76
|
+
end
|
77
|
+
if prefix != @prefix_path
|
78
|
+
@prefix_path = prefix
|
79
|
+
invalidate
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Return the root of this node
|
85
|
+
#
|
86
|
+
# @return AbsNode
|
87
|
+
#
|
88
|
+
def root
|
89
|
+
return @root if @root
|
90
|
+
@root = parent.nil? ? self : parent.root
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# @return [String] path to this node
|
95
|
+
#
|
96
|
+
def path
|
97
|
+
return @path unless @path.nil?
|
98
|
+
if @parent.nil?
|
99
|
+
@path = @content
|
100
|
+
else
|
101
|
+
@path = @parent.path + AbsNode::path_separator + @content
|
102
|
+
end
|
103
|
+
@path
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# @return [String] path to this node with prefix
|
108
|
+
#
|
109
|
+
def path_with_prefix
|
110
|
+
return @path_with_prefix unless @path_with_prefix.nil?
|
111
|
+
if @parent.nil?
|
112
|
+
@path_with_prefix = @prefix_path.nil? ? @content : @prefix_path + @content
|
113
|
+
else
|
114
|
+
@path_with_prefix = @parent.path_with_prefix + AbsNode::path_separator + @content
|
115
|
+
end
|
116
|
+
@path_with_prefix
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# @return [FixNum] depth of this node
|
121
|
+
#
|
122
|
+
def depth
|
123
|
+
return @depth unless @depth.nil?
|
124
|
+
@depth = @parent.nil? ? 1 : @parent.depth + 1
|
125
|
+
@depth
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# Accept a node visitor
|
130
|
+
#
|
131
|
+
def accept( visitor )
|
132
|
+
not_implemented
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_s
|
136
|
+
@content.to_s
|
137
|
+
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
def parent=( parent )
|
142
|
+
@parent = parent
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TreeVisitor
|
3
|
+
#
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class CliTree
|
7
|
+
|
8
|
+
def self.run
|
9
|
+
self.new.parse_args( ARGV )
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_args( argv )
|
13
|
+
|
14
|
+
options = { :verbose => true, :force => false, :algo => 'build' }
|
15
|
+
|
16
|
+
opts = OptionParser.new
|
17
|
+
opts.banner = "Usage: tree.rb [options] [directory]"
|
18
|
+
|
19
|
+
opts.separator ""
|
20
|
+
opts.separator "list contents of directories in a tree-like format"
|
21
|
+
opts.separator "this is a clone of tree unix command written in ruby"
|
22
|
+
|
23
|
+
opts.separator ""
|
24
|
+
opts.separator "options: "
|
25
|
+
|
26
|
+
opts.on("-h", "--help", "Show this message") do
|
27
|
+
puts opts
|
28
|
+
return 0
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("--version", "Show the version") do
|
32
|
+
puts "tree.rb version #{TreeVisitor::version}"
|
33
|
+
return 0
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-a", "All file are listed") do |v|
|
37
|
+
options[:all_files] = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-d", "List directories only") do |v|
|
41
|
+
options[:only_directories] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
45
|
+
options[:verbose] = v
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-q", "--quiet", "quiet mode as --no-verbose") do |v|
|
49
|
+
options[:verbose] = false
|
50
|
+
end
|
51
|
+
|
52
|
+
algos = %w[build visit]
|
53
|
+
algo_aliases = { "b" => "build", "v" => "visit" }
|
54
|
+
|
55
|
+
algo_list = (algo_aliases.keys + algos).join(',')
|
56
|
+
opts.on("--algo ALGO", algos, algo_aliases, "Select algo"," (#{algo_list})") do |algo|
|
57
|
+
options[:algo] = algo
|
58
|
+
end
|
59
|
+
|
60
|
+
rest = opts.parse(argv)
|
61
|
+
|
62
|
+
# p options
|
63
|
+
# p ARGV
|
64
|
+
|
65
|
+
if rest.length < 1
|
66
|
+
puts opts
|
67
|
+
return 1
|
68
|
+
end
|
69
|
+
|
70
|
+
dirname = rest[0]
|
71
|
+
dirname = File.expand_path( dirname )
|
72
|
+
|
73
|
+
# puts "reading : #{dirname}"
|
74
|
+
|
75
|
+
dtw = DirTreeWalker.new( dirname )
|
76
|
+
unless options[:all_files]
|
77
|
+
# TODO: la regex e' corretta ed un file che inizia con ".."??
|
78
|
+
dtw.ignore(/^\.[^.]+/) # ignore all file starting with "."
|
79
|
+
end
|
80
|
+
|
81
|
+
dtw.visit_leaf = !options[:only_directories]
|
82
|
+
|
83
|
+
case options[:algo]
|
84
|
+
when 'build'
|
85
|
+
visitor = BuildDirTreeVisitor.new
|
86
|
+
dtw.run( visitor )
|
87
|
+
puts visitor.root.to_str
|
88
|
+
puts
|
89
|
+
puts "#{visitor.nr_directories} directories, #{visitor.nr_files} files"
|
90
|
+
when 'visit'
|
91
|
+
visitor = PrintDirTreeVisitor.new
|
92
|
+
dtw.run( visitor )
|
93
|
+
end
|
94
|
+
return 0
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TreeVisitor
|
3
|
+
|
4
|
+
#
|
5
|
+
# Visit a directory tree
|
6
|
+
# not TreeNode related
|
7
|
+
#
|
8
|
+
class DirProcessor
|
9
|
+
|
10
|
+
def initialize( &action )
|
11
|
+
@processors = {}
|
12
|
+
@default_processor = action
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_processor( re, &action )
|
16
|
+
@processors[ re ] = action
|
17
|
+
end
|
18
|
+
|
19
|
+
def process( dirname )
|
20
|
+
@dirname = dirname
|
21
|
+
old_dirname = Dir.pwd
|
22
|
+
Dir.chdir( @dirname )
|
23
|
+
Dir["**/*"].each { |f|
|
24
|
+
pn = Pathname.new( f ).expand_path
|
25
|
+
# puts "#{self.class.name}#loadfromdir #{f}"
|
26
|
+
next if pn.directory?
|
27
|
+
process_file( pn )
|
28
|
+
}
|
29
|
+
Dir.chdir( old_dirname )
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def process_file( pn )
|
36
|
+
# puts "file: #{f}"
|
37
|
+
pair = @processors.find { |re,action| re =~ pn.to_s }
|
38
|
+
unless pair.nil?
|
39
|
+
pair[1].call( pn )
|
40
|
+
else
|
41
|
+
@default_processor.call( pn ) if @default_processor
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|