这是直接取自 ExtUtils::MakeMaker 的源代码prompt
功能。我想,有人可能会想尽一切办法来欺骗它。但在某些时候,破坏者必须拥有破坏者的所有权。
对于大多数目的来说,这应该足够了:
my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;
首先,它检查 STDIN 是否向 TTY 打开。如果是,请检查 STDOUT 是否为。如果 STDOUT 不是,则它也不能打开到文件或字符特殊文件。
Update:
IO::Prompt::Tiny 使用以下内容:
# Copied (without comments) from IO::Interactive::Tiny by Daniel Muey,
# based on IO::Interactive by Damian Conway and brian d foy
sub _is_interactive {
my ($out_handle) = ( @_, select );
return 0 if not -t $out_handle;
if ( tied(*ARGV) or defined( fileno(ARGV) ) ) {
return -t *STDIN if defined $ARGV && $ARGV eq '-';
return @ARGV > 0 && $ARGV[0] eq '-' && -t *STDIN if eof *ARGV;
return -t *ARGV;
}
else {
return -t *STDIN;
}
}
IO::Interactive::Tiny 添加了注释来解释发生了什么:
sub is_interactive {
my ($out_handle) = (@_, select); # Default to default output handle
# Not interactive if output is not to terminal...
return 0 if not -t $out_handle;
# If *ARGV is opened, we're interactive if...
if ( tied(*ARGV) or defined(fileno(ARGV)) ) { # IO::Interactive::Tiny: this is the only relavent part of Scalar::Util::openhandle() for 'openhandle *ARGV'
# ...it's currently opened to the magic '-' file
return -t *STDIN if defined $ARGV && $ARGV eq '-';
# ...it's at end-of-file and the next file is the magic '-' file
return @ARGV>0 && $ARGV[0] eq '-' && -t *STDIN if eof *ARGV;
# ...it's directly attached to the terminal
return -t *ARGV;
}
# If *ARGV isn't opened, it will be interactive if *STDIN is attached
# to a terminal.
else {
return -t *STDIN;
}
}
我已经验证了 IO::Interactive 中的逻辑与 IO::Interactive::Tiny 的逻辑相同。因此,如果您的目标是在适当的情况下进行提示,请考虑使用 IO::Prompt::Tiny。如果您的需求比 IO::Prompt::Tiny 支持的更细致,您可以使用 IO::Interactive::Tiny 来提供此特定功能。
虽然您使用自己的解决方案可能基本上是安全的,但使用这些 CPAN 模块之一的一个优点是,它们可能会得到积极维护,并且如果结果证明它们不足以达到其宣传的目的,则会收到报告和最终更新。