如何在不打印换行符的情况下使用 Term::ReadLine 读取用户输入?

How can I read user input using Term::ReadLine without having the newline character printed out?

如何在用户按下 Enter 时使用 Term::ReadLine 读取用户输入而不打印换行符?

我想这样做的原因是因为我想从屏幕底部的提示中读取用户输入(如 lessvim)。目前,按 Enter 会导致屏幕向下滚动,这可能是个问题。另外,我想避免此时不得不诉诸 ncurses

设置 $term->Attribs->{echo_control_characters}0undefoff 似乎不起作用。

#!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

我可以使用 Term::ReadKeycbreak 作为读取模式来做到这一点:

#!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';

但那样我就无法使用 Term::ReadLine 功能,例如历史记录、完成和行编辑。

您可以设置 rl_getc_function 在打印之前拦截回车 return,如 问题所示。以下对我有用:

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