How can I read user input using Term::ReadLine
without having a newline character printed out when the user presses Enter?
The reason why I want to do this is because I want to read user input from a prompt at the very bottom of the screen (as in less
or vim
). Currently, pressing Enter causes the screen to scroll down, and that can be an issue. Also, I'd like to avoid having to appeal to ncurses
at this point.
Setting
$term->Attribs->{echo_control_characters}
to 0
, undef
, or off
doesn't seem to work.
#!perl
use Term::ReadLine;
use Term::ReadKey;
my $term = new Term::ReadLine ('me');
$term->ornaments(0);
$term->Attribs->{echo_control_characters} = 0;
print STDERR "\e[2J\e[s\e[" . ( ( GetTerminalSize() ) [1] ) . ";1H"; # clear screen, save cursor position, and go to the bottom;
my $input = $term->readline('> ');
print STDOUT "\e[uinput = $input\n"; # restore cursor position, and print
I could do that using Term::ReadKey
with cbreak
as read mode:
#!perl
use Term::ReadKey;
ReadMode 'cbreak';
my ( $k, $input );
print STDERR "> ";
while ( defined ( $k = ReadKey 0 ) and $k !~ /\n/ )
{
$input .= $k;
print STDERR $k;
}
print STDOUT "input = $input\n";
ReadMode 'restore';
But then I wouldn't be able to use Term::ReadLine
features, such as history, completion, and line editing.
CodePudding user response:
You can set the rl_getc_function
to intercept the carriage return before it is printed as shown in this question. The following works for me:
use strict;
use warnings;
BEGIN {
$ENV{PERL_RL} = "Gnu";
}
use Term::ReadLine;
use Term::ReadKey;
my $term = Term::ReadLine->new('me');
my $attr = $term->Attribs;
$term->ornaments(0);
$attr->{getc_function} = sub {
my $ord = $term->getc($attr->{instream});
if ( $ord == 13 ) { # carriage return pressed
$attr->{done} = 1;
return 0;
}
return $ord;
};
print STDERR "\e[2J\e[s\e[" . ( ( GetTerminalSize() ) [1] ) . ";1H";
my $input = $term->readline('> ');
print STDOUT "\e[uinput = $input\n"; # restore cursor position, and print