From 67cde82066a1f318e7d9313b3420949a9d2316a4 Mon Sep 17 00:00:00 2001 From: KP64 Date: Wed, 12 Jul 2023 19:06:41 +0300 Subject: [PATCH] refactor: :heavy_plus_sign: Added terminal_size dependency The addition of the 'terminal_size' crate provides a cross-platform way of getting the current terminal dimensions. This allows to refactor tty.rs to a single file instead of the previously used 3 files (mod.rs, windows.rs & unix.rs). --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/context/mod.rs | 9 +++++---- src/progress.rs | 2 +- src/tty.rs | 16 ++++++++++++++++ src/tty/mod.rs | 41 ----------------------------------------- src/tty/unix.rs | 14 -------------- src/tty/windows.rs | 32 -------------------------------- 8 files changed, 34 insertions(+), 92 deletions(-) create mode 100644 src/tty.rs delete mode 100644 src/tty/mod.rs delete mode 100644 src/tty/unix.rs delete mode 100644 src/tty/windows.rs diff --git a/Cargo.lock b/Cargo.lock index 90778b58..9e60f9fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,7 @@ dependencies = [ "regex", "strip-ansi-escapes", "tempfile", + "terminal_size", "thiserror", "winapi", ] @@ -908,6 +909,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix 0.37.7", + "windows-sys 0.48.0", +] + [[package]] name = "thiserror" version = "1.0.40" diff --git a/Cargo.toml b/Cargo.toml index 31f2c53b..dfd6d96e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ indextree = "4.6.0" lscolors = { version = "0.13.0", features = ["ansi_term"] } once_cell = "1.17.0" regex = "1.7.3" +terminal_size = "0.2.6" thiserror = "1.0.40" [target.'cfg(unix)'.dependencies] diff --git a/src/context/mod.rs b/src/context/mod.rs index 948770b0..fbcfd1e2 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -1,5 +1,5 @@ use super::disk_usage::{file_size::DiskUsage, units::PrefixKind}; -use crate::tty; + use args::Reconciler; use clap::{FromArgMatches, Parser}; use color::Coloring; @@ -12,6 +12,7 @@ use regex::Regex; use std::{ borrow::Borrow, convert::From, + io::{stdin, stdout, IsTerminal}, num::NonZeroUsize, path::{Path, PathBuf}, thread::available_parallelism, @@ -206,11 +207,11 @@ pub struct Context { /* INTERNAL USAGE BELOW */ ////////////////////////// /// Is stdin in a tty? - #[clap(skip = tty::stdin_is_tty())] + #[clap(skip = stdin().is_terminal())] pub stdin_is_tty: bool, /// Is stdin in a tty? - #[clap(skip = tty::stdout_is_tty())] + #[clap(skip = stdout().is_terminal())] pub stdout_is_tty: bool, /// Restricts column width of size not including units @@ -465,7 +466,7 @@ impl Context { /// Setter for `window_width` which is set to the current terminal emulator's window width. #[inline] pub fn set_window_width(&mut self) { - self.window_width = crate::tty::get_window_width(self.stdout_is_tty); + self.window_width = crate::tty::get_window_width(); } /// Answers whether disk usage is asked to be reported in bytes. diff --git a/src/progress.rs b/src/progress.rs index 73ca59ab..ebf7bc6c 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -136,7 +136,7 @@ impl<'a> Indicator<'a> { let int_handler = move || { let _ = mailbox.try_send(Message::Finish); - tty::restore_tty(); + tty::restore(); }; ctrlc::set_handler(int_handler).expect("Failed to set interrupt handler"); diff --git a/src/tty.rs b/src/tty.rs new file mode 100644 index 00000000..6fd27af0 --- /dev/null +++ b/src/tty.rs @@ -0,0 +1,16 @@ +use crossterm::{cursor, ExecutableCommand}; +use terminal_size::terminal_size; +use std::io; + +/// Restore terminal settings. +pub fn restore() { + io::stdout() + .execute(cursor::Show) + .expect("Failed to restore cursor"); +} + +/// Attempts to get the current size of the tty's window. Returns `None` if stdout isn't tty or if +/// failed to get width. +pub fn get_window_width() -> Option { + Some(usize::from(terminal_size()?.0 .0)) +} diff --git a/src/tty/mod.rs b/src/tty/mod.rs deleted file mode 100644 index f5cd922b..00000000 --- a/src/tty/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(clippy::module_name_repetitions)] -use crossterm::{cursor, ExecutableCommand}; -use std::io::{stdin, stdout, IsTerminal}; - -#[cfg(windows)] -mod windows; - -#[cfg(unix)] -mod unix; - -/// Is stdin connected to a tty? Should be `false` if `erdtree` is on the receiving end of a -/// pipeline. -pub fn stdin_is_tty() -> bool { - stdin().is_terminal() -} - -/// Is stdout connected to a tty? Should be `false` if output is redirected to a file for example. -pub fn stdout_is_tty() -> bool { - stdout().is_terminal() -} - -/// Restore terminal settings. -pub fn restore_tty() { - stdout() - .execute(cursor::Show) - .expect("Failed to restore cursor"); -} - -/// Attempts to get the current size of the tty's window. Returns `None` if stdout isn't tty or if -/// failed to get width. -pub fn get_window_width(stdout_is_tty: bool) -> Option { - if !stdout_is_tty { - return None; - } - - #[cfg(windows)] - return unsafe { windows::win_width() }; - - #[cfg(unix)] - return unsafe { unix::win_width() }; -} diff --git a/src/tty/unix.rs b/src/tty/unix.rs deleted file mode 100644 index b1a61ed0..00000000 --- a/src/tty/unix.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::{io, mem::MaybeUninit, os::fd::AsRawFd}; - -/// Attempts to get the current width of the tty's window. Returns `None` if error. -pub(super) unsafe fn win_width() -> Option { - let mut winsize: MaybeUninit = MaybeUninit::uninit(); - let tty_fd: libc::c_int = io::stdout().as_raw_fd(); - - if libc::ioctl(tty_fd, libc::TIOCGWINSZ, winsize.as_mut_ptr()) != 0 { - return None; - } - let libc::winsize { ws_col, .. } = winsize.assume_init(); - - Some(usize::from(ws_col)) -} diff --git a/src/tty/windows.rs b/src/tty/windows.rs deleted file mode 100644 index 796236b2..00000000 --- a/src/tty/windows.rs +++ /dev/null @@ -1,32 +0,0 @@ -use winapi::um::{ - processenv::GetStdHandle, - winbase::STD_OUTPUT_HANDLE, - wincon::GetConsoleScreenBufferInfo, - wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT}, -}; - -/// Attempts to get the current width of the tty's window. Returns `None` if error. -pub(super) unsafe fn win_width() -> Option { - let null_coord = COORD { X: 0, Y: 0 }; - let null_smallrect = SMALL_RECT { - Left: 0, - Top: 0, - Right: 0, - Bottom: 0, - }; - - let stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); - - let mut console_data = CONSOLE_SCREEN_BUFFER_INFO { - dwSize: null_coord, - dwCursorPosition: null_coord, - wAttributes: 0, - srWindow: null_smallrect, - dwMaximumWindowSize: null_coord, - }; - - (GetConsoleScreenBufferInfo(stdout_handle, &mut console_data) != 0) - .then_some(console_data.srWindow.Right - console_data.srWindow.Left + 1) - .map(usize::try_from) - .and_then(Result::ok) -}