[Templates-cvs] cvs commit: TT3/lib/Template/TT3 Scanner.pm
cvs@template-toolkit.org
cvs@template-toolkit.org
Mon, 15 Dec 2003 15:31:12 +0000
cvs 03/12/15 15:31:12
Modified: lib/Template/TT3 Scanner.pm
Log:
* moved scanning for end tag and line counting out of tag into scanner
scan() method
Revision Changes Path
1.4 +107 -19 TT3/lib/Template/TT3/Scanner.pm
Index: Scanner.pm
===================================================================
RCS file: /template-toolkit/TT3/lib/Template/TT3/Scanner.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Scanner.pm 2003/12/11 15:11:37 1.3
+++ Scanner.pm 2003/12/15 15:31:12 1.4
@@ -18,7 +18,7 @@
# modify it under the same terms as Perl itself.
#
# REVISION
-# $Id: Scanner.pm,v 1.3 2003/12/11 15:11:37 abw Exp $
+# $Id: Scanner.pm,v 1.4 2003/12/15 15:31:12 abw Exp $
#
#========================================================================
@@ -30,7 +30,7 @@
use vars qw( $VERSION $DEBUG $ERROR $WARNING $TAGS );
use base qw( Template::TT3::Base );
-$VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/);
$DEBUG = 0 unless defined $DEBUG;
$ERROR = '';
$TAGS = [ ];
@@ -105,7 +105,7 @@
# object so instead we keep a list of them for matching later.
foreach my $tag (@$tags) {
- my $start = $tag->start();
+ my $start = $tag->{ start };
if (ref $start eq 'Regexp') {
push(@$regexen, $start);
push(@$regtags, $tag);
@@ -164,10 +164,13 @@
$self->debug("scan()\n") if $DEBUG;
$self->{ reset } = 0;
+ $self->{ line } = 1;
+ $self->{ size } = 0;
SCAN_FOR_TAGS: {
# fetch the tagset information prepared by the tags() method
my ($tagmap, $regex, $regexen) = @$self{ qw( tagmap regex regexen ) };
+
if ($regex) {
$self->debug("scanning with regex: $regex\n") if $DEBUG;
}
@@ -178,15 +181,19 @@
# scan source text to identify text and tags
while ($$textref =~ /$regex/cg) {
- my ($pretext, $dirtok) = ($1, $2);
+ my ($pretext, $start) = ($1, $2);
+ my $end;
- # notify template document of any text preceeding a tag
- $document->text(\$pretext)
- || return $self->error($document->error())
- if defined $pretext && length $pretext;
+ # is there any text preceding the tag start?
+ if (defined $pretext && length $pretext) {
+ # count newlines and notify document
+ $self->{ line } += ($pretext =~ tr/\n//);
+ $document->text(\$pretext)
+ || return $self->scan_error($document->error());
+ }
# look for the tag object corresponding to this start token
- my $tag = $tagmap->{ $dirtok };
+ my $tag = $tagmap->{ $start };
# if there isn't an entry in the tag lookup table then we
# look through each regex to find out which one matches the
@@ -194,23 +201,73 @@
unless (defined $tag) {
my $regexen = $self->{ regexen };
for my $n (0..$#$regexen) {
- if ($dirtok =~ $regexen->[$n]) {
- $self->debug("matched $dirtok against $regexen->[$n]\n")
+ if ($start =~ $regexen->[$n]) {
+ $self->debug("matched $start against $regexen->[$n]\n")
if $DEBUG;
$tag = $self->{ regtags }->[$n]
- || return $self->error("no tag for regex $regexen->[$n]");
+ || return $self->scan_error("no tag for regex $regexen->[$n]");
# cached tag found for the start token in tagmap
- $tagmap->{ $dirtok } = $tag;
+ $tagmap->{ $start } = $tag;
last;
}
}
- return $self->error("no tag defined for '$dirtok'")
+ return $self->scan_error("no tag defined for '$start'")
unless defined $tag;
}
- # call tag object to scan the tag content
- $tag->scan($dirtok, $textref, $document)
- || return $self->error($tag->error());
+ # scan the tag content
+ if (defined ($end = $tag->{ end }) && length($end)) {
+ # this is a closed tag that has pre-defined start and end tokens.
+ # we scan up to the end tag, figure out how many lines the directive
+ # covers and then call the parse() method to parse the contents
+
+ $self->debug("scanning closed tag from $start to $end\n") if $DEBUG;
+
+ # generate regex to match end tag
+ my $regex = $tag->{ end_regex } ||= do {
+ $end = ref $end eq 'Regexp' ? $end : quotemeta($end);
+ qr/ \G (.*?) ($end) /sx;
+ };
+
+ # scan for closing tag and report error if not found
+ return $self->scan_error("no closing tag to match $start")
+ unless $$textref =~ /$regex/gc;
+ my ($content, $end) = ($1, $2);
+
+ # count lines in start tag, content and end tag
+ $self->{ size } = ( $start =~ tr/\n// )
+ + ( $content =~ tr/\n// )
+ + ( $end =~ tr/\n// );
+
+ # call tag scan() method to handle tag content
+ $tag->scan(\$content, $document, $start, $end)
+ || return $self->scan_error($tag->error());
+
+ # update document position
+ $self->{ line } += $self->{ size };
+ $self->{ size } = 0;
+ }
+ else {
+ # an open tag that has a start but no pre-defined end token.
+ # we save the current regex position, call the parse method to
+ # gobble up as much of the text as it likes, and then examine
+ # the regex position again, and count the newlines in the
+ # intervening text to update the document line position
+
+ $self->debug("scanning open tag from $start\n") if $DEBUG;
+
+ # save starting regex position
+ my $start_pos = pos($$textref) || 0;
+
+ # call tag scan() method to scan forwards
+ $tag->scan($textref, $document, $start)
+ || return $self->scan_error($tag->error());
+
+ # count any newlines consumed between start and end positions
+ my $end_pos = pos $$textref || 0;
+ my $substr = substr($$textref, $start_pos, $end_pos - $start_pos);
+ $self->{ line } += ($substr =~ tr/\n//);
+ }
# check to see if tags have changed
if ($self->{ reset }) {
@@ -220,10 +277,11 @@
}
}
+ # scan for any trailing text
if ($$textref =~ / \G (.+) /sx) {
my $text = $1;
$document->text(\$text)
- || return $self->error($document->error());
+ || return $self->scan_error($document->error());
}
return 1;
@@ -231,6 +289,35 @@
+sub line {
+ my $self = shift;
+ return @_ ? ($self->{ line } = shift) : $self->{ line };
+}
+
+sub size {
+ my $self = shift;
+ return @_ ? ($self->{ size } = shift) : $self->{ size };
+}
+
+sub position {
+ my $self = shift;
+
+ if (@_) {
+ $self->{ line } += shift;
+ $self->{ size } = @_ ? shift : 0;
+ }
+ if ($self->{ size }) {
+ my $end = $self->{ line } + $self->{ size };
+ return "$self->{ line }-$end";
+ }
+ else {
+ return $self->{ line };
+ }
+}
+
+
+
+
1;
__END__
@@ -260,7 +347,7 @@
=head1 VERSION
-$Revision: 1.3 $
+$Revision: 1.4 $
=head1 COPYRIGHT
@@ -279,3 +366,4 @@
# End:
#
# vim: expandtab shiftwidth=4:
+