treevisitor 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|