use std::fmt::{self, Display};
use std::time::{Duration, Instant};
pub mod plugins;
pub type StatusBar = Vec<Widget>;
pub trait Update: Display {
fn refresh(&mut self);
}
pub struct Bar(pub StatusBar);
pub struct Widget {
pub content: Box<dyn Update>,
pub intervel: Duration,
pub elapsed: Instant,
}
impl Widget {
pub fn new(content: Box<dyn Update>, intervel: u64) -> Widget {
Widget {
content,
intervel: Duration::from_secs(intervel),
elapsed: Instant::now(),
}
}
pub fn new_mili(content: Box<dyn Update>, intervel: u64) -> Widget {
Widget {
content,
intervel: Duration::from_millis(intervel),
elapsed: Instant::now(),
}
}
pub fn update(&mut self) {
if self.elapsed.elapsed() >= self.intervel {
self.content.refresh();
self.elapsed = Instant::now();
}
}
}
pub struct SubWidget(Box<dyn Update>);
impl SubWidget {
pub fn new(plugin: Box<dyn Update>) -> Box<SubWidget> {
Box::new(SubWidget(plugin))
}
fn update(&mut self) {
self.0.refresh()
}
}
pub struct Bridge(Vec<Box<SubWidget>>, Option<String>);
impl Bridge {
pub fn new(widgets: Vec<Box<SubWidget>>) -> Box<Bridge> {
Box::new(Bridge(widgets, None))
}
pub fn new_with_delim(widgets: Vec<Box<SubWidget>>) -> Box<Bridge> {
Box::new(Bridge(widgets, Some("|".to_string())))
}
pub fn new_with_custom_delim(widgets: Vec<Box<SubWidget>>, delim: &str) -> Box<Bridge> {
Box::new(Bridge(widgets, Some(delim.to_string())))
}
}
impl fmt::Display for Bridge {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut n = String::new();
if let Some(delim) = &self.1 {
for i in &self.0 {
n.push_str(format!("{} {} ", i.0, &delim).as_str());
}
for _i in delim.chars() {
n.pop();
}
} else {
for i in &self.0 {
n.push_str(format!("{} ", i.0).as_str());
}
}
n.pop();
write!(f, "{}", n)
}
}
impl Update for Bridge {
fn refresh(&mut self) {
for i in &mut self.0 {
i.update();
}
}
}
#[macro_export]
macro_rules! start_bar {
{$v:tt, $x:tt} => {
use std::process::Command;
use redblocks::Bar;
let mut bar = Bar($v);
let mut comm = Command::new("xsetroot");
loop {
let mut output = String::new();
let mut num = 0;
let count = bar.0.iter().count();
for i in &mut bar.0 {
if num == 0 {
i.update();
let pushing = format!("{}", i.content);
output.push_str(&pushing);
num += 1;
}else {
i.update();
let pushing = format!(" {} {}", $x, i.content);
output.push_str(&pushing);
}
}
let mut child = comm.args(&["-name", &output])
.spawn()
.expect("xset root not installed");
std::thread::sleep(std::time::Duration::from_millis(500));
child.kill().expect("No process to kill");
}
};
($v:ident) => {
use std::process::Command;
use redblocks::Bar;
let mut bar = Bar($v);
let mut comm = Command::new("xsetroot");
loop {
let mut output = String::new();
let mut num = 0;
let count = bar.0.iter().count();
for i in &mut bar.0 {
if num == 0 {
i.update();
let pushing = format!("{}", i.content);
output.push_str(&pushing);
num += 1;
}else {
i.update();
let pushing = format!(" | {}", i.content);
output.push_str(&pushing);
}
}
let mut child = comm.args(&["-name", &output])
.spawn()
.expect("xset root not installed");
std::thread::sleep(std::time::Duration::from_millis(500));
child.kill().expect("No process to kill");
}
};
}