Term :: ReadKey,原始模式下的非阻塞读取:检测EOF? [英] Term::ReadKey, non-blocking read in raw mode: Detect EOF?

查看:242
本文介绍了Term :: ReadKey,原始模式下的非阻塞读取:检测EOF?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将东西输入我的程序时,似乎没有任何像0x4这样的字符来表示EOF。

When I pipe stuff into my program, it does not seem to get any character like 0x4 to indicate EOF.

$ echo "abc" | map 'cat'
saw a: \x61
saw b: \x62
saw c: \x63
saw
: \x0A
zzzbc
^C

我必须按Ctrl + C退出,但我'我真的不确定Ctrl + C的作用。它可能让shell向管道发送SIGINT?我不知道管道如何在该级别上工作。

I have to press Ctrl+C to quit, but I'm not really sure what the Ctrl+C is acting on. It's probably having the shell send a SIGINT to the pipeline? I don't know how pipelines work on that level.

这是我的程序 map

#!/usr/bin/env perl

use strict;
use warnings;

use IO::Pty::Easy;
use Term::ReadKey;
use Encode;

$#ARGV % 2 and die "Odd number of args required.\n";

if ($#ARGV == -1) {
    warn ("No args provided. A command must be specified.\n");
    exit 1;
}

# be sure to enter the command as a string
my %mapping = @ARGV[-@ARGV..-2];

my $interactive = -t STDIN;

# my %mapping = @ARGV;
# my @mapkeys = keys %mapping;

# warn @mapkeys;
if ($interactive) {
    print "Spawning command in pty: @ARGV\n"
    # print "\nContinue? (y/n)";
    # my $y_n;
    # while (($y_n = <STDIN>) !~ /^(y|n)$/) {
    #     print '(y/n)';
    # }
    # exit if $y_n eq "n\n";
}

my $pty = IO::Pty::Easy->new();
my $spawnret = $pty->spawn("@ARGV")."\n";

print STDERR "Spawning has failed: @ARGV\n" if !$spawnret;

ReadMode 4;
END {
    ReadMode 0; # Reset tty mode before exiting
}

my $i = undef;
my $j = 0;

{
    local $| = 1;
    while (1) {
        myread();

        # responsive to key input, and pty output may be behind by 50ms
        my $key = ReadKey(0.05);
        # last if !defined($key) || !$key;
        if (defined($key)) {
            my $code = ord($key); # this byte is...
            if ($interactive and $code == 4) {
                # User types Ctrl+D
                print STDERR "Saw ^D from term, embarking on filicide with TERM signal\n";
                $pty->kill("TERM", 0); # blocks till death of child
                myread();
                $pty->close();
                last;
            }
            printf("saw %s: \\x%02X\n", $key, $code);

            # echo translated input to pty
            if ($key eq "a") {
                $pty->write("zzz"); # print 'Saw "a", wrote "zzz" to pty';
            } else {
                $pty->write($key); # print "Wrote to pty: $key";
            }
        }
    }
}

sub myread {
    # read out pty's activity to echo to stdout
    my $from_pty = $pty->read(0);
    if (defined($from_pty)) {
        if ($from_pty) {
            # print "read from pty -->$from_pty<--\n";
            print $from_pty;
        } else {
            if ($from_pty eq '') {
                # empty means EOF means pty has exited, so I exit because my fate is sealed
                print STDERR "Got back from pty EOF, quitting\n" if $interactive;
                $pty->close();
                last;
            }
        }
    }
}

那个会解释为什么会产生zzzbc。

That would explain why it produced "zzzbc".

现在我的问题是如何获得 map 才能知道 echo abc已达到输入结束?比照 echoabc| cat 自行完成。 ReadKey似乎没有提供用于确定这种情况的API。

Now my question is how can I get map to be able to know about echo "abc" having reached the end of input? cf. echo "abc" | cat completes on its own. ReadKey does not seem to provide API for determining this situation.

同样我不知道如何做同样的事情来将EOF传递给pty中的孩子。我认为当命令要写入文件或其他内容时,这可能会导致问题,因为EOF与发送终止信号是正确写入文件而不是干净地退出之间的区别。

Similarly I am not sure how to do the same to pass along the EOF to the child in the pty. I am thinking this might cause issues when a command is to write to a file or something, because EOF vs sending a kill signal is the difference between writing the file correctly and not exiting cleanly.

推荐答案

尝试从STDIN读取而不是那个$ pty对象。你通过shell创建的管道将数据传递给你的STDIN文件描述符0,perl就是你的句柄。

Try reading from STDIN and not that $pty object. The pipe you create via the shell passes the data to your STDIN file descriptor 0, which in perl is your handle .

$ pty,我认为这是你的终端。这就是脚本挂起的原因(我猜)。

The $pty, I assume that's your terminal. That's why the script just hangs (I guess).

这篇关于Term :: ReadKey,原始模式下的非阻塞读取:检测EOF?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆