The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

POE::Wheel::ReadLine - prompted terminal input with basic editing keys

SYNOPSIS

  # Create the wheel.
  $heap->{wheel} = POE::Wheel::ReadLine->new( InputEvent => got_input );

  # Trigger the wheel to read a line of input.
  $wheel->get( 'Prompt: ' );

  # Add a line to the wheel's input history.
  $wheel->addhistory( $input );

  # Input handler.  If $input is defined, then it contains a line of
  # input.  Otherwise $exception contains a word describing some kind
  # of user exception.  Currently these are 'interrupt' and 'cancel'.
  sub got_input_handler {
    my ($heap, $input, $exception) = @_[HEAP, ARG0, ARG1];
    if (defined $input) {
      $heap->{wheel}->addhistory($input);
      print "\tGot: $input\n";
      $heap->{wheel}->get('Prompt: '); # get another line
    }
    else {
      print "\tException: $exception\n";
    }
  }

  # Clear the terminal.
  $wheel->clear();

DESCRIPTION

ReadLine performs non-blocking, event-driven console input, using Term::Cap to interact with the terminal display and Term::ReadKey to interact with its keyboard.

ReadLine handles a number of common input editing keys; it also provides an input history list. It's not, however, a fully featured Term::ReadLine replacement, although it probably will approach one over time.

EDITING KEYS

These are the editing keystrokes that ReadLine uses to facilitate text editing. Some of them, such as Home, End, Insert, and Delete, may not work on every terminal.

Keystrokes are in the form X-y or X-X-z. X designates a modifier, which can be C for "control" or M for "meta". The only meta key currently supported is the Escape key, chr(27).

C-a (Control-A)
Home

Moves the cursor to the beginning of the line.

C-b
Left arrow

Moves the cursor one character back towards the beginning of the line.

C-c

Interrupt the program. This stops editing the current line and emits an InputEvent event. The event's ARG0 parameter is undefined, and its ARG1 parameter contains the word "interrupt".

C-d
Delete

Delete the character under the cursor.

C-e
End

Move the cursor to the end of the input line.

C-f
Right arrow

Move the cursor one character forward. This moves it closer to the end of the line.

C-g

Cancle text entry. This stops editing the current line and emits an InputEvent event. The event's ARG0 parameter is undefined, and its ARG1 parameter contains the word "cancel".

C-h
Backspace

Delete the character before the cursor.

C-j
Enter / Return

C-j is the newline keystroke on Unix-y systems. It ends text entry, firing an InputEvent with ARG0 containing the entered text (without the terminating newline). ARG1 is undefined because there is no exception.

C-k

Kill to end of line. Deletes all text from the cursor position to the end of the line.

C-l

Clear the screen and repaint the prompt and current input line.

C-m
Enter / Return

C-m is the newline keystroke on Unix-y systems. It ends text entry, firing an InputEvent with ARG0 containing the entered text (without the terminating newline). ARG1 is undefined because there is no exception.

C-n
Down arrow

Scroll forward through the line history list. This replaces the current input line with the one entered after it.

C-p
Up arrow

Scroll back through the line history list. This replaces the current input line with the one entered before it.

C-t

Transpose the character before the cursor with the one under it. Tihs si gerat fro fxiing cmoon tyopes.

C-u

Discard the entire line. Throws away everything and starts anew.

C-w
M-C-h (Escape Control-h)

Word rubout. Discards from just before the cursor to the beginning of the word immediately before it.

M-< (Escape-<)

First history line. Replaces the current input line with the first one in the history list.

M->

Last history line. Replaces the current input line with the last one in the history list. Pressing C-n or the down arrow key after this will recall whatever was being entered before the user began looking through the history list.

M-b

Move the cursor backwards one word. The cursor's final resting place is at the start of the word on or before the cursor's original location.

M-c

Capitalize the first letter on or after the cursor, and lowercase subsequent characters in the word. Some examples follow. The caret marks the character under the cursor before M-c is pressed.

  capITALize  tHiS   ... becomes ...   Capitalize  tHiS
  ^                                              ^

  capITALize  tHiS   ... becomes ...   capITALiZe  tHiS
          ^                                      ^

  capITALize  tHiS   ... becomes ...   capITALize  This
            ^                                          ^
M-d

Forward word delete. Deletes from the cursor position to the end of the first word on or after the cursor. The text that is deleted is the same as the text that M-c, M-l, and M-u change. It also coincides with the text that M-f skip.

M-f

Move the cursor forward one word. The cursor actually moves to the end of the first word under or after the cursor. This motion is the same for M-c, M-l, and M-u.

M-l

Uppercases the entire word beginning on or after the cursor position. Here are some examples; the caret points to the character under the cursor before and after M-u are pressed.

  LOWERCASE  THIS   ... becomes ...   lowercase  THIS
  ^                                            ^

  LOWERCASE  THIS   ... becomes ...   LOWERcase  THIS
       ^                                       ^

  LOWERCASE  THIS   ... becomes ...   LOWERCASE  this
           ^                                         ^
M-t

Transpose words.

If the cursor is within the last word in the input line, then that word is transposed with the one before it.

  one  two  three   ... becomes ...   one  three  two
               ^                                     ^

If the cursor is within any other word in the input line, then that word is transposed with the next one.

  one  two  three   ... becomes ...   two  one  three
   ^                                          ^

If the cursor is in the whitespace between words, then the words on either side of the whitespace are transposed.

  one  two  three   ... becomes ...   two  one  three
      ^                                       ^
M-u

Uppercases the entire word beginning on or after the cursor position. Here are some examples; the caret points to the character under the cursor before and after M-u are pressed.

  uppercase  this   ... becomes ...   UPPERCASE  this
  ^                                            ^

  uppercase  this   ... becomes ...   upperCASE  this
       ^                                       ^

  uppercase  this   ... becomes ...   uppercase  THIS
           ^                                         ^

PUBLIC METHODS

addhistory LIST_OF_LINES

Adds a list of lines, presumably from previous input, into the ReadLine wheel's input history. They will be available with C-p, C-n, and/or the up- and down arrow keys.

clear

Clears the terminal.

get PROMPT

Provide a prompt and enable input. The wheel will display the prompt and begin paying attention to the console keyboard after this method is called. Once a line or an exception is returned, the wheel will resume its quiescent state wherein it ignores keystrokes.

The quiet period between input events gives a program the opportunity to change the prompt or process lines before the next one arrives.

EVENTS AND PARAMETERS

InputEvent

InputEvent contains the name of the event that will be fired upon successful (or unsuccessful) terminal input. Every InputEvent handler receives two additional parameters, only one of which is ever defined at a time. ARG0 contains the input line, if one was present. If ARG0 is not defined, then ARG1 contains a word describing a user-generated exception:

The 'interrupt' exception means a user pressed C-c (^C) to interrupt the program. It's up to the input event's handler to decide what to do next.

The 'cancel' exception means a user pressed C-g (^G) to cancel a line of input.

Finally, ARG2 contains the ReadLine wheel's unique ID.

PutMode

PutMode specifies how the wheel will display text when its put() method is called.

put() displays text immediately when the user isn't being prompted for input. It will also pre-empt the user to display text right away when PutMode is "immediate".

When PutMode is "after", all put() text is held until after the user enters or cancels (See C-g) her input.

PutMode can also be "idle". In this mode, text is displayed right away if the keyboard has been idle for a certian period (see the IdleTime parameter). Otherwise it's held as in "after" mode until input is completed or canceled, or until the keyboard becomes idle for at least IdleTime seconds. This is ReadLine's default mode.

IdleTime

IdleTime specifies how long the keyboard must be idle before put() becomes immediate or buffered text is flushed to the display. It is only meaningful when InputMode is "idle". IdleTime defaults to two seconds.

SEE ALSO

POE::Wheel.

The SEE ALSO section in POE contains a table of contents covering the entire POE distribution.

BUGS

Non-optimal code

Dissociating the input and display cursors introduced a lot of code. Much of this code was thrown in hastily, and things can probably be done with less work. To do: Apply some thought to what's already been done.

The screen should update as quickly as possible, especially on slow systems. Do little or no calculation during displaying; either put it all before or after the display. Do it consistently for each handled keystroke, so that certain pairs of editing commands don't have extra perceived latency.

Unimplemented features

Input editing is not kept on one line. If it wraps, and a terminal cannot wrap back through a line division, the cursor will become lost. This bites, and it's the next against the wall in my bug hunting.

Unicode, or at least European code pages. I feel real bad about throwing away native representation of all the 8th-bit-set characters. I also have no idea how to do this, and I don't have a system to test this. Patches are recommended.

SIGWINCH tends to kill Perl quickly, and POE ignores it. Resizing a terminal window has no effect. Making this useful will require signal polling, perhaps in the wheel itself (either as a timer loop, a keystroke, or per every N keystrokes) or in POE::Kernel. I'm not sure which yet.

Tab completion:

  C-i     cycle through completions
  C-x *   insert possible completions
  C-x ?   list possible completions
  M-?     list possible completions

Input options:

  C-q     quoted insert (unprocessed keystroke)
  M-Tab   insert literal tab
  C-_     undo

History searching:

  C-s     search history
  C-r     reverse search history
  C-v     forward search history

GOTCHAS / FAQ

Q: Why do I lose my ReadLine prompt every time I send output to the screen?

A: You probably are using print or printf to write screen output. ReadLine doesn't track STDOUT itself, so it doesn't know when to refresh the prompt after you do this. Use ReadLine's put() method to write lines to the console.

AUTHORS & COPYRIGHTS

Please see POE for more information about authors and contributors.