File Coverage

blib/lib/AnyEvent/TermKey.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2011 -- leonerd@leonerd.org.uk
5              
6             package AnyEvent::TermKey;
7              
8 4     4   106423 use strict;
  4         9  
  4         166  
9 4     4   23 use warnings;
  4         8  
  4         184  
10              
11             our $VERSION = '0.02';
12              
13 4     4   22 use Carp;
  4         17  
  4         439  
14              
15 4     4   3336 use AnyEvent;
  4         23859  
  4         136  
16 4     4   9183 use Term::TermKey qw( RES_KEY RES_AGAIN );
  0            
  0            
17              
18             =head1 NAME
19              
20             C - terminal key input using C with C
21              
22             =head1 SYNOPSIS
23              
24             use AnyEvent::TermKey qw( FORMAT_VIM KEYMOD_CTRL );
25             use AnyEvent;
26            
27             my $cv = AnyEvent->condvar;
28            
29             my $aetk = AnyEvent::TermKey->new(
30             term => \*STDIN,
31            
32             on_key => sub {
33             my ( $key ) = @_;
34            
35             print "Got key: ".$key->termkey->format_key( $key, FORMAT_VIM )."\n";
36            
37             $cv->send if $key->type_is_unicode and
38             $key->utf8 eq "C" and
39             $key->modifiers & KEYMOD_CTRL;
40             },
41             );
42            
43             $cv->recv;
44              
45             =head1 DESCRIPTION
46              
47             This class implements an asynchronous perl wrapper around the C
48             library, which provides an abstract way to read keypress events in
49             terminal-based programs. It yields structures that describe keys, rather than
50             simply returning raw bytes as read from the TTY device.
51              
52             It internally uses an instance of L to access the underlying C
53             library. For details on general operation, including the representation of
54             keypress events as objects, see the documentation on that class.
55              
56             Proxy methods exist for normal accessors of C, and the usual
57             behaviour of the C or other methods is instead replaced by the
58             C event.
59              
60             =cut
61              
62             # Forward any requests for symbol imports on to Term::TermKey
63             sub import
64             {
65             shift; unshift @_, "Term::TermKey";
66             my $import = $_[0]->can( "import" );
67             goto &$import; # So as not to have to fiddle with Sub::UpLevel
68             }
69              
70             =head1 CONSTRUCTOR
71              
72             =cut
73              
74             =head2 $aetk = AnyEvent::TermKey->new( %args )
75              
76             This function returns a new instance of a C object. It
77             takes the following named arguments:
78              
79             =over 8
80              
81             =item term => IO or INT
82              
83             Optional. File handle or POSIX file descriptor number for the file handle to
84             use as the connection to the terminal. If not supplied C will be used.
85              
86             =item on_key => CODE
87              
88             CODE reference to the key-event handling callback. Will be passed an instance
89             of a C structure:
90              
91             $on_key->( $key )
92              
93             =back
94              
95             =cut
96              
97             sub new
98             {
99             my $class = shift;
100             my %args = @_;
101              
102             # TODO: Find a better algorithm to hunt my terminal
103             my $term = delete $args{term} || \*STDIN;
104              
105             my $on_key = $args{on_key};
106              
107             my $termkey = Term::TermKey->new( $term, delete $args{flags} || 0 );
108             if( !defined $termkey ) {
109             croak "Cannot construct a termkey instance\n";
110             }
111              
112             my $timeout;
113             my $iowatch = AnyEvent->io(
114             fh => $term,
115             poll => "r",
116             cb => sub {
117             undef $timeout;
118              
119             return unless $termkey->advisereadable == RES_AGAIN;
120              
121             my $ret;
122             while( ( $ret = $termkey->getkey( my $key ) ) == RES_KEY ) {
123             $on_key->( $key );
124             }
125              
126             if( $ret == RES_AGAIN ) {
127             $timeout = AnyEvent->timer(
128             after => $termkey->get_waittime / 1000,
129             cb => sub {
130             if( $termkey->getkey_force( my $key ) == RES_KEY ) {
131             $on_key->( $key );
132             }
133             },
134             );
135             }
136             },
137             );
138              
139             return bless {
140             termkey => $termkey,
141             iowatch => $iowatch,
142             on_key => $args{on_key},
143             }, $class;
144             }
145              
146             =head1 METHODS
147              
148             =cut
149              
150             =head2 $tk = $aetk->termkey
151              
152             Returns the C object being used to access the C
153             library. Normally should not be required; the proxy methods should be used
154             instead. See below.
155              
156             =cut
157              
158             sub termkey
159             {
160             my $self = shift;
161             return $self->{termkey};
162             }
163              
164             =head2 $flags = $aetk->get_flags
165              
166             =head2 $aetk->set_flags( $flags )
167              
168             =head2 $canonflags = $aetk->get_canonflags
169              
170             =head2 $aetk->set_canonflags( $canonflags )
171              
172             =head2 $msec = $aetk->get_waittime
173              
174             =head2 $aetk->set_waittime( $msec )
175              
176             =head2 $str = $aetk->get_keyname( $sym )
177              
178             =head2 $sym = $aetk->keyname2sym( $keyname )
179              
180             =head2 ( $ev, $button, $line, $col ) = $aetk->interpret_mouse( $key )
181              
182             =head2 $str = $aetk->format_key( $key, $format )
183              
184             =head2 $key = $aetk->parse_key( $str, $format )
185              
186             =head2 $key = $aetk->parse_key_at_pos( $str, $format )
187              
188             =head2 $cmp = $aetk->keycmp( $key1, $key2 )
189              
190             These methods all proxy to the C object, and allow transparent
191             use of the C object as if it was a subclass. Their
192             arguments, behaviour and return value are therefore those provided by that
193             class. For more detail, see the L documentation.
194              
195             =cut
196              
197             # Proxy methods for normal Term::TermKey access
198             foreach my $method (qw(
199             get_flags
200             set_flags
201             get_canonflags
202             set_canonflags
203             get_waittime
204             set_waittime
205             get_keyname
206             keyname2sym
207             interpret_mouse
208             format_key
209             parse_key
210             parse_key_at_pos
211             keycmp
212             )) {
213             no strict 'refs';
214             *{$method} = sub {
215             my $self = shift;
216             $self->termkey->$method( @_ );
217             };
218             }
219              
220             =head1 AUTHOR
221              
222             Paul Evans
223              
224             =cut
225              
226             0x55AA;