Impl 0.1.5 of swaybar_info

Implemented `--netdev_width=<width>` which sets the minimum width of the netdev
byte/KiB/MiB text displays.

Implemented `--netgraph_max_bytes=<bytes>` which displays a graph in text using
Unicode "Block Elements" symbols. The `<bytes>` argument determines the maximum
amount of bytes that will determine which block-character is printed on the
interval. The graph is always 10 characters wide, and the right side is the
most-recent side. Note that this always checks against the maximum of either
download or upload rates. For example, if `<bytes>` is set to 1024, and 128
bytes were downloaded and 512 bytes were uploaded in an interval, the "Lower
Half Block" Unicode symbol will be emitted (exactly half).

SwaybarObject was changed to use an `Option<String>` instead of an `Option<u16>`
for `min_width`.
This commit is contained in:
Stephen Seo 2022-10-18 21:04:28 +09:00
parent be77c5d70a
commit 7bba60e323
8 changed files with 157 additions and 17 deletions

2
Cargo.lock generated
View file

@ -141,7 +141,7 @@ dependencies = [
[[package]] [[package]]
name = "swaybar_info" name = "swaybar_info"
version = "0.1.4" version = "0.1.5"
dependencies = [ dependencies = [
"chrono", "chrono",
"regex", "regex",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "swaybar_info" name = "swaybar_info"
version = "0.1.4" version = "0.1.5"
edition = "2021" edition = "2021"
description = "Provides swaybar with info to be displayed" description = "Provides swaybar with info to be displayed"
license = "MIT" license = "MIT"

View file

@ -2,6 +2,23 @@
## Upcoming Changes ## Upcoming Changes
## 0.1.5
Implemented `--netdev_width=<width>` which sets the minimum width of the netdev
byte/KiB/MiB text displays.
Implemented `--netgraph_max_bytes=<bytes>` which displays a graph in text using
Unicode "Block Elements" symbols. The `<bytes>` argument determines the maximum
amount of bytes that will determine which block-character is printed on the
interval. The graph is always 10 characters wide, and the right side is the
most-recent side. Note that this always checks against the maximum of either
download or upload rates. For example, if `<bytes>` is set to 1024, and 128
bytes were downloaded and 512 bytes were uploaded in an interval, the "Lower
Half Block" Unicode symbol will be emitted (exactly half).
SwaybarObject was changed to use an `Option<String>` instead of an `Option<u16>`
for `min_width`.
## 0.1.4 ## 0.1.4
Implemented advanced usage of `--regex-cmd=...` such that output text and output Implemented advanced usage of `--regex-cmd=...` such that output text and output

View file

@ -17,12 +17,14 @@ tiling Wayland compositor](https://swaywm.org).
## Help Text ## Help Text
Usage: Usage:
-h | --help Prints help -h | --help Prints help
--netdev=<device_name> Check network traffic on specified device --netdev=<device_name> Check network traffic on specified device
--interval-sec=<seconds> Output at intervals of <seconds> (default 5) --netdev_width=<width> Sets the min-width of the netdev output (default 10)
--acpi-builtin Use "acpi -b" built-in fetching (battery info, with color) --netgraph_max_bytes=<bytes> Enable "graph" output when polling network traffic
--regex-cmd=<cmd>[SPLIT]<args...>[SPLIT]<regex> Use an output of a command as a metric --interval-sec=<seconds> Output at intervals of <seconds> (default 5)
--time-format=<date format string> Set the format string for the date --acpi-builtin Use "acpi -b" built-in fetching (battery info, with color)
--regex-cmd=<cmd>[SPLIT]<args...>[SPLIT]<regex> Use an output of a command as a metric
--time-format=<date format string> Set the format string for the date
## Usage ## Usage

View file

@ -19,6 +19,12 @@ pub fn get_args() -> ArgsResult {
} else if arg.starts_with("--netdev=") { } else if arg.starts_with("--netdev=") {
let (_, back) = arg.split_at(9); let (_, back) = arg.split_at(9);
map.insert("netdev".into(), back.into()); map.insert("netdev".into(), back.into());
} else if arg.starts_with("--netdev_width=") {
let (_, back) = arg.split_at(15);
map.insert("netdevwidth".into(), back.into());
} else if arg.starts_with("--netgraph_max_bytes=") {
let (_, back) = arg.split_at(21);
map.insert("netgraph".into(), back.into());
} else if arg.starts_with("--interval-sec=") { } else if arg.starts_with("--interval-sec=") {
let (_, back) = arg.split_at(15); let (_, back) = arg.split_at(15);
map.insert("interval-sec".into(), back.into()); map.insert("interval-sec".into(), back.into());
@ -52,6 +58,12 @@ pub fn print_usage() {
stderr_handle stderr_handle
.write_all(b" --netdev=<device_name>\t\t\t\tCheck network traffic on specified device\n") .write_all(b" --netdev=<device_name>\t\t\t\tCheck network traffic on specified device\n")
.ok(); .ok();
stderr_handle
.write_all(b" --netdev_width=<width>\t\t\t\tSets the min-width of the netdev output (default 10)\n")
.ok();
stderr_handle
.write_all(b" --netgraph_max_bytes=<bytes>\t\t\t\tEnable \"graph\" output when polling network traffic\n")
.ok();
stderr_handle stderr_handle
.write_all( .write_all(
b" --interval-sec=<seconds>\t\t\t\tOutput at intervals of <seconds> (default 5)\n", b" --interval-sec=<seconds>\t\t\t\tOutput at intervals of <seconds> (default 5)\n",
@ -69,7 +81,7 @@ pub fn print_usage() {
.ok(); .ok();
stderr_handle stderr_handle
.write_all( .write_all(
b" --date-format=<date format string>\t\t\tSet the format string for the date\n", b" --time-format=<date format string>\t\t\tSet the format string for the date\n",
) )
.ok(); .ok();
} }

View file

@ -44,12 +44,44 @@ fn main() {
} }
let mut net_obj: Option<proc::NetInfo> = None; let mut net_obj: Option<proc::NetInfo> = None;
let mut net_width: Option<u16> = Some(10);
let mut net_graph_max: Option<f64> = None;
let mut interval: Duration = Duration::from_secs(5); let mut interval: Duration = Duration::from_secs(5);
if args_result.map.contains_key("netdev") { if args_result.map.contains_key("netdev") {
net_obj = Some(proc::NetInfo::new( net_obj = Some(proc::NetInfo::new(
args_result.map.get("netdev").unwrap().to_owned(), args_result.map.get("netdev").unwrap().to_owned(),
)); ));
} }
if args_result.map.contains_key("netdevwidth") {
let width_result: Result<u16, _> = args_result.map.get("netdevwidth").unwrap().parse();
if let Ok(width) = width_result {
net_width = Some(width);
} else {
let mut stderr_handle = io::stderr().lock();
stderr_handle
.write_all(
format!("WARNING: Invalid value passed to --netdev_width=..., ignoring...\n")
.as_bytes(),
)
.ok();
}
}
if args_result.map.contains_key("netgraph") {
let graph_max_result: Result<f64, _> = args_result.map.get("netgraph").unwrap().parse();
if let Ok(graph_max) = graph_max_result {
net_graph_max = Some(graph_max);
} else {
let mut stderr_handle = io::stderr().lock();
stderr_handle
.write_all(
format!(
"WARNING: Invalid value passed to --netgraph_max_bytes=..., ignoring...\n"
)
.as_bytes(),
)
.ok();
}
}
if args_result.map.contains_key("interval-sec") { if args_result.map.contains_key("interval-sec") {
let seconds: Result<i64, _> = args_result.map.get("interval-sec").unwrap().parse(); let seconds: Result<i64, _> = args_result.map.get("interval-sec").unwrap().parse();
if let Ok(seconds_value) = seconds { if let Ok(seconds_value) = seconds {
@ -92,8 +124,15 @@ fn main() {
println!("["); println!("[");
let mut array = SwaybarArray::new(); let mut array = SwaybarArray::new();
let set_net_error = |is_empty: bool, array: &mut SwaybarArray| { let set_net_error = |is_empty: bool, array: &mut SwaybarArray, graph_max_opt: &Option<f64>| {
if is_empty { if is_empty {
if graph_max_opt.is_some() {
array.push_object(SwaybarObject::from_error_string(
"net_graph".to_owned(),
"net ERROR".into(),
));
}
let down_obj = let down_obj =
SwaybarObject::from_error_string("net_down".to_owned(), "Net ERROR".into()); SwaybarObject::from_error_string("net_down".to_owned(), "Net ERROR".into());
array.push_object(down_obj); array.push_object(down_obj);
@ -101,6 +140,12 @@ fn main() {
let up_obj = SwaybarObject::from_error_string("net_up".to_owned(), "Net ERROR".into()); let up_obj = SwaybarObject::from_error_string("net_up".to_owned(), "Net ERROR".into());
array.push_object(up_obj); array.push_object(up_obj);
} else { } else {
if graph_max_opt.is_some() {
if let Some(graph_ref) = array.get_by_name_mut("net_graph") {
graph_ref.update_as_error("Net ERROR".to_owned());
}
}
let down_ref_opt = array.get_by_name_mut("net_down"); let down_ref_opt = array.get_by_name_mut("net_down");
if let Some(down_ref) = down_ref_opt { if let Some(down_ref) = down_ref_opt {
down_ref.update_as_error("Net ERROR".to_owned()); down_ref.update_as_error("Net ERROR".to_owned());
@ -115,19 +160,39 @@ fn main() {
let handle_net = |is_empty: bool, let handle_net = |is_empty: bool,
net: &mut proc::NetInfo, net: &mut proc::NetInfo,
array: &mut SwaybarArray| array: &mut SwaybarArray,
graph_opt: &Option<f64>,
width: &Option<u16>|
-> Result<(), proc::Error> { -> Result<(), proc::Error> {
net.update()?; net.update()?;
let netinfo_string = net.get_netstring()?; let (netinfo_string, graph_string) = net.get_netstring(*graph_opt)?;
let netinfo_parts: Vec<&str> = netinfo_string.split_whitespace().collect(); let netinfo_parts: Vec<&str> = netinfo_string.split_whitespace().collect();
if is_empty { if is_empty {
if graph_opt.is_some() {
let mut graph_obj =
SwaybarObject::from_string("net_graph".to_owned(), graph_string);
graph_obj.color = Some("#ffff88".into());
array.push_object(graph_obj);
}
let mut width_string: Option<String> = None;
if let Some(width) = *width {
let mut string = String::with_capacity(width.into());
for _ in 0..width {
string.push('0');
}
width_string = Some(string);
}
{ {
let mut down_object = SwaybarObject::from_string( let mut down_object = SwaybarObject::from_string(
"net_down".to_owned(), "net_down".to_owned(),
format!("{} {}", netinfo_parts[0], netinfo_parts[1]), format!("{} {}", netinfo_parts[0], netinfo_parts[1]),
); );
down_object.color = Some("#ff8888ff".into()); down_object.color = Some("#ff8888ff".into());
down_object.min_width = width_string.clone();
down_object.align = Some(String::from("right"));
array.push_object(down_object); array.push_object(down_object);
} }
@ -137,9 +202,17 @@ fn main() {
format!("{} {}", netinfo_parts[2], netinfo_parts[3]), format!("{} {}", netinfo_parts[2], netinfo_parts[3]),
); );
up_object.color = Some("#88ff88ff".into()); up_object.color = Some("#88ff88ff".into());
up_object.min_width = width_string;
up_object.align = Some(String::from("right"));
array.push_object(up_object); array.push_object(up_object);
} }
} else { } else {
if graph_opt.is_some() {
if let Some(graph_obj) = array.get_by_name_mut("net_graph") {
graph_obj.full_text = graph_string;
}
}
if let Some(down_object) = array.get_by_name_mut("net_down") { if let Some(down_object) = array.get_by_name_mut("net_down") {
down_object down_object
.update_as_net_down(format!("{} {}", netinfo_parts[0], netinfo_parts[1])); .update_as_net_down(format!("{} {}", netinfo_parts[0], netinfo_parts[1]));
@ -158,11 +231,11 @@ fn main() {
// network traffic // network traffic
if let Some(net) = net_obj.as_mut() { if let Some(net) = net_obj.as_mut() {
if let Err(e) = handle_net(is_empty, net, &mut array) { if let Err(e) = handle_net(is_empty, net, &mut array, &net_graph_max, &net_width) {
let mut stderr_handle = io::stderr().lock(); let mut stderr_handle = io::stderr().lock();
stderr_handle.write_all(format!("{}\n", e).as_bytes()).ok(); stderr_handle.write_all(format!("{}\n", e).as_bytes()).ok();
net_obj = None; net_obj = None;
set_net_error(is_empty, &mut array); set_net_error(is_empty, &mut array, &net_graph_max);
} }
} }

View file

@ -58,6 +58,7 @@ impl std::error::Error for Error {
pub struct NetInfo { pub struct NetInfo {
dev_name: String, dev_name: String,
graph: String,
down: u64, down: u64,
prev_down: u64, prev_down: u64,
up: u64, up: u64,
@ -68,6 +69,7 @@ impl NetInfo {
pub fn new(dev_name: String) -> Self { pub fn new(dev_name: String) -> Self {
Self { Self {
dev_name, dev_name,
graph: String::from(" "),
down: 0, down: 0,
prev_down: 0, prev_down: 0,
up: 0, up: 0,
@ -109,7 +111,7 @@ impl NetInfo {
Ok(()) Ok(())
} }
pub fn get_netstring(&mut self) -> Result<String, Error> { pub fn get_netstring(&mut self, graph_max: Option<f64>) -> Result<(String, String), Error> {
let down_diff: f64 = (self.down - self.prev_down) as f64; let down_diff: f64 = (self.down - self.prev_down) as f64;
self.prev_down = self.down; self.prev_down = self.down;
let up_diff: f64 = (self.up - self.prev_up) as f64; let up_diff: f64 = (self.up - self.prev_up) as f64;
@ -132,7 +134,41 @@ impl NetInfo {
write!(&mut output, "{:.0} B", up_diff)?; write!(&mut output, "{:.0} B", up_diff)?;
} }
Ok(output) if let Some(graph_max) = graph_max {
let diff_max = if down_diff > up_diff {
down_diff
} else {
up_diff
};
let graph_value: u8 = if diff_max > graph_max {
8
} else {
(diff_max / graph_max * 8.0f64) as u8
};
let mut first = true;
let mut new_graph_string = String::with_capacity(10);
for current_char in self.graph.chars() {
if first {
first = false;
continue;
}
new_graph_string.push(current_char);
}
match graph_value {
0 => new_graph_string.push(' '),
1 => new_graph_string.push('▁'),
2 => new_graph_string.push('▂'),
3 => new_graph_string.push('▃'),
4 => new_graph_string.push('▄'),
5 => new_graph_string.push('▅'),
6 => new_graph_string.push('▆'),
7 => new_graph_string.push('▇'),
_ => new_graph_string.push('█'),
}
self.graph = new_graph_string;
}
Ok((output, self.graph.clone()))
} }
} }

View file

@ -38,7 +38,7 @@ pub struct SwaybarObject {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub border_right: Option<u16>, pub border_right: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub min_width: Option<u16>, pub min_width: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub align: Option<String>, pub align: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]