use super::*;
use std::io;
pub struct Spin<T: ?Sized = DefaultOutputDevice> {
title: String,
current: char,
chars: wheel::WheelIntoIter,
output: AtomicRefCell<T>,
}
impl Spin
{
#[inline]
pub fn with_title_default(title: &str, whl: wheel::Wheel) -> Self
{
Self::with_title(create_default_output_device(), title, whl)
}
#[inline]
pub fn new_default(whl: wheel::Wheel) -> Self
{
Self::new(create_default_output_device(), whl)
}
}
impl<T> Spin<T>
{
#[inline]
pub fn into_inner(self) -> T
{
self.output.into_inner()
}
}
impl<T: ?Sized> Spin<T>
{
#[inline]
pub fn inner_mut(&mut self) -> &mut T
{
self.output.get_mut()
}
#[inline]
pub fn inner(&self) -> Option<atomic_refcell::AtomicRef<'_, T>>
{
self.output.try_borrow().ok()
}
}
impl<T: io::Write> Spin<T>
{
pub fn with_title(output: T, title: &str, whl: wheel::Wheel) -> Self
{
let mut chars = whl.into_iter();
let current = chars.next().unwrap();
Self {
title: title.to_string(),
current,
chars,
output: AtomicRefCell::new(output)
}
}
pub fn new(output: T, whl: wheel::Wheel) -> Self
{
let mut chars = whl.into_iter();
let current = chars.next().unwrap();
Self {
title: String::new(),
current,
chars,
output: output.into()
}
}
pub fn complete(self) -> io::Result<()> {
let mut output = self.output.into_inner();
writeln!(&mut output, "{} ", (8u8 as char))
}
pub fn complete_with(self, msg: &str) -> io::Result<()>
{
let mut output = self.output.into_inner();
writeln!(&mut output, "{}{}", (8u8 as char), msg)
}
}
impl Default for Spin
{
fn default() -> Self
{
Self {
title: String::new(),
chars: wheel::Wheel::default().into_iter(),
current: '|',
output: AtomicRefCell::new(create_default_output_device())
}
}
}
impl<T: ?Sized + io::Write> Display for Spin<T>
{
fn refresh(&self)
{
let Ok(mut output) = self.output.try_borrow_mut() else { return };
let _ = write!(&mut output, "\r{} {}", self.title, self.current)
.and_then(move |_| flush!(? output));
}
fn blank(&self)
{
let Ok(mut output) = self.output.try_borrow_mut() else { return };
let _ = output.write_all(b"\r")
.and_then(|_|
stackalloc::stackalloc(self.title.chars().count(), b' ',
|spaces| output.write_all(spaces)))
.and_then(|_| write!(&mut output, " \r"))
.and_then(move |_| flush!(? output));
}
fn get_title(&self) -> &str
{
&self.title[..]
}
fn set_title(&mut self, from: &str)
{
let mut output = self.output.get_mut();
let size = self.title.chars().count();
let _ = output.write_all(b"\r")
.and_then(|_|
stackalloc::stackalloc(size, b' ',
|spaces| output.write_all(spaces)))
.and_then(|_| write!(&mut output, " \r"))
.and_then(|_| flush!(? output));
self.title = from.to_string();
let _ = write!(&mut output, "\r{} {}", self.title, self.current)
.and_then(move |_| flush!(? output));
}
fn update_dimensions(&mut self, _:usize){}
fn println(&self, string: &str)
{
self.blank();
if let Ok(mut output) = self.output.try_borrow_mut() {
let _ = writeln!(&mut output, "{}", string);
drop(output)
} else {
return;
}
self.refresh();
}
}
impl<T: ?Sized + io::Write> Spinner for Spin<T>
{
fn bump(&mut self)
{
self.current = self.chars.next().unwrap();
let mut output = self.output.get_mut();
let _ = write!(&mut output, "\r{} {}", self.title, self.current)
.and_then(move |_| flush!(? output));
}
}
impl<T: io::Write> WithTitle for Spin<T>
{
#[inline]
fn with_title(self, t: impl AsRef<str>) -> Self
{
Self {
title: t.as_ref().to_owned(),
..self
}
}
#[inline]
fn add_title(&mut self, t: impl AsRef<str>)
{
self.title = t.as_ref().to_owned();
}
#[inline] fn update(&mut self){}
#[inline] fn complete(self)
{
let _ = Spin::complete(self);
}
}