Skip to content

Commit cb3e5a2

Browse files
committed
Document print_tree IO default (#69)
Clarify that print_tree writes to by default when io: is not provided, and keep the traversal helper docs consistent.
1 parent c8d1302 commit cb3e5a2

2 files changed

Lines changed: 41 additions & 10 deletions

File tree

API-CHANGES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ smooth transition to the new APIs.
2121
* Added [Tree::TreeNode#cmp][cmp] to compare nodes using traversal or
2222
relationship policies without changing the name-based `<=>` behavior.
2323

24+
* [Tree::TreeNode#print_tree][print_tree] now accepts an `io:` keyword to
25+
redirect output (defaults to `$stdout`), and
26+
[Tree::TreeNode#print_tree_to_s][print_tree_to_s] returns the formatted
27+
output as a string.
28+
2429
## Release 2.2.0 Changes
2530

2631
* [Tree::TreeNode#add][add] now raises `ArgumentError` when attempting to add
@@ -194,6 +199,8 @@ smooth transition to the new APIs.
194199
[out_degree]: rdoc-ref:Tree::Utils::TreeMetricsHandler#out_degree
195200
[postordered_each]: rdoc-ref:Tree::TreeNode#postordered_each
196201
[preordered_each]: rdoc-ref:Tree::TreeNode#preordered_each
202+
[print_tree]: rdoc-ref:Tree::TreeNode#print_tree
203+
[print_tree_to_s]: rdoc-ref:Tree::TreeNode#print_tree_to_s
197204
[previous_sibling]: rdoc-ref:Tree::TreeNode#previous_sibling
198205
[remove_all]: rdoc-ref:Tree::TreeNode#remove_all!
199206
[rename_child]: rdoc-ref:Tree::TreeNode#rename_child

lib/tree/utils/traversal_methods.rb

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
module Tree
3333
module Utils
3434
# Provides traversal helpers for TreeNode.
35+
# rubocop:disable Metrics/ModuleLength
3536
module TreeTraversalHandler
37+
require 'stringio'
3638
# Traverses each node (including this node) of the (sub)tree rooted at this
3739
# node by yielding the nodes to the specified block.
3840
def each # :yields: node
@@ -133,10 +135,29 @@ def each_level
133135
end
134136

135137
# Pretty prints the (sub)tree rooted at this node.
138+
# Output defaults to +$stdout+ unless an +io:+ is provided.
136139
def print_tree(level = node_depth, max_depth = nil,
137-
block = lambda { |node, prefix|
138-
puts "#{prefix} #{node.name}"
139-
})
140+
block = nil, io: $stdout, &custom_block)
141+
block = resolve_print_block(block, custom_block, io)
142+
block.call(self, tree_prefix(level))
143+
144+
# Exit if the max level is defined, and reached.
145+
return unless max_depth.nil? || level < max_depth
146+
147+
# Child might be 'nil'
148+
children do |child|
149+
child&.print_tree(level + 1, max_depth, block, io: io)
150+
end
151+
end
152+
153+
# Returns the pretty-printed tree output as a string.
154+
def print_tree_to_s(level = node_depth, max_depth = nil)
155+
buffer = StringIO.new
156+
print_tree(level, max_depth, io: buffer)
157+
buffer.string
158+
end
159+
160+
def tree_prefix(level)
140161
prefix = ''.dup # dup must be invoked to make this mutable.
141162

142163
if root?
@@ -149,16 +170,19 @@ def print_tree(level = node_depth, max_depth = nil,
149170
prefix << (children? ? '+' : '>')
150171
end
151172

152-
block.call(self, prefix)
173+
prefix
174+
end
153175

154-
# Exit if the max level is defined, and reached.
155-
return unless max_depth.nil? || level < max_depth
176+
def resolve_print_block(block, custom_block, io)
177+
return block if block
178+
return custom_block if custom_block
156179

157-
# Child might be 'nil'
158-
children do |child|
159-
child&.print_tree(level + 1, max_depth, block)
160-
end
180+
lambda { |node, prefix|
181+
io.puts "#{prefix} #{node.name}"
182+
}
161183
end
184+
private :tree_prefix, :resolve_print_block
162185
end
186+
# rubocop:enable Metrics/ModuleLength
163187
end
164188
end

0 commit comments

Comments
 (0)