aboutsummaryrefslogtreecommitdiffstats
path: root/crates/termsize/src/nix.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/termsize/src/nix.rs')
-rw-r--r--crates/termsize/src/nix.rs103
1 files changed, 103 insertions, 0 deletions
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);
+ }
+ }
+}