File Coverage

blib/lib/MozRepl.pm
Criterion Covered Total %
statement 43 112 38.3
branch 3 26 11.5
condition 2 17 11.7
subroutine 11 18 61.1
pod 10 10 100.0
total 69 183 37.7


line stmt bran cond sub pod time code
1             package MozRepl;
2              
3 12     12   9523 use strict;
  12         23  
  12         480  
4 12     12   65 use warnings;
  12         22  
  12         653  
5              
6 12     12   62 use base qw(Class::Accessor::Fast Class::Data::Inheritable);
  12         21  
  12         29796  
7              
8             __PACKAGE__->mk_accessors($_) for (qw/client log plugins repl search/);
9             __PACKAGE__->mk_classdata($_) for (qw/log_class client_class/);
10              
11             __PACKAGE__->log_class('MozRepl::Log');
12             __PACKAGE__->client_class('MozRepl::Client');
13              
14 12     12   113112 use Text::SimpleTable;
  12         46149  
  12         947  
15 12     12   14769 use UNIVERSAL::require;
  12         39465  
  12         316  
16              
17 12     12   8405 use MozRepl::Util;
  12         48  
  12         157  
18              
19             =head1 NAME
20              
21             MozRepl - Perl interface of MozRepl
22              
23             =head1 VERSION
24              
25             version 0.06
26              
27             =cut
28              
29             our $VERSION = '0.06';
30              
31             =head1 SYNOPSIS
32              
33             use strict;
34             use warnings;
35              
36             use MozRepl;
37              
38             my $repl = MozRepl->new;
39             $repl->setup; ### You must write it.
40              
41             $repl->execute(q|window.alert("Internet Explorer:<")|);
42              
43             print $repl->repl_inspect({ source => "window" });
44             print $repl->repl_search({ pattern => "^getElement", source => "document"});
45              
46             =head1 DESCRIPTION
47              
48             MozRepl is accessing and control firefox using telnet, provided MozLab extension.
49             This module is perl interface of MozRepl.
50              
51             Additionaly this is enable to extend by writing plugin module.
52             You want to write plugin, see L or other plugins.
53              
54             =head2 For cygwin users
55              
56             In cygwin, please add binmode param as 1 in client args.
57              
58             $repl->setup({
59             client => {
60             extra_client_args => {
61             binmode => 1
62             }
63             }
64             });
65              
66             =head1 METHODS
67              
68             =head2 new($args)
69              
70             Create L instance.
71             One argument, and it must be hash reference.
72              
73             =over 4
74              
75             =item search
76              
77             L's arguments.
78             If you want to search modules has not prefix like 'MozRepl::Plugin',
79             then you are set this value like below.
80              
81             my $repl = MozRepl->new({ search => [qw/MyRepl::Plugin OtherRepl::Plugin/] });
82              
83             =back
84              
85             =cut
86              
87             sub new {
88 11     11 1 134 my ($class, $args) = @_;
89              
90 11 50 33     79 if (exists $args->{search} && ref $args->{search} eq 'ARRAY') {
91 0         0 unshift(@{$args->{search}}, "MozRepl::Plugin");
  0         0  
92 0         0 my %seen = ();
93 0         0 $args->{search} = [grep { ++$seen{$_} } @{$args->{search}}];
  0         0  
  0         0  
94             }
95             else {
96 11         61 $args->{search} = ["MozRepl::Plugin"];
97             }
98              
99 11         28 my $pluggable = "Module::Pluggable::Fast";
100              
101 11         67 my %param = (
102             "require" => 1,
103             "name" => "__load_plugins",
104             "search" => $args->{search}
105             );
106              
107 11         119 $pluggable->use(%param);
108              
109 11         309 my $self = $class->SUPER::new({
110             client => undef,
111             log => undef,
112             repl => 'repl',
113             plugins => {},
114             search => $args->{search}
115             });
116              
117 11         200 return $self;
118             }
119              
120             =head2 setup($args)
121              
122             Setup logging, client, plugins.
123             One argument, must be hash reference.
124              
125             =over 4
126              
127             =item log
128              
129             Hash reference or undef.
130             See L, L.
131              
132             =item client
133              
134             Hash reference or undef.
135             See L, L.
136              
137             =item plugins
138              
139             Hash reference or undef
140             See L.
141              
142             =back
143              
144             =cut
145              
146             sub setup {
147 11     11 1 113 my ($self, $args) = @_;
148              
149 11         76 $self->setup_log($args->{log});
150 11         101 $self->setup_client($args->{client});
151              
152 0 0       0 if ($self->log->is_debug) {
153 0         0 my $table = Text::SimpleTable->new([15, 'type'], [60, 'module']);
154 0         0 $table->row('logging', $self->log_class);
155 0         0 $table->row('client', $self->client_class);
156 0         0 $self->log->debug("---- Delegating classes ----\n" . $table->draw);
157             }
158              
159 0         0 $self->setup_plugins($args->{plugins});
160             }
161              
162             =head2 setup_log($args)
163              
164             Create logging instance. default class is L.
165             If you want to change log class, then set class name using L.
166              
167             This method is only called in L.
168              
169             One arguments, array reference.
170             If you want to limit log levels, specify levels like below.
171              
172             $repl->setup_log([qw/info warn error fatal/]);
173              
174             See L.
175              
176              
177             If you want to use another log class, and already instanciate it,
178             then you should call and set the instance before setup() method process.
179              
180             Example,
181              
182             my $repl = MozRepl->new;
183             $repl->log($another_log_instance);
184             $repl->setup($config);
185              
186             =cut
187              
188             sub setup_log {
189 11     11 1 40 my ($self, $args) = @_;
190              
191 11   50     143 $args ||= [qw/debug info warn error fatal/];
192              
193             ### skip already exists log instance
194 11 50       69 unless ($self->log) {
195 11         241 $self->log_class->use;
196 11         105 $self->log($self->log_class->new(@$args));
197             }
198             else {
199 0         0 $self->log_class(ref $self->log);
200             }
201              
202 11 50       95 return unless ($self->log->is_debug);
203              
204 11         112 $self->log->debug('MozRepl logging enabled');
205             }
206              
207             =head2 setup_client($args)
208              
209             Create (telnet) client instance. default class is L.
210             If you want to change client class, then set class name using L.
211              
212             This method is only called in L.
213              
214             One arguments, hash reference.
215             See L.
216              
217             =cut
218              
219             sub setup_client {
220 11     11 1 47 my ($self, $args) = @_;
221              
222 11         60 $self->client_class->use;
223 11         131 $self->client($self->client_class->new($self, $args));
224 11         99 $self->client->setup($self);
225             }
226              
227             =head2 setup_plugins($args)
228              
229             Setup plugins.
230             One argument, must be hash reference, it will be passed each plugin's as new method arguments.
231             And L too.
232              
233             This method is only called in L.
234              
235             =cut
236              
237             sub setup_plugins {
238 0     0 1   my ($self, $args) = @_;
239              
240 0           $self->plugins({});
241              
242 0           my @plugins = $self->load_plugins($args);
243              
244 0           for my $plugin (@plugins) {
245 0           $self->setup_plugin($plugin, $args);
246             }
247             }
248              
249             =head2 setup_plugin($plugin, $args)
250              
251             Create plugin instance, and mixin method to self.
252             Method name is detect by plugin's package, see L.
253              
254             =cut
255              
256             sub setup_plugin {
257 0     0 1   my ($self, $plugin, $args) = @_;
258              
259 0 0         return if ($self->enable_plugin($plugin));
260              
261 0           my $plugin_obj = $plugin->new($args);
262 0           $plugin_obj->setup($self, $args);
263              
264 0           my $method = MozRepl::Util->plugin_to_method($plugin, $self->search);
265              
266 0 0         unless ($self->can($method)) {
267 12     12   14179 no strict 'refs';
  12         1588  
  12         28601  
268              
269 0           $self->log->debug('define method : ' . $method);
270              
271 0           *{__PACKAGE__ . "::" . $method} = sub {
272 0     0     my ($repl, @args) = @_;
273 0           $plugin_obj->execute($repl, @args);
274 0           };
275             }
276              
277 0           $self->plugins->{$plugin} = $plugin_obj;
278             }
279              
280             =head2 load_plugins
281              
282             Load available plugins.
283             One argument, must be hash reference or undef.
284              
285             =over 4
286              
287             =item plugins
288              
289             Array reference.
290             Specify only plugins you want to use.
291              
292             $repl->load_plugins({ plugins => [qw/Repl::Print Repl::Inspect/] });
293              
294             =item except_plugins
295              
296             Array reference.
297             Specify except plugins you want to use.
298              
299             $repl->load_plugins({ except_plugins => [qw/JSON/] });
300              
301             =back
302              
303             =cut
304              
305             sub load_plugins {
306 0     0 1   my ($self, $args) = @_;
307              
308 0           my @available_plugins = grep { $_ ne 'MozRepl::Plugin::Base' } $self->__load_plugins;
  0            
309 0           my %plugins = ();
310 0           my %except_plugins = ();
311              
312 0           $self->log->debug(sprintf("Available plugins (%d)", scalar(@available_plugins)));
313              
314 0 0 0       if ($self->log->is_debug && @available_plugins) {
315 0           my $table = Text::SimpleTable->new([80, 'Available plugin']);
316 0           $table->row($_) for (@available_plugins);
317 0           $self->log->debug("---- Available plugin list ----\n" . $table->draw);
318             }
319              
320 0 0         return if (@available_plugins == 0);
321              
322 0 0 0       if ($args->{plugins} && ref $args->{plugins} eq 'ARRAY') {
323 0           $plugins{$_} = 1 for (map { MozRepl::Util->canonical_plugin_name($_) } @{$args->{plugins}});
  0            
  0            
324             }
325             else {
326 0           @plugins{@available_plugins} = map { 1 } @available_plugins;
  0            
327             }
328              
329 0 0 0       if ($args->{except_plugins} && ref $args->{except_plugins} eq 'ARRAY') {
330 0           $except_plugins{$_} = 1 for (map { MozRepl::Util->canonical_plugin_name($_) } @{$args->{except_plugins}});
  0            
  0            
331             }
332              
333 0           my @plugins =
334 0           grep { $plugins{$_} }
335 0           grep { !$except_plugins{$_} }
336 0           grep { $_ ne "MozRepl::Plugin::Base" }
337             @available_plugins;
338              
339 0           $self->log->debug(sprintf("Load plugins (%d)", scalar(@plugins)));
340              
341 0 0 0       if ($self->log->is_debug && @plugins) {
342 0           my $table = Text::SimpleTable->new([80, 'Load plugin']);
343 0           $table->row($_) for (@plugins);
344 0           $self->log->debug("---- Load plugin list ----\n" . $table->draw);
345             }
346              
347 0 0         wantarray ? @plugins : \@plugins;
348             }
349              
350             =head2 enable_plugin($plugin)
351              
352             Return whether the specified plugin is enabled or not.
353              
354             =cut
355              
356             sub enable_plugin {
357 0     0 1   my ($self, $plugin) = @_;
358              
359 0 0         return ((grep { $_ eq $plugin } keys %{$self->plugins}) == 1) ? 1 : 0;
  0            
  0            
360             }
361              
362             =head2 execute($command)
363              
364             Execute command and return result string.
365             See L.
366              
367             =cut
368              
369             sub execute {
370 0     0 1   my ($self, $command) = @_;
371              
372 0           $self->client->execute($self, $command);
373             }
374              
375             =head2 finalize()
376              
377             Finalize connection.
378              
379             =cut
380              
381             sub finalize {
382 0     0 1   my ($self, $args) = @_;
383              
384 0           $self->client->quit;
385             }
386              
387             =head2 client($client)
388              
389             Accessor of client object. See L.
390              
391             =head2 log($log)
392              
393             Accessor of log object. See L.
394              
395             =head2 plugins($plugins)
396              
397             Accessor of plugin table, key is plugin class name, value is plugin instance.
398              
399             =head2 repl($repl)
400              
401             Accessor of "repl" object name.
402             If two or more connection to MozRepl, this name is added number on postfix like 'repl1'.
403              
404             =head2 search($search)
405              
406             Accessor of search pathes. See L.
407              
408             =head2 log_class($class)
409              
410             Logging class name. default value is "L"
411              
412             =head2 client_class($class)
413              
414             Client class name. default value is "L"
415              
416             =head1 SEE ALSO
417              
418             =over 4
419              
420             =item L
421              
422             =item L
423              
424             =item http://dev.hyperstruct.net/mozlab
425              
426             =item http://dev.hyperstruct.net/mozlab/wiki/MozRepl
427              
428             =back
429              
430             =head1 AUTHOR
431              
432             Toru Yamaguchi, C<< >>
433              
434             =head1 BUGS
435              
436             Please report any bugs or feature requests to
437             C, or through the web interface at
438             L. I will be notified, and then you'll automatically be
439             notified of progress on your bug as I make changes.
440              
441             =head1 COPYRIGHT & LICENSE
442              
443             Copyright 2007 Toru Yamaguchi, All Rights Reserved.
444              
445             This program is free software; you can redistribute it and/or modify it
446             under the same terms as Perl itself.
447              
448             =cut
449              
450             1; # End of MozRepl