1extern crate libc;
2extern crate atty;
3
4use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort};
5use self::libc::ioctl;
6use self::super::Size;
7
8#[repr(C)]
10#[derive(Debug)]
11pub struct UnixSize {
12 pub rows: c_ushort,
14 pub cols: c_ushort,
16 x: c_ushort,
17 y: c_ushort,
18}
19
20pub fn get() -> Option<Size> {
22 if atty::isnt(atty::Stream::Stdout) {
24 return None;
25 }
26 let us = UnixSize {
27 rows: 0,
28 cols: 0,
29 x: 0,
30 y: 0,
31 };
32 let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &us) };
33 if r == 0 {
34 Some(Size {
35 rows: us.rows,
36 cols: us.cols,
37 })
38 } else {
39 None
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::get;
46 use super::super::Size;
47 use std::process::{Command, Output, Stdio};
48
49 #[cfg(target_os = "macos")]
50 fn stty_size() -> Output {
51 Command::new("stty")
52 .arg("-f")
53 .arg("/dev/stderr")
54 .arg("size")
55 .stderr(Stdio::inherit())
56 .output()
57 .unwrap()
58 }
59
60 #[cfg(not(target_os = "macos"))]
61 fn stty_size() -> Output {
62 Command::new("stty")
63 .arg("-F")
64 .arg("/dev/stderr")
65 .arg("size")
66 .stderr(Stdio::inherit())
67 .output()
68 .unwrap()
69 }
70
71 #[test]
72 fn test_shell() {
73 let output = stty_size();
74 assert!(output.status.success());
75 let stdout = String::from_utf8(output.stdout).unwrap();
76 let mut data = stdout.split_whitespace();
77 let rs = data.next().unwrap().parse::<u16>().unwrap();
78 let cs = data.next().unwrap().parse::<u16>().unwrap();
79 if let Some(Size { rows, cols }) = get() {
80 assert_eq!(rows, rs);
81 assert_eq!(cols, cs);
82 }
83 }
84}