diff options
-rw-r--r-- | Cargo.lock | 11 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/context/args.rs | 20 | ||||
-rw-r--r-- | src/context/column.rs | 13 | ||||
-rw-r--r-- | src/context/config/toml/test.rs | 2 | ||||
-rw-r--r-- | src/context/error.rs | 9 | ||||
-rw-r--r-- | src/context/mod.rs | 9 | ||||
-rw-r--r-- | src/icons/mod.rs | 2 | ||||
-rw-r--r-- | src/progress.rs | 2 | ||||
-rw-r--r-- | src/tree/mod.rs | 43 | ||||
-rw-r--r-- | src/tree/node/mod.rs | 22 | ||||
-rw-r--r-- | src/tty.rs | 16 | ||||
-rw-r--r-- | src/tty/mod.rs | 41 | ||||
-rw-r--r-- | src/tty/unix.rs | 14 | ||||
-rw-r--r-- | src/tty/windows.rs | 32 |
15 files changed, 54 insertions, 183 deletions
@@ -299,6 +299,7 @@ dependencies = [ "regex", "strip-ansi-escapes", "tempfile", + "terminal_size", "thiserror", "winapi", ] @@ -909,6 +910,16 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -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/args.rs b/src/context/args.rs index 17027cc..0608a23 100644 --- a/src/context/args.rs +++ b/src/context/args.rs @@ -66,7 +66,7 @@ pub trait Reconciler: CommandFactory + FromArgMatches { let argument_source = user_args .value_source(id_str) .map_or(&config_args, |source| { - if matches!(source, ValueSource::CommandLine) { + if source == ValueSource::CommandLine { &user_args } else { &config_args @@ -112,25 +112,19 @@ fn init_empty_args() -> Vec<OsString> { /// Loads an [`ArgMatches`] from `.erdtreerc`. #[inline] fn load_rc_config_args() -> Option<ArgMatches> { - if let Some(rc_config) = config::rc::read_config_to_string() { + config::rc::read_config_to_string().map(|rc_config| { let parsed_args = config::rc::parse(&rc_config); - let config_args = Context::command().get_matches_from(parsed_args); - - return Some(config_args); - } - - None + Context::command().get_matches_from(parsed_args) + }) } /// Loads an [`ArgMatches`] from `.erdtree.toml`. #[inline] fn load_toml_config_args(named_table: Option<&str>) -> Result<Option<ArgMatches>, Error> { - if let Ok(toml_config) = config::toml::load() { + config::toml::load().map_or(Ok(None), |toml_config| { let parsed_args = config::toml::parse(toml_config, named_table)?; let config_args = Context::command().get_matches_from(parsed_args); - return Ok(Some(config_args)); - } - - Ok(None) + Ok(Some(config_args)) + }) } diff --git a/src/context/column.rs b/src/context/column.rs index 16bf5f8..c66daa4 100644 --- a/src/context/column.rs +++ b/src/context/column.rs @@ -3,6 +3,7 @@ use std::convert::From; /// Utility struct to help store maximum column widths for attributes of each node. Each width is /// measured as the number of columns of the tty's window. +#[derive(Default)] pub struct Properties { pub max_size_width: usize, pub max_size_unit_width: usize, @@ -32,18 +33,8 @@ impl From<&Context> for Properties { }; Self { - max_size_width: 0, max_size_unit_width: unit_width, - #[cfg(unix)] - max_nlink_width: 0, - #[cfg(unix)] - max_ino_width: 0, - #[cfg(unix)] - max_block_width: 0, - #[cfg(unix)] - max_owner_width: 0, - #[cfg(unix)] - max_group_width: 0, + ..Default::default() } } } diff --git a/src/context/config/toml/test.rs b/src/context/config/toml/test.rs index adba50d..368c9db 100644 --- a/src/context/config/toml/test.rs +++ b/src/context/config/toml/test.rs @@ -21,7 +21,7 @@ fn parse_toml() -> Result<(), Box<dyn std::error::Error>> { threads = 10 "#; - config_file.write(toml_contents.as_bytes())?; + config_file.write_all(toml_contents.as_bytes())?; let file = config_file .path() diff --git a/src/context/error.rs b/src/context/error.rs index 6b2e82b..89fbb74 100644 --- a/src/context/error.rs +++ b/src/context/error.rs @@ -2,7 +2,6 @@ use super::config::toml::error::Error as TomlError; use clap::{parser::MatchesError, Error as ClapError}; use ignore::Error as IgnoreError; use regex::Error as RegexError; -use std::convert::From; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -25,7 +24,7 @@ pub enum Error { PatternNotProvided, #[error("{0}")] - ConfigError(TomlError), + ConfigError(#[from] TomlError), #[error("{0}")] MatchError(#[from] MatchesError), @@ -36,9 +35,3 @@ pub enum Error { #[error("Please migrate from `erdtreerc` to `.erdtree.toml` to make use of `--config`")] Rc, } - -impl From<TomlError> for Error { - fn from(value: TomlError) -> Self { - Self::ConfigError(value) - } -} diff --git a/src/context/mod.rs b/src/context/mod.rs index 948770b..fbcfd1e 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/icons/mod.rs b/src/icons/mod.rs index 7ac580f..01e9298 100644 --- a/src/icons/mod.rs +++ b/src/icons/mod.rs @@ -13,7 +13,7 @@ pub mod fs; /// Attempts to return an icon given a file extension along with its default color code 8-bit /// value. fn icon_from_ext(ext: &OsStr) -> Option<(u8, &'static str)> { - EXT_ICON_MAP.get(ext).map(|(code, icon)| (*code, *icon)) + EXT_ICON_MAP.get(ext).copied() } /// Attempts to return an icon based on file type. diff --git a/src/progress.rs b/src/progress.rs index 73ca59a..ebf7bc6 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/tree/mod.rs b/src/tree/mod.rs index be2b7ee..f4c4845 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -207,12 +207,7 @@ impl Tree { for child_id in &children { let index = *child_id; - let is_dir = { - let arena = tree[index].get(); - arena.is_dir() - }; - - if is_dir { + if tree[index].get().is_dir() { Self::assemble_tree( tree, index, @@ -252,10 +247,6 @@ impl Tree { let dir = tree[current_node_id].get(); - #[cfg(unix)] - Self::update_column_properties(column_properties, dir, ctx); - - #[cfg(not(unix))] Self::update_column_properties(column_properties, dir, ctx); children.sort_by(|&id_a, &id_b| { @@ -321,7 +312,6 @@ impl Tree { } /// Updates [`column::Properties`] with provided [`Node`]. - #[cfg(unix)] fn update_column_properties(col_props: &mut column::Properties, node: &Node, ctx: &Context) { if let Some(file_size) = node.file_size() { if ctx.byte_metric() && ctx.human { @@ -348,6 +338,7 @@ impl Tree { }; } + #[cfg(unix)] if ctx.long { if let Some(owner) = node.owner() { let owner_len = owner.len(); @@ -390,35 +381,6 @@ impl Tree { } } } - - /// Updates [column::Properties] with provided [Node]. - #[cfg(not(unix))] - fn update_column_properties(col_props: &mut column::Properties, node: &Node, ctx: &Context) { - if let Some(file_size) = node.file_size() { - if ctx.byte_metric() && ctx.human { - let out = format!("{file_size}"); - let [size, unit]: [&str; 2] = - out.split(' ').collect::<Vec<&str>>().try_into().unwrap(); - - let file_size_cols = size.len(); - let file_size_unit_cols = unit.len(); - - if file_size_cols > col_props.max_size_width { - col_props.max_size_width = file_size_cols; - } - - if file_size_unit_cols > col_props.max_size_unit_width { - col_props.max_size_unit_width = file_size_unit_cols; - } - } else { - let file_size_cols = utils::num_integral(file_size.value()); - - if file_size_cols > col_props.max_size_width { - col_props.max_size_width = file_size_cols; - } - }; - } - } } impl TryFrom<&Context> for WalkParallel { @@ -435,6 +397,7 @@ impl TryFrom<&Context> for WalkParallel { builder .follow_links(ctx.follow) .git_ignore(!ctx.no_ignore) + .git_global(!ctx.no_ignore) .hidden(!ctx.hidden) .overrides(ctx.no_git_override()?) .same_file_system(ctx.same_fs) diff --git a/src/tree/node/mod.rs b/src/tree/node/mod.rs index cca2e9e..b010469 100644 --- a/src/tree/node/mod.rs +++ b/src/tree/node/mod.rs @@ -94,11 +94,7 @@ impl Node { let blocks = self.metadata.blocks(); - if blocks == 0 { - None - } else { - Some(blocks) - } + (blocks != 0).then_some(blocks) } /// Timestamp of when file was last modified. @@ -123,22 +119,14 @@ impl Node { /// Returns the underlying `ino` of the [`DirEntry`]. #[cfg(unix)] - pub const fn ino(&self) -> Option<u64> { - if let Some(inode) = self.inode { - Some(inode.ino) - } else { - None - } + pub fn ino(&self) -> Option<u64> { + self.inode.map(|inode| inode.ino) } /// Returns the underlying `nlink` of the [`DirEntry`]. #[cfg(unix)] - pub const fn nlink(&self) -> Option<u64> { - if let Some(inode) = self.inode { - Some(inode.nlink) - } else { - None - } + pub fn nlink(&self) -> Option<u64> { + self.inode.map(|inode| inode.nlink) } /// Returns `true` if node is a directory. diff --git a/src/tty.rs b/src/tty.rs new file mode 100644 index 0000000..6fd27af --- /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<usize> { + Some(usize::from(terminal_size()?.0 .0)) +} diff --git a/src/tty/mod.rs b/src/tty/mod.rs deleted file mode 100644 index f5cd922..0000000 --- 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<usize> { - 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 b1a61ed..0000000 --- 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<usize> { - let mut winsize: MaybeUninit<libc::winsize> = 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 796236b..0000000 --- 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<usize> { - 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) -} |