当从git钩子调用时,stdin read_line不等待用户输入

时间:2015-09-19 08:11:42

标签: rust githooks tty

我是一个绝对的Rust初学者,试图构建一个简单的确认函数(是或否),但我不能让用户输入任何东西,该函数只是保持循环而不等待用户输入:

""
""
""
etc.  

是以下简化版的结果。

use std::process;
use std::io;

pub fn confirm() {
  loop {
    let mut answer = String::new();

    io::stdin().read_line(&mut answer)
      .ok()
      .expect("Failed to read line");

    println!("{:?}", answer);
  }
}

我已经围绕guessing game示例构建了我的函数,我的程序的其余部分没有做任何事情,只是读取文件和打印文本。

也许是因为我的程序(git hook)的启动方式?

2 个答案:

答案 0 :(得分:3)

假设问题是您的git提交挂钩正在non-interactive environment中运行,您可以按照该问题中列出的建议直接打开/dev/tty。与STDIN不同,我们不把它当作一个神奇的全局变量,而是将它传递到我们需要的地方:

use std::io::{self, BufRead, BufReader};
use std::fs::File;

type Tty = BufReader<File>;

fn open_tty() -> io::Result<Tty> {
    let f = try!(File::open("/dev/tty"));
    Ok(BufReader::new(f))
}

fn confirm(tty: &mut Tty) -> io::Result<String> {
    let mut answer = String::new();
    try!(tty.read_line(&mut answer));
    Ok(answer)
}

fn inner_main() -> io::Result<()> {
    let mut tty = try!(open_tty());
    let answer = try!(confirm(&mut tty));

    println!("The answer was: {}", answer);

    Ok(())
}

fn main() {
    inner_main().unwrap()
}

注意这不会与平台无关。具体来说,这不太可能在Windows上运行!

我也继续前进并允许io::Result在整个程序中传播,只在最外层的炮弹恐慌。

答案 1 :(得分:2)

您是否正在Rust Playground上测试该功能?在终端中运行该程序似乎工作正常。话虽如此,stdin会阻止无保证,但你可以改变函数来检查字符串是否为空,只有在它不存在时才返回。

use std::io;

fn main() {
    println!("{:?}", confirm());
}

fn confirm() -> String {
    loop {
        let mut answer = String::new();

        io::stdin().read_line(&mut answer)
                   .ok()
                   .expect("Failed to read line");

        if !answer.is_empty() && answer != "\n" && answer != "\r\n" {
            return answer
        }
    }
}