duplicate_finder/tty/
unix.rs1extern crate libc;
2use super::{Height, Width};
3
4#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
6fn ioctl_conv<T: Into<libc::c_ulong>>(v: T) -> libc::c_ulong {
7 v.into()
8}
9
10#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
12fn ioctl_conv<T: Copy>(v: T) -> T {
13 v
14}
15
16pub fn terminal_size() -> Option<(Width, Height)> {
20 use self::libc::{ioctl, isatty, winsize, STDOUT_FILENO, TIOCGWINSZ};
21 let is_tty: bool = unsafe { isatty(STDOUT_FILENO) == 1 };
22
23 if !is_tty {
24 return None;
25 }
26
27 let (rows, cols) = unsafe {
28 let mut winsize = winsize {
29 ws_row: 0,
30 ws_col: 0,
31 ws_xpixel: 0,
32 ws_ypixel: 0,
33 };
34 ioctl(STDOUT_FILENO, ioctl_conv(TIOCGWINSZ), &mut winsize);
35 let rows = if winsize.ws_row > 0 {
36 winsize.ws_row
37 } else {
38 0
39 };
40 let cols = if winsize.ws_col > 0 {
41 winsize.ws_col
42 } else {
43 0
44 };
45 (rows as u16, cols as u16)
46 };
47
48 if rows > 0 && cols > 0 {
49 Some((Width(cols), Height(rows)))
50 } else {
51 None
52 }
53}
54
55pub fn move_cursor_up(n: usize) -> String {
57 format!("\x1B[{}A", n)
58}
59
60#[test]
61fn compare_with_stty() {
63 use std::process::Command;
64 use std::process::Stdio;
65 let mut args = vec!["-F", "/dev/stderr", "size"];
66 if cfg!(target_os = "macos") {
67 args[0] = "-f"
68 }
69 let output = Command::new("stty")
70 .args(&args)
71 .stderr(Stdio::inherit())
72 .output()
73 .unwrap();
74 let stdout = String::from_utf8(output.stdout).unwrap();
75 assert!(output.status.success());
76
77 let mut data = stdout.split_whitespace();
79 let rows = u16::from_str_radix(data.next().unwrap(), 10).unwrap();
80 let cols = u16::from_str_radix(data.next().unwrap(), 10).unwrap();
81 println!("{}", stdout);
82 println!("{} {}", rows, cols);
83
84 if let Some((Width(w), Height(h))) = terminal_size() {
85 assert_eq!(rows, h);
86 assert_eq!(cols, w);
87 }
88}