rubytree 1.0.0 → 1.0.2

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.
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2017-12-21 12:49:25 anupam>
7
+ # Time-stamp: <2021-12-29 13:01:54 anupam>
8
8
  #
9
- # Copyright (C) 2013, 2015, 2017 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2013, 2015, 2017, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -36,15 +36,13 @@
36
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
37
  #
38
38
 
39
- require_relative '../../../lib/tree'
40
39
  require 'structured_warnings'
41
40
 
42
41
  module Tree::Utils
43
42
  # Provides utility functions to measure various tree metrics.
44
43
  module TreeMetricsHandler
45
44
  # noinspection RubyUnusedLocalVariable
46
- def self.included(base)
47
-
45
+ def self.included(_base)
48
46
  # @!group Metrics and Measures
49
47
 
50
48
  # @!attribute [r] size
@@ -56,7 +54,7 @@ module Tree::Utils
56
54
  #
57
55
  # @return [Integer] Total number of nodes in this (sub)tree.
58
56
  def size
59
- inject(0) {|sum, node| sum + 1 if node}
57
+ inject(0) { |sum, node| sum + 1 if node }
60
58
  end
61
59
 
62
60
  # @!attribute [r] length
@@ -68,7 +66,7 @@ module Tree::Utils
68
66
  # @return [Integer] The total number of nodes in this (sub)tree.
69
67
  # @see #size
70
68
  def length
71
- self.size
69
+ size
72
70
  end
73
71
 
74
72
  # @!attribute [r] node_height
@@ -82,6 +80,7 @@ module Tree::Utils
82
80
  # @return [Integer] Height of the node.
83
81
  def node_height
84
82
  return 0 if is_leaf?
83
+
85
84
  1 + @children.collect { |child| child.node_height }.max
86
85
  end
87
86
 
@@ -100,6 +99,7 @@ module Tree::Utils
100
99
  # @return [Integer] Depth of this node.
101
100
  def node_depth
102
101
  return 0 if is_root?
102
+
103
103
  1 + parent.node_depth
104
104
  end
105
105
 
@@ -134,6 +134,7 @@ module Tree::Utils
134
134
  'Please use node_depth() or node_height() instead (bug # 22535)'
135
135
 
136
136
  return 1 if is_leaf?
137
+
137
138
  1 + @children.collect { |child| child.depth }.max
138
139
  end
139
140
 
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Marco Ziccardi and Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2015-05-30 16:04:00 anupam>
7
+ # Time-stamp: <2021-12-29 13:01:58 anupam>
8
8
  #
9
- # Copyright (C) 2015 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2015, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -36,14 +36,11 @@
36
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
37
  #
38
38
 
39
- require_relative '../../../lib/tree'
40
-
41
39
  module Tree::Utils
42
40
  # Provides utility methods for path extraction
43
41
  module TreePathHandler
44
42
  # noinspection RubyUnusedLocalVariable
45
- def self.included(base)
46
-
43
+ def self.included(_base)
47
44
  # @!group Node Path
48
45
 
49
46
  # Returns the path of this node from the root as a string, with the node
@@ -90,5 +87,4 @@ module Tree::Utils
90
87
  # @!endgroup
91
88
  end # self.included
92
89
  end
93
-
94
90
  end
@@ -40,7 +40,6 @@ require_relative '../../../lib/tree/utils/utils'
40
40
  # Provides utility methods to merge two {Tree::TreeNode} based trees.
41
41
  # @since 0.9.0
42
42
  module Tree::Utils::TreeMergeHandler
43
-
44
43
  # @!group Merging Trees
45
44
 
46
45
  # Merge two trees that share the same root node and returns <em>a new
@@ -62,7 +61,7 @@ module Tree::Utils::TreeMergeHandler
62
61
  # have the same root node as self.
63
62
  def merge(other_tree)
64
63
  check_merge_prerequisites(other_tree)
65
- merge_trees(self.root.dup, other_tree.root)
64
+ merge_trees(root.dup, other_tree.root)
66
65
  end
67
66
 
68
67
  # Merge in another tree (that shares the same root node) into +this+ tree.
@@ -79,8 +78,8 @@ module Tree::Utils::TreeMergeHandler
79
78
  # @raise [ArgumentError] This exception is raised if _other_tree_ does not
80
79
  # have the same root node as self.
81
80
  def merge!(other_tree)
82
- check_merge_prerequisites( other_tree )
83
- merge_trees( self.root, other_tree.root )
81
+ check_merge_prerequisites(other_tree)
82
+ merge_trees(root, other_tree.root)
84
83
  end
85
84
 
86
85
  private
@@ -97,7 +96,7 @@ module Tree::Utils::TreeMergeHandler
97
96
  'You can only merge in another instance of Tree::TreeNode'
98
97
  end
99
98
 
100
- unless self.root.name == other_tree.root.name
99
+ unless root.name == other_tree.root.name
101
100
  raise ArgumentError,
102
101
  'Unable to merge trees as they do not share the same root'
103
102
  end
@@ -121,10 +120,9 @@ module Tree::Utils::TreeMergeHandler
121
120
  end
122
121
 
123
122
  tree1.children.each do |child|
124
- merge_trees( child, tree2[child.name] ) unless tree2[child.name].nil?
123
+ merge_trees(child, tree2[child.name]) unless tree2[child.name].nil?
125
124
  end
126
125
 
127
126
  tree1
128
127
  end
129
-
130
128
  end
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2015-05-30 14:25:57 anupam>
7
+ # Time-stamp: <2021-12-29 13:02:08 anupam>
8
8
  #
9
- # Copyright (C) 2012, 2015 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2012, 2015, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -37,8 +37,6 @@
37
37
 
38
38
  # Provides utilities and mixin modules for RubyTree.
39
39
 
40
- require_relative '../../../lib/tree'
41
-
42
40
  module Tree::Utils
43
41
  # Empty module. Being used as a namespace.
44
42
  end
data/lib/tree/version.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Copyright (c) 2012, 2013, 2014, 2015, 2017 Anupam Sengupta
7
+ # Copyright (c) 2012, 2013, 2014, 2015, 2017, 2020, 2021 Anupam Sengupta
8
8
  #
9
9
  # All rights reserved.
10
10
  #
@@ -34,8 +34,7 @@
34
34
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  #
36
36
 
37
- #
38
37
  module Tree
39
38
  # Rubytree Package Version
40
- VERSION = '1.0.0'
39
+ VERSION = '1.0.2'.freeze
41
40
  end
data/lib/tree.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
10
10
  #
11
11
 
12
- # Copyright (c) 2006-2015, 2017 Anupam Sengupta
12
+ # Copyright (c) 2006-2021 Anupam Sengupta
13
13
  #
14
14
  # All rights reserved.
15
15
  #
@@ -47,7 +47,6 @@ require 'tree/tree_deps'
47
47
  # This module also acts as the namespace for all classes in the *RubyTree*
48
48
  # package.
49
49
  module Tree
50
-
51
50
  # == TreeNode Class Description
52
51
  #
53
52
  # This class models the nodes for an *N-ary* tree data structure. The
@@ -109,11 +108,11 @@ module Tree
109
108
  # +content+ attribute for any non-unique node requirements.
110
109
  #
111
110
  # If you want to change the name, you probably want to call +rename+
112
- # instead.
111
+ # instead. Note that +name=+ is a protected method.
113
112
  #
114
113
  # @see content
115
114
  # @see rename
116
- attr_reader :name
115
+ attr_accessor :name
117
116
 
118
117
  # @!attribute [rw] content
119
118
  # Content of this node. Can be +nil+. Note that there is no
@@ -177,7 +176,7 @@ module Tree
177
176
  return nil if is_root?
178
177
 
179
178
  parentage_array = []
180
- prev_parent = self.parent
179
+ prev_parent = parent
181
180
  while prev_parent
182
181
  parentage_array << prev_parent
183
182
  prev_parent = prev_parent.parent
@@ -216,18 +215,20 @@ module Tree
216
215
  #
217
216
  # @see #[]
218
217
  def initialize(name, content = nil)
219
- raise ArgumentError, 'Node name HAS to be provided!' if name == nil
220
- @name, @content = name, content
218
+ raise ArgumentError, 'Node name HAS to be provided!' if name.nil?
219
+
220
+ @name = name
221
+ @content = content
221
222
 
222
- if name.kind_of?(Integer)
223
+ if name.is_a?(Integer)
223
224
  warn StructuredWarnings::StandardWarning,
224
225
  'Using integer as node name.'\
225
226
  ' Semantics of TreeNode[] may not be what you expect!'\
226
227
  " #{name} #{content}"
227
228
  end
228
229
 
229
- self.set_as_root!
230
- @children_hash = Hash.new
230
+ set_as_root!
231
+ @children_hash = {}
231
232
  @children = []
232
233
  end
233
234
 
@@ -254,22 +255,21 @@ module Tree
254
255
  # Alias for {Tree::TreeNode#detached_subtree_copy}
255
256
  #
256
257
  # @see Tree::TreeNode#detached_subtree_copy
257
- alias :dup :detached_subtree_copy
258
+ alias dup detached_subtree_copy
258
259
 
259
260
  # Returns a {marshal-dump}[http://ruby-doc.org/core-1.8.7/Marshal.html]
260
261
  # representation of the (sub)tree rooted at this node.
261
262
  #
262
263
  def marshal_dump
263
- self.collect { |node| node.create_dump_rep }
264
+ collect { |node| node.create_dump_rep }
264
265
  end
265
266
 
266
267
  # Creates a dump representation of this node and returns the same as
267
268
  # a hash.
268
- def create_dump_rep # :nodoc:
269
- {name: @name,
270
- parent: (is_root? ? nil : @parent.name),
271
- content: Marshal.dump(@content)
272
- }
269
+ def create_dump_rep # :nodoc:
270
+ { name: @name,
271
+ parent: (is_root? ? nil : @parent.name),
272
+ content: Marshal.dump(@content) }
273
273
  end
274
274
 
275
275
  protected :create_dump_rep
@@ -284,7 +284,7 @@ module Tree
284
284
  # self and makes itself the root.
285
285
  #
286
286
  def marshal_load(dumped_tree_array)
287
- nodes = { }
287
+ nodes = {}
288
288
  dumped_tree_array.each do |node_hash|
289
289
  name = node_hash[:name]
290
290
  parent_name = node_hash[:parent]
@@ -297,7 +297,7 @@ module Tree
297
297
  # This is the root node, hence initialize self.
298
298
  initialize(name, content)
299
299
 
300
- nodes[name] = self # Add self to the list of nodes
300
+ nodes[name] = self # Add self to the list of nodes
301
301
  end
302
302
  end
303
303
  end
@@ -309,7 +309,7 @@ module Tree
309
309
  #
310
310
  # @return [String] A string representation of the node.
311
311
  def to_s
312
- "Node Name: #{@name} Content: #{(@content.to_s || '<Empty>')} Parent: #{(is_root? ? '<None>' : @parent.name.to_s)} Children: #{@children.length} Total Nodes: #{size}"
312
+ "Node Name: #{@name} Content: #{@content.to_s || '<Empty>'} Parent: #{is_root? ? '<None>' : @parent.name.to_s} Children: #{@children.length} Total Nodes: #{size}"
313
313
  end
314
314
 
315
315
  # @!group Structure Modification
@@ -377,19 +377,18 @@ module Tree
377
377
  # @see #<<
378
378
  def add(child, at_index = -1)
379
379
  # Only handles the immediate child scenario
380
- raise ArgumentError,
381
- 'Attempting to add a nil node' unless child
382
- raise ArgumentError,
383
- 'Attempting add node to itself' if self.equal?(child)
384
- raise ArgumentError,
385
- 'Attempting add root as a child' if child.equal?(root)
386
-
387
- # Lazy mans unique test, won't test if children of child are unique in
380
+ raise ArgumentError, 'Attempting to add a nil node' unless child
381
+
382
+ raise ArgumentError, 'Attempting add node to itself' if equal?(child)
383
+
384
+ raise ArgumentError, 'Attempting add root as a child' if child.equal?(root)
385
+
386
+ # Lazy man's unique test, won't test if children of child are unique in
388
387
  # this tree too.
389
388
  raise "Child #{child.name} already added!"\
390
389
  if @children_hash.include?(child.name)
391
390
 
392
- child.parent.remove! child if child.parent # Detach from the old parent
391
+ child.parent&.remove! child # Detach from the old parent
393
392
 
394
393
  if insertion_range.include?(at_index)
395
394
  @children.insert(at_index, child)
@@ -400,7 +399,7 @@ module Tree
400
399
  "#{insertion_range.min} to #{insertion_range.max} exist."
401
400
  end
402
401
 
403
- @children_hash[child.name] = child
402
+ @children_hash[child.name] = child
404
403
  child.parent = self
405
404
  child
406
405
  end
@@ -408,7 +407,7 @@ module Tree
408
407
  # Return a range of valid insertion positions. Used in the #add method.
409
408
  def insertion_range
410
409
  max = @children.size
411
- min = -(max+1)
410
+ min = -(max + 1)
412
411
  min..max
413
412
  end
414
413
 
@@ -424,7 +423,7 @@ module Tree
424
423
  old_name = @name
425
424
 
426
425
  if is_root?
427
- self.name=(new_name)
426
+ self.name = new_name
428
427
  else
429
428
  @parent.rename_child old_name, new_name
430
429
  end
@@ -441,20 +440,10 @@ module Tree
441
440
  # pass a String (Integer names may cause *surprises*)
442
441
  def rename_child(old_name, new_name)
443
442
  raise ArgumentError, "Invalid child name specified: #{old_name}"\
444
- unless @children_hash.has_key?(old_name)
443
+ unless @children_hash.key?(old_name)
445
444
 
446
445
  @children_hash[new_name] = @children_hash.delete(old_name)
447
- @children_hash[new_name].name=(new_name)
448
- end
449
-
450
- # Protected method to set the name of this node.
451
- # This method should *NOT* be invoked by client code.
452
- #
453
- # @param [Object] new_name The node Name to set.
454
- #
455
- # @return [Object] The new name.
456
- def name=(new_name)
457
- @name = new_name
446
+ @children_hash[new_name].name = new_name
458
447
  end
459
448
 
460
449
  # Replaces the specified child node with another child node on this node.
@@ -510,7 +499,7 @@ module Tree
510
499
  # @param [Tree::TreeNode] parent The parent node.
511
500
  #
512
501
  # @return [Tree::TreeNode] The parent node.
513
- def parent=(parent) # :nodoc:
502
+ def parent=(parent) # :nodoc:
514
503
  @parent = parent
515
504
  @node_depth = nil
516
505
  end
@@ -549,7 +538,7 @@ module Tree
549
538
  # Protected method which sets this node as a root node.
550
539
  #
551
540
  # @return +nil+.
552
- def set_as_root! # :nodoc:
541
+ def set_as_root! # :nodoc:
553
542
  self.parent = nil
554
543
  end
555
544
 
@@ -560,7 +549,7 @@ module Tree
560
549
  # The nodes become immutable after this operation. In effect, the entire tree's
561
550
  # structure and contents become _read-only_ and cannot be changed.
562
551
  def freeze_tree!
563
- each {|node| node.freeze}
552
+ each { |node| node.freeze }
564
553
  end
565
554
 
566
555
  # @!endgroup
@@ -600,14 +589,13 @@ module Tree
600
589
  #
601
590
  # @see #add
602
591
  # @see #initialize
603
- def [](name_or_index, num_as_name=false)
604
- raise ArgumentError,
605
- 'Name_or_index needs to be provided!' if name_or_index == nil
592
+ def [](name_or_index, num_as_name = false)
593
+ raise ArgumentError, 'Name_or_index needs to be provided!' if name_or_index.nil?
606
594
 
607
- if name_or_index.kind_of?(Integer) and not num_as_name
595
+ if name_or_index.is_a?(Integer) && !num_as_name
608
596
  @children[name_or_index]
609
597
  else
610
- if num_as_name and not name_or_index.kind_of?(Integer)
598
+ if num_as_name && !name_or_index.is_a?(Integer)
611
599
  warn StructuredWarnings::StandardWarning,
612
600
  'Redundant use of the `num_as_name` flag for non-integer node name'
613
601
  end
@@ -630,19 +618,18 @@ module Tree
630
618
  # @return [Tree::TreeNode] this node, if a block if given
631
619
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
632
620
  # noinspection RubyUnusedLocalVariable
633
- def each(&block) # :yields: node
621
+ def each # :yields: node
622
+ return to_enum unless block_given?
634
623
 
635
- return self.to_enum unless block_given?
636
-
637
- node_stack = [self] # Start with this node
624
+ node_stack = [self] # Start with this node
638
625
 
639
626
  until node_stack.empty?
640
- current = node_stack.shift # Pop the top-most node
641
- if current # Might be 'nil' (esp. for binary trees)
642
- yield current # and process it
643
- # Stack children of the current node at top of the stack
644
- node_stack = current.children.concat(node_stack)
645
- end
627
+ current = node_stack.shift # Pop the top-most node
628
+ next unless current # Might be 'nil' (esp. for binary trees)
629
+
630
+ yield current # and process it
631
+ # Stack children of the current node at top of the stack
632
+ node_stack = current.children.concat(node_stack)
646
633
  end
647
634
 
648
635
  self if block_given?
@@ -658,7 +645,7 @@ module Tree
658
645
  #
659
646
  # @return [Tree::TreeNode] this node, if a block if given
660
647
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
661
- def preordered_each(&block) # :yields: node
648
+ def preordered_each(&block) # :yields: node
662
649
  each(&block)
663
650
  end
664
651
 
@@ -672,8 +659,8 @@ module Tree
672
659
  # @return [Tree::TreeNode] this node, if a block if given
673
660
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
674
661
  # noinspection RubyUnusedLocalVariable
675
- def postordered_each(&block)
676
- return self.to_enum(:postordered_each) unless block_given?
662
+ def postordered_each
663
+ return to_enum(:postordered_each) unless block_given?
677
664
 
678
665
  # Using a marked node in order to skip adding the children of nodes that
679
666
  # have already been visited. This allows the stack depth to be controlled,
@@ -683,15 +670,15 @@ module Tree
683
670
 
684
671
  until node_stack.empty?
685
672
  peek_node = node_stack[0]
686
- if peek_node.node.has_children? and not peek_node.visited
673
+ if peek_node.node.has_children? && !peek_node.visited
687
674
  peek_node.visited = true
688
675
  # Add the children to the stack. Use the marking structure.
689
676
  marked_children =
690
- peek_node.node.children.map {|node| marked_node.new(node, false)}
677
+ peek_node.node.children.map { |node| marked_node.new(node, false) }
691
678
  node_stack = marked_children.concat(node_stack)
692
679
  next
693
680
  else
694
- yield node_stack.shift.node # Pop and yield the current node
681
+ yield node_stack.shift.node # Pop and yield the current node
695
682
  end
696
683
  end
697
684
 
@@ -711,10 +698,10 @@ module Tree
711
698
  # @return [Tree::TreeNode] this node, if a block if given
712
699
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
713
700
  # noinspection RubyUnusedLocalVariable
714
- def breadth_each(&block)
715
- return self.to_enum(:breadth_each) unless block_given?
701
+ def breadth_each
702
+ return to_enum(:breadth_each) unless block_given?
716
703
 
717
- node_queue = [self] # Create a queue with self as the initial entry
704
+ node_queue = [self] # Create a queue with self as the initial entry
718
705
 
719
706
  # Use a queue to do breadth traversal
720
707
  until node_queue.empty?
@@ -739,9 +726,9 @@ module Tree
739
726
  #
740
727
  # @return [Array<Tree::TreeNode>] An array of the child nodes, if no block
741
728
  # is given.
742
- def children
729
+ def children(&block)
743
730
  if block_given?
744
- @children.each {|child| yield child}
731
+ @children.each(&block)
745
732
  self
746
733
  else
747
734
  @children.clone
@@ -763,15 +750,37 @@ module Tree
763
750
  # @return [Tree::TreeNode] this node, if a block if given
764
751
  # @return [Array<Tree::TreeNode>] An array of the leaf nodes
765
752
  # noinspection RubyUnusedLocalVariable
766
- def each_leaf(&block)
753
+ def each_leaf
767
754
  if block_given?
768
- self.each { |node| yield(node) if node.is_leaf? }
755
+ each { |node| yield(node) if node.is_leaf? }
769
756
  self
770
757
  else
771
758
  self.select { |node| node.is_leaf? }
772
759
  end
773
760
  end
774
761
 
762
+ # Yields every level of the (sub)tree rooted at this node to the
763
+ # specified block.
764
+ #
765
+ # Will yield this node as well since it is considered the first level.
766
+ #
767
+ # @yieldparam level [Array<Tree::TreeNode>] All nodes in the level
768
+ #
769
+ # @return [Tree::TreeNode] this node, if a block if given
770
+ # @return [Enumerator] an enumerator on this tree, if a block is *not* given
771
+ def each_level
772
+ if block_given?
773
+ level = [self]
774
+ until level.empty?
775
+ yield level
776
+ level = level.map(&:children).flatten
777
+ end
778
+ self
779
+ else
780
+ each
781
+ end
782
+ end
783
+
775
784
  # @!endgroup
776
785
 
777
786
  # @!group Navigating the Child Nodes
@@ -866,9 +875,11 @@ module Tree
866
875
  self
867
876
  else
868
877
  return [] if is_root?
878
+
869
879
  siblings = []
870
- parent.children {|my_sibling|
871
- siblings << my_sibling if my_sibling != self}
880
+ parent.children do |my_sibling|
881
+ siblings << my_sibling if my_sibling != self
882
+ end
872
883
  siblings
873
884
  end
874
885
  end
@@ -930,8 +941,9 @@ module Tree
930
941
  # this node is a 'predecessor'. Returns 'nil' if the other
931
942
  # object is not a 'Tree::TreeNode'.
932
943
  def <=>(other)
933
- return nil if other == nil || other.class != Tree::TreeNode
934
- self.name <=> other.name
944
+ return nil if other.nil? || other.class != Tree::TreeNode
945
+
946
+ name <=> other.name
935
947
  end
936
948
 
937
949
  # Pretty prints the (sub)tree rooted at this node.
@@ -940,9 +952,10 @@ module Tree
940
952
  # @param [Integer] max_depth optional maximum depth at which the printing
941
953
  # with stop.
942
954
  # @param [Proc] block optional block to use for rendering
943
- def print_tree(level = self.node_depth, max_depth = nil,
955
+ def print_tree(level = node_depth, max_depth = nil,
944
956
  block = lambda { |node, prefix|
945
- puts "#{prefix} #{node.name}" })
957
+ puts "#{prefix} #{node.name}"
958
+ })
946
959
  prefix = ''
947
960
 
948
961
  if is_root?
@@ -960,10 +973,11 @@ module Tree
960
973
  # Exit if the max level is defined, and reached.
961
974
  return unless max_depth.nil? || level < max_depth
962
975
 
963
- children { |child|
964
- child.print_tree(level + 1,
965
- max_depth, block) if child } # Child might be 'nil'
976
+ # Child might be 'nil'
977
+ children do |child|
978
+ child&.print_tree(level + 1,
979
+ max_depth, block)
980
+ end
966
981
  end
967
-
968
982
  end
969
983
  end