X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FXML%2FTags.pm;h=9249691a3a69786460fdb2367545c744b61dafa3;hb=213f0aaf607d0a2192ff8c4f1be1d0ef78e4ebb5;hp=40f692668eb574e32792d5cfa168289b5669fad1;hpb=623466840fcb5aff4788fa80ee12947853e908e1;p=catagits%2FWeb-Simple.git diff --git a/lib/XML/Tags.pm b/lib/XML/Tags.pm index 40f6926..9249691 100644 --- a/lib/XML/Tags.pm +++ b/lib/XML/Tags.pm @@ -5,6 +5,8 @@ use warnings FATAL => 'all'; use File::Glob (); +require overload; + my $IN_SCOPE = 0; sub import { @@ -19,12 +21,12 @@ sub import { $IN_SCOPE = 1; } -sub sanitize { +sub to_xml_string { map { # string == text -> HTML, scalarref == raw HTML, other == passthrough ref($_) ? (ref $_ eq 'SCALAR' ? $$_ : $_) : do { local $_ = $_; # copy - s/&/&/g; s/"/"/g; s//>/g; $_; + s/&/&/g; s/"/"/g; s//>/g; $_; } } @_ } @@ -40,13 +42,14 @@ sub _find_target { sub _set_glob { # stupid insanity. delete anything already there so we disassociated - # the *CORE::GLOBAL::glob typeglob. Then the compilation of the eval + # the *CORE::GLOBAL::glob typeglob. Then the string reference call # revivifies it - i.e. creates us a new glob, which we get a reference # to, which we can then assign to. - # doing it without the eval doesn't - it binds to the version in scope + # doing it without the quotes doesn't - it binds to the version in scope # at compile time, which means after a delete you get a nice warm segv. delete ${CORE::GLOBAL::}{glob}; - *{eval '\*CORE::GLOBAL::glob'} = $_[0]; + no strict 'refs'; + *{'CORE::GLOBAL::glob'} = $_[0]; } sub _export_tags_into { @@ -55,13 +58,18 @@ sub _export_tags_into { no strict 'refs'; tie *{"${into}::${tag}"}, 'XML::Tags::TIEHANDLE', \"<${tag}>"; } - _set_glob(sub { \('<'.$_[0].'>'); }); + _set_glob(sub { + local $XML::Tags::StringThing::IN_GLOBBERY = 1; + \('<'."$_[0]".'>'); + }); + overload::constant(q => sub { XML::Tags::StringThing->from_constant(@_) }); return sub { foreach my $tag (@tags) { no strict 'refs'; delete ${"${into}::"}{$tag} } _set_glob(\&File::Glob::glob); + overload::remove_constant('q'); $IN_SCOPE = 0; }; } @@ -81,4 +89,47 @@ package XML::Tags::Unex; sub DESTROY { local $@; eval { $_[0]->(); 1 } || warn "ARGH: $@" } +package XML::Tags::StringThing; + +use overload ( + '.' => 'concat', + '""' => 'stringify', + fallback => 1 +); + +sub stringify { + join( + '', + ((our $IN_GLOBBERY) + ? XML::Tags::to_xml_string(@{$_[0]}) + : (map +(ref $_ ? $$_ : $_), @{$_[0]}) + ) + ); +} + +sub from_constant { + my ($class, $initial, $parsed, $type) = @_; + return $parsed unless $type eq 'qq'; + return $class->new($parsed); +} + +sub new { + my ($class, $string) = @_; + bless([ \$string ], $class); +} + +sub concat { + my ($self, $other, $rev) = @_; + my @extra = do { + if (ref($other) && ($other =~ /[a-z]=[A-Z]/) && $other->isa(__PACKAGE__)) { + @{$other} + } else { + $other; + } + }; + my @new = @{$self}; + $rev ? unshift(@new, @extra) : push(@new, @extra); + bless(\@new, ref($self)); +} + 1;