From 90be9730a62e2a935ccf01cdd6e320c65624722a Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Fri, 1 Jan 2021 18:09:28 -0500 Subject: [PATCH] feature: Add network interface filtering (#381) Adds a new option in the config file to filter out network interfaces. Also add the option to filter by whole words. Interface follows that of the existing ones: ```toml [net_filter] is_list_ignored = false list = ["virbr0.*"] regex = true case_sensitive = false whole_word = false ``` --- .vscode/settings.json | 2 + CHANGELOG.md | 2 + README.md | 20 ++++- assets/temp_filter_post3.png | Bin 0 -> 85155 bytes sample_configs/demo_config.toml | 16 ---- src/app.rs | 4 +- src/app/data_harvester.rs | 23 +++-- src/app/data_harvester/disks.rs | 107 +++++++++++----------- src/app/data_harvester/network.rs | 122 ++++++++++++++++---------- src/app/data_harvester/temperature.rs | 116 ++++++++++++++++-------- src/bin/main.rs | 4 +- src/constants.rs | 9 ++ src/data_conversion.rs | 67 ++++---------- src/lib.rs | 5 +- src/options.rs | 16 +++- 15 files changed, 293 insertions(+), 220 deletions(-) create mode 100644 assets/temp_filter_post3.png diff --git a/.vscode/settings.json b/.vscode/settings.json index 6002bb85..9a10ba3f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,6 +65,7 @@ "hjkl", "htop", "indexmap", + "iwlwifi", "keybinds", "le", "libc", @@ -112,6 +113,7 @@ "use", "use curr usage", "utime", + "virbr", "virt", "vsize", "whitespaces", diff --git a/CHANGELOG.md b/CHANGELOG.md index 5db3e343..de00824c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#379](https://github.com/ClementTsang/bottom/pull/379): Adds `--process_command` flag and corresponding config option to default to showing a process' command. +- [#381](https://github.com/ClementTsang/bottom/pull/381): Adds a filter in the config file for network interfaces. + ## Changes - [#372](https://github.com/ClementTsang/bottom/pull/372): Hides the SWAP graph and legend in normal mode if SWAP is 0. diff --git a/README.md b/README.md index 943a001e..8adbc580 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ A cross-platform graphical process/system monitor with a customizable interface - [Config flags](#config-flags) - [Theming](#theming) - [Layout](#layout) - - [Disk and temperature filtering](#disk-and-temperature-filtering) + - [Disk and temperature filtering](#disk-temperature-and-network-filtering) - [Battery](#battery) - [Compatibility](#compatibility) - [FAQ](#faq) @@ -670,9 +670,9 @@ Furthermore, you can have duplicate widgets. This means you could do something l and get the following CPU donut: ![CPU donut](./assets/cpu_layout.png) -#### Disk and temperature filtering +#### Disk, temperature, and network filtering -You can hide specific disks and temperature sensors by name in the config file via `disk_filter` and `temp_filter` respectively. Regex (`regex = true`) and case-sensitivity (`case_sensitive = true`) are supported, but are off by default. +You can hide specific disks, temperature sensors, and networks by name in the config file via `disk_filter`, `temp_filter`, and `net_filter` respectively. Regex (`regex = true`), case-sensitivity (`case_sensitive = true`), and matching only the entire word (`whole_word = true`) are supported, but are off by default. For example, let's say , given this disk list: @@ -712,6 +712,20 @@ Now, flipping to `case_sensitive = false` would instead show: ![Temp filter after with case sensitivity off](./assets/temp_filter_post2.png) +Lastly, let's say I want to filter out _exactly_ "iwlwifi_1" from my results. I could do: + +```toml +[temp_filter] +is_list_ignored = true +list = ["iwlwifi_1"] +case_sensitive = true +whole_word = true +``` + +This will match the entire word, "iwlwifi_1", and ignore any result that exactly matches it: + +![Temp filter after with whole_word](./assets/temp_filter_post3.png) + ### Battery You can get battery statistics (charge, time to fill/discharge, consumption in watts, and battery health) via the battery widget. diff --git a/assets/temp_filter_post3.png b/assets/temp_filter_post3.png new file mode 100644 index 0000000000000000000000000000000000000000..f84886d11e10334ceae416e2f3f42d66d0267883 GIT binary patch literal 85155 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 ZMw;!_WLdZiU;_a^3bOBIU{a=m{||FGx2XUC literal 0 HcmV?d00001 diff --git a/sample_configs/demo_config.toml b/sample_configs/demo_config.toml index f7fcb6b0..e6c5cf71 100644 --- a/sample_configs/demo_config.toml +++ b/sample_configs/demo_config.toml @@ -13,19 +13,3 @@ whole_word = false regex = true default_widget_type = "cpu" default_widget_count = 1 - -[colors] -# Based on gruvbox: https://github.com/morhetz/gruvbox -table_header_color="#458588" -widget_title_color="#cc241d" -cpu_core_colors=["#cc241d", "#98971a", "#d79921", "#458588", "#b16286", "#689d6a", "#fb4934", "#b8bb26", "#fabd2f", "#83a598"] -ram_color="#fb4934" -swap_color="#fabd2f" -rx_color="#458588" -tx_color="#689d6a" -border_color="#ebdbb2" -highlighted_border_color="#fe8019" -text_color="#ebdbb2" -graph_color="#ebdbb2" -selected_text_color="#282828" -selected_bg_color="#458588" diff --git a/src/app.rs b/src/app.rs index 7fae7cf0..5b2dbe90 100644 --- a/src/app.rs +++ b/src/app.rs @@ -57,12 +57,14 @@ pub struct AppConfigFields { } /// For filtering out information +#[derive(Debug, Clone)] pub struct DataFilters { pub disk_filter: Option, pub temp_filter: Option, + pub net_filter: Option, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Filter { pub is_list_ignored: bool, pub list: Vec, diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index 63d9a07c..0fc8c6a5 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -14,6 +14,8 @@ use crate::app::layout_manager::UsedWidgets; use futures::join; +use super::DataFilters; + pub mod batteries; pub mod cpu; pub mod disks; @@ -96,15 +98,15 @@ pub struct DataCollector { battery_list: Option>, #[cfg(target_os = "linux")] page_file_size_kb: u64, + filters: DataFilters, } -impl Default for DataCollector { - fn default() -> Self { - // trace!("Creating default data collector..."); +impl DataCollector { + pub fn new(filters: DataFilters) -> Self { DataCollector { data: Data::default(), #[cfg(not(target_os = "linux"))] - sys: System::new_with_specifics(sysinfo::RefreshKind::new()), // FIXME: Make this run on only macOS and Windows. + sys: System::new_with_specifics(sysinfo::RefreshKind::new()), #[cfg(target_os = "linux")] previous_cpu_times: vec![], #[cfg(target_os = "linux")] @@ -132,11 +134,10 @@ impl Default for DataCollector { // page_file_size_kb libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024 }, + filters, } } -} -impl DataCollector { pub fn init(&mut self) { #[cfg(target_os = "linux")] { @@ -147,6 +148,7 @@ impl DataCollector { self.sys.refresh_memory(); self.mem_total_kb = self.sys.get_total_memory(); + // TODO: Would be good to get this and network list running on a timer instead...? // Refresh components list once... if self.widgets_to_harvest.use_temp { self.sys.refresh_components_list(); @@ -295,6 +297,7 @@ impl DataCollector { &mut self.total_tx, current_instant, self.widgets_to_harvest.use_net, + &self.filters.net_filter, ) } #[cfg(not(target_os = "windows"))] @@ -305,12 +308,14 @@ impl DataCollector { &mut self.total_tx, current_instant, self.widgets_to_harvest.use_net, + &self.filters.net_filter, ) } }; let mem_data_fut = mem::get_mem_data(self.widgets_to_harvest.use_mem); - let disk_data_fut = disks::get_disk_usage(self.widgets_to_harvest.use_disk); - let disk_io_usage_fut = disks::get_io_usage(false, self.widgets_to_harvest.use_disk); + let disk_data_fut = + disks::get_disk_usage(self.widgets_to_harvest.use_disk, &self.filters.disk_filter); + let disk_io_usage_fut = disks::get_io_usage(self.widgets_to_harvest.use_disk); let temp_data_fut = { #[cfg(not(target_os = "linux"))] { @@ -318,6 +323,7 @@ impl DataCollector { &self.sys, &self.temperature_type, self.widgets_to_harvest.use_temp, + &self.filters.temp_filter, ) } @@ -326,6 +332,7 @@ impl DataCollector { temperature::get_temperature_data( &self.temperature_type, self.widgets_to_harvest.use_temp, + &self.filters.temp_filter, ) } }; diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs index 8c447a46..5a67a909 100644 --- a/src/app/data_harvester/disks.rs +++ b/src/app/data_harvester/disks.rs @@ -1,3 +1,5 @@ +use crate::app::Filter; + #[derive(Debug, Clone, Default)] pub struct DiskHarvest { pub name: String, @@ -15,9 +17,7 @@ pub struct IOData { pub type IOHarvest = std::collections::HashMap>; -pub async fn get_io_usage( - get_physical: bool, actually_get: bool, -) -> crate::utils::error::Result> { +pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result> { if !actually_get { return Ok(None); } @@ -26,37 +26,23 @@ pub async fn get_io_usage( let mut io_hash: std::collections::HashMap> = std::collections::HashMap::new(); - if get_physical { - let physical_counter_stream = heim::disk::io_counters_physical().await?; - futures::pin_mut!(physical_counter_stream); - while let Some(io) = physical_counter_stream.next().await { - if let Ok(io) = io { - let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); - io_hash.insert( - mount_point.to_string(), - Some(IOData { - read_bytes: io.read_bytes().get::(), - write_bytes: io.write_bytes().get::(), - }), - ); - } - } - } else { - let counter_stream = heim::disk::io_counters().await?; - futures::pin_mut!(counter_stream); + let counter_stream = heim::disk::io_counters().await?; + futures::pin_mut!(counter_stream); - while let Some(io) = counter_stream.next().await { - if let Ok(io) = io { - let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); - io_hash.insert( - mount_point.to_string(), - Some(IOData { - read_bytes: io.read_bytes().get::(), - write_bytes: io.write_bytes().get::(), - }), - ); - } + while let Some(io) = counter_stream.next().await { + if let Ok(io) = io { + let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); + + // FIXME: [MOUNT POINT] Add the filter here I guess? + + io_hash.insert( + mount_point.to_string(), + Some(IOData { + read_bytes: io.read_bytes().get::(), + write_bytes: io.write_bytes().get::(), + }), + ); } } @@ -64,7 +50,7 @@ pub async fn get_io_usage( } pub async fn get_disk_usage( - actually_get: bool, + actually_get: bool, name_filter: &Option, ) -> crate::utils::error::Result>> { if !actually_get { return Ok(None); @@ -77,26 +63,43 @@ pub async fn get_disk_usage( futures::pin_mut!(partitions_stream); while let Some(part) = partitions_stream.next().await { - if let Ok(part) = part { - let partition = part; - let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?; + if let Ok(partition) = part { + let name = (partition + .device() + .unwrap_or_else(|| std::ffi::OsStr::new("Name Unavailable")) + .to_str() + .unwrap_or("Name Unavailable")) + .to_string(); - vec_disks.push(DiskHarvest { - free_space: usage.free().get::(), - used_space: usage.used().get::(), - total_space: usage.total().get::(), - mount_point: (partition - .mount_point() - .to_str() - .unwrap_or("Name Unavailable")) - .to_string(), - name: (partition - .device() - .unwrap_or_else(|| std::ffi::OsStr::new("Name Unavailable")) - .to_str() - .unwrap_or("Name Unavailable")) - .to_string(), - }); + let mount_point = (partition + .mount_point() + .to_str() + .unwrap_or("Name Unavailable")) + .to_string(); + + let to_keep = if let Some(filter) = name_filter { + let mut ret = filter.is_list_ignored; + for r in &filter.list { + if r.is_match(&name) { + ret = !filter.is_list_ignored; + break; + } + } + ret + } else { + true + }; + + if to_keep { + let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?; + vec_disks.push(DiskHarvest { + free_space: usage.free().get::(), + used_space: usage.used().get::(), + total_space: usage.total().get::(), + mount_point, + name, + }); + } } } diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs index dcb496cd..55d757f6 100644 --- a/src/app/data_harvester/network.rs +++ b/src/app/data_harvester/network.rs @@ -20,6 +20,7 @@ impl NetworkHarvest { pub async fn get_network_data( sys: &sysinfo::System, prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64, curr_time: Instant, actually_get: bool, + filter: &Option, ) -> crate::utils::error::Result> { use sysinfo::{NetworkExt, SystemExt}; @@ -31,52 +32,83 @@ pub async fn get_network_data( let mut total_tx: u64 = 0; let networks = sys.get_networks(); - for (_, network) in networks { - total_rx += network.get_total_received(); - total_tx += network.get_total_transmitted(); - } + for (name, network) in networks { + let to_keep = if let Some(filter) = filter { + let mut ret = filter.is_list_ignored; + for r in &filter.list { + if r.is_match(&name) { + ret = !filter.is_list_ignored; + break; + } + } + ret + } else { + true + }; - let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64(); - - let (rx, tx) = if elapsed_time == 0.0 { - (0, 0) - } else { - ( - ((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64, - ((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64, - ) - }; - - *prev_net_rx = total_rx; - *prev_net_tx = total_tx; - Ok(Some(NetworkHarvest { - rx, - tx, - total_rx, - total_tx, - })) -} - -#[cfg(not(target_os = "windows"))] -pub async fn get_network_data( - prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64, - curr_time: Instant, actually_get: bool, -) -> crate::utils::error::Result> { - use futures::StreamExt; - - if !actually_get { - return Ok(None); - } - - let io_data = heim::net::io_counters().await?; - futures::pin_mut!(io_data); - let mut total_rx: u64 = 0; - let mut total_tx: u64 = 0; - - while let Some(io) = io_data.next().await { - if let Ok(io) = io { - total_rx += io.bytes_recv().get::(); - total_tx += io.bytes_sent().get::(); + if to_keep { + total_rx += network.get_total_received(); + total_tx += network.get_total_transmitted(); + } + } + + let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64(); + + let (rx, tx) = if elapsed_time == 0.0 { + (0, 0) + } else { + ( + ((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64, + ((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64, + ) + }; + + *prev_net_rx = total_rx; + *prev_net_tx = total_tx; + Ok(Some(NetworkHarvest { + rx, + tx, + total_rx, + total_tx, + })) +} + +// FIXME: Eventually make it so that this thing also takes individual usage into account, so we can allow for showing per-interface! +#[cfg(not(target_os = "windows"))] +pub async fn get_network_data( + prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64, + curr_time: Instant, actually_get: bool, filter: &Option, +) -> crate::utils::error::Result> { + use futures::StreamExt; + + if !actually_get { + return Ok(None); + } + + let io_data = heim::net::io_counters().await?; + futures::pin_mut!(io_data); + let mut total_rx: u64 = 0; + let mut total_tx: u64 = 0; + + while let Some(io) = io_data.next().await { + if let Ok(io) = io { + let to_keep = if let Some(filter) = filter { + let mut ret = filter.is_list_ignored; + for r in &filter.list { + if r.is_match(&io.interface()) { + ret = !filter.is_list_ignored; + break; + } + } + ret + } else { + true + }; + + if to_keep { + total_rx += io.bytes_recv().get::(); + total_tx += io.bytes_sent().get::(); + } } } diff --git a/src/app/data_harvester/temperature.rs b/src/app/data_harvester/temperature.rs index 512850c9..1c818e31 100644 --- a/src/app/data_harvester/temperature.rs +++ b/src/app/data_harvester/temperature.rs @@ -1,9 +1,10 @@ use std::cmp::Ordering; +use crate::app::Filter; + #[derive(Default, Debug, Clone)] pub struct TempHarvest { - pub component_name: Option, - pub component_label: Option, + pub name: String, pub temperature: f32, } @@ -22,7 +23,7 @@ impl Default for TemperatureType { #[cfg(not(target_os = "linux"))] pub async fn get_temperature_data( - sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool, + sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool, filter: &Option, ) -> crate::utils::error::Result>> { use sysinfo::{ComponentExt, SystemExt}; @@ -42,17 +43,35 @@ pub async fn get_temperature_data( let sensor_data = sys.get_components(); for component in sensor_data { - temperature_vec.push(TempHarvest { - component_name: None, - component_label: Some(component.get_label().to_string()), - temperature: match temp_type { - TemperatureType::Celsius => component.get_temperature(), - TemperatureType::Kelvin => convert_celsius_to_kelvin(component.get_temperature()), - TemperatureType::Fahrenheit => { - convert_celsius_to_fahrenheit(component.get_temperature()) + let name = component.get_label().to_string(); + + let to_keep = if let Some(filter) = filter { + let mut ret = filter.is_list_ignored; + for r in &filter.list { + if r.is_match(&name) { + ret = !filter.is_list_ignored; + break; } - }, - }); + } + ret + } else { + true + }; + + if to_keep { + temperature_vec.push(TempHarvest { + name, + temperature: match temp_type { + TemperatureType::Celsius => component.get_temperature(), + TemperatureType::Kelvin => { + convert_celsius_to_kelvin(component.get_temperature()) + } + TemperatureType::Fahrenheit => { + convert_celsius_to_fahrenheit(component.get_temperature()) + } + }, + }); + } } temp_vec_sort(&mut temperature_vec); @@ -61,7 +80,7 @@ pub async fn get_temperature_data( #[cfg(target_os = "linux")] pub async fn get_temperature_data( - temp_type: &TemperatureType, actually_get: bool, + temp_type: &TemperatureType, actually_get: bool, filter: &Option, ) -> crate::utils::error::Result>> { use futures::StreamExt; use heim::units::thermodynamic_temperature; @@ -75,26 +94,51 @@ pub async fn get_temperature_data( let mut sensor_data = heim::sensors::temperatures().boxed_local(); while let Some(sensor) = sensor_data.next().await { if let Ok(sensor) = sensor { - temperature_vec.push(TempHarvest { - component_name: Some(sensor.unit().to_string()), - component_label: if let Some(label) = sensor.label() { - Some(label.to_string()) - } else { - None - }, - temperature: match temp_type { - TemperatureType::Celsius => sensor - .current() - .get::(), - TemperatureType::Kelvin => { - sensor.current().get::() + let component_name = Some(sensor.unit().to_string()); + let component_label = if let Some(label) = sensor.label() { + Some(label.to_string()) + } else { + None + }; + + let name = match (component_name, component_label) { + (Some(name), Some(label)) => format!("{}: {}", name, label), + (None, Some(label)) => label.to_string(), + (Some(name), None) => name.to_string(), + (None, None) => String::default(), + }; + + let to_keep = if let Some(filter) = filter { + let mut ret = filter.is_list_ignored; + for r in &filter.list { + if r.is_match(&name) { + ret = !filter.is_list_ignored; + break; } - TemperatureType::Fahrenheit => sensor - .current() - .get::( - ), - }, - }); + } + ret + } else { + true + }; + + if to_keep { + temperature_vec.push(TempHarvest { + name, + temperature: match temp_type { + TemperatureType::Celsius => sensor + .current() + .get::( + ), + TemperatureType::Kelvin => { + sensor.current().get::() + } + TemperatureType::Fahrenheit => sensor + .current() + .get::( + ), + }, + }); + } } } @@ -116,9 +160,5 @@ fn temp_vec_sort(temperature_vec: &mut Vec) { None => Ordering::Equal, }); - temperature_vec.sort_by(|a, b| { - a.component_name - .partial_cmp(&b.component_name) - .unwrap_or(Ordering::Equal) - }); + temperature_vec.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap_or(Ordering::Equal)); } diff --git a/src/bin/main.rs b/src/bin/main.rs index 47572bcf..24aacd2f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -121,6 +121,7 @@ fn main() -> Result<()> { thread_termination_lock.clone(), thread_termination_cvar.clone(), &app.app_config_fields, + app.filters.clone(), app.used_widgets.clone(), ); @@ -192,8 +193,7 @@ fn main() -> Result<()> { // Disk if app.used_widgets.use_disk { - app.canvas_data.disk_data = - convert_disk_row(&app.data_collection, &app.filters.disk_filter); + app.canvas_data.disk_data = convert_disk_row(&app.data_collection); } // Temperatures diff --git a/src/constants.rs b/src/constants.rs index 8f44e427..c50a51d8 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -479,12 +479,21 @@ pub const OLD_CONFIG_TEXT: &str = r##"# This is a default config file for bottom #list = ["/dev/sda\\d+", "/dev/nvme0n1p2"] #regex = true #case_sensitive = false +#whole_word = false #[temp_filter] #is_list_ignored = false #list = ["cpu", "wifi"] #regex = false #case_sensitive = false +#whole_word = false + +#[net_filter] +#is_list_ignored = false +#list = ["virbr0.*"] +#regex = true +#case_sensitive = false +#whole_word = false "##; pub const CONFIG_TOP_HEAD: &str = r##"# This is bottom's config file. diff --git a/src/data_conversion.rs b/src/data_conversion.rs index fb12ba80..c683e62f 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -2,7 +2,7 @@ //! can actually handle. use crate::Pid; use crate::{ - app::{data_farmer, data_harvester, App, Filter, ProcWidgetState}, + app::{data_farmer, data_harvester, App, ProcWidgetState}, utils::{self, gen_util::*}, }; use data_harvester::processes::ProcessSorting; @@ -84,45 +84,20 @@ pub struct ConvertedCpuData { pub fn convert_temp_row(app: &App) -> Vec> { let current_data = &app.data_collection; let temp_type = &app.app_config_fields.temperature_type; - let temp_filter = &app.filters.temp_filter; let mut sensor_vector: Vec> = current_data .temp_harvest .iter() - .filter_map(|temp_harvest| { - let name = match (&temp_harvest.component_name, &temp_harvest.component_label) { - (Some(name), Some(label)) => format!("{}: {}", name, label), - (None, Some(label)) => label.to_string(), - (Some(name), None) => name.to_string(), - (None, None) => String::default(), - }; - - let to_keep = if let Some(temp_filter) = temp_filter { - let mut ret = temp_filter.is_list_ignored; - for r in &temp_filter.list { - if r.is_match(&name) { - ret = !temp_filter.is_list_ignored; - break; - } - } - ret - } else { - true - }; - - if to_keep { - Some(vec![ - name, - (temp_harvest.temperature.ceil() as u64).to_string() - + match temp_type { - data_harvester::temperature::TemperatureType::Celsius => "C", - data_harvester::temperature::TemperatureType::Kelvin => "K", - data_harvester::temperature::TemperatureType::Fahrenheit => "F", - }, - ]) - } else { - None - } + .map(|temp_harvest| { + vec![ + temp_harvest.name.clone(), + (temp_harvest.temperature.ceil() as u64).to_string() + + match temp_type { + data_harvester::temperature::TemperatureType::Celsius => "C", + data_harvester::temperature::TemperatureType::Kelvin => "K", + data_harvester::temperature::TemperatureType::Fahrenheit => "F", + }, + ] }) .collect(); @@ -133,26 +108,12 @@ pub fn convert_temp_row(app: &App) -> Vec> { sensor_vector } -pub fn convert_disk_row( - current_data: &data_farmer::DataCollection, disk_filter: &Option, -) -> Vec> { +pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec> { let mut disk_vector: Vec> = Vec::new(); current_data .disk_harvest .iter() - .filter(|disk_harvest| { - if let Some(disk_filter) = disk_filter { - for r in &disk_filter.list { - if r.is_match(&disk_harvest.name) { - return !disk_filter.is_list_ignored; - } - } - disk_filter.is_list_ignored - } else { - true - } - }) .zip(¤t_data.io_labels) .for_each(|(disk, (io_read, io_write))| { let converted_free_space = get_simple_byte_values(disk.free_space, false); @@ -174,6 +135,10 @@ pub fn convert_disk_row( ]); }); + if disk_vector.is_empty() { + disk_vector.push(vec!["No Disks Found".to_string(), "".to_string()]); + } + disk_vector } diff --git a/src/lib.rs b/src/lib.rs index 1f10990e..120c1c10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -620,7 +620,8 @@ pub fn create_collection_thread( >, control_receiver: std::sync::mpsc::Receiver, termination_ctrl_lock: Arc>, termination_ctrl_cvar: Arc, - app_config_fields: &app::AppConfigFields, used_widget_set: UsedWidgets, + app_config_fields: &app::AppConfigFields, filters: app::DataFilters, + used_widget_set: UsedWidgets, ) -> std::thread::JoinHandle<()> { // trace!("Creating collection thread."); let temp_type = app_config_fields.temperature_type.clone(); @@ -630,7 +631,7 @@ pub fn create_collection_thread( thread::spawn(move || { // trace!("Spawned collection thread."); - let mut data_state = data_harvester::DataCollector::default(); + let mut data_state = data_harvester::DataCollector::new(filters); // trace!("Created default data state."); data_state.set_collected_data(used_widget_set); data_state.set_temperature_type(temp_type); diff --git a/src/options.rs b/src/options.rs index 8301094a..999a8cf1 100644 --- a/src/options.rs +++ b/src/options.rs @@ -30,6 +30,7 @@ pub struct Config { pub row: Option>, pub disk_filter: Option, pub temp_filter: Option, + pub net_filter: Option, } impl Config { @@ -216,6 +217,7 @@ pub struct IgnoreList { pub list: Vec, pub regex: Option, pub case_sensitive: Option, + pub whole_word: Option, } pub fn build_app( @@ -413,6 +415,8 @@ pub fn build_app( get_ignore_list(&config.disk_filter).context("Update 'disk_filter' in your config file")?; let temp_filter = get_ignore_list(&config.temp_filter).context("Update 'temp_filter' in your config file")?; + let net_filter = + get_ignore_list(&config.net_filter).context("Update 'net_filter' in your config file")?; // One more thing - we have to update the search settings of our proc_state_map, and create the hashmaps if needed! // Note that if you change your layout, this might not actually match properly... not sure if/where we should deal with that... @@ -472,6 +476,7 @@ pub fn build_app( .filters(DataFilters { disk_filter, temp_filter, + net_filter, }) .config(config.clone()) .config_path(config_path) @@ -907,17 +912,24 @@ fn get_ignore_list(ignore_list: &Option) -> error::Result