added MaybeSilent, improved trait impls

master
Avril 4 years ago
parent 3497125383
commit 8d826ac3ad
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -2,7 +2,7 @@
name = "termprogress" name = "termprogress"
description = "A terminal progress bar renderer with status and spinners" description = "A terminal progress bar renderer with status and spinners"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
version = "0.2.4" version = "0.3.4"
authors = ["Avril <flanchan@cumallover.me>"] authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018" edition = "2018"
@ -14,4 +14,7 @@ default = ["size"]
size = ["terminal_size"] size = ["terminal_size"]
[dependencies] [dependencies]
terminal_size = {version = "0.1", optional = true} terminal_size = {version = "0.1", optional = true}
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,24 @@
extern crate rustc_version;
use rustc_version::{version, version_meta, Channel};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=stable");
}
Channel::Beta => {
println!("cargo:rustc-cfg=beta");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=nightly");
}
Channel::Dev => {
println!("cargo:rustc-cfg=dev");
}
}
}

@ -51,3 +51,147 @@ pub trait WithTitle: Sized + Display
fn complete(self); fn complete(self);
} }
impl<T> WithTitle for Box<T>
where T: WithTitle + ?Sized
{
fn with_title(len: usize, string: impl AsRef<str>) -> Self
{
Box::new(T::with_title(len, string))
}
fn update(&mut self)
{
self.as_mut().update()
}
fn complete(self)
{
(*self).complete()
}
}
impl<T> Display for Box<T>
where T: Display + ?Sized
{
#[inline] fn refresh(&self)
{
self.as_ref().refresh();
}
#[inline] fn blank(&self)
{
self.as_ref().blank();
}
#[inline] fn println(&self, string: &str)
{
self.as_ref().println(string);
}
#[inline] fn eprintln(&self, string: &str)
{
self.as_ref().eprintln(string);
}
#[inline] fn get_title(&self) -> &str
{
self.as_ref().get_title()
}
#[inline] fn set_title(&mut self, from: &str)
{
self.as_mut().set_title(from);
}
#[inline] fn update_dimensions(&mut self, to: usize)
{
self.as_mut().update_dimensions(to);
}
}
impl<T> ProgressBar for Box<T>
where T: ProgressBar + ?Sized
{
#[inline] fn set_progress(&mut self, value: f64)
{
self.as_mut().set_progress(value)
}
#[inline] fn get_progress(&self) -> f64
{
self.as_ref().get_progress()
}
}
impl<T> Spinner for Box<T>
where T: Spinner + ?Sized
{
#[inline] fn bump(&mut self)
{
self.as_mut().bump()
}
}
#[cfg(nightly)] mod never
{
use super::*;
impl Display for !
{
#[inline] fn refresh(&self)
{
}
#[inline] fn blank(&self)
{
}
#[inline] fn println(&self, _: &str)
{
}
#[inline] fn eprintln(&self, _: &str)
{
}
#[inline] fn get_title(&self) -> &str
{
*self
}
#[inline] fn set_title(&mut self, _: &str)
{
}
#[inline] fn update_dimensions(&mut self, _: usize)
{
}
}
impl ProgressBar for !
{
#[inline] fn set_progress(&mut self, _: f64)
{
}
#[inline] fn get_progress(&self) -> f64
{
*self
}
}
impl Spinner for !
{
#[inline] fn bump(&mut self){}
}
impl WithTitle for !
{
#[inline] fn with_title(_: usize, _: impl AsRef<str>) -> Self
{
unreachable!()
}
#[inline] fn update(&mut self)
{
}
#[inline] fn complete(self)
{
}
}
}
#[cfg(nightly)] pub use never::*;

@ -1,3 +1,5 @@
#![cfg_attr(nightly, feature(never_type))]
#![allow(dead_code)] #![allow(dead_code)]
macro_rules! flush { macro_rules! flush {

@ -40,3 +40,280 @@ impl WithTitle for Silent
#[inline] fn complete(self) {} #[inline] fn complete(self) {}
} }
/// An enum wrapper for a progress bar or spinner that might be silent.
#[derive(Debug)]
pub enum MaybeSilent<T>
{
/// There is no progress
Silent,
/// There is progress
Loud(T),
}
impl<T> Display for MaybeSilent<T>
where T: Display
{
fn refresh(&self)
{
if let Self::Loud(this) = self {
this.refresh();
}
}
fn blank(&self)
{
if let Self::Loud(this) = self {
this.blank();
}
}
fn println(&self, string: &str)
{
if let Self::Loud(this) = self {
this.println(string);
}
}
fn eprintln(&self, string: &str)
{
if let Self::Loud(this) = self {
this.eprintln(string)
}
}
fn get_title(&self) -> &str
{
if let Self::Loud(this) = self {
this.get_title()
} else {
""
}
}
fn set_title(&mut self, from: &str)
{
if let Self::Loud(this) = self {
this.set_title(from);
}
}
fn update_dimensions(&mut self, to: usize)
{
if let Self::Loud(this) = self {
this.update_dimensions(to)
}
}
}
impl<T> ProgressBar for MaybeSilent<T>
where T: ProgressBar
{
fn set_progress(&mut self, value: f64)
{
if let Self::Loud(this) = self {
this.set_progress(value)
}
}
fn get_progress(&self) -> f64
{
if let Self::Loud(this) = self {
this.get_progress()
} else {
0.0
}
}
}
impl<T> Spinner for MaybeSilent<T>
where T: Spinner
{
fn bump(&mut self)
{
if let Self::Loud(this) = self {
this.bump()
}
}
}
/// A trait for creating a progress bar or spinner with a title.
impl<T> WithTitle for MaybeSilent<T>
where T: WithTitle
{
fn with_title(len: usize, string: impl AsRef<str>) -> Self
{
Self::Loud(T::with_title(len, string))
}
fn update(&mut self)
{
if let Self::Loud(this) = self {
this.update()
}
}
fn complete(self)
{
if let Self::Loud(this) = self {
this.complete()
}
}
}
impl<T> From<Option<T>> for MaybeSilent<T>
{
#[inline] fn from(from: Option<T>) -> Self
{
match from {
Some(from) => Self::Loud(from),
None => Self::Silent,
}
}
}
impl<T> From<MaybeSilent<T>> for Option<T>
{
fn from(from: MaybeSilent<T>) -> Self
{
match from {
MaybeSilent::Loud(loud) => Some(loud),
_ => None,
}
}
}
/// Return a `MaybeSilent` that is always silent
#[cfg(nightly)]
pub const fn always() -> MaybeSilent<!>
{
MaybeSilent::Silent
}
/// Return a `MaybeSilent` that is always silent
#[cfg(not(nightly))]
pub const fn always() -> MaybeSilent<Silent>
{
MaybeSilent::Silent
}
impl<T> MaybeSilent<T>
{
/// Is this the not silent variant?
#[inline] pub fn is_loud(&self) -> bool
{
!self.is_silent()
}
/// Is this the silent variant?
#[inline] pub fn is_silent(&self) -> bool
{
if let Self::Silent = self {
true
} else {
false
}
}
/// Create a new `MaybeSilent` with a value.
pub const fn new_some(value: T) -> Self
{
Self::Loud(value)
}
/// Create a new `MaybeSilent` with a potential value
#[inline] pub fn new<U>(from: U) -> Self
where U: Into<Option<T>>
{
match from.into() {
Some(x) => Self::Loud(x),
_ => Self::Silent,
}
}
/// Get a reference to the inner type if possible
pub fn as_ref(&self) -> Option<&T>
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a mutable reference to the inner type if possible
pub fn as_mut(&mut self) -> Option<&mut T>
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a dynamic mutable reference to the internal value if it is `Display`.
pub fn as_display_mut(&mut self) -> Option<&mut (dyn Display + 'static)>
where T: Display + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Consume this instance and return the inner value if possible
#[inline] pub fn into_inner(self) -> Option<T>
{
self.into()
}
/// Consume this instance and return silent if it had no value
#[inline] pub fn into_silent(self) -> Option<Silent>
{
match self {
Self::Silent => Some(Silent),
_ => None
}
}
/// Get a dynamic mutable reference to the internal value if it is `ProgressBar`
pub fn as_bar_mut(&mut self) -> Option<&mut (dyn ProgressBar + 'static)>
where T: ProgressBar + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a dynamic mutable reference to the internal value if it is `Spinner`.
pub fn as_spinner_mut(&mut self) -> Option<&mut (dyn Spinner + 'static)>
where T: Spinner + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a dynamic reference to the internal value if it is `Display`.
pub fn as_display(&self) -> Option<&(dyn Display + 'static)>
where T: Display + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a dynamic reference to the internal value if it is `ProgressBar`
pub fn as_bar(&self) -> Option<&(dyn ProgressBar + 'static)>
where T: ProgressBar + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
/// Get a dynamic reference to the internal value if it is `Spinner`.
pub fn as_spinner(&self) -> Option<&(dyn Spinner + 'static)>
where T: Spinner + 'static
{
match self {
Self::Loud(loud) => Some(loud),
_ => None
}
}
}

Loading…
Cancel
Save