阅读用户输入时如何避免回显换行符?

时间:2011-08-14 13:51:15

标签: ruby

我正在用Ruby写一个类似curses的程序,我正在使用stty和ansi转义字符来实现我想要的。当我想获得用户输入时,我的问题就出现了。像许多基于控制台的程序一样,我希望从终端的底部获得用户输入。

因此,我将光标放在屏幕的底部并调用Readline.readline(或任何方法来获取用户输入)。像往常一样,它会读取所有内容,直到我返回,并打印换行符。由于光标位于终端的最后一行,它会滚动一行,这会弄乱屏幕。

我该如何避免这种情况?我试图用stty来阻止新行的回应,但我没有成功。也许可以使用stty来阻止终端滚动?当然,我可以编写自己的方法来捕获输入,一次读取一个字符(并捕获“返回”),但我想使用readline提供的所有额外内容。

1 个答案:

答案 0 :(得分:1)

Ruby Readline是GNU Readline库的一个简单包装器,它直接管理终端模式 - 这就是为什么使用stty修改终端设置可能没什么好运的原因。 Readline.readline方法专门将终端置于原始模式,并将所有字符回送到STDOUT(或者Ruby 1.9的Readline.output,默认为STDOUT)。

不幸的是,Ruby Readline包装器完全包装GNU Readline库; GNU Readline为redisplay提供了许多函数,但Ruby Readline包装器不公开这些函数。

如果您特别想使用Readline和Ruby并且需要忽略该换行符,那么您没有大量的选择。一个选项,有点愚蠢,是打开一个管道作为中介,监听自己的线程,并将所有Readline输出转发给它。以下是完成此操作,但请注意,这不是您真正想要的(并且在OSX上它需要ruby 1.9.2链接到readline而不是libedit,因为libedit阻塞了)....

require 'readline'

`mkfifo /tmp/readline-pipe`

Readline.output = File.open("/tmp/readline-pipe", "w+")

Thread.new {
  input = open("/tmp/readline-pipe", "r+")
  while true
    character = input.getc
    if character != "\n"
      $stdout.write(character)
      $stdout.flush
    end
  end
}

begin
  while line = Readline.readline("", true)
    $stdout.write(" NEWLINE ENTERED BUT NOT DISPLAYED ")
    $stdout.flush
  end
rescue EOFError
  puts "Exiting..."
end