diff --git a/src/date.rs b/src/date.rs deleted file mode 100644 index 3254c11..0000000 --- a/src/date.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::load_config::Settings; -use chrono::prelude::*; - -pub fn fmt_date(setting: &Settings) -> String { - let now = Local::now(); - - format!( - " {} {} {}", - setting.time.icon, - now.format(&setting.time.format), - setting.seperator - ) -} diff --git a/src/disk.rs b/src/disk.rs deleted file mode 100644 index 3c5db62..0000000 --- a/src/disk.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::load_config::Settings; -use std::process::Command; - -pub fn disk_free(setting: &Settings) -> String { - let cmd = Command::new("sh") - .arg("-c") - .args(&["df -h"]) - .output() - .unwrap(); - let output = String::from_utf8_lossy(&cmd.stdout); - let mut disk_used = String::new(); - for line in output.lines() { - if line.ends_with('/') { - let splited = line.split_whitespace().collect::>(); - disk_used = splited[2].to_string(); - break; - } - } - format!( - " {} {} {}", - setting.disk.icon, disk_used, setting.seperator - ) -} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..3af6f72 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,300 @@ +use chrono::prelude::*; +use std::env; +use std::fs::File; +use std::io::Error; +use std::io::Read; +use std::process::Command; +use std::thread; +use std::time::Duration; +use yaml_rust::{yaml, YamlLoader}; + +pub struct Config { + pub seperator: String, + pub time: Time, + pub memory: Memory, + pub disk: Disk, + pub volume: Volume, +} + +pub struct Time { + pub format: String, + pub icon: String, +} + +pub struct Memory { + pub icon: String, + pub enabled: bool, +} + +pub struct Disk { + pub icon: String, + pub enabled: bool, +} + +pub struct Volume { + pub icon: String, + pub enabled: bool, +} + +pub fn load_config() -> Result { + let yml_source = env::var("HOME").unwrap() + "/.config/rsblocks/rsblocks.yml"; + let mut data = String::new(); + let mut file = match File::open(yml_source) { + Ok(file) => file, + Err(_) => { + println!("~/.config/rsblocks/rsblocks.yml file not found, loading defaults!"); + return Ok(load_defaults()); + } + }; + file.read_to_string(&mut data)?; + + let yml_content = &YamlLoader::load_from_str(&data).unwrap()[0]; + let config = gen_default_config(yml_content); + Ok(config) +} + +fn gen_default_config(doc: &yaml::Yaml) -> Config { + // setting icons + let seperator = get_or_set_string(doc, "general", "seperator", "|"); + let time_icon = get_or_set_string(doc, "time", "icon", ""); + let time_format = get_or_set_string(doc, "time", "format", "%T"); + let mem_icon = get_or_set_string(doc, "memory", "icon", ""); + let disk_icon = get_or_set_string(doc, "disk", "icon", ""); + let volume_icon = get_or_set_string(doc, "volume", "icon", ""); + + // everything false by default + let disk_enabled = get_or_set_bool(doc, "disk", "enable"); + let memory_enabled = get_or_set_bool(doc, "memory", "enable"); + let volume_enabled = get_or_set_bool(doc, "volume", "enable"); + + Config { + seperator, + time: Time { + format: time_format, + icon: time_icon, + }, + memory: Memory { + icon: mem_icon, + enabled: memory_enabled, + }, + disk: Disk { + icon: disk_icon, + enabled: disk_enabled, + }, + volume: Volume { + icon: volume_icon, + enabled: volume_enabled, + }, + } +} + +// getting a boolean value from rsblocks.yml file or set it false if it does not exist +fn get_or_set_bool(doc: &yaml::Yaml, parent: &str, child: &str) -> bool { + let val: bool; + if doc[parent][child].is_badvalue() { + val = false; + } else { + val = doc[parent][child].as_bool().unwrap() + } + val +} + +// getting a String value from the rsblocks.yml file or set the default in the last parameter +fn get_or_set_string(doc: &yaml::Yaml, parent: &str, child: &str, default_val: &str) -> String { + let val: String; + if doc[parent][child].is_badvalue() { + val = String::from(default_val) + } else { + val = String::from(doc[parent][child].as_str().unwrap()); + } + + val +} + +fn load_defaults() -> Config { + Config { + seperator: String::from("|"), + time: Time { + format: String::from("%T"), + icon: String::from(""), + }, + memory: Memory { + icon: String::from(""), + enabled: false, + }, + disk: Disk { + icon: String::from(""), + enabled: false, + }, + volume: Volume { + icon: String::from(""), + enabled: false, + }, + } +} +/* LOADING CONFIGS ENDS HERE */ + +/* Running the program: + +TODO: this is sucks, i want to update each one in a diffrent delay, maybe i'll try to use threads +*/ +pub fn run(config: Config) { + loop { + let mut bar = String::from(""); + + // the order of the IF's below matters to the final format + + if config.volume.enabled { + // volume return String + bar.push_str(&get_sound(&config)); + } + + if config.disk.enabled { + // disk_free return String + bar.push_str(&disk_free(&config)); + } + + if config.memory.enabled { + // mem return Result + bar.push_str(&mem(&config).unwrap()); + } + + bar.push_str(&fmt_date(&config)); + + Command::new("xsetroot") + .arg("-name") + .arg(bar) + .output() + .unwrap(); + + thread::sleep(Duration::from_millis(75)); + } +} + +// format bar date/time +pub fn fmt_date(config: &Config) -> String { + let now = Local::now(); + + format!( + " {} {} {}", + config.time.icon, + now.format(&config.time.format), + config.seperator + ) +} + +pub fn disk_free(config: &Config) -> String { + let cmd = Command::new("sh") + .arg("-c") + .args(&["df -h"]) + .output() + .unwrap(); + let output = String::from_utf8_lossy(&cmd.stdout); + let mut disk_used = String::new(); + for line in output.lines() { + if line.ends_with('/') { + let splited = line.split_whitespace().collect::>(); + disk_used = splited[2].to_string(); + break; + } + } + format!( + " {} {} {}", + config.disk.icon, disk_used, config.seperator + ) +} + +// TODO: what a horrible solution to get the sound, i dont like it +// find another way you dumb fuck + +pub fn get_sound(config: &Config) -> String { + let cmd_content = Command::new("amixer") + .args(&["-D", "pulse", "get", "Master"]) + .output() + .expect("Make sure that you have alsa-utils installed on your system"); + + let vol: String = String::from_utf8_lossy(&cmd_content.stdout) + .lines() + .last() + .expect("failed to get sound volume") + .split('[') + .collect::>()[1] + .split(']') + .collect::>()[0] + .trim() + .to_string(); + + format!(" {} {} {}", config.volume.icon, vol, config.seperator) +} + +pub fn mem(config: &Config) -> Result { + let mut buf = String::new(); + + File::open("/proc/meminfo")?.read_to_string(&mut buf)?; + + let mut mem_total: u32 = 0; + let mut shmem: u32 = 0; + let mut mem_free: u32 = 0; + let mut mem_buffers: u32 = 0; + let mut mem_cached: u32 = 0; + let mut mem_srecl: u32 = 0; + + for line in buf.lines() { + if mem_total > 0 + && shmem > 0 + && mem_free > 0 + && mem_buffers > 0 + && mem_cached > 0 + && mem_srecl > 0 + { + break; + } + if line.starts_with("MemTotal") { + assign_val(line, &mut mem_total); + } + if line.starts_with("SReclaimable") { + assign_val(line, &mut mem_srecl) + } + if line.starts_with("Cached") { + assign_val(line, &mut mem_cached) + } + + if line.starts_with("Shmem") { + assign_val(line, &mut shmem); + } + + if line.starts_with("MemFree") { + assign_val(line, &mut mem_free); + } + if line.starts_with("Buffers") { + assign_val(line, &mut mem_buffers); + } + } + + let mem_used = (mem_total + shmem - mem_free - mem_buffers - mem_cached - mem_srecl) / 1024; + let result: String; + if mem_used > 1000 { + result = format!( + " {} {:.1}G {}", + config.memory.icon, + mem_used as f32 / 1000.0, + config.seperator + ); + } else { + result = format!( + " {} {}M {}", + config.memory.icon, mem_used, config.seperator + ); + } + Ok(result) +} + +fn assign_val(line: &str, assignable: &mut u32) { + let parsed: u32 = line.split(':').collect::>()[1] + .trim() + .split(' ') + .collect::>()[0] + .parse() + .unwrap(); + *assignable = parsed; +} diff --git a/src/load_config.rs b/src/load_config.rs deleted file mode 100644 index 763b635..0000000 --- a/src/load_config.rs +++ /dev/null @@ -1,128 +0,0 @@ -use std::env; -use std::{fs::File, io::Error, io::Read}; -use yaml_rust::{yaml, YamlLoader}; - -pub struct Time { - pub format: String, - pub icon: String, -} - -pub struct Memory { - pub icon: String, - pub enabled: bool, -} - -pub struct Disk { - pub icon: String, - pub enabled: bool, -} - -pub struct Volume { - pub icon: String, - pub enabled: bool, -} - -pub struct Settings { - pub seperator: String, - pub time: Time, - pub memory: Memory, - pub disk: Disk, - pub volume: Volume, -} - -pub fn load() -> Result { - let yml_source = env::var("HOME").unwrap() + "/.config/rsblocks/rsblocks.yml"; - let mut data = String::new(); - let mut file = match File::open(yml_source) { - Ok(file) => file, - Err(_) => { - println!("~/.config/rsblocks/rsblocks.yml file not found, loading defaults!"); - return Ok(load_defaults()); - } - }; - file.read_to_string(&mut data)?; - - let yml_content = &YamlLoader::load_from_str(&data).unwrap()[0]; - let settings = gen_settings(yml_content); - Ok(settings) -} - -fn gen_settings(doc: &yaml::Yaml) -> Settings { - // setting icons - let seperator = get_or_set_string(doc, "general", "seperator", "|"); - let time_icon = get_or_set_string(doc, "time", "icon", ""); - let time_format = get_or_set_string(doc, "time", "format", "%T"); - let mem_icon = get_or_set_string(doc, "memory", "icon", ""); - let disk_icon = get_or_set_string(doc, "disk", "icon", ""); - let volume_icon = get_or_set_string(doc, "volume", "icon", ""); - - // setting enable status, everything false by default - let disk_enabled = get_or_set_bool(doc, "disk", "enable"); - let memory_enabled = get_or_set_bool(doc, "memory", "enable"); - let volume_enabled = get_or_set_bool(doc, "volume", "enable"); - - Settings { - seperator, - time: Time { - format: time_format, - icon: time_icon, - }, - memory: Memory { - icon: mem_icon, - enabled: memory_enabled, - }, - disk: Disk { - icon: disk_icon, - enabled: disk_enabled, - }, - volume: Volume { - icon: volume_icon, - enabled: volume_enabled, - }, - } -} - -// getting the bool value from rsblocks.yml file or set it false if it does not exist -fn get_or_set_bool(doc: &yaml::Yaml, parent: &str, child: &str) -> bool { - let val: bool; - if doc[parent][child].is_badvalue() { - val = false; - } else { - val = doc[parent][child].as_bool().unwrap() - } - val -} - -// getting the value from the rsblocks.yml file or set the default in the last parameter -fn get_or_set_string(doc: &yaml::Yaml, parent: &str, child: &str, default_val: &str) -> String { - let val: String; - if doc[parent][child].is_badvalue() { - val = String::from(default_val) - } else { - val = String::from(doc[parent][child].as_str().unwrap()); - } - - val -} - -fn load_defaults() -> Settings { - Settings { - seperator: String::from("|"), - time: Time { - format: String::from("%T"), - icon: String::from(""), - }, - memory: Memory { - icon: String::from(""), - enabled: false, - }, - disk: Disk { - icon: String::from(""), - enabled: false, - }, - volume: Volume { - icon: String::from(""), - enabled: false, - }, - } -} diff --git a/src/main.rs b/src/main.rs index c496e6a..2211cb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,46 +1,6 @@ -use std::process::Command; -use std::thread; -use std::time::Duration; - -mod date; -mod disk; -mod load_config; -mod mem; -mod sound; - -// TODO: this is sucks, maybe thread, i want to spawn some threads +use rsblocks; fn main() { - let settings = load_config::load().unwrap(); - sound::get_sound(&settings); - loop { - let mut bar = String::from(""); - - // the order of the IF's below matters to the final format - - if settings.volume.enabled { - // volume return String - bar.push_str(&sound::get_sound(&settings)); - } - - if settings.disk.enabled { - // disk_free return String - bar.push_str(&disk::disk_free(&settings)); - } - - if settings.memory.enabled { - // mem return Result - bar.push_str(&mem::mem(&settings).unwrap()); - } - - bar.push_str(&date::fmt_date(&settings)); - - Command::new("xsetroot") - .arg("-name") - .arg(bar) - .output() - .unwrap(); - - thread::sleep(Duration::from_millis(75)); - } + let config = rsblocks::load_config().unwrap(); + rsblocks::run(config); } diff --git a/src/mem.rs b/src/mem.rs deleted file mode 100644 index 8245c29..0000000 --- a/src/mem.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::fs::File; -use std::io::Read; - -use crate::load_config::Settings; - -//MemUsed = Memtotal + Shmem - MemFree - Buffers - Cached - SReclaimable -pub fn mem(setting: &Settings) -> Result { - let mut buf = String::new(); - - File::open("/proc/meminfo")?.read_to_string(&mut buf)?; - - let mut mem_total: u32 = 0; - let mut shmem: u32 = 0; - let mut mem_free: u32 = 0; - let mut mem_buffers: u32 = 0; - let mut mem_cached: u32 = 0; - let mut mem_srecl: u32 = 0; - - for line in buf.lines() { - if mem_total > 0 - && shmem > 0 - && mem_free > 0 - && mem_buffers > 0 - && mem_cached > 0 - && mem_srecl > 0 - { - break; - } - if line.starts_with("MemTotal") { - assign_val(line, &mut mem_total); - } - if line.starts_with("SReclaimable") { - assign_val(line, &mut mem_srecl) - } - if line.starts_with("Cached") { - assign_val(line, &mut mem_cached) - } - - if line.starts_with("Shmem") { - assign_val(line, &mut shmem); - } - - if line.starts_with("MemFree") { - assign_val(line, &mut mem_free); - } - if line.starts_with("Buffers") { - assign_val(line, &mut mem_buffers); - } - } - - let mem_used = (mem_total + shmem - mem_free - mem_buffers - mem_cached - mem_srecl) / 1024; - let result: String; - if mem_used > 1000 { - result = format!( - " {} {:.1}G {}", - setting.memory.icon, - mem_used as f32 / 1000.0, - setting.seperator - ); - } else { - result = format!( - " {} {}M {}", - setting.memory.icon, mem_used, setting.seperator - ); - } - Ok(result) -} - -fn assign_val(line: &str, assignable: &mut u32) { - let parsed: u32 = line.split(':').collect::>()[1] - .trim() - .split(' ') - .collect::>()[0] - .parse() - .unwrap(); - *assignable = parsed; -} diff --git a/src/sound.rs b/src/sound.rs deleted file mode 100644 index 6367cac..0000000 --- a/src/sound.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::load_config::Settings; -use std::process::Command; - -// TODO: what a horrible solution to get the sound, i dont like it -// find another way you dumb fuck - -pub fn get_sound(setting: &Settings) -> String { - let cmd_content = Command::new("amixer") - .args(&["-D", "pulse", "get", "Master"]) - .output() - .expect("Make sure that you have alsa-utils installed on your system"); - - let vol: String = String::from_utf8_lossy(&cmd_content.stdout) - .lines() - .last() - .expect("failed to get sound volume") - .split('[') - .collect::>()[1] - .split(']') - .collect::>()[0] - .trim() - .to_string(); - - format!(" {} {} {}", setting.volume.icon, vol, setting.seperator) -}