From dba83eb64a99e3c412ada777d9e9e53c19aafdf9 Mon Sep 17 00:00:00 2001 From: Rasmus Rosengren Date: Fri, 27 Aug 2021 15:11:55 +0200 Subject: [PATCH] Add basic blocks --- Cargo.lock | 185 +++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + src/blocks/cpu.rs | 34 ++++++++ src/blocks/memory.rs | 35 ++++++++ src/blocks/mod.rs | 3 + src/blocks/time.rs | 32 ++++++++ src/main.rs | 123 +++++++++------------------- src/util.rs | 15 ++++ 8 files changed, 345 insertions(+), 84 deletions(-) create mode 100644 src/blocks/cpu.rs create mode 100644 src/blocks/memory.rs create mode 100644 src/blocks/mod.rs create mode 100644 src/blocks/time.rs create mode 100644 src/util.rs diff --git a/Cargo.lock b/Cargo.lock index 0a068ef..73338d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,67 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "bumpalo" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +[[package]] +name = "bytesize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + [[package]] name = "flume" version = "0.10.9" @@ -27,6 +76,12 @@ dependencies = [ "spin", ] +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures-core" version = "0.3.16" @@ -56,9 +111,11 @@ dependencies = [ name = "i3status-simple" version = "0.1.0" dependencies = [ + "chrono", "flume", "serde", "serde_json", + "systemstat", ] [[package]] @@ -82,6 +139,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.101" @@ -106,6 +176,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + [[package]] name = "nanorand" version = "0.6.1" @@ -115,6 +191,38 @@ dependencies = [ "getrandom", ] +[[package]] +name = "nom" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" +dependencies = [ + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "pin-project" version = "1.0.8" @@ -153,6 +261,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "ryu" version = "1.0.5" @@ -205,6 +319,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "1.0.75" @@ -216,12 +336,49 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "systemstat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a934f8fe2f893260080fdde71e840b35308f48bf3bd3b261cb24e668c4b48db3" +dependencies = [ + "bytesize", + "chrono", + "lazy_static", + "libc", + "nom", + "time", + "winapi", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -281,3 +438,31 @@ name = "wasm-bindgen-shared" version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" diff --git a/Cargo.toml b/Cargo.toml index bfb1f86..4c355a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,8 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = "0.4" flume = "0.10" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +systemstat = "0.1" \ No newline at end of file diff --git a/src/blocks/cpu.rs b/src/blocks/cpu.rs new file mode 100644 index 0000000..dae6af8 --- /dev/null +++ b/src/blocks/cpu.rs @@ -0,0 +1,34 @@ +use systemstat::Platform; + +use crate::Block; + +pub struct CpuBlock { + pub id: usize, +} + +impl Block for CpuBlock { + fn id(&self) -> usize { + self.id + } + + fn name(&self) -> &str { + "cpu" + } + + fn run( + &mut self, + _event_r: flume::Receiver, + update_s: flume::Sender<(usize, String)>, + ) { + let sys = systemstat::System::new(); + loop { + let cpu = sys.cpu_load_aggregate().unwrap(); + std::thread::sleep(std::time::Duration::from_millis(1000)); + let cpu = cpu.done().unwrap(); + let load_percentage = 100.0 * cpu.user; + update_s + .send((self.id, format!(" Cpu: {:.2}% ", load_percentage))) + .unwrap(); + } + } +} diff --git a/src/blocks/memory.rs b/src/blocks/memory.rs new file mode 100644 index 0000000..f4b7c36 --- /dev/null +++ b/src/blocks/memory.rs @@ -0,0 +1,35 @@ +use systemstat::Platform; + +use crate::Block; + +pub struct MemoryBlock { + pub id: usize, +} + +impl Block for MemoryBlock { + fn id(&self) -> usize { + self.id + } + + fn name(&self) -> &str { + "memory" + } + + fn run( + &mut self, + _event_r: flume::Receiver, + update_s: flume::Sender<(usize, String)>, + ) { + let sys = systemstat::System::new(); + loop { + let mem = sys.memory().unwrap(); + let bytes_used = systemstat::saturating_sub_bytes(mem.total, mem.free).as_u64(); + let bytes_total = mem.total.as_u64(); + let mem_percentage = 100.0 * bytes_used as f64 / bytes_total as f64; + update_s + .send((self.id, format!(" Mem: {:.2}% ", mem_percentage))) + .unwrap(); + std::thread::sleep(std::time::Duration::from_millis(1000)); + } + } +} diff --git a/src/blocks/mod.rs b/src/blocks/mod.rs new file mode 100644 index 0000000..c5d3a14 --- /dev/null +++ b/src/blocks/mod.rs @@ -0,0 +1,3 @@ +pub mod cpu; +pub mod memory; +pub mod time; diff --git a/src/blocks/time.rs b/src/blocks/time.rs new file mode 100644 index 0000000..b5d9814 --- /dev/null +++ b/src/blocks/time.rs @@ -0,0 +1,32 @@ +use chrono::Timelike; + +use crate::Block; + +pub struct TimeBlock { + pub id: usize, +} + +impl Block for TimeBlock { + fn id(&self) -> usize { + self.id + } + + fn name(&self) -> &str { + "time" + } + + fn run( + &mut self, + _event_r: flume::Receiver, + update_s: flume::Sender<(usize, String)>, + ) { + loop { + let now = chrono::Local::now(); + let time_string = now.format(" %a %d/%m %R ").to_string(); + update_s.send((self.id, time_string)).unwrap(); + + let second = now.second() as u64; + std::thread::sleep(std::time::Duration::from_secs(60 - second)); + } + } +} diff --git a/src/main.rs b/src/main.rs index 22dccd0..4ef96c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ -use std::sync::mpsc; -use std::{collections::HashMap, io::Write}; +mod blocks; +mod protocol; +mod util; + +use std::collections::HashMap; use protocol::i3bar_event::I3BarEvent; @@ -8,48 +11,54 @@ use crate::protocol::{ i3bar_event::read_event, }; -mod protocol; - fn main() { - protocol::init(); - - let (event_s, event_r) = flume::unbounded(); - std::thread::spawn(move || loop { - let event = read_event().unwrap(); - event_s.send(event).unwrap(); - }); - let blocks = vec![ - TestBlock { id: 0, n: 0 }, - TestBlock { id: 1, n: 1 }, - TestBlock { id: 2, n: 2 }, - TestBlock { id: 3, n: 3 }, + Box::new(blocks::time::TimeBlock { id: 0 }) as Box, + Box::new(blocks::memory::MemoryBlock { id: 1 }) as Box, + Box::new(blocks::cpu::CpuBlock { id: 2 }) as Box, ]; - let (update_s, update_r) = flume::unbounded(); - let block_ids: Vec<_> = blocks.iter().map(|b| b.id()).collect(); - for block in blocks { - let event_r = event_r.clone(); + let (update_s, update_r) = flume::unbounded(); + let block_metas = blocks + .iter() + .map(|b| (b.id(), b.name().to_string())) + .collect::>(); + let mut event_senders = HashMap::new(); + + // Start all the blocks + for mut block in blocks { + let (event_s, event_r) = flume::unbounded(); + event_senders.insert(block.id(), event_s); let update_s = update_s.clone(); std::thread::spawn(move || { block.run(event_r, update_s); }); } + // Receive events and send them to the correct blocks + std::thread::spawn(move || loop { + let event = read_event().unwrap(); + let id = event.instance.parse().unwrap(); + if let Some(event_sender) = event_senders.get(&id) { + event_sender.send(event).unwrap(); + } + }); + + protocol::init(); + let mut cache = HashMap::new(); loop { let (id, content) = update_r.recv().unwrap(); cache.insert(id, content); - let rendered_blocks = block_ids + let rendered_blocks = block_metas .iter() - .filter_map(|id| cache.get(id).map(|content| content.clone())) - .map(|content| I3BarBlock { + .rev() + .filter_map(|(id, name)| cache.get(id).map(|content| (id, name, content.clone()))) + .map(|(id, name, content)| I3BarBlock { full_text: content, - color: Some(String::from("#ff0000")), - background: Some(String::from("#00ff00")), - border: Some(String::from("#0000ff")), - border_right: Some(16), - border_left: Some(16), + name: name.clone(), + instance: id.to_string(), + color: Some(String::from("#ffffff")), ..Default::default() }) .collect(); @@ -62,63 +71,9 @@ pub trait Block { fn name(&self) -> &str; - fn run(self, event_r: flume::Receiver, update_s: flume::Sender<(usize, String)>); -} - -pub enum Event { - I3Bar(I3BarEvent), - Poll, -} - -struct TestBlock { - id: usize, - n: i32, -} - -impl Block for TestBlock { - fn id(&self) -> usize { - self.id - } - - fn name(&self) -> &str { - "test" - } - fn run( - mut self, + &mut self, event_r: flume::Receiver, update_s: flume::Sender<(usize, String)>, - ) { - let (poll_s, poll_r) = flume::unbounded(); - std::thread::spawn(move || loop { - std::thread::sleep(std::time::Duration::from_millis(333)); - poll_s.send(()).unwrap(); - }); - - loop { - flume::Selector::new() - .recv(&event_r, |msg| msg.map(|msg| Event::I3Bar(msg))) - .recv(&poll_r, |_| Ok(Event::Poll)) - .wait() - .unwrap(); - self.n += 1; - update_s - .send((self.id(), format!(" hello {} ", self.n))) - .unwrap(); - } - } -} - -pub fn debug<'s, S1, S2>(loc: S1, content: S2) -where - S1: AsRef, - S2: AsRef, -{ - let mut file = std::fs::OpenOptions::new() - .append(true) - .create(true) - .open("/home/rosen/dev/i3status-simple/debug.log") - .unwrap(); - file.write_all(format!("[{:?}]: {:?}\n", loc.as_ref(), content.as_ref()).as_bytes()) - .unwrap(); + ); } diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..496a092 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,15 @@ +use std::io::Write; + +pub fn _debug<'s, S1, S2>(loc: S1, content: S2) +where + S1: AsRef, + S2: AsRef, +{ + let mut file = std::fs::OpenOptions::new() + .append(true) + .create(true) + .open("/home/rosen/dev/i3status-simple/debug.log") + .unwrap(); + file.write_all(format!("[{:?}]: {:?}\n", loc.as_ref(), content.as_ref()).as_bytes()) + .unwrap(); +}