Diff
diff --git a/src/bar/bar.rs b/src/bar/bar.rs
index 7c022c6..8a356a7 100644
--- a/src/bar/bar.rs
+++ b/src/bar/bar.rs
@@ -1,9 +1,6 @@
-use super::blocks::{Block, Clock, Sep, Uname};
+use super::blocks::Block;
use super::font::{Font, FontDraw};
-use crate::config::{
- CLOCK_COLOR, CLOCK_FORMAT, FONT, SCHEME_NORMAL, SCHEME_OCCUPIED, SCHEME_SELECTED, SEP_COLOR,
- SEPARATOR, TAGS, UNAME_COLOR, UNAME_PREFIX,
-};
+use crate::config::{FONT, SCHEME_NORMAL, SCHEME_OCCUPIED, SCHEME_SELECTED, STATUS_BLOCKS, TAGS};
use anyhow::Result;
use std::time::Instant;
use x11rb::COPY_DEPTH_FROM_PARENT;
@@ -42,7 +39,7 @@ impl Bar {
}
let font = Font::new(display, screen_num as i32, FONT)?;
- let height = (font.height() as f32 * 1.25) as u16;
+ let height = (font.height() as f32 * 1.5) as u16;
connection.create_window(
COPY_DEPTH_FROM_PARENT,
@@ -87,13 +84,17 @@ impl Bar {
})
.collect();
- let blocks: Vec<Box<dyn Block>> = vec![
- Box::new(Uname::new(UNAME_PREFIX, UNAME_COLOR)),
- Box::new(Sep::new(SEPARATOR, SEP_COLOR)),
- Box::new(Clock::new(CLOCK_FORMAT, CLOCK_COLOR)),
- ];
+ let blocks: Vec<Box<dyn Block>> = STATUS_BLOCKS
+ .iter()
+ .map(|config| config.to_block())
+ .collect();
let block_last_updates = vec![Instant::now(); blocks.len()];
+ // let blocks: Vec<Box<dyn Block>> = vec![
+ // Box::new(Uname::new(UNAME_PREFIX, UNAME_COLOR)),
+ // Box::new(Sep::new(SEPARATOR, SEP_COLOR)),
+ // Box::new(Clock::new(CLOCK_FORMAT, CLOCK_COLOR)),
+ // ];
Ok(Bar {
window,
diff --git a/src/bar/blocks/battery.rs b/src/bar/blocks/battery.rs
new file mode 100644
index 0000000..736fc47
--- /dev/null
+++ b/src/bar/blocks/battery.rs
@@ -0,0 +1,68 @@
+use super::Block;
+use anyhow::Result;
+use std::fs;
+use std::time::Duration;
+
+pub struct Battery {
+ format_charging: String,
+ format_discharging: String,
+ format_full: String,
+ interval: Duration,
+ color: u32,
+ battery_path: String,
+}
+
+impl Battery {
+ pub fn new(
+ format_charging: &str,
+ format_discharging: &str,
+ format_full: &str,
+ interval_secs: u64,
+ color: u32,
+ ) -> Self {
+ Self {
+ format_charging: format_charging.to_string(),
+ format_discharging: format_discharging.to_string(),
+ format_full: format_full.to_string(),
+ interval: Duration::from_secs(interval_secs),
+ color,
+ battery_path: "/sys/class/power_supply/BAT0".to_string(),
+ }
+ }
+
+ fn read_file(&self, filename: &str) -> Result<String> {
+ let path = format!("{}/{}", self.battery_path, filename);
+ Ok(fs::read_to_string(path)?.trim().to_string())
+ }
+
+ fn get_capacity(&self) -> Result<u32> {
+ Ok(self.read_file("capacity")?.parse()?)
+ }
+
+ fn get_status(&self) -> Result<String> {
+ self.read_file("status")
+ }
+}
+
+impl Block for Battery {
+ fn content(&mut self) -> Result<String> {
+ let capacity = self.get_capacity()?;
+ let status = self.get_status()?;
+
+ let format = match status.as_str() {
+ "Charging" => &self.format_charging,
+ "Full" => &self.format_full,
+ _ => &self.format_discharging,
+ };
+
+ Ok(format.replace("{}", &capacity.to_string()))
+ }
+
+ fn interval(&self) -> Duration {
+ self.interval
+ }
+
+ fn color(&self) -> u32 {
+ self.color
+ }
+}
diff --git a/src/bar/blocks/clock.rs b/src/bar/blocks/clock.rs
deleted file mode 100644
index 0a7f666..0000000
--- a/src/bar/blocks/clock.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use super::Block;
-use anyhow::Result;
-use chrono::Local;
-use std::time::Duration;
-
-pub struct Clock {
- format: &'static str,
- color: u32,
-}
-
-impl Clock {
- pub fn new(format: &'static str, color: u32) -> Self {
- Self { format, color }
- }
-}
-
-impl Block for Clock {
- fn content(&mut self) -> Result<String> {
- let now = Local::now();
- Ok(now.format(self.format).to_string())
- }
-
- fn interval(&self) -> Duration {
- Duration::from_secs(1)
- }
-
- fn color(&self) -> u32 {
- self.color
- }
-}
diff --git a/src/bar/blocks/datetime.rs b/src/bar/blocks/datetime.rs
new file mode 100644
index 0000000..6ce6b3d
--- /dev/null
+++ b/src/bar/blocks/datetime.rs
@@ -0,0 +1,38 @@
+use super::Block;
+use anyhow::Result;
+use chrono::Local;
+use std::time::Duration;
+
+pub struct DateTime {
+ format_template: String,
+ time_format: String,
+ interval: Duration,
+ color: u32,
+}
+
+impl DateTime {
+ pub fn new(format_template: &str, time_format: &str, interval_secs: u64, color: u32) -> Self {
+ Self {
+ format_template: format_template.to_string(),
+ time_format: time_format.to_string(),
+ interval: Duration::from_secs(interval_secs),
+ color,
+ }
+ }
+}
+
+impl Block for DateTime {
+ fn content(&mut self) -> Result<String> {
+ let now = Local::now();
+ let time_str = now.format(&self.time_format).to_string();
+ Ok(self.format_template.replace("{}", &time_str))
+ }
+
+ fn interval(&self) -> Duration {
+ self.interval
+ }
+
+ fn color(&self) -> u32 {
+ self.color
+ }
+}
diff --git a/src/bar/blocks/mod.rs b/src/bar/blocks/mod.rs
index a36c343..6c9ccc3 100644
--- a/src/bar/blocks/mod.rs
+++ b/src/bar/blocks/mod.rs
@@ -1,20 +1,96 @@
use anyhow::Result;
use std::time::Duration;
-pub mod clock;
-pub mod sep;
-pub mod uname;
+mod battery;
+mod datetime;
+mod shell;
-pub use clock::Clock;
-pub use sep::Sep;
-pub use uname::Uname;
+use battery::Battery;
+use datetime::DateTime;
+use shell::ShellBlock;
pub trait Block {
fn content(&mut self) -> Result<String>;
fn interval(&self) -> Duration;
fn color(&self) -> u32;
+}
+
+pub struct BlockConfig {
+ pub format: &'static str,
+ pub command: BlockCommand,
+ pub interval_secs: u64,
+ pub color: u32,
+}
+
+pub enum BlockCommand {
+ Shell(&'static str),
+ DateTime(&'static str),
+ Battery {
+ format_charging: &'static str,
+ format_discharging: &'static str,
+ format_full: &'static str,
+ },
+ Static(&'static str),
+}
+
+impl BlockConfig {
+ pub fn to_block(&self) -> Box<dyn Block> {
+ match self.command {
+ BlockCommand::Shell(cmd) => Box::new(ShellBlock::new(
+ self.format,
+ cmd,
+ self.interval_secs,
+ self.color,
+ )),
+ BlockCommand::DateTime(fmt) => Box::new(DateTime::new(
+ self.format,
+ fmt,
+ self.interval_secs,
+ self.color,
+ )),
+ BlockCommand::Battery {
+ format_charging,
+ format_discharging,
+ format_full,
+ } => Box::new(Battery::new(
+ format_charging,
+ format_discharging,
+ format_full,
+ self.interval_secs,
+ self.color,
+ )),
+ BlockCommand::Static(text) => Box::new(StaticBlock::new(
+ &format!("{}{}", self.format, text),
+ self.color,
+ )),
+ }
+ }
+}
+
+struct StaticBlock {
+ text: String,
+ color: u32,
+}
+
+impl StaticBlock {
+ fn new(text: &str, color: u32) -> Self {
+ Self {
+ text: text.to_string(),
+ color,
+ }
+ }
+}
+
+impl Block for StaticBlock {
+ fn content(&mut self) -> Result<String> {
+ Ok(self.text.clone())
+ }
+
+ fn interval(&self) -> Duration {
+ Duration::from_secs(u64::MAX)
+ }
- fn on_click(&mut self) -> Result<()> {
- Ok(())
+ fn color(&self) -> u32 {
+ self.color
}
}
diff --git a/src/bar/blocks/sep.rs b/src/bar/blocks/sep.rs
deleted file mode 100644
index 07f1c7a..0000000
--- a/src/bar/blocks/sep.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use super::Block;
-use anyhow::Result;
-use std::time::Duration;
-
-pub struct Sep {
- text: &'static str,
- color: u32,
-}
-
-impl Sep {
- pub fn new(text: &'static str, color: u32) -> Self {
- Self { text, color }
- }
-}
-
-impl Block for Sep {
- fn content(&mut self) -> Result<String> {
- Ok(self.text.to_string())
- }
-
- fn interval(&self) -> Duration {
- Duration::from_secs(u64::MAX)
- }
-
- fn color(&self) -> u32 {
- self.color
- }
-}
diff --git a/src/bar/blocks/shell.rs b/src/bar/blocks/shell.rs
new file mode 100644
index 0000000..51a20df
--- /dev/null
+++ b/src/bar/blocks/shell.rs
@@ -0,0 +1,39 @@
+use super::Block;
+use anyhow::Result;
+use std::process::Command;
+use std::time::Duration;
+
+pub struct ShellBlock {
+ format: String,
+ command: String,
+ interval: Duration,
+ color: u32,
+}
+
+impl ShellBlock {
+ pub fn new(format: &str, command: &str, interval_secs: u64, color: u32) -> Self {
+ Self {
+ format: format.to_string(),
+ command: command.to_string(),
+ interval: Duration::from_secs(interval_secs),
+ color,
+ }
+ }
+}
+
+impl Block for ShellBlock {
+ fn content(&mut self) -> Result<String> {
+ let output = Command::new("sh").arg("-c").arg(&self.command).output()?;
+
+ let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
+ Ok(self.format.replace("{}", &result))
+ }
+
+ fn interval(&self) -> Duration {
+ self.interval
+ }
+
+ fn color(&self) -> u32 {
+ self.color
+ }
+}
diff --git a/src/bar/blocks/uname.rs b/src/bar/blocks/uname.rs
deleted file mode 100644
index 5a0bc7e..0000000
--- a/src/bar/blocks/uname.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use super::Block;
-use anyhow::Result;
-use std::process::Command;
-use std::time::Duration;
-
-pub struct Uname {
- cached_version: String,
- prefix: &'static str,
- color: u32,
-}
-
-impl Uname {
- pub fn new(prefix: &'static str, color: u32) -> Self {
- Self {
- cached_version: String::new(),
- prefix,
- color,
- }
- }
-}
-
-impl Block for Uname {
- fn content(&mut self) -> Result<String> {
- if self.cached_version.is_empty() {
- let output = Command::new("uname").arg("-r").output()?;
- self.cached_version = String::from_utf8_lossy(&output.stdout).trim().to_string();
- }
- Ok(format!("{}{}", self.prefix, self.cached_version))
- }
-
- fn interval(&self) -> Duration {
- Duration::from_secs(u64::MAX)
- }
-
- fn color(&self) -> u32 {
- self.color
- }
-}
diff --git a/src/bar/mod.rs b/src/bar/mod.rs
index c3f1d80..3009746 100644
--- a/src/bar/mod.rs
+++ b/src/bar/mod.rs
@@ -1,9 +1,9 @@
mod bar;
mod blocks;
mod font;
-// mod widgets; // TODO: implement later
pub use bar::Bar;
+pub use blocks::{BlockCommand, BlockConfig};
// Bar position (for future use)
#[derive(Debug, Clone, Copy)]
diff --git a/src/config.rs b/src/config.rs
index e22ec98..90905fa 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,3 +1,4 @@
+use crate::bar::{BlockCommand, BlockConfig};
use crate::keyboard::handlers::Key;
use crate::keyboard::{Arg, KeyAction, keycodes};
use x11rb::protocol::xproto::KeyButMask;
@@ -8,7 +9,7 @@ use x11rb::protocol::xproto::KeyButMask;
pub const BORDER_WIDTH: u32 = 1;
pub const BORDER_FOCUSED: u32 = 0x6dade3;
pub const BORDER_UNFOCUSED: u32 = 0xbbbbbb;
-pub const FONT: &str = "JetBrainsMono Nerd Font:style=Bold:size=12";
+pub const FONT: &str = "JetBrainsMono Nerd Font:style=Bold:size=14";
// ========================================
// DEFAULTS
@@ -110,11 +111,41 @@ pub const KEYBINDINGS: &[Key] = &[
// ========================================
// STATUS BAR BLOCKS
// ========================================
-pub const CLOCK_FORMAT: &str = " %a, %b %d - %-I:%M %P"; // "Fri, Oct 03 - 7:58 pm"
-pub const SEPARATOR: &str = " | ";
-pub const UNAME_COLOR: u32 = RED;
-pub const UNAME_PREFIX: &str = " ";
-pub const SEP_COLOR: u32 = GRAY_LIGHT;
-pub const CLOCK_COLOR: u32 = CYAN;
+pub const STATUS_BLOCKS: &[BlockConfig] = &[
+ BlockConfig {
+ format: "",
+ command: BlockCommand::Battery {
+ format_charging: " Bat: {}%",
+ format_discharging: " Bat:{}%",
+ format_full: " Bat: {}%",
+ },
+ interval_secs: 30,
+ color: BLUE,
+ },
+ BlockConfig {
+ format: " | ",
+ command: BlockCommand::Static(""),
+ interval_secs: u64::MAX,
+ color: GRAY_LIGHT,
+ },
+ BlockConfig {
+ format: " {}",
+ command: BlockCommand::Shell("uname -r"),
+ interval_secs: u64::MAX,
+ color: RED,
+ },
+ BlockConfig {
+ format: " | ",
+ command: BlockCommand::Static(""),
+ interval_secs: u64::MAX,
+ color: GRAY_LIGHT,
+ },
+ BlockConfig {
+ format: " {}",
+ command: BlockCommand::DateTime("%a, %b %d - %-I:%M %P"),
+ interval_secs: 1,
+ color: CYAN,
+ },
+];
const SHIFT: KeyButMask = KeyButMask::SHIFT;