From 678483acc1150e1494faf8480a7aebc288339e36 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 1 Aug 2023 12:02:24 +0100 Subject: [PATCH] Feature `size`: Added `Bar::try_new_*()` functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bar: Changed default size(s) to constants instead of magic numbers. Fortune for termprogress's current commit: Half curse − 半凶 --- Cargo.toml | 4 +++ src/lib.rs | 21 ++++++++++++++++ src/progress.rs | 66 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 24cba95..6187b1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,12 @@ edition = "2018" [features] default = ["size"] +# Use terminal size when drawing bars. size = ["terminal_size"] +# React to `SIGWINCH` when `stdout` is a terminal (linux only.) +reactive = [] + [dependencies] terminal_size = {version = "0.1", optional = true} [build-dependencies] diff --git a/src/lib.rs b/src/lib.rs index b712bb5..4933e26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,9 @@ macro_rules! flush { } } +#[cfg(feature="size")] +use std::os::unix::io::*; + mod util; mod inter; pub use inter::*; @@ -20,6 +23,24 @@ pub mod wheel; pub mod spinner; pub mod silent; +/// Returns true if `stdout` has a terminal output and can be used with terminal size responsiveness. +/// +/// Requires `size` feature. +#[cfg(feature="size")] +pub fn has_terminal_output_default() -> bool +{ + terminal_size::terminal_size().is_some() +} + +/// Returns true if `f` has a terminal output and can be used with terminal size responsiveness. +/// +/// Requires `size` feature. +#[cfg(feature="size")] +pub fn has_terminal_output(f: &(impl AsRawFd + ?Sized)) -> bool +{ + terminal_size::terminal_size_using_fd(f.as_raw_fd()).is_some() +} + /// The prelude exposes the traits for spinners and progress bars, and the `spinner::Spin` and `progress::Bar` types for easy access and use. pub mod prelude { pub use super::inter::*; diff --git a/src/progress.rs b/src/progress.rs index 84ef52d..242592c 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -1,8 +1,9 @@ -//! Progress bar that has a size and also a max size. +///! Progress bar that has a size and also a max size. use super::*; use std::{ fmt::Write, + io, }; /// A progress bar with a size and optionally title. It implements the `ProgressBar` trait, and is the default progress bar. @@ -23,7 +24,7 @@ use std::{ /// It renders in the terminal like: /// `[========================= ]: 50% this is a title that may get cut if it reaches max le...` #[derive(Debug)] -pub struct Bar +pub struct Bar/* //TODO: Implement this after try_new(), WINCH, etc*/ { width: usize, max_width: usize, @@ -32,17 +33,27 @@ pub struct Bar title: String, #[cfg(feature="size")] fit_to_term: bool, + //output_to: T } -impl Default for Bar +/// The default size of the terminal bar when the programmer does not provide her own. +/// Or if `size` is not used. +pub const DEFAULT_SIZE: usize = 50; + +/// The default size of the max render bar when the programmer does not provide her own. +/// Or if `size` is not used. +pub const DEFAULT_MAX_BORDER_SIZE: usize = 20; + +impl/**/ Default for Bar/**/ { + #[inline] fn default() -> Self { - Self::new(50) + Self::new(DEFAULT_SIZE) } } -impl Bar +impl/**/ Bar/**/ { /// Create a new bar `width` long with a title. pub fn with_title(width: usize, title: impl AsRef) -> Self @@ -52,6 +63,21 @@ impl Bar this.update(); this } + + /// Attempt to create a new bar with max display width of our terminal and a title. + /// + /// If `stdout` is not a terminal, then `None` is returned. + #[cfg(feature="size")] + pub fn try_new_with_title(width: usize, title: impl AsRef) -> Option + { + let (terminal_size::Width(tw), _) = terminal_size::terminal_size()?; + let tw = usize::from(tw); + let mut o = Self::with_max(if width < tw {width} else {tw}, tw); + o.set_title(title.as_ref()); + o.fit_to_term = true; + o.update(); + Some(o) + } #[inline] fn autofit(&mut self) @@ -64,6 +90,8 @@ impl Bar /// /// # Notes /// Without feature `size`, will be the same as `Self::with_max(width, width +20)` + /// + /// To try to create one that always adheres to `size`, use the `try_new()` family of functions. #[cfg_attr(not(feature="size"), inline)] pub fn new(width: usize) -> Self { @@ -75,16 +103,40 @@ impl Bar o.fit_to_term = true; o } else { - let mut o = Self::with_max(width, width +20); + let mut o = Self::with_max(width, width + DEFAULT_MAX_BORDER_SIZE); o.fit_to_term = true; o } }; #[cfg(not(feature="size"))] return { - Self::with_max(width, width +20) + Self::with_max(width, width +DEFAULT_MAX_BORDER_SIZE) }; } + + /// Attempt to create a new bar with max display width of our terminal. + /// + /// If `stdout` is not a terminal, then `None` is returned. + #[cfg(feature="size")] + pub fn try_new(width: usize) -> Option + { + let (terminal_size::Width(tw), _) = terminal_size::terminal_size()?; + let tw = usize::from(tw); + let mut o = Self::with_max(if width < tw {width} else {tw}, tw); + o.fit_to_term = true; + Some(o) + } + + /// Attempt to create a new bar with max display width of our terminal. + /// + /// If `stdout` is not a terminal, then `None` is returned. + #[cfg(feature="size")] + #[inline] + pub fn try_new_default_size() -> Option + { + Self::try_new(DEFAULT_SIZE) + } + /// Create a bar with a max display width /// /// # Panics