2016-01-04 14 views
2

Некоторое время назад от Perl и хотел бы изменить скрипт, который я написал как арт-проект давно. В исходном скрипте используется Term :: ReadKey, чтобы пользователь мог вводить произвольный текст в терминал Mac/Linux. По мере ввода текст создает различные плавающие шаблоны в терминале. Я хочу адаптировать сценарий так, чтобы вместо чтения ключей, когда они вводятся, он может читать из текстовых файлов, периодически записываемых другим процессом. Но ему нужно будет читать персонажи каким-то контролируемым образом (не все сразу), чтобы (грубо) подражать человеческой типизации.Perl Term :: ReadKey - читать из файла, как если бы он набирался.

Что я пробовал: Term :: страница человека ReadKey говорит он может читать из дескриптора вместо STDIN - но по какой-то причине, я не мог получить эту работу, либо стандартный файл или FIFO. Я также пробовал читать текст из файла, используя «open» и помещая символы в массив. Но итерация через массив осложнилась из-за необходимости добавлять задержки между символами без приостановки остальной части скрипта. (Я могу представить это как потенциальное решение, но я не уверен, как лучше всего его спроектировать, чтобы избежать зависания времени, если скрипт не стал громоздким.)

Удивление, если есть относительно простой способ приблизиться к этому - Предполагая, что это вообще возможно?

Вот «мясо» из существующего сценария (удалили различные подпрограммы, которые добавляют дополнительные эффекты, основанные на различных нажатиях.)

#!/usr/bin/perl 

use Time::HiRes(usleep); 
use Term::ReadKey; 


$|=1; 

$starttime = time; 
$startphrase = '     '; 

$startsleepval = 3000; 

$phrase = $startphrase; 
$sleepval = $startsleepval; 
$dosleep = 1; 


$SIG{'INT'}=\&quitsub; 
$SIG{'QUIT'}=\&quitsub; 

# One Ctrl-C clears text and resets program. # Three Ctrl-C's to quit. 

sub quitsub {print color 'reset' if ($dosleep); $phrase = $startphrase; $sleepval=$startsleepval; $SIG{'INT'}=\&secondhit;} 
sub secondhit { $SIG{'INT'}=\&outtahere; } 
sub outtahere {print color 'reset'; sleep 1; print "\n\n\t\t\t\n\n"; exit(0);} 


while (1) { 
    print "$phrase "; 
    if ($dosleep) { 
     usleep ($sleepval); 
    } 
    ReadMode 3; 

    ##### Here is where it reads from the terminal. Can characters be read from a file in a similar sequential fashion? ##### 
    $key = ReadKey(-1); 
    $now = time; 
    if ((defined($key)) and ($now > $starttime + 5)) { 
     $phrase = $phrase.$key; 
     $SIG{'INT'}=\&quitsub; 
    } 
    # user can also create interesting effects with spacebar, tab and arrow keys. 

    ReadMode 0; # this may appear redundant, but has a subtle visual effect. At least that's what I commented in the original 2003 script. 

} 

# end main loop 

ответ

1

Проблема здесь заключается в том, что ваш сценарий может попытаться прочитать из файла все, что вы хотите, но если процесс, который на самом деле записывает в файл, сбрасывается все сразу, вы собрались все вместе.

Кроме того, несколько вещей:

  • , если вы действительно хотите использовать ReadKey, вы, вероятно, следует использовать ReadMode 5, если вы не знаете CR или CR использование/LF вашего файла.

  • также проверить Term::ReadKey и вы увидите, что вы, вероятно, хотите что-то вроде ReadKey 0, $file

  • это, вероятно, лучше всего, если вы уронили Term :: ReadKey полностью и использовать File::Tail вместо зацикливания над добавленными символами по одному

  • Ваш последний код, скорее всего, будет тем, что проходит через массив символов, как вы уже пытались сделать.

+0

Интересные идеи, но я не получил ни одного из них для работы. Файл :: Tail, похоже, не помог решить проблемы времени. Пробовал все предложения Term :: ReadKey, но проблема заключается не в том, что персонажи выплевывают все сразу; когда я читаю из дескриптора файла, персонажи вообще не выплюнули. Пробовал обычный файл, а также fifo. – artistwhocodes