Last active
April 4, 2021 11:15
Star
You must be signed in to star a gist
An experimential module that uses Keyword::Simple to provide syntax for optionally loading a module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package optionally; | |
# optionally load a module and import functions | |
# | |
# Syntax: | |
# | |
# use optionally; | |
# optionally use Module::Foo 1.37 function1 function2; | |
# | |
# This was an experiment, and is not at all ready for real use. | |
use strict; | |
use warnings; | |
use Keyword::Simple (); | |
use Carp qw/ croak /; | |
use Module::Runtime qw/ require_module /; | |
use Class::Unload (); | |
my %have_loaded; | |
sub import | |
{ | |
my $importing_package = caller; | |
Keyword::Simple::define('optionally' => sub { | |
my $line = shift; | |
# my ($matched, $action, $module, $rest) = ( $$line =~ m!\A(\s*(\S+)\s+(\S+)\s*(.*?);)!ms ) | |
my ($matched, $action, $module, $rest) = ( $$line =~ m!\A(\s*(\S+)\s+(\S+)\s*(.*?);)! ) | |
or croak "syntax error near 'optiona'"; | |
substr($$line, 0, length($matched)) = "BEGIN { optionally::run(\"$importing_package\", \"$action\", \"$module\", \"$rest\"); }"; | |
}); | |
} | |
sub run | |
{ | |
my ($importing_package, $action, $module_name, $rest) = @_; | |
croak "sorry, I don't know how to optionally '$action' yet ..." unless $action eq 'use'; | |
# If we can't even load the specified package, then silently do no more | |
return unless require_module($module_name); | |
$have_loaded{ $module_name } = 1; | |
my @args = split(/\s+/, $rest); | |
# If there's no args, then we call the default import on the | |
if (@args > 0 && _looks_like_version_number($args[0])) { | |
my $required_version = shift @args; | |
eval "${module_name}->VERSION($required_version);\n"; | |
if ($@) { | |
delete $INC{ $module_name }; | |
Class::Unload->unload($module_name); | |
return; | |
} | |
} | |
if (@args > 0) { | |
no strict 'refs'; | |
foreach my $subname (@args) { | |
*{"${importing_package}::$subname"} = *{"${module_name}::$subname"}{CODE} | |
// croak "No $subname() available for import from $module_name"; | |
} | |
} | |
else { | |
eval "package $importing_package; ${module_name}->import()"; | |
} | |
} | |
sub _looks_like_version_number | |
{ | |
my $string = shift; | |
return $string =~ m!^[0-9\.]+$!; | |
} | |
sub loaded | |
{ | |
my $module_name = shift; | |
print STDERR "HELLO!\n"; | |
return $have_loaded{ $module_name }; | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment