Как я могу добраться, ввод данных пользователем, не ожидая входят в Perl?

Я пытаюсь сделать интерактивный сценарий оболочки в Perl.

Единственный ввод данных пользователем, который я могу найти, следующий:

 $name = <STDIN>;
 print STDOUT "Hello $name\n";

Но в этом должен всегда нажимать пользователь, вводят для изменений для вступления в силу. Как я могу заставить программу сразу продолжиться после того, как кнопка была нажата?

14
задан Hermann Ingjaldsson 29 June 2010 в 11:24
поделиться

2 ответа

Из ответа perlfaq8 на Как мне прочитать только один ключ, не дожидаясь возврата ключа? {{1 }} :


Управление буферизацией ввода в значительной степени зависит от системы. Во многих системах вы можете просто использовать команду stty, как показано в getc в perlfunc, но, как вы видите, это уже вводит вас в затруднения переносимости.

open(TTY, "+</dev/tty") or die "no tty: $!";
system "stty  cbreak </dev/tty >/dev/tty 2>&1";
$key = getc(TTY);       # perhaps this works
# OR ELSE
sysread(TTY, $key, 1);  # probably this does
system "stty -cbreak </dev/tty >/dev/tty 2>&1";

Модуль Term :: ReadKey от CPAN предлагает простой в использовании интерфейс, который должен быть более эффективным, чем использование stty для каждого ключа. Он даже включает ограниченную поддержку Windows.

use Term::ReadKey;
ReadMode('cbreak');
$key = ReadKey(0);
ReadMode('normal');

Однако для использования кода требуется, чтобы у вас был работающий компилятор C и вы могли использовать его для сборки и установки модуля CPAN. Вот решение, использующее стандартный модуль POSIX, который уже есть в вашей системе (при условии, что ваша система поддерживает POSIX).

use HotKey;
$key = readkey();

А вот модуль HotKey, который скрывает несколько загадочные вызовы для управления структурами POSIX termios.

# HotKey.pm
package HotKey;

@ISA = qw(Exporter);
@EXPORT = qw(cbreak cooked readkey);

use strict;
use POSIX qw(:termios_h);
my ($term, $oterm, $echo, $noecho, $fd_stdin);

$fd_stdin = fileno(STDIN);
$term     = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm     = $term->getlflag();

$echo     = ECHO | ECHOK | ICANON;
$noecho   = $oterm & ~$echo;

sub cbreak {
    $term->setlflag($noecho);  # ok, so i don't want echo either
    $term->setcc(VTIME, 1);
    $term->setattr($fd_stdin, TCSANOW);
}

sub cooked {
    $term->setlflag($oterm);
    $term->setcc(VTIME, 0);
    $term->setattr($fd_stdin, TCSANOW);
}

sub readkey {
    my $key = '';
    cbreak();
    sysread(STDIN, $key, 1);
    cooked();
    return $key;
}

END { cooked() }

1;
16
ответ дан 1 December 2019 в 12:51
поделиться

Вы можете использовать модуль Term :: ReadKey для проверки нажатия клавиш.

5
ответ дан 1 December 2019 в 12:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: