Class: Arrow::Template::Iterator
- Includes:
- Enumerable
- Defined in:
- lib/arrow/template/iterator.rb
Overview
The Arrow::Template::Iterator class, instances of which can be used to provide an iteration context to nodes in an Arrow template.
Lots of the ideas for this class were stolen/influenced in no small way by Hal Fulton’s “super-iterator” post to the Ruby-talk ML [ruby-talk: 46337].
Examples
### Render the directive's bracketed nodes once for each item in the
### iterated content.
def render_subnodes( attribute, template, scope )
res = []
iterator = Arrow::Template::Iterator.new( attribute )
iterator.each {|iter,*blockArgs|
# Process the nodes
template.with_overridden_attributes( scope, 'iterator' => iter ) {|template|
res << template.render( @subnodes, scope )
}
}
return *res
end
Authors
-
Michael Granger <[email protected]>
Please see the file LICENSE in the top-level directory for licensing details.
Instance Attribute Summary collapse
-
#items ⇒ Object
The list of items in this iteration.
-
#iteration ⇒ Object
The index of the current iteration.
-
#lastItem ⇒ Object
readonly
The item previous to the currently iterated one.
-
#nextItem ⇒ Object
readonly
The item which succeeds the currently iterated one.
Instance Method Summary collapse
-
#break ⇒ Object
Cause iteration to immediately terminate, ala the ‘break’ keyword.
-
#each ⇒ Object
The primary iteration interface.
-
#even? ⇒ Boolean
Return
true
if the current iteration is an even-numbered iteration. -
#even_or_odd ⇒ Object
Returns either “even” if the iteration is in even-numbered iteration, or “odd”.
-
#first? ⇒ Boolean
Returns
true
if the current iteration is the first one. -
#initialize(*items) ⇒ Iterator
constructor
Create a new Arrow::Template::Iterator object for the given
items
. -
#last? ⇒ Boolean
Returns
true
if the current iteration is the last one. -
#odd? ⇒ Boolean
Returns
true
if the current iteration is an odd-numbered iteration. -
#redo ⇒ Object
Redo the current iteration.
-
#restart ⇒ Object
Cause iteration to begin over again.
-
#skip(n = 1) ⇒ Object
Cause the next
n
items to be skipped. -
#skipped? ⇒ Boolean
Returns
true
if the last iteration skipped one or more items.
Methods inherited from Object
deprecate_class_method, deprecate_method, inherited
Constructor Details
#initialize(*items) ⇒ Iterator
Create a new Arrow::Template::Iterator object for the given items
.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/arrow/template/iterator.rb', line 48 def initialize( *items ) if items.length == 1 && items[0].is_a?( Enumerable ) @items = items[0] else @items = items end @iteration = nil @lastItem = nil @item = nil @nextItem = nil @iterating = false @skipped = false @marker = nil end |
Instance Attribute Details
#items ⇒ Object
The list of items in this iteration
70 71 72 |
# File 'lib/arrow/template/iterator.rb', line 70 def items @items end |
#iteration ⇒ Object
The index of the current iteration
73 74 75 |
# File 'lib/arrow/template/iterator.rb', line 73 def iteration @iteration end |
#lastItem ⇒ Object (readonly)
The item previous to the currently iterated one. If this is the first iteration, this will be nil
.
77 78 79 |
# File 'lib/arrow/template/iterator.rb', line 77 def lastItem @lastItem end |
#nextItem ⇒ Object (readonly)
The item which succeeds the currently iterated one. If this is the last iteration, this will be nil
.
81 82 83 |
# File 'lib/arrow/template/iterator.rb', line 81 def nextItem @nextItem end |
Instance Method Details
#break ⇒ Object
Cause iteration to immediately terminate, ala the ‘break’ keyword
155 156 157 158 |
# File 'lib/arrow/template/iterator.rb', line 155 def break # Jump back into the outer loop of #each throw( :break ) if @iterating end |
#each ⇒ Object
The primary iteration interface.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/arrow/template/iterator.rb', line 85 def each items = @items.dup @items = @items.entries raise LocalJumpError, "no block given" unless block_given? #self.log.debug "Iterating over @items = %p" % [ @items ] # Save this point so #restart can jump back here later. This is in a # loop because it needs to be remade after it's used the first time. until @marker @marker = callcc {|cc| cc} end @iterating = true @iteration = 0 # Mark the outer loop for #break catch( :break ) { until @iteration >= @items.length # Catch a skip with the number of items to skip. Unskipped # iterations "skip" 0 items. n = catch( :skip ) { @lastItem = self.first? ? nil : @items[ @iteration - 1 ] @item = @items[ @iteration ] @nextItem = self.last? ? nil : @items[ @iteration + 1 ] if @item.is_a?( Array ) yield( self, *@item ) else yield( self, @item ) end 0 } # Set the skipped flag for next iteration if we're skipping @skipped = n.nonzero? @iteration += n + 1 end } #self.log.debug "Returning from Iterator#each" return @items ensure @items = items @iteration = nil @lastItem = nil @item = nil @nextItem = nil @iterating = false @skipped = false @marker = nil end |
#even? ⇒ Boolean
Return true
if the current iteration is an even-numbered iteration.
196 197 198 |
# File 'lib/arrow/template/iterator.rb', line 196 def even? return !self.odd? end |
#even_or_odd ⇒ Object
Returns either “even” if the iteration is in even-numbered iteration, or “odd”.
182 183 184 |
# File 'lib/arrow/template/iterator.rb', line 182 def even_or_odd return self.odd? ? "odd" : "even" end |
#first? ⇒ Boolean
Returns true
if the current iteration is the first one.
176 177 178 |
# File 'lib/arrow/template/iterator.rb', line 176 def first? return @iteration == 0 end |
#last? ⇒ Boolean
Returns true
if the current iteration is the last one.
202 203 204 |
# File 'lib/arrow/template/iterator.rb', line 202 def last? return @iteration == @items.length - 1 end |
#odd? ⇒ Boolean
Returns true
if the current iteration is an odd-numbered iteration.
189 190 191 |
# File 'lib/arrow/template/iterator.rb', line 189 def odd? return @iterating && ( @iteration % 2 ).nonzero? end |
#redo ⇒ Object
Redo the current iteration
149 150 151 |
# File 'lib/arrow/template/iterator.rb', line 149 def redo throw( :skip, -1 ) if @iterating end |
#restart ⇒ Object
Cause iteration to begin over again
162 163 164 165 166 |
# File 'lib/arrow/template/iterator.rb', line 162 def restart # Call back into the continuation that was saved at the beginning of # #each @marker.call if @iterating end |
#skip(n = 1) ⇒ Object
Cause the next n
items to be skipped
142 143 144 145 |
# File 'lib/arrow/template/iterator.rb', line 142 def skip( n=1 ) # Jump back into #each with the number of iterations to skip throw( :skip, n ) if @iterating end |
#skipped? ⇒ Boolean
Returns true
if the last iteration skipped one or more items.
170 171 172 |
# File 'lib/arrow/template/iterator.rb', line 170 def skipped? @skipped end |