package Hook; use strict; use warnings; use Exporter; use Carp; our @ISA = qw(Exporter); our @EXPORT = qw(register_hook add_hook call_hook); our %HOOKS = (); our %HOOK_DOC = (); sub register_hook { my ($hook, $docs) = @_; croak "No hook name given" unless $hook; croak "No hook documentation given" unless $docs; $HOOKS{$hook} ||=[]; $HOOK_DOC{$hook}=$docs; } sub call_hook { my ($hook, @args) = @_; croak "No hook name given" unless $hook; croak "Hook '$hook' unknown" unless exists $HOOKS{$hook}; foreach my $subref ( @{ $HOOKS{$hook}} ) { $subref->[0]->( @args); } } sub add_hook { my ($hook, $sub, $docs) = @_; croak "No hook name given" unless $hook; croak "No subroutine given" unless $sub; croak "No documentation given" unless $docs; push @{ $HOOKS{$hook}}, [ $sub, $docs]; } sub hook_docs { my $hook = shift; croak "No hook name given" unless $hook; $HOOK_DOC{$hook}; } =head1 NAME Hook - emacs-like support for event hooks =head1 SYNOPSIS What the end program does: use User; use User::EmailMe; # ... $user->save(); A hypothetical user module: package User; use Hook; register_hook 'user-add-hook', 'This hook is called after a user is added'; sub save { # ... call_hook 'user-add-hook', $user; } A hypothetical add-on module: package User::EmailMe; add_hook 'user-add-hook', \&email_me, 'This subroutine emails a defined address when a user is added.'; =head1 DESCRIPTION Hooks allow the programmer to define an appropriate time for add-on modules to execute. =head1 AUTHOR John Borwick =cut 1;