parent
6a204e619e
commit
061c3589ac
11 changed files with 636 additions and 48 deletions
@ -0,0 +1,58 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! `swayrbar` lib.
|
||||
|
||||
use crate::bar::module::BarModuleFn; |
||||
use env_logger::Env; |
||||
use serde_json; |
||||
use std::thread; |
||||
|
||||
pub mod module; |
||||
|
||||
pub fn start() { |
||||
env_logger::Builder::from_env(Env::default().default_filter_or("warn")) |
||||
.init(); |
||||
|
||||
thread::spawn(handle_input); |
||||
let mods: Vec<Box<dyn BarModuleFn>> = vec![ |
||||
crate::bar::module::window::BarModuleWindow::init(), |
||||
crate::bar::module::sysinfo::BarModuleSysInfo::init(), |
||||
crate::bar::module::date::BarModuleDate::init(), |
||||
]; |
||||
generate_status(&mods); |
||||
} |
||||
|
||||
pub fn handle_input() { |
||||
// TODO: Read stdin and react to click events.
|
||||
} |
||||
|
||||
pub fn generate_status(mods: &[Box<dyn BarModuleFn>]) { |
||||
println!("{{\"version\": 1}}"); |
||||
// status_command should output an infinite array meaning we emit an
|
||||
// opening [ and never the closing bracket.
|
||||
println!("["); |
||||
|
||||
loop { |
||||
let mut blocks = vec![]; |
||||
for m in mods { |
||||
blocks.push(m.build()); |
||||
} |
||||
let json = serde_json::to_string_pretty(&blocks) |
||||
.unwrap_or_else(|_| "".to_string()); |
||||
println!("{},", json); |
||||
thread::sleep(std::time::Duration::from_secs(1)); |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use swaybar_types as s; |
||||
|
||||
pub mod date; |
||||
pub mod sysinfo; |
||||
pub mod window; |
||||
|
||||
pub trait BarModuleFn { |
||||
fn init() -> Box<dyn BarModuleFn> |
||||
where |
||||
Self: Sized; |
||||
fn name() -> String |
||||
where |
||||
Self: Sized; |
||||
fn instance(&self) -> String; |
||||
fn build(&self) -> s::Block; |
||||
} |
@ -0,0 +1,62 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! The date `swayrbar` module.
|
||||
|
||||
use crate::bar::module::BarModuleFn; |
||||
use swaybar_types as s; |
||||
|
||||
pub struct BarModuleDate { |
||||
pub instance: String, |
||||
} |
||||
|
||||
impl BarModuleFn for BarModuleDate { |
||||
fn init() -> Box<dyn BarModuleFn> { |
||||
Box::new(BarModuleDate { |
||||
instance: "0".to_string(), |
||||
}) |
||||
} |
||||
|
||||
fn name() -> String { |
||||
String::from("date") |
||||
} |
||||
|
||||
fn instance(&self) -> String { |
||||
self.instance.clone() |
||||
} |
||||
|
||||
fn build(&self) -> s::Block { |
||||
let d = chrono::Local::now().format("%F %X").to_string(); |
||||
s::Block { |
||||
name: Some(Self::name()), |
||||
instance: Some(self.instance.clone()), |
||||
full_text: d, |
||||
align: Some(s::Align::Right), |
||||
markup: Some(s::Markup::Pango), |
||||
short_text: None, |
||||
color: None, |
||||
background: None, |
||||
border: None, |
||||
border_top: None, |
||||
border_bottom: None, |
||||
border_left: None, |
||||
border_right: None, |
||||
min_width: None, |
||||
urgent: None, |
||||
separator: None, |
||||
separator_block_width: None, |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,71 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! The date `swayrbar` module.
|
||||
|
||||
use crate::bar::module::BarModuleFn; |
||||
use std::cell::RefCell; |
||||
use swaybar_types as s; |
||||
use sysinfo; |
||||
use sysinfo::SystemExt; |
||||
|
||||
pub struct BarModuleSysInfo { |
||||
pub instance: String, |
||||
system: RefCell<sysinfo::System>, |
||||
} |
||||
|
||||
impl BarModuleFn for BarModuleSysInfo { |
||||
fn init() -> Box<dyn BarModuleFn> { |
||||
Box::new(BarModuleSysInfo { |
||||
instance: "0".to_string(), |
||||
system: RefCell::new(sysinfo::System::new_all()), |
||||
}) |
||||
} |
||||
|
||||
fn name() -> String { |
||||
String::from("sysinfo") |
||||
} |
||||
|
||||
fn instance(&self) -> String { |
||||
self.instance.clone() |
||||
} |
||||
|
||||
fn build(&self) -> s::Block { |
||||
let x = String::from("{cpu_usage_avg}"); |
||||
self.system.borrow_mut().refresh_specifics( |
||||
sysinfo::RefreshKind::new().with_cpu().with_memory(), |
||||
); |
||||
|
||||
s::Block { |
||||
name: Some(Self::name()), |
||||
instance: Some(self.instance.clone()), |
||||
full_text: x, |
||||
align: Some(s::Align::Right), |
||||
markup: Some(s::Markup::Pango), |
||||
short_text: None, |
||||
color: None, |
||||
background: None, |
||||
border: None, |
||||
border_top: None, |
||||
border_bottom: None, |
||||
border_left: None, |
||||
border_right: None, |
||||
min_width: None, |
||||
urgent: None, |
||||
separator: None, |
||||
separator_block_width: None, |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! The window `swayrbar` module.
|
||||
|
||||
use crate::bar::module::BarModuleFn; |
||||
use std::cell::RefCell; |
||||
use swaybar_types as s; |
||||
use swayipc as ipc; |
||||
|
||||
pub struct NodeIter<'a> { |
||||
stack: Vec<&'a ipc::Node>, |
||||
} |
||||
|
||||
impl<'a> NodeIter<'a> { |
||||
fn new(node: &'a ipc::Node) -> NodeIter { |
||||
NodeIter { stack: vec![node] } |
||||
} |
||||
} |
||||
|
||||
impl<'a> Iterator for NodeIter<'a> { |
||||
type Item = &'a ipc::Node; |
||||
|
||||
fn next(&mut self) -> Option<Self::Item> { |
||||
if let Some(node) = self.stack.pop() { |
||||
for n in &node.floating_nodes { |
||||
self.stack.push(n); |
||||
} |
||||
for n in &node.nodes { |
||||
self.stack.push(n); |
||||
} |
||||
Some(node) |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub struct BarModuleWindow { |
||||
pub instance: String, |
||||
connection: RefCell<swayipc::Connection>, |
||||
} |
||||
|
||||
impl BarModuleFn for BarModuleWindow { |
||||
fn init() -> Box<dyn BarModuleFn> { |
||||
Box::new(BarModuleWindow { |
||||
instance: "0".to_string(), |
||||
connection: RefCell::new( |
||||
ipc::Connection::new() |
||||
.expect("Couldn't get a sway IPC connection"), |
||||
), |
||||
}) |
||||
} |
||||
|
||||
fn name() -> String { |
||||
String::from("window") |
||||
} |
||||
|
||||
fn instance(&self) -> String { |
||||
self.instance.clone() |
||||
} |
||||
|
||||
fn build(&self) -> s::Block { |
||||
let x: String = match self.connection.borrow_mut().get_tree() { |
||||
Ok(root) => { |
||||
let o: Option<&ipc::Node> = |
||||
NodeIter::new(&root).find(|n| n.focused); |
||||
o.map(|w| w.name.clone().unwrap_or_default()) |
||||
.unwrap_or_else(String::new) |
||||
} |
||||
Err(err) => format!("{}", err), |
||||
}; |
||||
s::Block { |
||||
name: Some(Self::name()), |
||||
instance: Some(self.instance.clone()), |
||||
full_text: x, |
||||
align: Some(s::Align::Right), |
||||
markup: Some(s::Markup::Pango), |
||||
short_text: None, |
||||
color: None, |
||||
background: None, |
||||
border: None, |
||||
border_top: None, |
||||
border_bottom: None, |
||||
border_left: None, |
||||
border_right: None, |
||||
min_width: None, |
||||
urgent: None, |
||||
separator: None, |
||||
separator_block_width: None, |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! The `swayrbar` binary.
|
||||
|
||||
fn main() { |
||||
// TODO: We need a config file cmd line option so that each bar can have
|
||||
// its own config.
|
||||
swayr::bar::start(); |
||||
} |
@ -0,0 +1,71 @@ |
||||
// Copyright (C) 2022 Tassilo Horn <tsdh@gnu.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use lazy_static::lazy_static; |
||||
|
||||
lazy_static! { |
||||
pub static ref PLACEHOLDER_RX: regex::Regex = regex::Regex::new( |
||||
r"\{(?P<name>[^}:]+)(?::(?P<fmtstr>\{[^}]*\})(?P<clipstr>[^}]*))?\}" |
||||
) |
||||
.unwrap(); |
||||
} |
||||
|
||||
pub fn maybe_html_escape(do_it: bool, text: String) -> String { |
||||
if do_it { |
||||
text.replace('<', "<") |
||||
.replace('>', ">") |
||||
.replace('&', "&") |
||||
} else { |
||||
text |
||||
} |
||||
} |
||||
|
||||
macro_rules! fmt_replace { |
||||
( $fmt_str:expr, $html_escape:ident, |
||||
{ $( $($pat:pat)|+ => $exp:expr, )+ } |
||||
) => { |
||||
$crate::fmt_replace::PLACEHOLDER_RX |
||||
.replace_all($fmt_str, |caps: ®ex::Captures| { |
||||
let value: String = match &caps["name"] { |
||||
$( |
||||
$( | $pat )+ => { |
||||
let val = $exp; |
||||
let fmt_str = caps.name("fmtstr") |
||||
.map_or("{}", |m| m.as_str()); |
||||
let clipped_str = caps.name("clipstr") |
||||
.map_or("", |m| m.as_str()); |
||||
$crate::fmt_replace::maybe_html_escape( |
||||
$html_escape, |
||||
crate::rtfmt::format(fmt_str, &val, clipped_str), |
||||
) |
||||
} |
||||
)+ |
||||
_ => caps[0].to_string(), |
||||
}; |
||||
value |
||||
}).into() |
||||
}; |
||||
} |
||||
|
||||
#[test] |
||||
fn foo() { |
||||
let foo = "{a}, {b}"; |
||||
let html_escape = true; |
||||
let x: String = fmt_replace!(foo, html_escape, { |
||||
"a" => "1".to_string(), |
||||
"b" => "2".to_string(), |
||||
"c" => "3".to_owned(), |
||||
}); |
||||
} |
Loading…
Reference in new issue