aboutsummaryrefslogtreecommitdiffstats
path: root/crates/termsize/src
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-02-16 10:10:07 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-02-16 10:10:07 +0100
commit9da970f1f44f19432680e255f91f73fbb8fbe3c8 (patch)
tree7bf2e5ded6d81b4ae76a080eaa5f80418343a5a9 /crates/termsize/src
parentrefactor(treewide): Remove all references of the now obsolete update_raw.py (diff)
downloadyt-9da970f1f44f19432680e255f91f73fbb8fbe3c8.zip
chore(crates/termsize): Vendor
Diffstat (limited to 'crates/termsize/src')
-rw-r--r--crates/termsize/src/lib.rs53
-rw-r--r--crates/termsize/src/nix.rs103
-rw-r--r--crates/termsize/src/other.rs14
-rw-r--r--crates/termsize/src/win.rs52
4 files changed, 222 insertions, 0 deletions
diff --git a/crates/termsize/src/lib.rs b/crates/termsize/src/lib.rs
new file mode 100644
index 0000000..e037176
--- /dev/null
+++ b/crates/termsize/src/lib.rs
@@ -0,0 +1,53 @@
+#![deny(missing_docs)]
+
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2025 softprops <d.tangren@gmail.com>
+// SPDX-License-Identifier: MIT
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+//! Termsize is a tiny crate that provides a simple
+//! interface for retrieving the current
+//! [terminal interface](http://www.manpagez.com/man/4/tty/) size
+//!
+//! ```rust
+//! extern crate termsize;
+//!
+//! termsize::get().map(|size| println!("rows {} cols {}", size.rows, size.cols));
+//! ```
+
+/// Container for number of rows and columns
+#[derive(Debug)]
+pub struct Size {
+ /// number of rows
+ pub rows: u16,
+ /// number of columns
+ pub cols: u16,
+}
+
+#[cfg(unix)]
+#[path = "nix.rs"]
+mod imp;
+
+#[cfg(windows)]
+#[path = "win.rs"]
+mod imp;
+
+#[cfg(not(any(unix, windows)))]
+#[path = "other.rs"]
+mod imp;
+
+pub use imp::get;
+
+#[cfg(test)]
+mod tests {
+ use super::get;
+ #[test]
+ fn test_get() {
+ assert!(get().is_some())
+ }
+}
diff --git a/crates/termsize/src/nix.rs b/crates/termsize/src/nix.rs
new file mode 100644
index 0000000..77fa574
--- /dev/null
+++ b/crates/termsize/src/nix.rs
@@ -0,0 +1,103 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2025 softprops <d.tangren@gmail.com>
+// SPDX-License-Identifier: MIT
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+extern crate libc;
+
+use std::io::IsTerminal;
+
+use self::{
+ super::Size,
+ libc::{c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ},
+};
+
+/// A representation of the size of the current terminal
+#[repr(C)]
+#[derive(Debug)]
+pub struct UnixSize {
+ /// number of rows
+ pub rows: c_ushort,
+ /// number of columns
+ pub cols: c_ushort,
+ x: c_ushort,
+ y: c_ushort,
+}
+
+/// Gets the current terminal size
+pub fn get() -> Option<Size> {
+ // http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
+ if !std::io::stdout().is_terminal() {
+ return None;
+ }
+ let mut us = UnixSize {
+ rows: 0,
+ cols: 0,
+ x: 0,
+ y: 0,
+ };
+ let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut us) };
+ if r == 0 {
+ Some(Size {
+ rows: us.rows,
+ cols: us.cols,
+ })
+ } else {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{super::Size, get};
+ use std::process::{Command, Output, Stdio};
+
+ #[cfg(target_os = "macos")]
+ fn stty_size() -> Output {
+ Command::new("stty")
+ .arg("-f")
+ .arg("/dev/stderr")
+ .arg("size")
+ .stderr(Stdio::inherit())
+ .output()
+ .expect("expected stty output")
+ }
+
+ #[cfg(not(target_os = "macos"))]
+ fn stty_size() -> Output {
+ Command::new("stty")
+ .arg("-F")
+ .arg("/dev/stderr")
+ .arg("size")
+ .stderr(Stdio::inherit())
+ .output()
+ .expect("expected stty output")
+ }
+
+ #[test]
+ fn test_shell() {
+ let output = stty_size();
+ assert!(output.status.success());
+ let stdout = String::from_utf8(output.stdout).expect("expected utf8");
+ let mut data = stdout.split_whitespace();
+ let rs = data
+ .next()
+ .expect("expected row")
+ .parse::<u16>()
+ .expect("expected u16 col");
+ let cs = data
+ .next()
+ .expect("expected col")
+ .parse::<u16>()
+ .expect("expected u16 col");
+ if let Some(Size { rows, cols }) = get() {
+ assert_eq!(rows, rs);
+ assert_eq!(cols, cs);
+ }
+ }
+}
diff --git a/crates/termsize/src/other.rs b/crates/termsize/src/other.rs
new file mode 100644
index 0000000..8a02f22
--- /dev/null
+++ b/crates/termsize/src/other.rs
@@ -0,0 +1,14 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2025 softprops <d.tangren@gmail.com>
+// SPDX-License-Identifier: MIT
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+/// Gets the current terminal size
+pub fn get() -> Option<super::Size> {
+ None
+}
diff --git a/crates/termsize/src/win.rs b/crates/termsize/src/win.rs
new file mode 100644
index 0000000..666a0fc
--- /dev/null
+++ b/crates/termsize/src/win.rs
@@ -0,0 +1,52 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2025 softprops <d.tangren@gmail.com>
+// SPDX-License-Identifier: MIT
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::ptr;
+
+use winapi::um::{
+ fileapi::{CreateFileA, OPEN_EXISTING},
+ handleapi::INVALID_HANDLE_VALUE,
+ wincon::{GetConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO},
+ winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE},
+};
+
+use self::super::Size;
+
+/// Gets the current terminal size
+pub fn get() -> Option<Size> {
+ // http://rosettacode.org/wiki/Terminal_control/Dimensions#Windows
+ let handle = unsafe {
+ CreateFileA(
+ b"CONOUT$\0".as_ptr() as *const i8,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ ptr::null_mut(),
+ OPEN_EXISTING,
+ 0,
+ ptr::null_mut(),
+ )
+ };
+ if handle == INVALID_HANDLE_VALUE {
+ return None;
+ }
+ let info = unsafe {
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
+ let mut info = ::std::mem::MaybeUninit::<CONSOLE_SCREEN_BUFFER_INFO>::uninit();
+ if GetConsoleScreenBufferInfo(handle, info.as_mut_ptr()) == 0 {
+ None
+ } else {
+ Some(info.assume_init())
+ }
+ };
+ info.map(|inf| Size {
+ rows: (inf.srWindow.Bottom - inf.srWindow.Top + 1) as u16,
+ cols: (inf.srWindow.Right - inf.srWindow.Left + 1) as u16,
+ })
+}