X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FHTML%2FZoom%2FFilterBuilder.pm;h=316d56c6a1214ecdd04b00e12c328cbfde8c3e1a;hb=50b9ca86389321f2f5ed7efb39a31d07efc5a4ac;hp=0659cca8d0d6eacc6cd9352c000fc99150e231a9;hpb=dae33531219f600d126f485532fd20e5ad1b4be1;p=catagits%2FHTML-Zoom.git diff --git a/lib/HTML/Zoom/FilterBuilder.pm b/lib/HTML/Zoom/FilterBuilder.pm index 0659cca..316d56c 100644 --- a/lib/HTML/Zoom/FilterBuilder.pm +++ b/lib/HTML/Zoom/FilterBuilder.pm @@ -2,37 +2,27 @@ package HTML::Zoom::FilterBuilder; use strict; use warnings FATAL => 'all'; +use base qw(HTML::Zoom::SubObject); use HTML::Zoom::CodeStream; -sub new { bless({}, shift) } - sub _stream_from_code { - HTML::Zoom::CodeStream->new({ code => $_[1] }) + shift->_zconfig->stream_utils->stream_from_code(@_) } sub _stream_from_array { - shift; # lose $self - HTML::Zoom::CodeStream->from_array(@_) + shift->_zconfig->stream_utils->stream_from_array(@_) } sub _stream_from_proto { - my ($self, $proto) = @_; - my $ref = ref $proto; - if (not $ref) { - return $self->_stream_from_array({ type => 'TEXT', raw => $proto }); - } elsif ($ref eq 'ARRAY') { - return $self->_stream_from_array(@$proto); - } elsif ($ref eq 'CODE') { - return $proto->(); - } elsif ($ref eq 'SCALAR') { - require HTML::Zoom::Parser::BuiltIn; - return HTML::Zoom::Parser::BuiltIn->html_to_stream($$proto); - } - die "Don't know how to turn $proto (ref $ref) into a stream"; + shift->_zconfig->stream_utils->stream_from_proto(@_) } sub _stream_concat { - shift->_stream_from_array(@_)->flatten; + shift->_zconfig->stream_utils->stream_concat(@_) +} + +sub _flatten_stream_of_streams { + shift->_zconfig->stream_utils->flatten_stream_of_streams(@_) } sub set_attribute { @@ -102,7 +92,7 @@ sub collect { my $name = $evt->{name}; my $depth = 1; my $_next = $content ? 'peek' : 'next'; - $stream = $filter->($stream) if $filter; + $stream = do { local $_ = $stream; $filter->($stream) } if $filter; my $collector = $self->_stream_from_code(sub { return unless $stream; while (my ($evt) = $stream->$_next) { @@ -211,14 +201,37 @@ sub replace_content { sub repeat { my ($self, $repeat_for, $options) = @_; $options->{into} = \my @into; - my $map_repeat = sub { - local $_ = $self->_stream_from_array(@into); - $_[0]->($_) - }; + my @between; + my $repeat_between = delete $options->{repeat_between}; + if ($repeat_between) { + $options->{filter} = sub { + $_->select($repeat_between)->collect({ into => \@between }) + }; + } my $repeater = sub { - $self->_stream_from_proto($repeat_for) - ->map($map_repeat) - ->flatten + my $s = $self->_stream_from_proto($repeat_for); + # We have to test $repeat_between not @between here because + # at the point we're constructing our return stream @between + # hasn't been populated yet - but we can test @between in the + # map routine because it has been by then and that saves us doing + # the extra stream construction if we don't need it. + $self->_flatten_stream_of_streams(do { + if ($repeat_between) { + $s->map(sub { + local $_ = $self->_stream_from_array(@into); + (@between && $s->peek) + ? $self->_stream_concat( + $_[0]->($_), $self->_stream_from_array(@between) + ) + : $_[0]->($_) + }) + } else { + $s->map(sub { + local $_ = $self->_stream_from_array(@into); + $_[0]->($_) + }) + } + }) }; $self->replace($repeater, $options); }