File Coverage

blib/lib/Zoidberg/Fish.pm
Criterion Covered Total %
statement 11 74 14.8
branch 0 40 0.0
condition 0 15 0.0
subroutine 5 20 25.0
pod 16 17 94.1
total 32 166 19.2


line stmt bran cond sub pod time code
1             package Zoidberg::Fish;
2              
3             our $VERSION = '0.981';
4              
5 17     17   1857 use strict;
  17         22  
  17         621  
6 17     17   90 use Zoidberg::Utils 'error';
  17         35  
  17         122  
7              
8             our $ERROR_CALLER = 1;
9              
10             =head1 NAME
11              
12             Zoidberg::Fish - Base class for loadable Zoidberg plugins
13              
14             =head1 SYNOPSIS
15              
16             package My_Zoid_Plugin;
17             use base 'Zoidberg::Fish';
18              
19             FIXME some example code
20              
21             =head1 DESCRIPTION
22              
23             Once this base class is used your module smells like fish -- Zoidberg WILL eat it.
24             It supplies stub methods for hooks and has some routines to simplefy the interface to
25             Zoidberg. One should realize that the bases of a plugin is not the module but
26             the config file. Any module can be used as plugin as long as it's properly configged.
27             The B should describe this in more detail.
28              
29             FIXME update the above text
30              
31             =head1 METHODS
32              
33             =over 4
34              
35             =item C
36              
37             Simple constructor that bootstraps same attributes. When your module smells like fish
38             Zoidberg will give it's constructor two arguments, a reference to itself and the name by
39             which your module is identified. From this all other config can be deducted.
40              
41             # Default attributes created by this constructor:
42            
43             $self->{shell} # a reference to the parent Zoidberg object
44             $self->{zoidname} # name by which your module is identified
45             $self->{settings} # reference to hash with global settings
46             $self->{config} # hash with plugin specific config
47              
48             =cut
49              
50             =item C
51              
52             To be overloaded, will be called directly after the constructor.
53             Do things you normally do in the constructor like loading files, opening sockets
54             or setting defaults here.
55              
56             =cut
57              
58             sub new {
59 16     16 1 57 my ($class, $zoid, $name) = @_;
60 16         214 my $self = {
61             parent => $zoid, # DEPRECATED !
62             shell => $zoid,
63             zoidname => $name,
64             settings => $zoid->{settings},
65             config => $zoid->{settings}{$name},
66             round_up => 1,
67             };
68 16         115 bless $self, $class;
69             }
70              
71 0     0 1 0 sub init {}
72              
73             # ########## #
74             # some stubs #
75             # ########## #
76              
77             =item C
78              
79             =item C
80              
81             These methods return a reference to the attributes by the same name.
82              
83             =cut
84              
85 0     0 1 0 sub config { $_[0]{config} }
86              
87 0     0 1 0 sub shell { $_[0]{shell} }
88              
89             =item C
90              
91             A stub doing absolutely nothing, but by calling it from
92             a dispatch table the plugin is loaded.
93              
94             =item C
95              
96             Removes this plugin from the various dispatchtables, and deletes the object.
97              
98             =cut
99              
100 16     16 1 64 sub plug { 1 } # when called the module will be loaded
101              
102 0     0 1 0 sub unplug { delete $_[0]->{shell}{objects}{$_[0]{zoidname}} }
103              
104             # ####################### #
105             # event and command logic #
106             # ####################### #
107              
108             =item C
109              
110             Broadcast an event to whoever might be listening.
111              
112             =cut
113              
114 0     0 0 0 sub call { die 'deprecated routine used' }
115              
116             sub broadcast {
117 0     0 1 0 my $self = shift;
118 0         0 $self->{shell}->broadcast(@_);
119             }
120              
121             =item C<< add_events({ event => sub { .. } }) >>
122              
123             =item C
124              
125             Used to add new event hooks.
126             In the second form the events are hooked to call the likely
127             named subroutine in the current object.
128              
129             =item C
130              
131             Removes an event. Wipes the stacks for the named events
132             of all routines belonging to this plugin.
133              
134             =item C<< add_commands({ command => sub { .. } }) >>
135              
136             =item C
137              
138             Used to add new builtin commands.
139             In the second form the commands are hooked to call the likely
140             named subroutine in the current object.
141              
142             =item C
143              
144             Removes a command. Wipes the stacks for the named commands
145             of all routines belonging to this plugin.
146              
147             =item C sub { ... })>
148              
149             TODO
150              
151             =item C
152              
153             TODO
154              
155             =cut
156              
157             sub add_events { # get my events unless @_ ?
158 0     0 1 0 my $self = shift;
159 0 0       0 error 'add_events needs args' unless @_;
160 0         0 my %events;
161 0 0       0 if( my $reftype = ref($_[0]) ) {
162 0 0       0 %events = ( $reftype eq 'HASH' ) ? %{ shift() } : @{ shift() };
  0         0  
  0         0  
163             } else {
164 0         0 %events = (map {($_ => "->$$self{zoidname}->$_")} @_);
  0         0  
165             }
166             $$self{shell}{events}{$_} = [$events{$_}, $$self{zoidname}]
167 0         0 for keys %events;
168             }
169              
170             sub wipe_events {
171 0     0 1 0 my $self = shift;
172 0 0       0 error 'wipe_events needs args' unless @_;
173 0         0 tied( %{$$self{shell}{events}} )->wipe( $$self{zoidname}, @_ );
  0         0  
174             }
175              
176             sub add_commands { # get my commands unless @_ ?
177 0     0 1 0 my $self = shift;
178 0 0       0 error 'add_commands needs args' unless @_;
179 0         0 my %commands;
180 0 0       0 if ( my $reftype = ref($_[0]) ) {
181 0 0       0 %commands = ( $reftype eq 'HASH' ) ? %{ shift() } : @{ shift() };
  0         0  
  0         0  
182             } else {
183 0         0 %commands = (map {($_ => "->$$self{zoidname}->$_")} @_);
  0         0  
184             }
185             $$self{shell}{commands}{$_} = [$commands{$_}, $$self{zoidname}]
186 0         0 for keys %commands;
187             }
188              
189             sub wipe_commands {
190 0     0 1 0 my $self = shift;
191 0 0       0 error 'wipe_commands needs args' unless @_;
192 0         0 tied( %{$$self{shell}{commands}} )->wipe( $$self{zoidname}, @_ );
  0         0  
193             }
194              
195             sub add_expansion {
196 0     0 1 0 todo()
197             }
198              
199             sub wipe_expansions {
200 0     0 1 0 todo()
201             }
202              
203             # ########### #
204             # other stuff #
205             # ########### #
206              
207             =item C
208              
209             See man L(1) for the context configuration details.
210              
211             =cut
212              
213             sub add_context { # ALERT this logic might change
214 0     0 1 0 my $self = shift;
215 0 0       0 my %context = ref($_[0]) ? (%{shift()}) : (splice @_);
  0         0  
216 0   0     0 my $cname = delete($context{name}) || $$self{zoidname};
217 0         0 my $fp = delete($context{from_package});
218 0         0 my $nw = delete($context{no_words});
219 0 0 0     0 for (values %context) { $_ = "->$$self{zoidname}->$_" unless ref $_ or /^\W/ }
  0         0  
220              
221 0 0       0 if ($fp) { # autoconnect
222             $self->can($_) and $context{$_} ||= "->$$self{zoidname}->$_"
223 0   0     0 for qw/word_list handler completion_function intel filter parser word_expansion/;
      0        
224             }
225              
226 0         0 for (qw/filter word_list word_expansion/) { # stacks
227 0 0       0 $self->{shell}{parser}{$_} = delete $context{$_}
228             if exists $context{$_};
229             }
230              
231 0 0       0 if ($nw) { # no words
232 0         0 push @{$$self{shell}{no_words}}, $cname;
  0         0  
233             }
234              
235 0 0       0 $self->{shell}{parser}{$cname} = [\%context, $$self{zoidname}]
236             if keys %context; # maybe there were only stacks
237 0         0 return $cname;
238             }
239              
240             =item C
241              
242             Get interactive input. The default is optional.
243             If the default is either 'Y' or 'N' a boolean value is returned.
244              
245             =cut
246              
247             sub ask { # FIXME FIXME FIXME hide chars and no hist whe $pass FIXME FIXME FIXME
248 0     0 1 0 my ($self, $quest, $def, $pass) = @_;
249 0         0 $quest =~ s/\s*$/ /;
250 0 0       0 $quest .= ($def =~ /^n$/i) ? '[yN] '
    0          
    0          
251             : ($def =~ /^y$/i) ? '[Yn] ' : "[$def] " if $def;
252 0         0 my $ans = $$self{shell}->builtin('readline', $quest);
253 0         0 $ans =~ s/^\s*|\s*$//g;
254 0 0       0 $ans = $def unless length $ans;
255 0 0       0 return( ($def =~ /^[ny]$/i) ? ($ans =~ /y/i) : $ans );
256             }
257              
258              
259             =item C
260              
261             Is called when the plugin is unloaded or when a sudden DESTROY occurs.
262             To be overloaded, do things like saving files or closing sockets here.
263              
264             =cut
265              
266 2     2 1 12 sub round_up {} # put shutdown sequence here -- like saving files etc.
267              
268             sub DESTROY {
269 0     0     my $self = shift;
270 0 0 0       $self->round_up if $$self{round_up} && $$self{shell}{round_up};
271             }
272              
273             1;
274              
275             __END__