treevisitor 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/LICENSE.txt +20 -0
  2. data/README.rdoc +42 -0
  3. data/Rakefile +9 -0
  4. data/VERSION.yml +5 -0
  5. data/bin/tree.rb +9 -0
  6. data/examples/find_files.rb +17 -0
  7. data/examples/print_files.rb +15 -0
  8. data/lib/tree_visitor.rb +2 -0
  9. data/lib/treevisitor.rb +31 -0
  10. data/lib/treevisitor/abs_node.rb +146 -0
  11. data/lib/treevisitor/cli/cli_tree.rb +98 -0
  12. data/lib/treevisitor/dir_processor.rb +46 -0
  13. data/lib/treevisitor/dir_tree_walker.rb +164 -0
  14. data/lib/treevisitor/leaf_node.rb +33 -0
  15. data/lib/treevisitor/tree_node.rb +247 -0
  16. data/lib/treevisitor/tree_node_visitor.rb +29 -0
  17. data/lib/treevisitor/visitors/block_tree_node_visitor.rb +21 -0
  18. data/lib/treevisitor/visitors/build_dir_tree_visitor.rb +53 -0
  19. data/lib/treevisitor/visitors/callback_tree_node_visitor.rb +43 -0
  20. data/lib/treevisitor/visitors/callback_tree_node_visitor2.rb +61 -0
  21. data/lib/treevisitor/visitors/clone_tree_node_visitor.rb +39 -0
  22. data/lib/treevisitor/visitors/depth_tree_node_visitor.rb +27 -0
  23. data/lib/treevisitor/visitors/flat_print_tree_node_visitors.rb +20 -0
  24. data/lib/treevisitor/visitors/print_dir_tree_visitor.rb +21 -0
  25. data/lib/treevisitor/visitors/print_tree_node_visitor.rb +40 -0
  26. data/lib/treevisitor_cli.rb +7 -0
  27. data/spec/fixtures/test_dir/.dir_with_dot/dummy.txt +0 -0
  28. data/spec/fixtures/test_dir/dir.1/dir.1.2/file.1.2.1 +0 -0
  29. data/spec/fixtures/test_dir/dir.1/file.1.1 +0 -0
  30. data/spec/fixtures/test_dir/dir.2/file.2.1 +0 -0
  31. data/spec/spec_helper.rb +29 -0
  32. data/spec/treevisitor/cli/cli_tree_spec.rb +58 -0
  33. data/spec/treevisitor/dir_processor_spec.rb +15 -0
  34. data/spec/treevisitor/dir_tree_walker_spec.rb +33 -0
  35. data/spec/treevisitor/tree_node_dsl_spec.rb +153 -0
  36. data/spec/treevisitor/tree_node_spec.rb +153 -0
  37. data/spec/treevisitor/tree_node_visitor_spec.rb +70 -0
  38. data/tasks/jeweler.rake +55 -0
  39. data/tasks/rspec.rake +34 -0
  40. data/tasks/rubyforge.rake +28 -0
  41. data/tasks/yard.rake +36 -0
  42. 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
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ # Load tasks
5
+ Dir.glob('tasks/**/*.rake').each { |r| Rake.application.add_import r }
6
+
7
+ task :test => :check_dependencies
8
+ task :default => :spec
9
+
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 4
5
+ :build:
data/bin/tree.rb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+
4
+ cwd = File.expand_path( File.join( File.dirname(__FILE__), "..", "lib" ) )
5
+ $:.unshift(cwd) unless $:.include?(cwd)
6
+ require 'treevisitor_cli'
7
+
8
+ include TreeVisitor
9
+ exit CliTree.run
@@ -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 )
@@ -0,0 +1,2 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'treevisitor'
@@ -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