1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
|
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2009-2025 -- leonerd@leonerd.org.uk
package Term::TermKey 0.19;
use v5.14;
use warnings;
use Exporter 'import';
require XSLoader;
XSLoader::load( __PACKAGE__, our $VERSION );
=head1 NAME
C<Term::TermKey> - perl wrapper around C<libtermkey>
=head1 SYNOPSIS
=for highlighter language=perl
use Term::TermKey;
my $tk = Term::TermKey->new( \*STDIN );
print "Press any key\n";
$tk->waitkey( my $key );
print "You pressed: " . $tk->format_key( $key, 0 );
=head1 DESCRIPTION
=over 4
B<Note> that C<libtermkey> itself is deprecated in favour of its eventual
merge into C<libtickit>. As a result, uses of this module should also be
considered deprecated. Consider rewriting code to use L<Tickit> instead;
either by creating a L<Tickit::Term> to receive key input events, or perform a
more wholescale rewrite into using C<Tickit> generally for all screen
interaction purposes.
=back
This module provides a light perl wrapper around the C<libtermkey> library.
This library attempts to provide an abstract way to read keypress events in
terminal-based programs by providing structures that describe keys, rather
than simply returning raw bytes as read from the TTY device.
This version of C<Term::TermKey> requires C<libtermkey> version at least 0.16.
=head2 Multi-byte keys, ambiguous keys, and waittime
Some keypresses generate multiple bytes from the terminal. There is also the
ambiguity between multi-byte CSI or SS3 sequences, and the Escape key itself.
The waittime timer is used to distinguish them.
When some bytes arrive that could be the start of possibly multiple different
keypress events, the library will attempt to wait for more bytes to arrive
that would finish it. If no more bytes arrive after this time, then the bytes
will be reported as events as they stand, even if this results in interpreting
a partially-complete Escape sequence as a literal Escape key followed by some
normal letters or other symbols.
Similarly, if the start of an incomplete UTF-8 sequence arrives when the
library is in UTF-8 mode, this will be reported as the UTF-8 replacement
character (U+FFFD) if it is incomplete after this time.
=cut
=head1 CONSTRUCTOR
=cut
=head2 new
$tk = Term::TermKey->new( $fh, $flags );
Construct a new C<Term::TermKey> object that wraps the given term handle.
C<$fh> should be either an IO handle reference, an integer referring to a
plain POSIX file descriptor, of C<undef>. C<$flags> is optional, but if given
should contain the flags to pass to C<libtermkey>'s constructor. Assumes a
default of 0 if not supplied. See the C<FLAG_*> constants.
=head2 new_abstract
$tk = Term::TermKey->new_abstract( $termtype, $flags );
Construct a new abstract C<Term::TermKey> object not associated with a
filehandle. Input may be fed to it using the C<push_bytes()> method
rather than C<waitkey()> or C<advisereadable()>. The name of the termtype
should be given in the C<$termtype> string.
=cut
=head1 METHODS
=cut
# The following documents the various XS-implemented methods in TermKey.xs in
# the same order
=head2 start
=head2 stop
$success = $tk->start;
$success = $tk->stop;
Start or stop IO interactions from the instance. Starting will send the
terminal initialisation sequence and set up C<termios(5)> settings, stopping
will send the terminal shutdown sequence and restore C<termios(5)> back to the
initial values. After construction, a C<Term::TermKey> instance is already
started, but these methods may be used to suspend and resume, for example, on
receipt of a C<SIGTSTP> signal requesting that the application background
itself.
Returns false if it fails; C<$!> will contain an error code.
=head2 is_started
$started = $tk->is_started;
Returns true if the instance has been started, or false if it is stopped.
=head2 get_flags
=head2 set_flags
$flags = $tk->get_flags;
$tk->set_flags( $newflags );
Accessor and mutator for the flags. One of the C<FLAG_UTF8> or C<FLAG_RAW>
flags will be set, even if neither was present in the constructor, as in this
case the library will attempt to detect if the current locale is UTF-8 aware
or not.
=cut
=head2 get_canonflags
=head2 set_canonflags
$canonflags = $tk->get_canonflags;
$tk->set_canonflags( $newcanonflags );
Accessor and mutator for the canonicalisation flags.
=cut
=head2 get_waittime
=head2 set_waittime
$msec = $tk->get_waittime;
$tk->set_waittime( $msec );
Accessor and mutator for the maximum wait time in miliseconds. The underlying
C<libtermkey> library will have specified a default value when the object was
constructed.
=cut
=head2 get_buffer_remaining
$bytes = $tk->get_buffer_remaining;
Accessor returning the number of bytes of buffer space remaining in the
buffer; the space in which C<push_bytes> can write.
=head2 get_buffer_size
=head2 set_buffer_size
$bytes = $tk->get_buffer_size;
$tk->set_buffer_size( $size );
Accessor and mutator to for the total buffer size to store pending bytes. If
the underlying C<termkey_set_buffer_size(3)> call fails, the
C<set_buffer_size> method will throw an exception.
=cut
=head2 getkey
$res = $tk->getkey( $key );
Attempt to retrieve a single keypress event from the buffer, and put it in
C<$key>. If successful, will return C<RES_KEY> to indicate that the C<$key>
structure now contains a new keypress event. If C<$key> is an undefined lvalue
(such as a new scalar variable) it will be initialised to contain a new key
structure.
If nothing is in the buffer it will return C<RES_NONE>. If the buffer contains
a partial keypress event which does not yet contain all the bytes required, it
will return C<RES_AGAIN> (see above section about multibyte events). If no
events are ready and the input stream is now closed, will return C<RES_EOF>.
This method will not block, nor will it perform any IO on the underlying file
descriptor. For a normal blocking read, see C<waitkey()>.
=cut
=head2 getkey_force
$res = $tk->getkey_force( $key );
Similar to C<getkey()>, but will not return C<RES_AGAIN> if a partial match
was found. Instead, it will force an interpretation of the bytes, even if this
means interpreting the start of an C<< <Esc> >>-prefixed multibyte sequence as
a literal C<Escape> key followed by normal letters. If C<$key> is an undefined
lvalue (such as a new scalar variable) it will be initialised to contain a new
key structure.
This method will not block, nor will it perform any IO on the underlying file
descriptor. For a normal blocking read, see C<waitkey()>.
=cut
=head2 waitkey
$res = $tk->waitkey( $key );
Attempt to retrieve a single keypress event from the buffer, or block until
one is available. If successful, will return C<RES_KEY> to indicate that the
C<$key> structure now contains a new keypress event. If an IO error occurs it
will return C<RES_ERROR>, and if the input stream is now closed it will return
C<RES_EOF>.
If C<$key> is an undefined lvalue (such as a new scalar variable) it will be
initialised to contain a new key structure.
=cut
=head2 advisereadable
$res = $tk->advisereadable;
Inform the underlying library that new input may be available on the
underlying file descriptor and so it should call C<read()> to obtain it.
Will return C<RES_AGAIN> if it read at least one more byte, C<RES_NONE> if no
more input was found, or C<RES_ERROR> if an IO error occurs.
Normally this method would only be used in programs that want to use
C<Term::TermKey> asynchronously; see the EXAMPLES section. This method
gracefully handles an C<EAGAIN> error from the underlying C<read()> syscall.
=cut
=head2 push_bytes
$len = $tk->push_bytes( $bytes );
Feed more bytes into the input buffer. This is primarily useful for feeding
input into filehandle-less instances, constructed by passing C<undef> or C<-1>
as the filehandle to the constructor. After calling this method, these bytes
will be available to read as keypresses by the C<getkey> method.
=cut
=head2 get_keyname
$str = $tk->get_keyname( $sym );
Returns the name of a key sym, such as returned by
C<< Term::TermKey::Key->sym() >>.
=cut
=head2 keyname2sym
$sym = $tk->keyname2sym( $keyname );
Look up the sym for a named key. The result of this method call can be
compared directly against the value returned by
C<< Term::TermKey::Key->sym() >>. Because this method has to perform a linear
search of key names, it is best called rarely, perhaps during program
initialisation, and the result stored for easier comparisons during runtime.
=cut
=head2 interpret_unknown_csi
( $cmd, @args ) = $tk->interpret_unknown_csi( $key );
If C<$key> contains an unknown CSI event then its command and arguments are
returned in a list. C<$cmd> will be a string of 1 to 3 characters long,
containing the initial and intermediate characters if present, followed by the
main command character. C<@args> will contain the numerical arguments, where
missing arguments are replaced by -1. If C<$key> does not contain an unknown
CSI event then an empty list is returned.
Note that this method needs to be called immediately after C<getkey> or
C<waitkey>, or at least, before calling either of those methods again. The
actual CSI sequence is retained in the F<libtermkey> buffer, and only
retrieved by this method call. Calling C<getkey> or C<waitkey> again may
overwrite that buffer.
=cut
=head2 format_key
$str = $tk->format_key( $key, $format );
Return a string representation of the keypress event in C<$key>, following the
flags given. See the descriptions of the flags, below, for more detail.
This may be useful for matching keypress events against keybindings stored in
a hash. See EXAMPLES section for more detail.
=cut
=head2 parse_key
$key = $tk->parse_key( $str, $format );
Return a keypress event by parsing the string representation in C<$str>,
following the flags given. This method is an inverse of C<format_key>.
This may be useful for parsing entries from a configuration file or similar.
=cut
=head2 parse_key_at_pos
$key = $tk->parse_key_at_pos( $str, $format );
Return a keypress event by parsing the string representation in a region of
C<$str>, following the flags given.
Where C<parse_key> will start at the beginning of the string and requires the
entire input to be consumed, this method will start at the current C<pos()>
position in C<$str> (or at the beginning of the string if none is yet set),
and after a successful parse, will update it to the end of the matched
section. This position does not have to be at the end of the string. C<$str>
must therefore be a real scalar variable, and not a string literal.
This may be useful for incremental parsing of configuration or other data, out
of a larger string.
=cut
=head2 keycmp
$cmp = $tk->keycmp( $key1, $key2 );
Compares the two given keypress events, returning a number less than, equal
to, or greater than zero, depending on the ordering. Keys are ordered first by
type (unicode, keysym, function, mouse), then by value within that type, then
finally by modifier bits.
This may be useful in C<sort> expressions:
my @sorted_keys = sort { $tk->keycmp( $a, $b ) } @keys;
=cut
=head1 KEY OBJECTS
The C<Term::TermKey::Key> subclass is used to store a single keypress event.
Objects in this class cannot be changed by perl code. C<getkey()>,
C<getkey_force()> or C<waitkey()> will overwrite the contents of the structure
with a new value.
Keys cannot be constructed, but C<getkey()>, C<getkey_force()> or C<waitkey()>
will place a new key structure in the C<$key> variable if it is undefined when
they are called. C<parse_key()> and C<parse_key_at_pos()> will return new
keys.
=head2 type
$key->type;
The type of event. One of C<TYPE_UNICODE>, C<TYPE_FUNCTION>, C<TYPE_KEYSYM>,
C<TYPE_MOUSE>, C<TYPE_POSITION>, C<TYPE_MODEREPORT>, C<TYPE_UNKNOWN_CSI>.
=head2 type_is_...
$key->type_is_unicode;
$key->type_is_function;
$key->type_is_keysym;
$key->type_is_mouse;
$key->type_is_position;
$key->type_is_modereport;
$key->type_is_unknown_csi;
Shortcuts which return a boolean.
=head2 codepoint
$key->codepoint;
The Unicode codepoint number for C<TYPE_UNICODE>, or 0 otherwise.
=head2 number
$key->number;
The function key number for C<TYPE_FUNCTION>, or 0 otherwise.
=head2 sym
$key->sym;
The key symbol number for C<TYPE_KEYSYM>, or 0 otherwise. This can be passed
to C<< Term::TermKey->get_keyname() >>, or compared to a result earlier
obtained from C<< Term::TermKey->keyname2sym() >>.
=head2 modifiers
$key->modifiers;
The modifier bitmask. Can be compared against the C<KEYMOD_*> constants.
=head2 modifier_...
$key->modifier_shift;
$key->modifier_alt;
$key->modifier_ctrl;
Shortcuts which return a boolean if the appropriate modifier is present.
=head2 utf8
$key->utf8;
A string representation of the given Unicode codepoint. If the underlying
C<termkey> library is in UTF-8 mode then this will be a UTF-8 string. If it is
in raw mode, then this will be a single raw byte.
=head2 mouseev
=head2 button
$key->mouseev;
$key->button;
The details of a mouse event for C<TYPE_MOUSE>, or C<undef> for other types of
event.
=head2 line
=head2 col
$key->line;
$key->col;
The details of a mouse or position event, or C<undef> for other types of
event.
=head2 termkey
$key->termkey;
Return the underlying C<Term::TermKey> object this key was retrieved from.
=head2 format
$str = $key->format( $format );
Returns a string representation of the keypress event, identically to calling
C<format_key> on the underlying C<Term::TermKey> object.
=cut
sub Term::TermKey::Key::format
{
my $self = shift;
return $self->termkey->format_key( $self, @_ );
}
=head1 EXPORTED CONSTANTS
The following constant names are all derived from the underlying C<libtermkey>
library. For more detail see the documentation on the library.
These constants are possible values of C<< $key->type >>
=over 4
=item C<TYPE_UNICODE>
a Unicode codepoint
=item C<TYPE_FUNCTION>
a numbered function key
=item C<TYPE_KEYSYM>
a symbolic key
=item C<TYPE_MOUSE>
a mouse movement or button press or release
=item C<TYPE_POSITION>
a cursor position report
=item C<TYPE_MODEREPORT>
an ANSI or DEC mode report
=item C<TYPE_UNKNOWN_CSI>
an unrecognised CSI sequence
=back
These constants are result values from C<getkey()>, C<getkey_force()>,
C<waitkey()> or C<advisereadable()>
=over 4
=item C<RES_NONE>
No key event is ready.
=item C<RES_KEY>
A key event has been provided.
=item C<RES_EOF>
No key events are ready and the terminal has been closed, so no more will
arrive.
=item C<RES_AGAIN>
No key event is ready yet, but a partial one has been found. This is only
returned by C<getkey()>. To obtain the partial result even if it never
completes, call C<getkey_force()>.
=item C<RES_ERROR>
Returned by C<waitkey> or C<advisereadable> if an IO error occurs while trying
to read another key event.
=back
These constants are key modifier masks for C<< $key->modifiers >>
=over 4
=item C<KEYMOD_SHIFT>
=item C<KEYMOD_ALT>
=item C<KEYMOD_CTRL>
Should be obvious ;)
=back
These constants are types of mouse event which may be returned by
C<< $key->mouseev >> or C<interpret_mouse>:
=over 4
=item C<MOUSE_UNKNOWN>
The type of mouse event was not recognised
=item C<MOUSE_PRESS>
The event reports a mouse button being pressed
=item C<MOUSE_DRAG>
The event reports the mouse being moved while a button is held down
=item C<MOUSE_RELEASE>
The event reports the mouse buttons being released, or the mouse moved without
a button held.
=back
These constants are flags for the constructor, C<< Term::TermKey->new >>
=over 4
=item C<FLAG_NOINTERPRET>
Do not attempt to interpret C0 codes into keysyms (ie. C<Backspace>, C<Tab>,
C<Enter>, C<Escape>). Instead report them as plain C<Ctrl-letter> events.
=item C<FLAG_CONVERTKP>
Convert xterm's alternate keypad symbols into the plain ASCII codes they would
represent.
=item C<FLAG_RAW>
Ignore locale settings; do not attempt to recombine UTF-8 sequences. Instead
report only raw values.
=item C<FLAG_UTF8>
Ignore locale settings; force UTF-8 recombining on.
=item C<FLAG_NOTERMIOS>
Even if the terminal file descriptor represents a TTY device, do not call the
C<tcsetattr()> C<termios> function on it to set in canonical input mode.
=item C<FLAG_SPACESYMBOL>
Sets the C<CANON_SPACESYMBOL> canonicalisation flag. See below.
=item C<FLAG_CTRLC>
Disable the C<SIGINT> behaviour of the C<Ctrl-C> key, allowing it to be read
as a modified Unicode keypress.
=item C<FLAG_EINTR>
Disable retry on signal interrupt; instead report it as an error with
C<RES_ERROR> and C<$!> set to C<EINTR>. Without this flag, IO operations will
be retried if interrupted.
=back
These constants are canonicalisation flags for C<set_canonflags> and
C<get_canonflags>
=over 4
=item C<CANON_SPACESYMBOL>
With this flag set, the Space key will appear as a C<TYPE_KEYSYM> key event
whose symname is C<"Space">. Without this flag, it appears as a normal
C<TYPE_UNICODE> character.
=item C<CANON_DELBS>
With this flag set, the ASCII C<DEL> byte is interpreted as the C<"Backspace">
keysym, rather than C<"DEL">. This flag does not affect the interpretation of
ASCII C<BS>, which is always represented as C<"Backspace">.
=back
These constants are flags to C<format_key>
=over 4
=item C<FORMAT_LONGMOD>
Print full modifier names e.g. C<Shift-> instead of abbreviating to C<S->.
=item C<FORMAT_CARETCTRL>
If the only modifier is C<Ctrl> on a plain character, render it as C<^X>.
=item C<FORMAT_ALTISMETA>
Use the name C<Meta> or the letter C<M> instead of C<Alt> or C<A>.
=item C<FORMAT_WRAPBRACKET>
If the key event is a special key instead of unmodified Unicode, wrap it in
C<< <brackets> >>.
=item C<FORMAT_MOUSE_POS>
If the event is a mouse event, also include the cursor position; rendered as
C<@ ($col,$line)>
=item C<FORMAT_VIM>
Shortcut to C<FORMAT_ALTISMETA|FORMAT_WRAPBRACKET>; which gives an output
close to the format the F<vim> editor uses.
=back
=cut
=head1 EXAMPLES
=head2 A simple print-until-C<Ctrl-C> loop
This program just prints every keypress until the user presses C<Ctrl-C>.
use Term::TermKey qw( FLAG_UTF8 RES_EOF FORMAT_VIM );
my $tk = Term::TermKey->new(\*STDIN);
# ensure perl and libtermkey agree on Unicode handling
binmode( STDOUT, ":encoding(UTF-8)" ) if $tk->get_flags & FLAG_UTF8;
while( ( my $ret = $tk->waitkey( my $key ) ) != RES_EOF ) {
print "Got key: ".$tk->format_key( $key, FORMAT_VIM )."\n";
}
=head2 Configuration of custom keypresses
Because C<format_key()> yields a plain string representation of a keypress it
can be used as a hash key to look up a "handler" routine for the key.
The following implements a simple line input program, though obviously lacking
many features in a true line editor like F<readline>.
use Term::TermKey qw( FLAG_UTF8 RES_EOF FORMAT_LONGMOD );
my $tk = Term::TermKey->new(\*STDIN);
# ensure perl and libtermkey agree on Unicode handling
binmode( STDOUT, ":encoding(UTF-8)" ) if $tk->get_flags & FLAG_UTF8;
my $line = "";
$| = 1;
my %key_handlers = (
"Enter" => sub {
print "\nThe line is: $line\n";
$line = "";
},
"Backspace" => sub {
return unless length $line;
substr( $line, -1, 1 ) = "";
print "\cH \cH"; # erase it
},
# other handlers ...
);
while( ( my $ret = $tk->waitkey( my $key ) ) != RES_EOF ) {
my $handler = $key_handlers{ $tk->format_key( $key, FORMAT_LONGMOD ) };
if( $handler ) {
$handler->( $key );
}
elsif( $key->type_is_unicode and !$key->modifiers ) {
my $char = $key->utf8;
$line .= $char;
print $char;
}
}
=head2 Asynchronous operation
Because the C<getkey()> method performs no IO itself, it can be combined with
the C<advisereadable()> method in an asynchronous program.
use IO::Select;
use Term::TermKey qw(
FLAG_UTF8 RES_KEY RES_AGAIN RES_EOF FORMAT_VIM
);
my $select = IO::Select->new();
my $tk = Term::TermKey->new(\*STDIN);
$select->add(\*STDIN);
# ensure perl and libtermkey agree on Unicode handling
binmode( STDOUT, ":encoding(UTF-8)" ) if $tk->get_flags & FLAG_UTF8;
sub on_key
{
my ( $tk, $key ) = @_;
print "You pressed " . $tk->format_key( $key, FORMAT_VIM ) . "\n";
}
my $again = 0;
while(1) {
my $timeout = $again ? $tk->get_waittime/1000 : undef;
my @ready = $select->can_read($timeout);
if( !@ready ) {
my $ret;
while( ( $ret = $tk->getkey_force( my $key ) ) == RES_KEY ) {
on_key( $tk, $key );
}
}
while( my $fh = shift @ready ) {
if( $fh == \*STDIN ) {
$tk->advisereadable;
my $ret;
while( ( $ret = $tk->getkey( my $key ) ) == RES_KEY ) {
on_key( $tk, $key );
}
$again = ( $ret == RES_AGAIN );
exit if $ret == RES_EOF;
}
# Deal with other filehandles here
}
}
There may also be more appropriate modules on CPAN for particular event
frameworks; see the C<SEE ALSO> section below.
=cut
=head1 SEE ALSO
=over 4
=item *
L<http://www.leonerd.org.uk/code/libtermkey/> - C<libtermkey> home page
=item *
L<Term::TermKey::Async> - terminal key input using C<libtermkey> with
L<IO::Async>
=item *
L<POE::Wheel::TermKey> - terminal key input using C<libtermkey> with L<POE>
=item *
L<AnyEvent::TermKey> - terminal key input using C<libtermkey> with L<AnyEvent>
=back
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
0x55AA;
|