summaryrefslogtreecommitdiffstats
path: root/vendor/terminal_size/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /vendor/terminal_size/src
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/terminal_size/src')
-rw-r--r--vendor/terminal_size/src/lib.rs37
-rw-r--r--vendor/terminal_size/src/unix.rs111
-rw-r--r--vendor/terminal_size/src/windows.rs52
3 files changed, 200 insertions, 0 deletions
diff --git a/vendor/terminal_size/src/lib.rs b/vendor/terminal_size/src/lib.rs
new file mode 100644
index 000000000..e933b2140
--- /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.48.0 (2020-11-19)
+//!
+//! # 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, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Width(pub u16);
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+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 000000000..59af979d0
--- /dev/null
+++ b/vendor/terminal_size/src/unix.rs
@@ -0,0 +1,111 @@
+use super::{Height, Width};
+use std::os::unix::io::RawFd;
+use rustix::fd::BorrowedFd;
+
+/// 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(rustix::io::raw_stdout())
+}
+
+/// 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 rustix::termios::{isatty, tcgetwinsize};
+
+ // TODO: Once I/O safety is stabilized, the enlosing function here should
+ // be unsafe due to taking a `RawFd`. We should then move the main
+ // logic here into a new function which takes a `BorrowedFd` and is safe.
+ let fd = unsafe { BorrowedFd::borrow_raw(fd) };
+
+ if !isatty(fd) {
+ return None;
+ }
+
+ let winsize = tcgetwinsize(fd).ok()?;
+
+ 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 000000000..74315d6ab
--- /dev/null
+++ b/vendor/terminal_size/src/windows.rs
@@ -0,0 +1,52 @@
+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 windows_sys::Win32::System::Console::{GetStdHandle, 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 windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
+ use windows_sys::Win32::System::Console::{
+ GetConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT,
+ };
+
+ // convert between windows_sys::Win32::Foundation::HANDLE and std::os::windows::raw::HANDLE
+ let hand = handle as windows_sys::Win32::Foundation::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))
+}