]> git.vpit.fr Git - perl/scripts/xchat.git/blob - Xchat/XPI.pm
Don't create a plugin object for modules
[perl/scripts/xchat.git] / Xchat / XPI.pm
1 package Xchat::XPI;
2
3 use strict;
4 use warnings;
5
6 use Tie::RefHash;
7
8 use Xchat;
9
10 our $VERSION = '0.05';
11
12 use constant { COLOR_TAG => "\00307" };
13
14 my @attributes;
15 BEGIN {
16  @attributes = qw/tag name version desc author email url banner/;
17 }
18
19 local *PH;
20
21 sub new {
22  my $class = shift;
23  $class    = ref($class) || $class;
24  my %opts  = @_;
25
26  my $caller = (caller 0)[0];
27  $opts{tag}     ||= ($caller =~ /([^:]*):*$/) ? $1 : 'UNKNOWN';
28  $opts{name}    ||= $opts{tag};
29  $opts{desc}    ||= $opts{name};
30  $opts{version} ||= do { no strict 'refs'; ${$caller.'::VERSION'} }
31                 || '0.01';
32
33  my $email = $opts{email};
34  $email    = "<$email>" if defined $email;
35
36  my $who = join ', ', grep defined, $opts{author}, $email, $opts{url};
37  $who    = " ($who)" if length $who;
38  $opts{banner} = $opts{desc} . $who;
39
40  my $ph = bless \do { local *PH }, $class;
41  tie *$ph, $ph, @_;
42
43  *$ph->{$_}  = $opts{$_} for @attributes;
44  *$ph->{buf} = '';
45
46  Xchat::register(@opts{qw/name version banner/}, sub {
47   $ph->flush;
48   if (*$ph->{atexit_id}) {
49    my @callbacks = sort { *$ph->{atexit}{$b} <=> *$ph->{atexit}{$a} }
50                     keys %{*$ph->{atexit}};
51    $_->($ph) for @callbacks;
52   }
53   undef $ph;
54  });
55  $ph->add_atexit($opts{unload}) if $opts{unload};
56
57  $ph->print("\002", $ph->name, ' v', $ph->version,
58             " loaded\002 (", $ph->banner, ")\n");
59
60  return $ph;
61 }
62
63 BEGIN {
64  eval "sub $_ { my \$ph = \$_[0]; *\$ph->{$_} }" for @attributes;
65 }
66
67 sub print {
68  my $ph = shift;
69
70  @_ = ($_) unless @_;
71
72  my $ret  = 0;
73  my $data = join '', *$ph->{buf}, @_;
74
75  while ((my $i = index $data, "\n") >= 0) {
76   Xchat::print(COLOR_TAG . $ph->tag . "\t" . (substr $data, 0, ($i + 1), ''));
77   $ret = 1;
78  }
79
80  *$ph->{buf} = $data;
81
82  return $ret;
83 }
84
85 sub printf { shift->print(sprintf @_) }
86
87 sub flush {
88  my ($ph) = @_;
89
90  if (length $ph->{buf}) {
91   $ph->print("\n");
92  } else {
93   return;
94  }
95 }
96
97 sub add_atexit {
98  my ($ph, $callback) = @_;
99
100  if (!*$ph->{atexit_id}) {
101   tie my %h, 'Tie::RefHash';
102   *$ph->{atexit} = \%h;
103  }
104
105  return *$ph->{atexit}{$callback} = ++*$ph->{atexit_id};
106 }
107
108 sub remove_atexit {
109  my ($ph, $callback) = @_;
110
111  if (exists *$ph->{atexit}{$callback}) {
112   delete *$ph->{atexit}{$callback};
113   return 1;
114  }
115
116  return 0;
117 }
118
119 sub TIEHANDLE {
120  my $ph = shift;
121  (defined $ph && $ph->isa(__PACKAGE__)) ? $ph : shift->new(@_);
122 }
123
124 sub PRINT  { shift->print(@_) }
125
126 sub PRINTF { shift->printf(@_) }
127
128 1;