tree.rb 0.3.0

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.
Files changed (58) hide show
  1. data/.gemtest +0 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +160 -0
  4. data/Rakefile +12 -0
  5. data/bin/tree.rb +9 -0
  6. data/examples/directory_walker/directory_without_subdirectory.rb +37 -0
  7. data/examples/directory_walker/find_files.rb +18 -0
  8. data/examples/directory_walker/print_files.rb +12 -0
  9. data/examples/protovis/directory_to_json_visitor.rb +15 -0
  10. data/examples/protovis/index.html +87 -0
  11. data/examples/protovis/protovis-r3.2.js +277 -0
  12. data/examples/protovis/treevisitor.js +33 -0
  13. data/examples/protovis/treevisitor.png +0 -0
  14. data/lib/tree_visitor.rb +2 -0
  15. data/lib/treevisitor/abs_node.rb +144 -0
  16. data/lib/treevisitor/basic_tree_node_visitor.rb +44 -0
  17. data/lib/treevisitor/cli/cli_tree.rb +121 -0
  18. data/lib/treevisitor/directory_walker.rb +300 -0
  19. data/lib/treevisitor/leaf_node.rb +33 -0
  20. data/lib/treevisitor/tree_node.rb +296 -0
  21. data/lib/treevisitor/tree_node_visitor.rb +120 -0
  22. data/lib/treevisitor/util/dir_processor.rb +46 -0
  23. data/lib/treevisitor/version.rb +4 -0
  24. data/lib/treevisitor/visitors/block_tree_node_visitor.rb +21 -0
  25. data/lib/treevisitor/visitors/build_dir_tree_visitor.rb +57 -0
  26. data/lib/treevisitor/visitors/callback_tree_node_visitor2.rb +48 -0
  27. data/lib/treevisitor/visitors/clone_tree_node_visitor.rb +39 -0
  28. data/lib/treevisitor/visitors/depth_tree_node_visitor.rb +27 -0
  29. data/lib/treevisitor/visitors/directory_to_hash_visitor.rb +33 -0
  30. data/lib/treevisitor/visitors/flat_print_tree_node_visitors.rb +20 -0
  31. data/lib/treevisitor/visitors/print_dir_tree_visitor.rb +21 -0
  32. data/lib/treevisitor/visitors/print_tree_node_visitor.rb +40 -0
  33. data/lib/treevisitor.rb +40 -0
  34. data/lib/treevisitor_cli.rb +7 -0
  35. data/spec/fixtures/test_dir_1/.dir_with_dot/dummy.txt +0 -0
  36. data/spec/fixtures/test_dir_1/dir.1/dir.1.2/file.1.2.1 +0 -0
  37. data/spec/fixtures/test_dir_1/dir.1/file.1.1 +0 -0
  38. data/spec/fixtures/test_dir_1/dir.2/file.2.1 +0 -0
  39. data/spec/fixtures/test_dir_2/[Dsube]/sub/.gitkeep +0 -0
  40. data/spec/spec_helper.rb +27 -0
  41. data/spec/treevisitor/cli/cli_tree_spec.rb +69 -0
  42. data/spec/treevisitor/directory_walker_spec.rb +99 -0
  43. data/spec/treevisitor/tree_dsl_spec.rb +57 -0
  44. data/spec/treevisitor/tree_dsl_with_derived_class1_spec.rb +53 -0
  45. data/spec/treevisitor/tree_dsl_with_derived_class_spec.rb +51 -0
  46. data/spec/treevisitor/tree_node_paths_spec.rb +70 -0
  47. data/spec/treevisitor/tree_node_spec.rb +135 -0
  48. data/spec/treevisitor/tree_node_visitor_delegate_spec.rb +35 -0
  49. data/spec/treevisitor/tree_node_visitor_dsl_spec.rb +66 -0
  50. data/spec/treevisitor/util/dir_processor_spec.rb +13 -0
  51. data/spec/treevisitor/visitors/block_tree_node_visitor_spec.rb +25 -0
  52. data/spec/treevisitor/visitors/callback_tree_node_visitor2_spec.rb +38 -0
  53. data/spec/treevisitor/visitors/depth_tree_node_visitor_spec.rb +28 -0
  54. data/spec/treevisitor/visitors/tree_node_visitors_spec.rb +27 -0
  55. data/tasks/rspec.rake +34 -0
  56. data/tasks/yard.rake +36 -0
  57. data/tree.rb.gemspec +70 -0
  58. metadata +231 -0
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TreeVisitor
3
+ #
4
+ # Visitor for DirTreeWalker
5
+ # Prints the node at enter
6
+ # TODO: join this con PrintTreeNodeVisitor
7
+ class PrintDirTreeVisitor # < BasicTreeNodeVisitor
8
+
9
+ def enter_node( pathname )
10
+ puts pathname
11
+ end
12
+
13
+ def exit_node( pathname )
14
+ end
15
+
16
+ def visit_leaf( pathname )
17
+ puts pathname
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TreeVisitor
3
+ #
4
+ # Prints TreeNode names indenting according to depth
5
+ #
6
+ class PrintTreeNodeVisitor # < BasicTreeNodeVisitor
7
+
8
+ def initialize
9
+ @depth = 0
10
+ end
11
+
12
+ def enter_node( tree_node )
13
+ str = ""
14
+ (0...@depth).step {
15
+ str << " |-"
16
+ }
17
+
18
+ if @depth == 0
19
+ puts str + tree_node.name.to_s
20
+ else
21
+ puts str + tree_node.name.to_s
22
+ end
23
+ @depth += 1
24
+ end
25
+
26
+ def exit_node( tree_node )
27
+ @depth -= 1
28
+ end
29
+
30
+ def visit_leaf( leaf_node )
31
+ str = ""
32
+ (0...@depth-1).step {
33
+ str << " |-"
34
+ }
35
+ str << " | "
36
+ puts str + leaf_node.name.to_s
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ #
4
+ # std lib
5
+ #
6
+ require 'pathname'
7
+ require 'yaml'
8
+
9
+ #
10
+ # rubygems
11
+ #
12
+ # require 'rubygems' # rubygems must be loaded from binary file (tree.rb) so $LOAD_PATH is not modified
13
+ require 'json'
14
+ require 'ansi/code'
15
+
16
+ #
17
+ # treevisitor
18
+ #
19
+
20
+ require "treevisitor/version"
21
+ require "treevisitor/abs_node"
22
+ require 'treevisitor/leaf_node'
23
+ require 'treevisitor/tree_node'
24
+ require 'treevisitor/basic_tree_node_visitor'
25
+ require 'treevisitor/tree_node_visitor'
26
+
27
+ require 'treevisitor/directory_walker'
28
+
29
+ #
30
+ # visitors
31
+ #
32
+ require 'treevisitor/visitors/block_tree_node_visitor'
33
+ require 'treevisitor/visitors/build_dir_tree_visitor'
34
+ require 'treevisitor/visitors/callback_tree_node_visitor2'
35
+ require 'treevisitor/visitors/clone_tree_node_visitor'
36
+ require 'treevisitor/visitors/depth_tree_node_visitor'
37
+ require 'treevisitor/visitors/print_dir_tree_visitor'
38
+ require 'treevisitor/visitors/directory_to_hash_visitor'
39
+
40
+ require 'treevisitor/util/dir_processor'
@@ -0,0 +1,7 @@
1
+ #
2
+ # cli
3
+ #
4
+
5
+ require 'optparse'
6
+ require 'treevisitor'
7
+ require "treevisitor/cli/cli_tree"
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # std lib
4
+ #
5
+ require "stringio"
6
+
7
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ require 'treevisitor'
9
+ require 'treevisitor_cli'
10
+ include TreeVisitor
11
+
12
+ FIXTURES = File.expand_path( File.join( File.dirname(__FILE__), "fixtures" ) )
13
+
14
+ def with_output_captured
15
+ old_stdout, old_stderr = $stdout, $stderr
16
+ out = StringIO.new
17
+ err = StringIO.new
18
+ $stdout = out
19
+ $stderr = err
20
+ begin
21
+ yield
22
+ ensure
23
+ $stdout = old_stdout
24
+ $stderr = old_stderr
25
+ end
26
+ { :stdout => out.string, :stderr => err.string }
27
+ end
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "..", "spec_helper")
3
+
4
+ describe CliTree do
5
+
6
+ it "help message" do
7
+ out = with_output_captured do
8
+ args = %w{-h}
9
+ CliTree.new.parse_args(args)
10
+ end
11
+ out[:stdout].should match /Usage:/
12
+ end
13
+
14
+ it "version" do
15
+ out = with_output_captured do
16
+ args = %w{--version}
17
+ CliTree.new.parse_args(args)
18
+ end
19
+ version = TreeVisitor::VERSION
20
+ out[:stdout].should match version
21
+ end
22
+
23
+ it "should accepts switch -d (directories only)" do
24
+ out = with_output_captured do
25
+ args = %w{-d}
26
+ args << File.join(FIXTURES, "test_dir_1")
27
+ CliTree.new.parse_args(args)
28
+ end
29
+ # puts out
30
+ out[:stdout].split("\n").length.should == 6
31
+
32
+ out = with_output_captured do
33
+ args = %w{-da}
34
+ args << File.join(FIXTURES, "test_dir_1")
35
+ CliTree.new.parse_args(args)
36
+ end
37
+ # puts out
38
+ out[:stdout].split("\n").length.should == 7
39
+ end
40
+
41
+ it "should accepts switch -a (all files)" do
42
+ out = with_output_captured do
43
+ args = %w{-a}
44
+ args << File.join(FIXTURES, "test_dir_1")
45
+ CliTree.new.parse_args(args)
46
+ end
47
+ # pp out
48
+ out[:stdout].split("\n").length.should == 11
49
+
50
+ out = with_output_captured do
51
+ args = []
52
+ args << File.join(FIXTURES, "test_dir_1")
53
+ CliTree.new.parse_args(args)
54
+ end
55
+ # puts out
56
+ out[:stdout].split("\n").length.should == 9
57
+ end
58
+
59
+ it "should show tree with inaccessible directories" do
60
+ out = with_output_captured do
61
+ args = []
62
+ args << File.join(FIXTURES, "test_dir_3_with_error")
63
+ CliTree.new.parse_args(args)
64
+ end
65
+ puts out
66
+ out[:stderr].should_not be_empty
67
+ out[:stdout].split("\n").length.should == 4
68
+ end
69
+ end
@@ -0,0 +1,99 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe DirTreeWalker do
5
+
6
+ it "should accept option :ignore" do
7
+ walker = DirTreeWalker.new :ignore => /^\./
8
+ walker.ignore_file?(".thumbnails").should be_true
9
+ walker.ignore_dir?(".thumbnails").should be_true
10
+ end
11
+
12
+ it "should accept option :ignore" do
13
+ walker = DirTreeWalker.new :ignore => ".git"
14
+ walker.ignore_file?(".git").should be_true
15
+ walker.ignore_dir?(".git").should be_true
16
+ end
17
+
18
+
19
+ it "should accept option :ignore_dir" do
20
+ dtw = DirTreeWalker.new :ignore_dir => [/^\./, "private_dir" ]
21
+ dtw.should be_ignore_dir ".git"
22
+ dtw.should be_ignore_dir "private_dir"
23
+ end
24
+
25
+ it "should accept option :ignore_file" do
26
+ dtw = DirTreeWalker.new :ignore_file => [/.xml/, /(ignore)|(orig)/ ]
27
+ dtw.should be_ignore_file "pippo.xml"
28
+ end
29
+
30
+ it "should accept option :match" do
31
+ dtw = DirTreeWalker.new :match => /.jpg/
32
+ dtw.should be_match "foo.jpg"
33
+ end
34
+
35
+ it "should ignore files and directory" do
36
+ walker = DirTreeWalker.new(".")
37
+
38
+ walker.ignore(/^\./)
39
+ walker.ignore_file?(".thumbnails").should be_true
40
+ walker.ignore_dir?(".thumbnails").should be_true
41
+
42
+ walker.ignore_dir("thumbnails")
43
+ walker.ignore_dir?(".thumbnails").should be_true
44
+ walker.ignore_dir?("thumbnails").should be_true
45
+ walker.ignore_dir?("pippo").should be_false
46
+
47
+ walker.ignore_file("xvpics")
48
+ walker.ignore_file?("xvpics").should be_true
49
+
50
+ walker.ignore("sub")
51
+ walker.ignore_file?("[Dsube]").should be_false
52
+ walker.ignore_dir?("[Dsube]").should be_false
53
+ end
54
+
55
+ it "should accumulate file names" do
56
+ dir_tree_walker = DirTreeWalker.new(File.join(FIXTURES, "test_dir_1"))
57
+
58
+ accumulator = []
59
+ visitor = BlockTreeNodeVisitor.new { |pathname| accumulator << File.basename(pathname) }
60
+ dir_tree_walker.run(visitor)
61
+ accumulator.length.should == 9
62
+ accumulator.sort.should == %w{ test_dir_1 dir.1 dir.1.2 file.1.2.1 file.1.1 dir.2 file.2.1 .dir_with_dot dummy.txt }.sort
63
+ end
64
+
65
+ it "should accumulate file names 2" do
66
+ dir_tree_walker = DirTreeWalker.new(File.join(FIXTURES, "test_dir_2"))
67
+ dir_tree_walker.ignore("sub")
68
+
69
+ accumulator = []
70
+ visitor = BlockTreeNodeVisitor.new { |pathname| accumulator << File.basename(pathname) }
71
+ dir_tree_walker.run(visitor)
72
+ accumulator.length.should == 2
73
+ accumulator.sort.should == %w{ [Dsube] test_dir_2 }.sort
74
+ end
75
+
76
+ it "should ignore not accessible directory" do
77
+
78
+ dir = File.join(FIXTURES, "test_dir_3_with_error")
79
+
80
+ f1 = File.join(dir, "no_accessible_dir")
81
+ Dir.rmdir(f1) if File.exist?(f1)
82
+ Dir.mkdir(f1, 0000)
83
+
84
+ f2 = File.join(dir, "accessible_dir")
85
+ Dir.rmdir(f2) if File.exist?(f2)
86
+ Dir.mkdir(f2)
87
+
88
+ dir_tree_walker = DirTreeWalker.new(File.join(FIXTURES, "test_dir_3_with_error"))
89
+ accumulator = []
90
+ visitor = BlockTreeNodeVisitor.new { |pathname| accumulator << File.basename(pathname) }
91
+ dir_tree_walker.run(visitor)
92
+ accumulator.length.should == 2
93
+ accumulator.sort.should == %w{accessible_dir test_dir_3_with_error }.sort
94
+
95
+ # Dir.rmdir(f1)
96
+ # Dir.rmdir(f2)
97
+ end
98
+
99
+ end
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe "TreeNodeDsl" do
5
+
6
+ it "should build tree with dsl" do
7
+ tree = TreeNode.create do
8
+ node "root" do
9
+ leaf "l1"
10
+ leaf "l2"
11
+ node "sub" do
12
+ leaf "l3"
13
+ end
14
+ node "wo leaves"
15
+ end
16
+ end
17
+
18
+ # puts tree.to_str
19
+ out =<<EOS
20
+ root
21
+ |-- l1
22
+ |-- l2
23
+ |-- sub
24
+ | `-- l3
25
+ `-- wo leaves
26
+ EOS
27
+ tree.to_str.should == out
28
+ end
29
+
30
+ it "test_dsl_block_with_arg" do
31
+ tree = TreeNode.create do
32
+ node "root" do |node|
33
+ node.prefix_path=("pre/")
34
+ leaf "l1"
35
+ leaf "l2"
36
+ node "sub" do
37
+ leaf "l3" do |leaf|
38
+ end
39
+ end
40
+ node "woleaves"
41
+ end
42
+ end
43
+
44
+ # puts tree.to_str
45
+ out =<<EOS
46
+ root
47
+ |-- l1
48
+ |-- l2
49
+ |-- sub
50
+ | `-- l3
51
+ `-- woleaves
52
+ EOS
53
+ tree.to_str.should == out
54
+ tree.find("l3").path_with_prefix.should == "pre/root/sub/l3"
55
+ end
56
+
57
+ end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe "Tree Node Dsl Derived Class with n-arg constructor" do
5
+
6
+ class ArgsTreeNode < TreeNode
7
+ attr_reader :description
8
+
9
+ def initialize(name, description, parent)
10
+ super(name, parent)
11
+ @description = description
12
+ end
13
+
14
+ def to_s
15
+ "a: #{description}"
16
+ end
17
+ end
18
+
19
+ class ArgsLeafNode < LeafNode
20
+ attr_reader :description
21
+
22
+ def initialize(name, description, parent)
23
+ super(name, parent)
24
+ @description = description
25
+ end
26
+
27
+ def to_s
28
+ "a: #{description}"
29
+ end
30
+ end
31
+
32
+ it "test_derivated_args" do
33
+ tree = TreeNode.create(ArgsTreeNode, ArgsLeafNode) do
34
+ node "root", "droot" do
35
+ leaf "l1", "dl1"
36
+ leaf "l2", "dl2"
37
+ node "sub", "dsub" do
38
+ leaf "l3", "dl3"
39
+ end
40
+ end
41
+ end
42
+
43
+ # puts tree.to_str
44
+ out =<<EOS
45
+ a: droot
46
+ |-- a: dl1
47
+ |-- a: dl2
48
+ `-- a: dsub
49
+ `-- a: dl3
50
+ EOS
51
+ tree.to_str.should == out
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe "Tree Node Dsl Derived Class with no-arg constructor " do
5
+
6
+ class DTreeNode < TreeNode
7
+ def to_s
8
+ "dt: #{content}"
9
+ end
10
+ end
11
+
12
+ class DLeafNode < LeafNode
13
+ def to_s
14
+ "dl: #{content}"
15
+ end
16
+ end
17
+
18
+ it "dsl with non-arg constructor" do
19
+ tree = TreeNode.create(DTreeNode, DLeafNode) do
20
+ node "root" do
21
+ leaf "l1"
22
+ leaf "l2"
23
+ node "sub" do
24
+ leaf "l3"
25
+ end
26
+ end
27
+ end
28
+
29
+ # puts tree.to_str
30
+ out =<<EOS
31
+ dt: root
32
+ |-- dl: l1
33
+ |-- dl: l2
34
+ `-- dt: sub
35
+ `-- dl: l3
36
+ EOS
37
+ tree.to_str.should == out
38
+
39
+ tree = DTreeNode.create(DLeafNode) do
40
+ node "root" do
41
+ leaf "l1"
42
+ leaf "l2"
43
+ node "sub" do
44
+ leaf "l3"
45
+ end
46
+ end
47
+ end
48
+ tree.to_str.should == out
49
+ end
50
+
51
+ end
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe TreeNode do
5
+
6
+ context "paths" do
7
+
8
+ before do
9
+ @tree = TreeNode.new("a")
10
+ ln1 = LeafNode.new("1", @tree)
11
+ ln2 = LeafNode.new("2", @tree)
12
+ @sub_tree = TreeNode.new("b", @tree)
13
+ @ln3 = LeafNode.new("3", @sub_tree)
14
+ @ln4 = LeafNode.new("12", @sub_tree)
15
+ end
16
+
17
+ it "correct path" do
18
+ @tree.path.should == "a"
19
+ @sub_tree.path.should == "a/b"
20
+ @tree.path_with_prefix.should == "a"
21
+ @sub_tree.path_with_prefix.should == "a/b"
22
+ end
23
+
24
+ it "assign prefix path with a /" do
25
+ @tree.prefix_path= "<root>/"
26
+
27
+ @tree.prefix_path.should == "<root>/"
28
+ @tree.path.should == "a"
29
+ @sub_tree.path.should == "a/b"
30
+ @tree.path_with_prefix.should == "<root>/a"
31
+ @sub_tree.path_with_prefix.should == "<root>/a/b"
32
+ end
33
+
34
+ it "assign empty prefix path" do
35
+ @tree.prefix_path= ""
36
+
37
+ @tree.prefix_path.should == "/"
38
+ @tree.path.should == "a"
39
+ @sub_tree.path.should == "a/b"
40
+ @tree.path_with_prefix.should == "/a"
41
+ @sub_tree.path_with_prefix.should == "/a/b"
42
+ end
43
+
44
+ it "assign prefix path wo a /" do
45
+ @tree.prefix_path= "<root>"
46
+
47
+ @tree.prefix_path.should == "<root>/"
48
+ @tree.path_with_prefix.should == "<root>/a"
49
+ @sub_tree.path_with_prefix.should == "<root>/a/b"
50
+ end
51
+
52
+ it "invalidate" do
53
+ @tree.prefix_path="root/"
54
+ @sub_tree.path.should == "a/b"
55
+ @sub_tree.path_with_prefix.should == "root/a/b"
56
+ @sub_tree.depth.should == 2
57
+
58
+ r = TreeNode.new("r")
59
+ r.add_child(@tree)
60
+ @sub_tree.path.should == "r/a/b"
61
+ @sub_tree.path_with_prefix.should == "r/a/b"
62
+
63
+ r.prefix_path="new_root/"
64
+ @sub_tree.path.should == "r/a/b"
65
+ @sub_tree.path_with_prefix.should == "new_root/r/a/b"
66
+ @sub_tree.depth.should == 3
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,135 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
3
+
4
+ describe TreeNode do
5
+
6
+ it "should initialize correctly" do
7
+ ta = TreeNode.new("a")
8
+ ta.should be_root
9
+
10
+ ln1 = LeafNode.new("1", ta)
11
+ ln1.parent.should == ta
12
+ ln1.should_not be_root
13
+
14
+ ln2 = LeafNode.new("2", ta)
15
+ tb = TreeNode.new("b", ta)
16
+ ln3 = LeafNode.new("3", tb)
17
+ ln3.parent.should == tb
18
+
19
+ # test depth
20
+ tb.depth.should == 2
21
+ ln3.depth.should == 3
22
+
23
+ # test nr_nodes
24
+ tb.nr_nodes.should == 1
25
+ ta.nr_nodes.should == 4
26
+
27
+ # puts ta.to_str
28
+ end
29
+
30
+ it "should add child and leaf" do
31
+ ta = TreeNode.new("a")
32
+ ta.should be_root
33
+
34
+ ln1 = LeafNode.new("1")
35
+ ta.add_leaf(ln1)
36
+ ln1.parent.should == ta
37
+
38
+ ln2 = LeafNode.new("2", ta)
39
+ ta.add_leaf(ln2)
40
+
41
+ tb = TreeNode.new("b", ta)
42
+ ln3 = LeafNode.new("3", tb)
43
+ tb.add_leaf(ln3)
44
+ ln3.parent.should == tb
45
+
46
+ ta.add_child(tb)
47
+ # puts ta.to_str
48
+ end
49
+
50
+ it "next and prev" do
51
+ ta = TreeNode.new("a")
52
+ ta.prev.should be_nil
53
+ ta.next.should be_nil
54
+
55
+ ln1 = LeafNode.new("1", ta)
56
+ ln1.prev.should be_nil
57
+ ln1.next.should be_nil
58
+
59
+ ln2 = LeafNode.new("2", ta)
60
+ ln2.prev.should == ln1
61
+ ln2.next.should be_nil
62
+
63
+ ln3 = LeafNode.new("3", ta)
64
+ ln2.next.should == ln3
65
+
66
+ tb = TreeNode.new("b", ta)
67
+ tb.next.should be_nil
68
+ tb.prev.should be_nil
69
+
70
+ tc = TreeNode.new("c", ta)
71
+ tc.prev.should == tb
72
+ tc.next.should be_nil
73
+ end
74
+
75
+ context "navigate tree" do
76
+
77
+ before do
78
+ @tree = TreeNode.new("a")
79
+ ln1 = LeafNode.new("1", @tree)
80
+ ln2 = LeafNode.new("2", @tree)
81
+ @sub_tree = TreeNode.new("b", @tree)
82
+ @ln3 = LeafNode.new("3", @sub_tree)
83
+ @ln4 = LeafNode.new("12", @sub_tree)
84
+ end
85
+
86
+ it "nr_nodes and nr_leaves and nr_children" do
87
+ @tree.nr_nodes.should == 5
88
+ @tree.nr_leaves.should == 4
89
+ @tree.nr_children.should == 1
90
+
91
+ @sub_tree.nr_nodes.should == 2
92
+ @sub_tree.nr_leaves.should == 2
93
+ @sub_tree.nr_children.should == 0
94
+ end
95
+
96
+
97
+ context "find" do
98
+
99
+ it "find by string" do
100
+ @tree.find("a").should === @tree
101
+ @tree.find("b").should === @sub_tree
102
+ @tree.find("3").should === @ln3
103
+ @tree.find("not existent").should be_nil
104
+ end
105
+
106
+ it "find by regex" do
107
+ @tree.find(/[a,b]/).should === @tree
108
+ @tree.find(/[b,c]/).should === @sub_tree
109
+ @tree.find(/\d\d/).should === @ln4
110
+ @tree.find(/not existent/).should be_nil
111
+ end
112
+
113
+ it "find with block" do
114
+ @tree.find { |e| e.content == "a" }.should === @tree
115
+ @tree.find { |e| e.content == "b" }.should === @sub_tree
116
+ @tree.find { |e| e.content == "3" }.should === @ln3
117
+ @tree.find { |e| e.content == "not existent" }.should be_nil
118
+ end
119
+
120
+ it "to_str" do
121
+ out = <<EOS
122
+ a
123
+ |-- 1
124
+ |-- 2
125
+ `-- b
126
+ |-- 3
127
+ `-- 12
128
+ EOS
129
+ @tree.to_str.should == out
130
+ end
131
+
132
+ end
133
+
134
+ end
135
+ end