Ruby:在 getch 上按箭头键后带有 gets 的“寄生虫”字符

Ruby: "Parasite" characters with gets after pressing arrow key on getch

提问人:Qwib 提问时间:12/9/2022 更新时间:12/13/2022 访问量:88

问:

我一直在寻找一种方法,在我的程序中实现“按任意键继续”功能,并认为我会使用 $stdin.getch。

似乎在大多数情况下都有效,但我注意到,如果我在提示按任何键时按下箭头键,下一个 get 命令将在它返回的字符串的开头有“寄生虫”字符,大概是因为箭头键给出了几个字符作为输入,只有第一个字符被 getch 读取, 其余的被保存以备下次获取。更准确地说,当我按向右箭头键时,getch 返回“\e”,下一个 get 返回带有“[C”前缀。

我想也许我必须刷新/清空 stdin 缓冲区,但 flush、iflush 和 ioflush 似乎没有任何作用。尝试在 gets 之前将 '' 写入 stdin 也不起作用。我也尝试过在 $stdin 上同步和 fsync,但它也不起作用。知道问题可能是什么吗?

Ruby IO 标准

评论

0赞 max pleaner 12/9/2022
也许你必须有一个额外的角色,如果你是第一个getch\e
0赞 Stefan 12/10/2022
某些键配置为生成多个字符。这些 ANSI 转义序列(如“光标前进”)由您的终端解释。如果您只想“清除”输入缓冲区,那么像第一个循环之后的小循环应该可以工作。如果要获取实际密钥,请参阅 stackoverflow.com/q/49541348/477037ESC [C$stdin.getch while $stdin.ready?$stdin.getch
0赞 Qwib 12/10/2022
@max 拾痂者 谢谢!成功了。我不得不连续两次(清除“[”和“C”),但除此之外,它就像一个魅力。
0赞 Qwib 12/10/2022
@Stefan是的,这也奏效了。只需要先要求 io/wait,但它似乎工作得很好。也谢谢你!

答:

0赞 Stefan 12/13/2022 #1

getch 将 IO 置于所谓的原始模式,然后读取单个字符。

但是,有些键在按下时会生成多个字符。例如,向右箭头键通常配置为生成 3 字节序列,该序列是“光标前进”的 ANSI 转义序列\e[C

现在,如果你尝试通过 来读取该序列,你只会得到 ,即第一个字符。所有后续字符(此处:和)将由下一个读取操作返回。getch\e[C

您可以手动将 stdin 置于原始模式,而不是通过 读取单个字符,并通过 readpartial 读取所有可用字符(不超过合理限制),例如:getch

$stdin.raw { |io| io.readpartial(100) }

上面在按下时返回整个序列,其行为类似于单字符键。"\e[C"getch

请注意,终端仿真器和操作系统的行为不同。以上对我来说很好,但您可能想自己在各种系统上测试该解决方案。