NAME
    "Term::TermKey" - perl wrapper around "libtermkey"

SYNOPSIS
     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 );

DESCRIPTION
    This module provides a light perl wrapper around the "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.

  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.

CONSTRUCTOR
  $tk = Term::TermKey->new( $term, $flags )
    Construct a new "Term::TermKey" object that wraps the given term handle.
    $term should be either an IO handle reference or an integer containing a
    plain POSIX file descriptor. $flags is optional, but if given, should
    contain the flags to pass to "libtermkey"'s constructor. Assumes a
    default of 0 if not supplied. See the "FLAG_*" constants.

METHODS
  $flags = $tk->get_flags
  $tk->set_flags( $newflags )
    Accessor and mutator for the flags. One of the "FLAG_UTF8" or "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.

  $msec = $tk->get_waittime
  $tk->set_waittime( $msec )
    Accessor and mutator for the maximum wait time in miliseconds. The
    underlying "libtermkey" library will have specified a default value when
    the object was constructed.

  $res = $tk->getkey( $key )
    Attempt to retrieve a single keypress event from the buffer, and put it
    in $key. If successful, will return "RES_KEY" to indicate that the $key
    structure now contains a new keypress event. If $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 "RES_NONE". If the buffer
    contains a partial keypress event which does not yet contain all the
    bytes required, it will return "RES_AGAIN" (see above section about
    multibyte events). If no events are ready and the input stream is now
    closed, will return "RES_EOF".

    This method will not block, nor will it perform any IO on the underlying
    file descriptor. For a normal blocking read, see "waitkey()".

  $res = $tk->getkey_force( $key )
    Similar to "getkey()", but will not return "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 "<Esc>"-prefixed
    multibyte sequence as a literal "Escape" key followed by normal letters.
    If $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 "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 "RES_KEY" to indicate
    that the $key structure now contains a new keypress event. The only
    other result it can return is "RES_EOF", to indicate that the input
    stream is now closed. If $key is an undefined lvalue (such as a new
    scalar variable) it will be initialised to contain a new key structure.

  $res = $tk->advisereadable
    Inform the underlying library that new input may be available on the
    underlying file descriptor and so it should call "read()" to obtain it.
    Will return "RES_AGAIN" if it read at least one more byte, or "RES_NONE"
    if no more input was found.

    Normally this method would only be used in programs that want to use
    "Term::TermKey" asynchronously; see the EXAMPLES section. This method
    gracefully handles an "EAGAIN" error from the underlying "read()"
    syscall.

  $str = $tk->get_keyname( $sym )
    Returns the name of a key sym, such as returned by
    "Term::TermKey::Key->sym()".

  $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
    "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.

  ( $ev, $button, $line, $col ) = $tk->interpret_mouse( $key )
    If $key contains a mouse event then its details are returned in a list.
    $ev will be one of the "TERMKEY_MOUSE_*" constants, $button will be the
    button number it relates to, and $line and $col will give the screen
    coordinates, numbered from 1. If $key does not contain a mouse event
    then an empty list is returned.

  $str = $tk->format_key( $key, $format )
    Return a string representation of the keypress event in $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.

  $key = $tk->parse_key( $str, $format )
    Return a keypress event by parsing the string representation in $str,
    following the flags given. This method is an inverse of "format_key".

    This may be useful for parsing entries from a configuration file or
    similar.

  $key = $tk->parse_key_at_pos( $str, $format )
    Return a keypress event by parsing the string representation in a region
    of $str, following the flags given.

    Where "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
    "pos()" position in $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. $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.

  $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 "sort" expressions:

     my @sorted_keys = sort { $tk->keycmp( $a, $b ) } @keys;

KEY OBJECTS
    The "Term::TermKey::Key" subclass is used to store a single keypress
    event. Objects in this class cannot be changed by perl code. "getkey()",
    "getkey_force()" or "waitkey()" will overwrite the contents of the
    structure with a new value.

    Keys cannot be constructed, but "getkey()", "getkey_force()" or
    "waitkey()" will place a new key structure in the $key variable if it is
    undefined when they are called. "parse_key()" and "parse_key_at_pos()"
    will return new keys.

  $key->type
    The type of event. One of "TYPE_UNICODE", "TYPE_FUNCTION",
    "TYPE_KEYSYM", "TYPE_MOUSE".

  $key->type_is_unicode
  $key->type_is_function
  $key->type_is_keysym
  $key->type_is_mouse
    Shortcuts which return a boolean.

    In the case of a mouse event, you must use the "interpret_mouse" method
    on the containing "Term::TermKey" object to access the event details.

  $key->codepoint
    The Unicode codepoint number for "TYPE_UNICODE", or 0 otherwise.

  $key->number
    The function key number for "TYPE_FUNCTION", or 0 otherwise.

  $key->sym
    The key symbol number for "TYPE_KEYSYM", or 0 otherwise. This can be
    passed to "Term::TermKey->get_keyname()", or compared to a result
    earlier obtained from "Term::TermKey->keyname2sym()".

  $key->modifiers
    The modifier bitmask. Can be compared against the "KEYMOD_*" constants.

  $key->modifier_shift
  $key->modifier_alt
  $key->modifier_ctrl
    Shortcuts which return a boolean if the appropriate modifier is present.

  $key->utf8
    A string representation of the given Unicode codepoint. If the
    underlying "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.

  $key->termkey
    Return the underlying "Term::TermKey" object this key was retrieved
    from.

  $str = $key->format( $format )
    Returns a string representation of the keypress event, identically to
    calling "format_key" on the underlying "Term::TermKey" object.

EXPORTED CONSTANTS
    The following constant names are all derived from the underlying
    "libtermkey" library. For more detail see the documentation on the
    library.

    These constants are possible values of "$key->type"

    "TYPE_UNICODE"
        a Unicode codepoint

    "TYPE_FUNCTION"
        a numbered function key

    "TYPE_KEYSYM"
        a symbolic key

    "TYPE_MOUSE"
        a mouse movement or button press or release

    These constants are result values from "getkey()", "getkey_force()",
    "waitkey()" or "advisereadable()"

    "RES_NONE"
        No key event is ready.

    "RES_KEY"
        A key event has been provided.

    "RES_EOF"
        No key events are ready and the terminal has been closed, so no more
        will arrive.

    "RES_AGAIN"
        No key event is ready yet, but a partial one has been found. This is
        only returned by "getkey()". To obtain the partial result even if it
        never completes, call "getkey_force()".

    These constants are key modifier masks for "$key->modifiers"

    "KEYMOD_SHIFT"
    "KEYMOD_ALT"
    "KEYMOD_CTRL"
        Should be obvious ;)

    These constants are types of mouse event which may be returned by
    "interpret_mouse":

    "TERMKEY_MOUSE_UNKNOWN"
        The type of mouse event was not recognised

    "TERMKEY_MOUSE_PRESS"
        The event reports a mouse button being pressed

    "TERMKEY_MOUSE_DRAG"
        The event reports the mouse being moved while a button is held down

    "TERMKEY_MOUSE_RELEASE"
        The event reports the mouse buttons being released, or the mouse
        moved without a button held.

    These constants are flags for the constructor, "Term::TermKey->new"

    "FLAG_NOINTERPRET"
        Do not attempt to interpret C0 codes into keysyms (ie. "Backspace",
        "Tab", "Enter", "Escape"). Instead report them as plain
        "Ctrl-letter" events.

    "FLAG_CONVERTKP"
        Convert xterm's alternate keypad symbols into the plain ASCII codes
        they would represent.

    "FLAG_RAW"
        Ignore locale settings; do not attempt to recombine UTF-8 sequences.
        Instead report only raw values.

    "FLAG_UTF8"
        Ignore locale settings; force UTF-8 recombining on.

    "FLAG_NOTERMIOS"
        Even if the terminal file descriptor represents a TTY device, do not
        call the "tcsetattr()" "termios" function on it to set in canonical
        input mode.

    "FLAG_SPACESYMBOL"
        Make the Space key appear as a named symbol. Without this flag, it
        appears as a normal Unicode character.

    "FLAG_CTRLC"
        Disable the "SIGINT" behaviour of the "Ctrl-C" key, allowing it to
        be read as a modified Unicode keypress.

    These constants are flags to "format_key"

    "FORMAT_LONGMOD"
        Print full modifier names e.g. "Shift-" instead of abbreviating to
        "S-".

    "FORMAT_CARETCTRL"
        If the only modifier is "Ctrl" on a plain character, render it as
        "^X".

    "FORMAT_ALTISMETA"
        Use the name "Meta" or the letter "M" instead of "Alt" or "A".

    "FORMAT_WRAPBRACKET"
        If the key event is a special key instead of unmodified Unicode,
        wrap it in "<brackets>".

    "FORMAT_MOUSE_POS"
        If the event is a mouse event, also include the cursor position;
        rendered as "@ ($col,$line)"

    "FORMAT_VIM"
        Shortcut to "FORMAT_ALTISMETA|FORMAT_WRAPBRACKET"; which gives an
        output close to the format the vim editor uses.

EXAMPLES
  A simple print-until-"Ctrl-C" loop
    This program just prints every keypress until the user presses "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";
     }

  Configuration of custom keypresses
    Because "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 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;
        }
     }

  Asynchronous operation
    Because the "getkey()" method performs no IO itself, it can be combined
    with the "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
        }
     }

    See also the Term::TermKey::Async module which provides a convenient
    wrapping of "Term::TermKey" for an IO::Async-based program.

TODO
    *   Consider if "$key = $tk->waitkey" is a better API. While underlying
        library only returns "RES_KEY" or "RES_NONE" that works but if it
        ever gains another value, all bets are off. Return undef and have a
        "->err" method? Going into messyland...

SEE ALSO
    *   <http://www.leonerd.org.uk/code/libtermkey/> - libtermkey home page

AUTHOR
    Paul Evans <leonerd@leonerd.org.uk>

