1pub fn width() -> usize {
10 terminal_width().unwrap_or(80)
11}
12
13pub fn is_tty() -> bool {
15 use std::io::IsTerminal;
16 std::io::stderr().is_terminal()
17}
18
19#[cfg(unix)]
20fn terminal_width() -> Option<usize> {
21 #[repr(C)]
23 struct Winsize {
24 rows: u16,
25 cols: u16,
26 _xpixel: u16,
27 _ypixel: u16,
28 }
29
30 let ws = Winsize {
31 rows: 0,
32 cols: 0,
33 _xpixel: 0,
34 _ypixel: 0,
35 };
36 #[cfg(target_os = "macos")]
38 const TIOCGWINSZ: u64 = 0x40087468;
39 #[cfg(not(target_os = "macos"))]
40 const TIOCGWINSZ: u64 = 0x5413;
41
42 let ret = unsafe { libc_ioctl(STDERR_FILENO, TIOCGWINSZ, &ws as *const Winsize) };
43 if ret == 0 && ws.cols > 0 {
44 Some(ws.cols as usize)
45 } else {
46 None
47 }
48}
49
50#[cfg(unix)]
51extern "C" {
52 #[link_name = "ioctl"]
53 fn libc_ioctl(fd: i32, request: u64, ...) -> i32;
54}
55
56#[cfg(unix)]
57const STDERR_FILENO: i32 = 2;
58
59#[cfg(windows)]
60fn terminal_width() -> Option<usize> {
61 use windows_sys::Win32::System::Console::{
62 GetConsoleScreenBufferInfo, GetStdHandle, CONSOLE_SCREEN_BUFFER_INFO, STD_ERROR_HANDLE,
63 };
64 unsafe {
65 let handle = GetStdHandle(STD_ERROR_HANDLE);
66 if handle == 0 {
67 return None;
68 }
69 let mut info: CONSOLE_SCREEN_BUFFER_INFO = std::mem::zeroed();
70 if GetConsoleScreenBufferInfo(handle, &mut info) != 0 {
71 let w = info.srWindow.Right - info.srWindow.Left + 1;
72 if w > 0 {
73 Some(w as usize)
74 } else {
75 None
76 }
77 } else {
78 None
79 }
80 }
81}
82
83#[cfg(not(any(unix, windows)))]
84fn terminal_width() -> Option<usize> {
85 None
86}