| Devel-INC-Sorted documentation | Contained in the Devel-INC-Sorted distribution. |
Devel::INC::Sorted - Keep your hooks in the begining of @INC
use Devel::INC::Sorted qw(inc_add_floating); inc_add_floating( \&my_inc_hook ); unshift @INC, \&other_hook; use lib 'blah'; push @INC, 'foo'; warn $INC[0]; # this is still \&my_inc_hook warn $INC[3]; # but \&other_hook was moved down to here
This module keeps @INC sorted much like Tie::Array::Sorted.
The default comparator partitions the members into floating and non floating,
allowing you to easily keep certain hooks in the begining of @INC.
The sort used is a stable one, to make sure that the order of @INC for
unsorted items remains unchanged.
All exports are optional
Add entries to @INC and call inc_float_entry on them.
Mark the arguments as floating (in the internal refhash).
Remove the items from the hash.
Untie @INC, leaving all it's current elements in place. Further
modifications to @INC will not cause resorting to happen.
This module is maintained using Darcs. You can get the latest version from
http://nothingmuch.woobling.org/code, and use darcs send to commit
changes.
Yuval Kogman <nothingmuch@woobling.org>
Copyright (c) 2008 Yuval Kogman. All rights reserved This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Devel-INC-Sorted documentation | Contained in the Devel-INC-Sorted distribution. |
#!/usr/bin/perl package Devel::INC::Sorted; use base qw(Exporter Tie::Array); use strict; use warnings; use sort 'stable'; use Scalar::Util qw(blessed reftype); use Tie::RefHash; our $VERSION = "0.02"; our @EXPORT_OK = qw(inc_add_floating inc_float_entry inc_unfloat_entry untie_inc); tie our %floating, 'Tie::RefHash'; sub import { my ( $self, @args ) = @_; $self->tie_inc( grep { ref } @args ); # if a code ref is given, pass it to TIEARRAY $self->export_to_level(1, $self, @args); } sub _args { my ( $self, @args ); if ( ( blessed($_[0]) or defined($_[0]) && !ref($_[0]) ) # class or object and ( $_[0]->isa(__PACKAGE__) ) ) { $self = shift; } else { $self = __PACKAGE__; } return ( $self->tie_inc, @_ ); } sub inc_add_floating { my ( $self, @args ) = &_args; $self->inc_float_entry(@args); $self->PUSH(@args); } sub inc_float_entry { my ( $self, @args ) = &_args; @floating{@args} = ( (1) x @args ); $self->_fixup; } sub inc_unfloat_entry { my ( $self, @args ) = &_args; delete @floating{@args}; $self->_fixup; } sub tie_inc { my ( $self, @args ) = @_; return $self if ref $self; return tied @INC if tied @INC; tie @INC, $self, $args[0], @INC; } sub untie_inc { my ( $self ) = &_args; no warnings 'untie'; # untying while tied() is referenced elsewhere warns untie @INC; @INC = @{ $self->{array} }; } # This code was adapted from Tie::Array::Sorted::Lazy # the reason it's not a subclass is because neither ::Sorted nor ::Sorted::Lazy # provide a stably sorted array, which is bad for our default comparator sub TIEARRAY { my ( $class, $comparator, @orig ) = @_; $comparator ||= sub { my ( $left, $right ) = @_; exists $floating{$right} <=> exists $floating{$left}; }; bless { array => \@orig, comp => $comparator, }, $class; } sub STORE { my ($self, $index, $elem) = @_; $self->{array}[$index] = $elem; $self->_fixup(); $self->{array}[$index]; } sub PUSH { my $self = shift; my $ret = push @{ $self->{array} }, @_; $self->_fixup(); $ret; } sub UNSHIFT { my $self = shift; my $ret = unshift @{ $self->{array} }, @_; $self->_fixup(); $ret; } sub _fixup { my $self = shift; $self->{array} = [ sort { $self->{comp}->($a, $b) } @{ $self->{array} } ]; $self->{dirty} = 0; } sub FETCH { $_[0]->{array}->[ $_[1] ]; } sub FETCHSIZE { scalar @{ $_[0]->{array} } } sub STORESIZE { $#{ $_[0]->{array} } = $_[1] - 1; } sub POP { pop(@{ $_[0]->{array} }); } sub SHIFT { shift(@{ $_[0]->{array} }); } sub EXISTS { exists $_[0]->{array}->[ $_[1] ]; } sub DELETE { delete $_[0]->{array}->[ $_[1] ]; } sub CLEAR { @{ $_[0]->{array} } = () } __PACKAGE__ __END__