Subverting case insensitivity for module names under Mac HFS
Ash Berlin
ash_cpan at firemirror.com
Mon Jun 23 11:07:16 BST 2008
On 23 Jun 2008, at 11:52, Andy Wardley wrote:
> I'm trying to write some code that will automagically load plugin
> modules on
> demand but I'm being thwarted by the case insensitivity of Apple's
> HFS.
>
> Case insensitivity is a Good Thing in this case. I would like a
> user to be
> able to write:
>
> [% USE wibble %]
>
> and have TT figure out that it needs to load the
> Template::Plugin::Wibble
> module. To make this Just Work[tm], I thought it was simple case
> of trying
> a few different capitalisations of the request module tacked onto my
> base
> name:
>
> * the name exactly as specified, e.g. FooBar ==>
> Template::Plugin::FooBar
> * the capitalised name, e.g. wibble => Template::Plugin::Wibble
> * the upper case name, e.g. url => Template::Plugin::URL
>
> The code looks something like this:
>
> sub load_plugin {
> my ($self, $name) = @_;
> my $bases = $self->plugin_base; # e.g. ['Template::Plugin']
> my @names = ($name, ucfirst $name, uc $name); # e.g. foo, Foo, FOO
> my $module;
>
> foreach my $base (@$bases) {
> foreach my $name (@names) {
> $module = $base . '::' . $name;
> return $module if UTILS->maybe_load_module($module);
> }
> }
> return $self->error_msg( not_found => plugin => $name );
> }
>
> So far so good. The load_plugin() module returns the name of the
> module
> that successfully loaded so we can write this:
>
> my $class = $self->load_plugin($name);
> $plugin = $class->new($config);
>
> Except that Apple's brain-dead HFS treats filenames case
> insensitively. It
> will merrily load Template::Plugin::URL if you ask for
> Template::Plugin::url
> without so much as raising an eyebrow. The problem is that Perl's
> classnames
> are case *sensitive*, so the subsequent new() call will fail:
>
> $class->new($config) # ===> Template::Plugin::url->new() #
> FAIL!
>
> Has anyone come across this before and found an easy and/or elegant
> way to
> work around it? The only approach that comes to mind is to let the
> module
> get loaded and then do some symbol table inspection to figure out
> what the
> class name really is. But that requires some messy OS detection and
> smells
> a bit like apple-scented camel droppings to me. Anyone got any
> better ideas?
>
> The TT2 approach is to use an explicit table mapping lower case
> names to their
> correct-case equivalents. However, that only works for the core
> plugins and
> doesn't include 3rd party plugin modules that may get installed later.
>
> Cheers
> A
You could maybe try mutley's Module::Pluggable(::Object) which ISTR
does some of that for you.
More information about the london.pm
mailing list