2022/10/07
Rustで標準入力がパイプか端末かを判定する
パイプから標準入力に渡した場合はそのまま処理し、端末から入力する場合はプロンプトを表示したくて調べた。
libcの ISATTY を使えばよい。
libc クレートか libc をラップした nix クレートでlibcの関数を叩ける。
ここでは Rust で使いやすいようにラップしてくれている nix
を使う。
nix::unistd::isatty
は指定されたファイルディスクリプタが端末を参照する場合に Ok(true)
を返すのでそこで判定する。
use std::{
error::Error,
io::{self, stdout, Write},
};
use nix::{libc::STDIN_FILENO, unistd::isatty};
fn main() -> Result<(), Box<dyn Error>> {
let mut buffer = String::new();
if let Ok(true) = isatty(STDIN_FILENO) {
print!("tty> ");
stdout().flush().unwrap();
}
let stdin = io::stdin();
stdin.read_line(&mut buffer)?;
print!("{}", buffer);
Ok(())
}
パイプから標準入力に文字列を渡すと渡した文字列がそのまま印字される。
$ echo Hello | cargo run
Hello
直接起動した際は term>
と印字され、文字列を入力して改行すると入力した文字が表示される。
$ cargo run
tty> Hello
Hello