X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FXML%2FTags.pm;h=0c9ff8b9d44cd1badabe86cf90c659aad5632eab;hb=b0420ad6326a86fe33cdbecfb58bba08bec52b74;hp=4acc85250566becb32d9eb9617ee59b1c18023df;hpb=cc050137def024a8d94bc86a46bd3d7af495cf18;p=catagits%2FWeb-Simple.git diff --git a/lib/XML/Tags.pm b/lib/XML/Tags.pm index 4acc852..0c9ff8b 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 { @@ -14,13 +16,12 @@ sub import { my $opts = shift(@args) if ref($args[0]) eq 'HASH'; my $target = $class->_find_target(0, $opts); my @tags = $class->_find_tags(@args); - $class->_setup_glob_override; my $unex = $class->_export_tags_into($target => @tags); $class->_install_unexporter($unex); $IN_SCOPE = 1; } -sub sanitize { +sub to_xml_string { map { # string == text -> HTML, scalarref == raw HTML, other == passthrough ref($_) ? (ref $_ eq 'SCALAR' ? $$_ : $_) @@ -39,21 +40,16 @@ sub _find_target { return (caller($level))[0]; } -{ - my $setup; - - sub _setup_glob_override { - return if $setup; - $setup = 1; - no warnings 'redefine'; - *CORE::GLOBAL::glob = sub { - for ($_[0]) { - # unless it smells like or - return File::Glob::glob($_[0]) unless (/^\/\w+$/ || /^\w+\s+\w+="/); - } - return \('<'.$_[0].'>'); - }; - } +sub _set_glob { + # stupid insanity. delete anything already there so we disassociated + # 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 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}; + no strict 'refs'; + *{'CORE::GLOBAL::glob'} = $_[0]; } sub _export_tags_into { @@ -62,11 +58,18 @@ sub _export_tags_into { no strict 'refs'; tie *{"${into}::${tag}"}, 'XML::Tags::TIEHANDLE', \"<${tag}>"; } + _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; }; } @@ -86,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;