<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">use strict;
use warnings;
package Sub::Install;
{
  $Sub::Install::VERSION = '0.927';
}
# ABSTRACT: install subroutines into packages easily

use Carp;
use Scalar::Util ();


sub _name_of_code {
  my ($code) = @_;
  require B;
  my $name = B::svref_2object($code)-&gt;GV-&gt;NAME;
  return $name unless $name =~ /\A__ANON__/;
  return;
}

# See also Params::Util, to which this code was donated.
sub _CODELIKE {
  (Scalar::Util::reftype($_[0])||'') eq 'CODE'
  || Scalar::Util::blessed($_[0])
  &amp;&amp; (overload::Method($_[0],'&amp;{}') ? $_[0] : undef);
}

# do the heavy lifting
sub _build_public_installer {
  my ($installer) = @_;

  sub {
    my ($arg) = @_;
    my ($calling_pkg) = caller(0);

    # I'd rather use ||= but I'm whoring for Devel::Cover.
    for (qw(into from)) { $arg-&gt;{$_} = $calling_pkg unless $arg-&gt;{$_} }

    # This is the only absolutely required argument, in many cases.
    Carp::croak "named argument 'code' is not optional" unless $arg-&gt;{code};

    if (_CODELIKE($arg-&gt;{code})) {
      $arg-&gt;{as} ||= _name_of_code($arg-&gt;{code});
    } else {
      Carp::croak
        "couldn't find subroutine named $arg-&gt;{code} in package $arg-&gt;{from}"
        unless my $code = $arg-&gt;{from}-&gt;can($arg-&gt;{code});

      $arg-&gt;{as}   = $arg-&gt;{code} unless $arg-&gt;{as};
      $arg-&gt;{code} = $code;
    }

    Carp::croak "couldn't determine name under which to install subroutine"
      unless $arg-&gt;{as};

    $installer-&gt;(@$arg{qw(into as code) });
  }
}

# do the ugly work

my $_misc_warn_re;
my $_redef_warn_re;
BEGIN {
  $_misc_warn_re = qr/
    Prototype\ mismatch:\ sub\ .+?  |
    Constant subroutine \S+ redefined
  /x;
  $_redef_warn_re = qr/Subroutine\ \S+\ redefined/x;
}

my $eow_re;
BEGIN { $eow_re = qr/ at .+? line \d+\.\Z/ };

sub _do_with_warn {
  my ($arg) = @_;
  my $code = delete $arg-&gt;{code};
  my $wants_code = sub {
    my $code = shift;
    sub {
      my $warn = $SIG{__WARN__} ? $SIG{__WARN__} : sub { warn @_ }; ## no critic
      local $SIG{__WARN__} = sub {
        my ($error) = @_;
        for (@{ $arg-&gt;{suppress} }) {
            return if $error =~ $_;
        }
        for (@{ $arg-&gt;{croak} }) {
          if (my ($base_error) = $error =~ /\A($_) $eow_re/x) {
            Carp::croak $base_error;
          }
        }
        for (@{ $arg-&gt;{carp} }) {
          if (my ($base_error) = $error =~ /\A($_) $eow_re/x) {
            return $warn-&gt;(Carp::shortmess $base_error);
          }
        }
        ($arg-&gt;{default} || $warn)-&gt;($error);
      };
      $code-&gt;(@_);
    };
  };
  return $wants_code-&gt;($code) if $code;
  return $wants_code;
}

sub _installer {
  sub {
    my ($pkg, $name, $code) = @_;
    no strict 'refs'; ## no critic ProhibitNoStrict
    *{"$pkg\::$name"} = $code;
    return $code;
  }
}

BEGIN {
  *_ignore_warnings = _do_with_warn({
    carp =&gt; [ $_misc_warn_re, $_redef_warn_re ]
  });

  *install_sub = _build_public_installer(_ignore_warnings(_installer));

  *_carp_warnings =  _do_with_warn({
    carp     =&gt; [ $_misc_warn_re ],
    suppress =&gt; [ $_redef_warn_re ],
  });

  *reinstall_sub = _build_public_installer(_carp_warnings(_installer));

  *_install_fatal = _do_with_warn({
    code     =&gt; _installer,
    croak    =&gt; [ $_redef_warn_re ],
  });
}


sub install_installers {
  my ($into) = @_;

  for my $method (qw(install_sub reinstall_sub)) {
    my $code = sub {
      my ($package, $subs) = @_;
      my ($caller) = caller(0);
      my $return;
      for (my ($name, $sub) = %$subs) {
        $return = Sub::Install-&gt;can($method)-&gt;({
          code =&gt; $sub,
          from =&gt; $caller,
          into =&gt; $package,
          as   =&gt; $name
        });
      }
      return $return;
    };
    install_sub({ code =&gt; $code, into =&gt; $into, as =&gt; $method });
  }
}


sub exporter {
  my ($arg) = @_;

  my %is_exported = map { $_ =&gt; undef } @{ $arg-&gt;{exports} };

  sub {
    my $class = shift;
    my $target = caller;
    for (@_) {
      Carp::croak "'$_' is not exported by $class" if !exists $is_exported{$_};
      install_sub({ code =&gt; $_, from =&gt; $class, into =&gt; $target });
    }
  }
}

BEGIN { *import = exporter({ exports =&gt; [ qw(install_sub reinstall_sub) ] }); }


1;

__END__

=pod

=head1 NAME

Sub::Install - install subroutines into packages easily

=head1 VERSION

version 0.927

=head1 SYNOPSIS

  use Sub::Install;

  Sub::Install::install_sub({
    code =&gt; sub { ... },
    into =&gt; $package,
    as   =&gt; $subname
  });

=head1 DESCRIPTION

This module makes it easy to install subroutines into packages without the
unsightly mess of C&lt;no strict&gt; or typeglobs lying about where just anyone can
see them.

=head1 FUNCTIONS

=head2 install_sub

  Sub::Install::install_sub({
   code =&gt; \&amp;subroutine,
   into =&gt; "Finance::Shady",
   as   =&gt; 'launder',
  });

This routine installs a given code reference into a package as a normal
subroutine.  The above is equivalent to:

  no strict 'refs';
  *{"Finance::Shady" . '::' . "launder"} = \&amp;subroutine;

If C&lt;into&gt; is not given, the sub is installed into the calling package.

If C&lt;code&gt; is not a code reference, it is looked for as an existing sub in the
package named in the C&lt;from&gt; parameter.  If C&lt;from&gt; is not given, it will look
in the calling package.

If C&lt;as&gt; is not given, and if C&lt;code&gt; is a name, C&lt;as&gt; will default to C&lt;code&gt;.
If C&lt;as&gt; is not given, but if C&lt;code&gt; is a code ref, Sub::Install will try to
find the name of the given code ref and use that as C&lt;as&gt;.

That means that this code:

  Sub::Install::install_sub({
    code =&gt; 'twitch',
    from =&gt; 'Person::InPain',
    into =&gt; 'Person::Teenager',
    as   =&gt; 'dance',
  });

is the same as:

  package Person::Teenager;

  Sub::Install::install_sub({
    code =&gt; Person::InPain-&gt;can('twitch'),
    as   =&gt; 'dance',
  });

=head2 reinstall_sub

This routine behaves exactly like C&lt;L&lt;/install_sub&gt;&gt;, but does not emit a
warning if warnings are on and the destination is already defined.

=head2 install_installers

This routine is provided to allow Sub::Install compatibility with
Sub::Installer.  It installs C&lt;install_sub&gt; and C&lt;reinstall_sub&gt; methods into
the package named by its argument.

 Sub::Install::install_installers('Code::Builder'); # just for us, please
 Code::Builder-&gt;install_sub({ name =&gt; $code_ref });

 Sub::Install::install_installers('UNIVERSAL'); # feeling lucky, punk?
 Anything::At::All-&gt;install_sub({ name =&gt; $code_ref });

The installed installers are similar, but not identical, to those provided by
Sub::Installer.  They accept a single hash as an argument.  The key/value pairs
are used as the C&lt;as&gt; and C&lt;code&gt; parameters to the C&lt;install_sub&gt; routine
detailed above.  The package name on which the method is called is used as the
C&lt;into&gt; parameter.

Unlike Sub::Installer's C&lt;install_sub&gt; will not eval strings into code, but
will look for named code in the calling package.

=head1 EXPORTS

Sub::Install exports C&lt;install_sub&gt; and C&lt;reinstall_sub&gt; only if they are
requested.

=head2 exporter

Sub::Install has a never-exported subroutine called C&lt;exporter&gt;, which is used
to implement its C&lt;import&gt; routine.  It takes a hashref of named arguments,
only one of which is currently recognize: C&lt;exports&gt;.  This must be an arrayref
of subroutines to offer for export.

This routine is mainly for Sub::Install's own consumption.  Instead, consider
L&lt;Sub::Exporter&gt;.

=head1 SEE ALSO

=over

=item L&lt;Sub::Installer&gt;

This module is (obviously) a reaction to Damian Conway's Sub::Installer, which
does the same thing, but does it by getting its greasy fingers all over
UNIVERSAL.  I was really happy about the idea of making the installation of
coderefs less ugly, but I couldn't bring myself to replace the ugliness of
typeglobs and loosened strictures with the ugliness of UNIVERSAL methods.

=item L&lt;Sub::Exporter&gt;

This is a complete Exporter.pm replacement, built atop Sub::Install.

=back

=head1 EXTRA CREDITS

Several of the tests are adapted from tests that shipped with Damian Conway's
Sub-Installer distribution.

=head1 AUTHOR

Ricardo SIGNES &lt;rjbs@cpan.org&gt;

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2005 by Ricardo SIGNES.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
</pre></body></html>