File Coverage

blib/lib/Wily.pm
Criterion Covered Total %
statement 24 113 21.2
branch 0 14 0.0
condition 0 3 0.0
subroutine 8 36 22.2
pod 2 11 18.1
total 34 177 19.2


line stmt bran cond sub pod time code
1             package Wily;
2              
3             =head1 NAME
4              
5             Wily - Perl extension for interfacing with Wily
6              
7             =head1 SYNOPSIS
8              
9             use Wily;
10             use Wily::Message;
11              
12             # opens a file in wily and exits when the window is destroyed
13              
14             my $wily = Wily->new();
15             my $win = $wily->win('/tmp/file_to_edit', 1);
16             $win->set_callback(Wily::Message::WEdestroy, sub {exit;});
17             $win->attach(Wily::Message::WEdestroy);
18             $wily->event_loop();
19              
20             =head1 DESCRIPTION
21              
22             Provides a reasonably high level OO interface to wily. A lower level
23             interface is available via Wily::RPC, and an even lower level one
24             through Wily::Message and Wily::Connect.
25              
26             The actual windows in wily are represented by Wily::Win objects.
27              
28             =head1 The Wily Objects
29              
30             The following operations can be performed with a Wily object.
31              
32             =cut
33              
34 1     1   24064 use v5.8;
  1         5  
  1         47  
35 1     1   6 use strict;
  1         2  
  1         31  
36 1     1   4 use warnings;
  1         2  
  1         32  
37              
38 1     1   521 use Wily::RPC;
  1         4  
  1         40  
39 1     1   10 use Wily::Message;
  1         2  
  1         721  
40              
41             our $VERSION = '0.02';
42              
43             =head2 Creating a Wily object
44              
45             $wily = Wily->new();
46              
47             Connects to wily and returns a Wily object.
48              
49             =cut
50             sub new {
51 0     0 0   my $package = shift;
52 0           my $self = {};
53 0   0       $self->{handle} = shift || Wily::RPC->new();
54 0           $self->{wins} = {};
55 0           return bless $self, $package;
56             }
57              
58             =head2 The main event loop
59              
60             $wily->event_loop();
61              
62             The event_loop() method never returns (unless the Wily connection breaks somehow),
63             incoming wily events will be dispatched to the appropriate Wily::Win objects.
64              
65             =cut
66             sub event_loop {
67 0     0 0   my $self = shift;
68 0           while ($self->handle_event()) {
69             }
70             }
71              
72             =head2 Dispatching events
73              
74             $wily->event_non_block();
75              
76             The event_non_block() method dispatches all pending events to the appropriate
77             Wily::Win objects, it won't block (unless the event handlers block) as it
78             will only dispatch events which have already been read from wily connection.
79              
80             =cut
81             sub events_non_block {
82 0     0 0   my $self = shift;
83 0           $self->handle_event() while not $self->{handle}->would_block();
84             }
85              
86             =head2 Dispatch an event
87              
88             $wily->handle_event()
89              
90             Dispatches a single event to the appropriate Wily::Win object. Will block if no
91             events are pending.
92              
93             Returns undef if the Wily connection breaks.
94              
95             =cut
96             sub handle_event {
97 0     0 0   my $self = shift;
98 0           my $msg = $self->{handle}->event();
99 0 0         return unless defined $msg;
100 0           $self->{wins}{$msg->{window_id}}->event($msg);
101 0           return 1;
102             }
103              
104             =head2 Bouncing events
105              
106             $wily->bounce($event);
107              
108             The bounce() method bounces an event back to wily, events which are not handled
109             should be sent back to wily so that the standard wily handling will be applied.
110              
111             =cut
112             sub bounce {
113 0     0 0   my $self = shift;
114 0           $self->{handle}->bounce(@_);
115             }
116              
117             =head2 Listing windows
118              
119             @windows = $wily->list();
120              
121             The list() method returns a list of the windows wily has open, each element of
122             the list is an array reference. The first entry of which is the name of the
123             window, and the second entry of which is a Wily::Win object representing the
124             window.
125              
126             =cut
127             sub list {
128 0     0 0   my $self = shift;
129 0           return map {[$_->[0], $self->win_from_id($_->[1])]}
  0            
130 0           map {[split /\t/, $_, 2]}
131             split /\n/, $self->{handle}->list();
132             }
133              
134             =head2 Getting the supported wily features
135              
136             @features = $wily->features();
137              
138             The features() method returns a list of all the features supported by the instance of
139             wily that is connected to.
140              
141             =cut
142             sub features {
143 0     0 1   my $self = shift;
144 0           return split ' ', $self->{handle}->features();
145             }
146              
147             =head2 Create a window
148              
149             $win = $wily->win($name, $backup);
150              
151             The win() method causes wily to open a window with the pathname set to $name and returns a
152             Wily::Win object repesenting the window. If $backup is 1 then wily will keep backups for the
153             window and enable the dirty indicator. If a window with the same name already exists then
154             the value of $backup is ignored and a reference to the existing window is returned.
155              
156             On failure undef is returned.
157              
158             =cut
159             sub win {
160 0     0 0   my $self = shift;
161 0           my $win = Wily::Win->new($self, @_);
162 0 0         return unless $win;
163 0 0         $self->{wins}{$win->{window_id}} = $win unless exists $self->{wins}{$win->{window_id}};
164 0           return $self->{wins}{$win->{window_id}};
165             }
166              
167             =head2 Get an existing window
168              
169             $win = $wily->win_from_id($id);
170              
171             The win_from_id() method returns a Wily::Win object representing the wily window with an
172             id of $id. Note, that the existance of the window is not actually checked, so method calls
173             on the Wily::Win object may fail.
174              
175             =cut
176             sub win_from_id {
177 0     0 0   my $self = shift;
178 0           my ($id) = @_;
179 0 0         return $self->{wins}{$id} if exists $self->{wins}{$id};
180 0           $self->{wins}{$id} = Wily::Win->new_from_id($self, $id);
181 0           return $self->{wins}{$id};
182             }
183              
184             =head2 Wily socket handle
185              
186             $socket = $wily->socket();
187              
188             The socket() method returns the socket that connects to wily. This can be used in
189             order to check for the availablility of data when integrating with other data sources.
190              
191             =cut
192             sub socket {
193 0     0 1   my $self = shift;
194 0           return $self->{handle}{s};
195             }
196              
197             =head2 Read the wily socket
198              
199             $wily->read_socket();
200              
201             Performs a read on the wily socket. This will block unless there is data available, so
202             usually you would call this after checking for the presence of data via something like
203             select.
204              
205             =cut
206             sub read_socket {
207 0     0 0   my $self = shift;
208 0           $self->{handle}->read_socket();
209             }
210              
211              
212             package Wily::Win;
213              
214             =head1 The Wily::Win Objects
215              
216             The following operations can be performed with a Wily::Win object.
217              
218             =head2 Creating Wily::Win objects
219              
220             Wily::Win objects should be created through a Wily object (or as the result
221             of the goto() method of an existing Wily::Win object. See the Wily documentation
222             for details on how to do so.
223              
224             =cut
225              
226 1     1   267 use strict;
  1         4  
  1         42  
227 1     1   6 use warnings;
  1         2  
  1         51  
228 1     1   5 use Carp;
  1         2  
  1         1199  
229              
230             our $VERSION = '0.01';
231              
232             sub new {
233 0     0     my $package = shift;
234 0           my ($wily, $name, $backup) = @_;
235 0           my $self = {};
236 0           $self->{wily} = $wily;
237 0           $self->{window_id} = $wily->{handle}->win($name, $backup);
238 0           $self->{callbacks} = {};
239 0           return bless $self, $package;
240             }
241              
242             sub new_from_id {
243 0     0     my $package = shift;
244 0           my ($wily, $id) = @_;
245 0           my $self = { wily => $wily, window_id => $id, callbacks => {} };
246 0           return bless $self, $package;
247             }
248              
249             sub event {
250 0     0     my $self = shift;
251 0           my $event = shift;
252              
253 0 0         if (exists $self->{callbacks}{$event->{type}}) {
254 0           $self->{callbacks}{$event->{type}}($event);
255             } else {
256 0           $self->{wily}->bounce($event);
257             }
258             }
259              
260             =head2 Attaching
261              
262             $win->attach($mask);
263              
264             The attach() method causes wily to send the requested events. $mask should be a
265             bitwise or (or just a sum) of the WE* cnstants in the Wily::Message package. If
266             the wily instance supports the 'detach' feature then attach() can be called
267             multiple times to attach for additional events.
268              
269             WEexec and WEgoto events are sent to the client vefore they are processed by wily, if
270             you want wily to process them they need to be bounce()d back to wily.
271              
272             To handle the events you will need to regster a function to be called for the
273             event type with the set_callback() method.
274              
275             Returns true on success and undef on failure.
276              
277             =cut
278             sub attach {
279 0     0     my $self = shift;
280 0           $self->{wily}{handle}->attach($self->{window_id}, @_);
281             }
282              
283             =head2 Detaching
284              
285             $win->detach($mask);
286              
287             The detach() mehod causes wily to stop sending the specified events. $mask should be a
288             bitwise or (or just a sum) of the WE* cnstants in the Wily::Message package.
289              
290             Note, that this is not part of the "standard" wily message set and hence you should
291             make sure to handle a failure when dealing with wily instances that don't support
292             this function.
293              
294             Returns true on success and undef on failure.
295              
296             =cut
297             sub detach {
298 0     0     my $self = shift;
299 0           $self->{wily}{handle}->detach($self->{window_id}, @_);
300             }
301              
302             =head2 Getting the name
303              
304             $name = $win->get_name();
305              
306             The get_name() method returns the name of the window.
307              
308             On failure undef is returned.
309              
310             =cut
311             sub get_name {
312 0     0     my $self = shift;
313 0           return $self->{wily}{handle}->get_name($self->{window_id}, @_);
314             }
315              
316             =head2 Getting the tools
317              
318             $tools = $win->get_tools();
319              
320             he get_tools() method returns the text of the tools in the window tag.
321              
322             On faiure undef is returned.
323              
324             =cut
325             sub get_tools {
326 0     0     my $self = shift;
327 0           return $self->{wily}{handle}->get_tools($self->{window_id}, @_);
328             }
329              
330             =head2 Searching
331              
332             ($win2, $r0, $r1) = $win->goto($p0, $p1, $search, $set_dot);
333              
334             The goto() method causes wily to act as if the user had selected the text $search with
335             B3 in the window. If this results in a search then the search starts
336             from the position indicated by the range [$p0, $p1) - if $p0 > $p1 then the search starts
337             from the current selection. If $set_dot is 1 then wily will select the resulting selection and
338             warp the mouse cursor to it. Returns the window and the range in that window found
339             by the search. This may be a different window (if the search text was a file name, for example).
340              
341             $search can be plain text to search for or an address that wily understands, or a wily
342             regular expression search - anything which works when B3ed.
343              
344             On failure () is returned.
345              
346             =cut
347             sub goto {
348 0     0     my $self = shift;
349 0           my @res = $self->{wily}{handle}->goto($self->{window_id}, @_);
350 0           $res[0] = $self->{wily}->win_from_id($res[0]);
351 0           return @res;
352             }
353              
354             =head2 Reading text
355              
356             $text = $win->read($p0, $p1);
357              
358             The read() method returns the text in the character range [$p0, $p1).
359             Note, that the text includes the character at $p0 but does not include the
360             character at $p1.
361              
362             On failure undef is returned.
363              
364             =cut
365             sub read {
366 0     0     my $self = shift;
367 0           return $self->{wily}{handle}->read($self->{window_id}, @_);
368             }
369              
370             =head2 Replacing text
371              
372             $win->replace($p0, $p1, $text);
373              
374             The replace() method replaces the text in the range [$p0, $p1) with $text. A true
375             value is returned on success, or undef on failure.
376              
377             =cut
378             sub replace {
379 0     0     my $self = shift;
380 0           return $self->{wily}{handle}->replace($self->{window_id}, @_);
381             }
382              
383             =head2 Executing commands
384              
385             $win->execute($cmd);
386              
387             The execute() method causes wily to act as if $cmd was selected with B2 in the window.
388             A true value is returned on success, or undef on failure.
389              
390             =cut
391             sub execute {
392 0     0     my $self = shift;
393 0           $self->{wily}{handle}->execute($self->{window_id}, @_);
394             }
395              
396             =head2 Setting the tools
397              
398             $win->set_tools($tools);
399              
400             The set_tools() method sets the tools in the tag of the window to $tools.
401             A true value is returned on success, or undef on failure.
402              
403             =cut
404             sub set_tools {
405 0     0     my $self = shift;
406 0           $self->{wily}{handle}->set_tools($self->{window_id}, @_);
407             }
408              
409             =head2 Setting the name
410              
411             $win->set_name($name);
412              
413             The set_name() method sets the name of the window to $name.
414             A true value is returned on success, or undef on failure.
415              
416             =cut
417             sub set_name {
418 0     0     my $self = shift;
419 0           $self->{wily}{handle}->set_name($self->{window_id}, @_);
420             }
421              
422             =head2 Setting event callbacks
423              
424             $win->set_callback($event_type, $function);
425              
426             Sets the callback for events of type $event_type to be $function. Whenever
427             an event of type $event_type is recieved it $function will be called
428             with the event as the only argument.
429              
430             Note, to actually begin recieve events attach() must be used.
431              
432             =cut
433             sub set_callback {
434 0     0     my $self = shift;
435 0           my ($type, $cb) = @_;
436 0           $self->{callbacks}{$type} = $cb;
437             }
438              
439             =head2 Removing event callbacks
440              
441             $win->remove_callback($event_type);
442              
443             The callback for events of type $event_type will be removed.
444              
445             =cut
446             sub remove_callback {
447 0     0     my $self = shift;
448 0           my ($type) = @_;
449 0           delete $self->{callbacks}{$type};
450             }
451              
452             =head2 Getting the window text
453              
454             $text = $win->get_body();
455              
456             The get_body() method returns the text in the window body. This is just a wrapper
457             around goto() and read(). Returns undef on failure.
458              
459             =cut
460             sub get_body {
461 0     0     my $self = shift;
462 0           my @goto = $self->goto(0, 0, ':,');
463 0 0         return unless @goto;
464 0           return $self->read($goto[1], $goto[2]);
465             }
466              
467             =head2 Setting the window text
468              
469             $win->set_body($text);
470              
471             The set_body() method sets the text in the body of the window to be $text. This is
472             just a wrapper around goto() and replace(). Returns undef on failure, true on success.
473              
474             =cut
475             sub set_body {
476 0     0     my $self = shift;
477 0           my ($s) = @_;
478 0           my @goto = $self->goto(0, 0, ':,');
479 0 0         return unless @goto;
480 0           $self->replace($goto[1], $goto[2], $s);
481             }
482              
483             1;
484             __END__