* This is useful in modules where HTTP API calls are made. Updating them every second is expensive, network intensive and can cause rate limits to be hit * Added get_name() function to modules for easier debug statements
190 lines
6.7 KiB
Rust
190 lines
6.7 KiB
Rust
use std::str;
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
use clap::Parser;
|
|
use crate::common::UpdateResult;
|
|
|
|
// Common utilities/types
|
|
mod common;
|
|
// Bar Modules
|
|
mod bar_modules;
|
|
|
|
// Commandline parsing
|
|
#[derive(Parser, Debug)]
|
|
#[command(name = "unibar")]
|
|
#[command(version = "1.0")]
|
|
#[command(about = "Get string of info for a status bar")]
|
|
#[command(about, long_about = "A tool that returns variety of components in a string
|
|
suitable to use in a status bar")]
|
|
struct CommandlineArgs {
|
|
/// Update interval in seconds
|
|
#[arg(short = 'i', long, default_value = "1")]
|
|
interval: u64,
|
|
|
|
/// Name of the weather station
|
|
#[arg(short = 's', long, default_value = "khio")]
|
|
weather_station: String,
|
|
|
|
/// Use Metric units in weather data. Imperial units otherwise
|
|
#[arg(short = 'm', long)]
|
|
weather_metric: bool,
|
|
|
|
/// Show music progess
|
|
#[arg(short = 'p', long)]
|
|
music_progress: bool,
|
|
|
|
/// Show verbose debug information during run
|
|
#[arg(short = 'D', long)]
|
|
debug: bool,
|
|
|
|
/// Show module debug information after all modules are evaluated
|
|
/// but before output is printed
|
|
#[arg(short = 'M', long)]
|
|
debug_modules: bool,
|
|
|
|
/// Show module debug information after all modules are evaluated
|
|
/// but before output is printed
|
|
#[arg(short = 'U', long)]
|
|
debug_update: bool,
|
|
}
|
|
|
|
//
|
|
// Application (Unibar)
|
|
//
|
|
//#[derive(Clone)]
|
|
struct Unibar {
|
|
opts: common::AppOptions,
|
|
bar_modules_enabled: Vec<Box<dyn bar_modules::BarModuleActions>>,
|
|
debug_modules_done: bool,
|
|
}
|
|
|
|
impl Unibar {
|
|
// --------------------
|
|
fn run(&mut self) {
|
|
if self.opts.debug {
|
|
self.debug_msg("Debugging ...");
|
|
}
|
|
self.check_options();
|
|
|
|
// Set up a list of all modules to be used
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_power::UnibarModulePower::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_date::UnibarModuleDate::new(self.opts.clone())));
|
|
self.bar_modules_enabled.push(Box::new(bar_modules::bar_module_time::UnibarModuleTime::new(self.opts.clone())));
|
|
|
|
// Run in a forever-loop ...
|
|
loop {
|
|
// ... to update the bar contents ...
|
|
self.update_bar_contents();
|
|
// ... at specfied interval
|
|
thread::sleep(Duration::from_millis(self.opts.interval * 1000));
|
|
}
|
|
|
|
}
|
|
|
|
// --------------------
|
|
fn update_bar_contents(&mut self) {
|
|
// Get module's part to be displayed in the bar
|
|
let mut parts = Vec::new();
|
|
for md in &mut self.bar_modules_enabled {
|
|
let mut mod_parts = Vec::new();
|
|
|
|
// Each bar module implements following 4 steps:
|
|
// * Clear data from previous iteration
|
|
// * Generate raw data with pertinent information
|
|
// * Return a unicode icon to be displayed
|
|
// * Return a String content to be displayed after the icon
|
|
//
|
|
// Following generates ICON+CONTENT string for a module to be displayed
|
|
// in the bar
|
|
match md.should_update() {
|
|
UpdateResult::Update => {
|
|
md.clear();
|
|
md.generate_data();
|
|
}
|
|
UpdateResult::Skip => {
|
|
if self.opts.debug_update {
|
|
println!("Skipping module {}", md.get_name());
|
|
}
|
|
}
|
|
}
|
|
mod_parts.push(md.get_icon());
|
|
mod_parts.push(md.get_content());
|
|
|
|
parts.push(mod_parts.join(" "));
|
|
}
|
|
|
|
self.show_module_debug();
|
|
|
|
// Print parts provided by each module
|
|
println!("status {}", parts.join(" "));
|
|
}
|
|
|
|
// --------------------
|
|
fn show_module_debug(&mut self) {
|
|
// Show module debug information if enabled
|
|
if self.opts.debug_modules {
|
|
if !self.debug_modules_done {
|
|
let bar_modules_debugged: Vec<Box<dyn bar_modules::BarModuleDebug>> = vec! [
|
|
Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_power::UnibarModulePower::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_date::UnibarModuleDate::new(self.opts.clone())),
|
|
Box::new(bar_modules::bar_module_time::UnibarModuleTime::new(self.opts.clone())),
|
|
];
|
|
for md in bar_modules_debugged {
|
|
md.post_debug();
|
|
}
|
|
self.debug_modules_done = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------
|
|
fn check_options(&self) -> bool {
|
|
let all_good = true;
|
|
|
|
// If there are option checks to be added, make all_good a
|
|
// mutable var and update its status
|
|
|
|
return all_good;
|
|
}
|
|
|
|
// --------------------
|
|
fn debug_msg(&self, msg: &str) {
|
|
println!("[Debug ] -----> {}", msg);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Entry point
|
|
//
|
|
fn main() {
|
|
let cmd_args = CommandlineArgs::parse();
|
|
let mut app = Unibar {
|
|
opts: common::AppOptions {
|
|
interval: cmd_args.interval as u64,
|
|
weather_units: if cmd_args.weather_metric { common::TemperatureUnits::Metric }
|
|
else { common::TemperatureUnits::Imperial },
|
|
weather_station: cmd_args.weather_station,
|
|
music_progress: cmd_args.music_progress,
|
|
debug: cmd_args.debug,
|
|
debug_modules: cmd_args.debug_modules,
|
|
debug_update: cmd_args.debug_update,
|
|
},
|
|
bar_modules_enabled: Vec::new(),
|
|
debug_modules_done: false,
|
|
};
|
|
|
|
app.run();
|
|
}
|
|
// References:
|
|
// https://reintech.io/blog/working-with-json-in-rust
|