shard-spectator/src/spectator/example_iterator.cr

53 lines
1.4 KiB
Crystal
Raw Normal View History

2020-10-17 17:23:51 +00:00
require "./example"
2021-05-08 02:09:33 +00:00
require "./node"
2020-10-17 17:23:51 +00:00
2018-11-13 17:06:43 +00:00
module Spectator
2018-11-20 18:51:47 +00:00
# Iterates through all examples in a group and its nested groups.
# Nodes are iterated in pre-order.
2018-11-13 17:06:43 +00:00
class ExampleIterator
include Iterator(Example)
2018-11-20 18:51:47 +00:00
# A stack is used to track where in the tree this iterator is.
@stack = Deque(Node).new(1)
2018-11-13 17:06:43 +00:00
2018-11-20 18:51:47 +00:00
# Creates a new iterator.
# The *group* is the example group to iterate through.
def initialize(@group : Node)
@stack.push(@group)
2018-11-13 17:06:43 +00:00
end
2018-11-20 18:51:47 +00:00
# Retrieves the next `Example`.
# If there are none left, then `Iterator::Stop` is returned.
2018-11-13 17:06:43 +00:00
def next
2018-11-20 18:51:47 +00:00
# Keep going until either:
# a. an example is found.
# b. the stack is empty.
2018-11-13 17:06:43 +00:00
until @stack.empty?
# Retrieve the next node.
2020-10-17 17:23:51 +00:00
# This could be an `Example` or a group.
node = @stack.pop
# If the node is a group, add its direct children to the queue
# in reverse order so that the tree is traversed in pre-order.
if node.is_a?(Indexable(Node))
node.reverse_each { |child| @stack.push(child) }
end
# Return the node if it's an example.
2018-11-20 18:51:47 +00:00
# Otherwise, advance and check the next one.
return node if node.is_a?(Example)
2018-11-13 17:06:43 +00:00
end
2018-11-20 18:51:47 +00:00
# Nothing left to iterate.
2018-11-13 17:06:43 +00:00
stop
end
2018-11-20 18:51:47 +00:00
# Restart the iterator at the beginning.
2018-11-13 17:06:43 +00:00
def rewind
@stack.clear
@stack.push(@group)
2018-11-13 17:06:43 +00:00
self
end
end
end