From 1c7d85aee060c30a4b424eb81e1909fe544d7c47 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 1 Aug 2023 12:57:12 +0100 Subject: [PATCH] Breaking change rework of `WithTitle` to allow for user-specified outputs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for termprogress's current commit: Curse − 凶 --- Cargo.toml | 2 +- src/inter.rs | 26 +++++++++++++--- src/progress.rs | 81 ++++++++++++++++++++++++++++++++++--------------- src/silent.rs | 19 ++++++++++-- src/spinner.rs | 14 +++++++-- 5 files changed, 108 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6187b1d..6a7a612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "termprogress" description = "A terminal progress bar renderer with status and spinners" license = "GPL-3.0-or-later" -version = "0.3.4" +version = "1.0.0" authors = ["Avril "] edition = "2018" diff --git a/src/inter.rs b/src/inter.rs index 1498e52..a177c9c 100644 --- a/src/inter.rs +++ b/src/inter.rs @@ -46,7 +46,17 @@ pub trait Spinner: Display /// A trait for creating a progress bar or spinner with a title. pub trait WithTitle: Sized + Display { - fn with_title(len: usize, string: impl AsRef) -> Self; + /// Add a title to this indicator. + #[inline] + fn with_title(mut self, string: impl AsRef) -> Self + { + self.add_title(string); + self + } + + /// Add a title to this indicator. + fn add_title(&mut self, string: impl AsRef); + fn update(&mut self); fn complete(self); } @@ -54,9 +64,13 @@ pub trait WithTitle: Sized + Display impl WithTitle for Box where T: WithTitle + ?Sized { - fn with_title(len: usize, string: impl AsRef) -> Self + /*fn with_title(len: usize, string: impl AsRef) -> Self { - Box::new(T::with_title(len, string)) + Box::new(T::with_title(len, string)) +}*/ + + fn add_title(&mut self, string: impl AsRef) { + (*self).add_title(string.as_ref()) } fn update(&mut self) { @@ -180,9 +194,13 @@ where T: Spinner + ?Sized impl WithTitle for ! { - #[inline] fn with_title(_: usize, _: impl AsRef) -> Self + #[inline] fn with_title(mut self, _: impl AsRef) -> Self { unreachable!() + } + #[inline] fn add_title(&mut self, _: impl AsRef) + { + } #[inline] fn update(&mut self) { diff --git a/src/progress.rs b/src/progress.rs index 242592c..b89db97 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -23,8 +23,9 @@ use std::{ /// # How it looks /// 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/* //TODO: Implement this after try_new(), WINCH, etc*/ +pub struct Bar //TODO: Implement this after try_new(), WINCH, etc { width: usize, max_width: usize, @@ -33,7 +34,7 @@ pub struct Bar/* //TODO: Implement this after try_new(), title: String, #[cfg(feature="size")] fit_to_term: bool, - //output_to: T + output: T } /// The default size of the terminal bar when the programmer does not provide her own. @@ -44,35 +45,41 @@ pub const DEFAULT_SIZE: usize = 50; /// Or if `size` is not used. pub const DEFAULT_MAX_BORDER_SIZE: usize = 20; -impl/**/ Default for Bar/**/ +impl Default for Bar { #[inline] fn default() -> Self { - Self::new(DEFAULT_SIZE) + Self::new(T::default(), 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 + pub fn with_title(output: impl Into, width: usize, title: impl AsRef) -> Self { - let mut this = Self::new(width); + let mut this = Self::new(output, width); this.set_title(title.as_ref()); this.update(); this } + + #[inline] fn add_title(&mut self, title: &str) + { + self.set_title(title); + self.update() + } /// 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 + pub fn try_new_with_title(output: impl Into, 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); + let mut o = Self::with_max(output.into(), if width < tw {width} else {tw}, tw); o.set_title(title.as_ref()); o.fit_to_term = true; o.update(); @@ -93,24 +100,24 @@ impl/**/ Bar/**/ /// /// 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 + pub fn new(output: impl Into, width: usize) -> Self { #[cfg(feature="size")] return { if let Some((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); + let mut o = Self::with_max(output.into(), if width < tw {width} else {tw}, tw); o.fit_to_term = true; o } else { - let mut o = Self::with_max(width, width + DEFAULT_MAX_BORDER_SIZE); + let mut o = Self::with_max(output.into(), width, width + DEFAULT_MAX_BORDER_SIZE); o.fit_to_term = true; o } }; #[cfg(not(feature="size"))] return { - Self::with_max(width, width +DEFAULT_MAX_BORDER_SIZE) + Self::with_max(output.into(), width, width +DEFAULT_MAX_BORDER_SIZE) }; } @@ -118,11 +125,11 @@ impl/**/ Bar/**/ /// /// If `stdout` is not a terminal, then `None` is returned. #[cfg(feature="size")] - pub fn try_new(width: usize) -> Option + pub fn try_new(output: impl Into, 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); + let mut o = Self::with_max(output, if width < tw {width} else {tw}, tw); o.fit_to_term = true; Some(o) } @@ -132,16 +139,16 @@ impl/**/ Bar/**/ /// If `stdout` is not a terminal, then `None` is returned. #[cfg(feature="size")] #[inline] - pub fn try_new_default_size() -> Option + pub fn try_new_default_size(to: impl Into) -> Option { - Self::try_new(DEFAULT_SIZE) + Self::try_new(to, DEFAULT_SIZE) } /// Create a bar with a max display width /// /// # Panics /// If `width` is larger than or equal to `max_width`. - pub fn with_max(width: usize, max_width: usize) -> Self + pub fn with_max(output: T, width: usize, max_width: usize) -> Self { let mut this = Self { width, @@ -151,12 +158,16 @@ impl/**/ Bar/**/ title: String::with_capacity(max_width - width), #[cfg(feature="size")] fit_to_term: false, - /*output_to: io::stdout(),*/ + output }; this.update(); this } +} + +impl Bar { + /// Fit to terminal's width if possible. /// /// # Notes @@ -254,7 +265,7 @@ fn ensure_lower(input: String, to: usize) -> String } } -impl Display for Bar +impl Display for Bar { fn refresh(&self) { @@ -293,7 +304,7 @@ impl Display for Bar } } -impl ProgressBar for Bar +impl ProgressBar for Bar { fn get_progress(&self) -> f64 { @@ -309,11 +320,11 @@ impl ProgressBar for Bar } } -impl WithTitle for Bar +impl WithTitle for Bar { - fn with_title(len: usize, string: impl AsRef) -> Self + fn add_title(&mut self, string: impl AsRef) { - Self::with_title(len, string) + (*self).add_title(string.as_ref()) } fn update(&mut self) { @@ -324,3 +335,25 @@ impl WithTitle for Bar self.complete(); } } + +const _:() = { + const fn declval() -> Bar { + unreachable!() + } + fn take_title(_: &(impl WithTitle + ?Sized)) {} + fn take_progress(_: &(impl ProgressBar + ?Sized)) {} + fn take_display(_: &(impl Display + ?Sized)) {} + fn test() + { + #[macro_export] macro_rules! assert_is_bar { + ($ty:path) => { + take_title(&declval::<$ty>()); + take_progress(&declval::<$ty>()); + take_display(&declval::<$ty>()); + } + } + + assert_is_bar!(io::Stdout); + assert_is_bar!(std::fs::File); + } +}; diff --git a/src/silent.rs b/src/silent.rs index 9c4cace..1fd1621 100644 --- a/src/silent.rs +++ b/src/silent.rs @@ -35,7 +35,8 @@ impl Spinner for Silent impl WithTitle for Silent { - #[inline] fn with_title(_: usize, _: impl AsRef) -> Self{Self} + #[inline] fn with_title(self, _: impl AsRef) -> Self{self} + #[inline] fn add_title(&mut self, _: impl AsRef) {} #[inline] fn update(&mut self) {} #[inline] fn complete(self) {} } @@ -138,16 +139,28 @@ impl Spinner for MaybeSilent impl WithTitle for MaybeSilent where T: WithTitle { - fn with_title(len: usize, string: impl AsRef) -> Self + #[inline] + fn add_title(&mut self, string: impl AsRef) { + if let Self::Loud(this) = self { + this.add_title(string); + } + } + #[inline] + fn with_title(self, string: impl AsRef) -> Self { - Self::Loud(T::with_title(len, string)) + match self { + Self::Loud(l) => Self::Loud(T::with_title(l, string)), + n => n, + } } + #[inline] fn update(&mut self) { if let Self::Loud(this) = self { this.update() } } + #[inline] fn complete(self) { if let Self::Loud(this) = self { diff --git a/src/spinner.rs b/src/spinner.rs index dabfc6d..aa5060f 100644 --- a/src/spinner.rs +++ b/src/spinner.rs @@ -125,9 +125,19 @@ impl Spinner for Spin impl WithTitle for Spin { - fn with_title(_: usize, t: impl AsRef) -> Self + #[inline] + fn with_title(self, t: impl AsRef) -> Self { - Self::with_title(t.as_ref(), Default::default()) + Self { + title: t.as_ref().to_owned(), + ..self + } + } + #[inline] + fn add_title(&mut self, t: impl AsRef) + { + self.title = t.as_ref().to_owned(); +// Self::with_title(t.as_ref(), Default::default()) } #[inline] fn update(&mut self){} #[inline] fn complete(self)