diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/terminal_size/src | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/terminal_size/src')
-rw-r--r-- | vendor/terminal_size/src/lib.rs | 37 | ||||
-rw-r--r-- | vendor/terminal_size/src/unix.rs | 117 | ||||
-rw-r--r-- | vendor/terminal_size/src/windows.rs | 53 |
3 files changed, 207 insertions, 0 deletions
diff --git a/vendor/terminal_size/src/lib.rs b/vendor/terminal_size/src/lib.rs new file mode 100644 index 0000000..6ef79be --- /dev/null +++ b/vendor/terminal_size/src/lib.rs @@ -0,0 +1,37 @@ +//! A simple utility for getting the size of a terminal. +//! +//! Supports both Linux, MacOS, and Windows. +//! +//! This crate requires a minimum rust version of 1.31.0 (2018-12-06) +//! +//! # Example +//! +//! ``` +//! use terminal_size::{Width, Height, terminal_size}; +//! +//! let size = terminal_size(); +//! if let Some((Width(w), Height(h))) = size { +//! println!("Your terminal is {} cols wide and {} lines tall", w, h); +//! } else { +//! println!("Unable to get terminal size"); +//! } +//! ``` +//! + +#[derive(Debug)] +pub struct Width(pub u16); +#[derive(Debug)] +pub struct Height(pub u16); + +#[cfg(unix)] +mod unix; +#[cfg(unix)] +pub use crate::unix::{terminal_size, terminal_size_using_fd}; + +#[cfg(windows)] +mod windows; +#[cfg(windows)] +pub use crate::windows::{terminal_size, terminal_size_using_handle}; + +#[cfg(not(any(unix, windows)))] +pub fn terminal_size() -> Option<(Width, Height)> { None } diff --git a/vendor/terminal_size/src/unix.rs b/vendor/terminal_size/src/unix.rs new file mode 100644 index 0000000..59ac276 --- /dev/null +++ b/vendor/terminal_size/src/unix.rs @@ -0,0 +1,117 @@ +use super::{Height, Width}; +use std::os::unix::io::RawFd; + +/// Returns the size of the terminal defaulting to STDOUT, if available. +/// +/// If STDOUT is not a tty, returns `None` +pub fn terminal_size() -> Option<(Width, Height)> { + terminal_size_using_fd(libc::STDOUT_FILENO) +} + +/// Returns the size of the terminal using the given file descriptor, if available. +/// +/// If the given file descriptor is not a tty, returns `None` +pub fn terminal_size_using_fd(fd: RawFd) -> Option<(Width, Height)> { + use libc::ioctl; + use libc::isatty; + use libc::{winsize as WinSize, TIOCGWINSZ}; + let is_tty: bool = unsafe { isatty(fd) == 1 }; + + if !is_tty { + return None; + } + + let mut winsize = WinSize { + ws_row: 0, + ws_col: 0, + ws_xpixel: 0, + ws_ypixel: 0, + }; + + if unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut winsize) } == -1 { + return None; + } + + let rows = winsize.ws_row; + let cols = winsize.ws_col; + + if rows > 0 && cols > 0 { + Some((Width(cols), Height(rows))) + } else { + None + } +} + +#[test] +/// Compare with the output of `stty size` +fn compare_with_stty() { + use std::process::Command; + use std::process::Stdio; + + let (rows, cols) = if cfg!(target_os = "illumos") { + // illumos stty(1) does not accept a device argument, instead using + // stdin unconditionally: + let output = Command::new("stty") + .stdin(Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success()); + + // stdout includes the row and columns thus: "rows = 80; columns = 24;" + let vals = String::from_utf8(output.stdout) + .unwrap() + .lines() + .map(|line| { + // Split each line on semicolons to get "k = v" strings: + line.split(';') + .map(str::trim) + .map(str::to_string) + .collect::<Vec<_>>() + }) + .flatten() + .filter_map(|term| { + // split each "k = v" string and look for rows/columns: + match term.splitn(2, " = ").collect::<Vec<_>>().as_slice() { + ["rows", n] | ["columns", n] => Some(n.parse().unwrap()), + _ => None, + } + }) + .collect::<Vec<_>>(); + (vals[0], vals[1]) + } else { + let output = if cfg!(target_os = "linux") { + Command::new("stty") + .arg("size") + .arg("-F") + .arg("/dev/stderr") + .stderr(Stdio::inherit()) + .output() + .unwrap() + } else { + Command::new("stty") + .arg("-f") + .arg("/dev/stderr") + .arg("size") + .stderr(Stdio::inherit()) + .output() + .unwrap() + }; + + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout).unwrap(); + // stdout is "rows cols" + let mut data = stdout.split_whitespace(); + println!("{}", stdout); + let rows = u16::from_str_radix(data.next().unwrap(), 10).unwrap(); + let cols = u16::from_str_radix(data.next().unwrap(), 10).unwrap(); + (rows, cols) + }; + println!("{} {}", rows, cols); + + if let Some((Width(w), Height(h))) = terminal_size() { + assert_eq!(rows, h); + assert_eq!(cols, w); + } else { + panic!("terminal_size() return None"); + } +} diff --git a/vendor/terminal_size/src/windows.rs b/vendor/terminal_size/src/windows.rs new file mode 100644 index 0000000..14f487f --- /dev/null +++ b/vendor/terminal_size/src/windows.rs @@ -0,0 +1,53 @@ +use super::{Height, Width}; +use std::os::windows::io::RawHandle; + +/// Returns the size of the terminal defaulting to STDOUT, if available. +/// +/// Note that this returns the size of the actual command window, and +/// not the overall size of the command window buffer +pub fn terminal_size() -> Option<(Width, Height)> { + use winapi::um::processenv::GetStdHandle; + use winapi::um::winbase::STD_OUTPUT_HANDLE; + + let handle = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) as RawHandle }; + + terminal_size_using_handle(handle) +} + +/// Returns the size of the terminal using the given handle, if available. +/// +/// If the given handle is not a tty, returns `None` +pub fn terminal_size_using_handle(handle: RawHandle) -> Option<(Width, Height)> { + use winapi::um::handleapi::INVALID_HANDLE_VALUE; + use winapi::um::wincon::{ + GetConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT, + }; + + // convert between winapi::um::winnt::HANDLE and std::os::windows::raw::HANDLE + let hand = handle as winapi::um::winnt::HANDLE; + + if hand == INVALID_HANDLE_VALUE { + return None; + } + + let zc = COORD { X: 0, Y: 0 }; + let mut csbi = CONSOLE_SCREEN_BUFFER_INFO { + dwSize: zc, + dwCursorPosition: zc, + wAttributes: 0, + srWindow: SMALL_RECT { + Left: 0, + Top: 0, + Right: 0, + Bottom: 0, + }, + dwMaximumWindowSize: zc, + }; + if unsafe { GetConsoleScreenBufferInfo(hand, &mut csbi) } == 0 { + return None; + } + + let w: Width = Width((csbi.srWindow.Right - csbi.srWindow.Left + 1) as u16); + let h: Height = Height((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) as u16); + Some((w, h)) +} |