Skip to content

Commit

Permalink
feature: Add ability to filter out disks and temp (#220)
Browse files Browse the repository at this point in the history
You can now filter out disks and temp sensors by name via config.
  • Loading branch information
ClementTsang authored Sep 3, 2020
1 parent a949073 commit cef3166
Show file tree
Hide file tree
Showing 20 changed files with 217 additions and 52 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"crossterm",
"curr",
"czvf",
"denylist",
"fpath",
"fract",
"gnueabihf",
Expand All @@ -57,6 +58,7 @@
"noheader",
"ntdef",
"nuget",
"nvme",
"paren",
"pmem",
"prepush",
Expand All @@ -82,6 +84,7 @@
"virt",
"vsize",
"whitespaces",
"wifi",
"winapi",
"winget",
"winnt",
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- [#208](https://github.com/ClementTsang/bottom/pull/208): Mouse support for tables and moving to widgets.

- [#217](https://github.com/ClementTsang/bottom/pull/217): Unofficial ARM support.

- [#220](https://github.com/ClementTsang/bottom/pull/220): Add ability to hide specific temperature and disk entries via config.

### Changes

- [#213](https://github.com/ClementTsang/bottom/pull/213), [#214](https://github.com/ClementTsang/bottom/pull/214): Updated help descriptions, added auto-complete generation.
Expand Down
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ If you want to help contribute by submitting a PR, by all means, I'm open! In re

- You can check clippy using `cargo clippy`.

- I use [cargo-husky](https://github.com/rhysd/cargo-husky) to automatically run a clippy check on push. You can disable this in the `Cargo.toml` file if you find this annoying.
- I use [cargo-husky](https://github.com/rhysd/cargo-husky) to automatically run a `cargo clippy` and `cargo test` check.

- You may notice that I have fern and log as dependencies; this is mostly for easy debugging via the `debug!()` macro. It writes to the
`debug.log` file that will automatically be created if you run in debug mode (so `cargo run`).
- You may notice that I have fern and log as dependencies; this is mostly for easy debugging via the `debug!()` macro. It writes to the `debug.log` file that will automatically be created if you run in debug mode (so `cargo run`).

And in regards to the pull request process:

Expand Down
57 changes: 50 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,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)
- [Battery](#battery)
- [Compatibility](#compatibility)
- [Contribution](#contribution)
Expand Down Expand Up @@ -352,16 +353,16 @@ Note that the `and` operator takes precedence over the `or` operator.

#### General

| | |
| ------------ | --------------------------------------------------------------------------------------------------------------------- |
| Mouse scroll | Table: Scroll<br>Chart: Zooms in or out by scrolling up or down respectively |
| Mouse click | Selects the clicked widget. For tables, clicking can also select a specific entry. Can be disabled via options/flags. |
| | |
| ------ | ---------------------------------------------------------------------------------------------------------------- |
| Scroll | Table: Scroll<br>Chart: Zooms in or out by scrolling up or down respectively |
| Click | Selects the clicked widget. For tables, clicking can also select an entry.<br>Can be disabled via options/flags. |

#### CPU bindings

| | |
| ------------ | --------------------------------------------------------------------- |
| Mouse scroll | Scrolling over an CPU core/average shows only that entry on the chart |
| | |
| ------ | --------------------------------------------------------------------- |
| Scroll | Scrolling over an CPU core/average shows only that entry on the chart |

## Features

Expand Down Expand Up @@ -596,6 +597,48 @@ 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

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.

For example, let's say , given this disk list:

![Disk filter not ignoring list](./assets/disk_filter_pre.png)

I wish to _only_ show disks that follow the form `/dev/sda\d+`, or `/dev/nvme0n1p2`:

```toml
[disk_filter]
is_list_ignored = false
list = ["/dev/sda\\d+", "/dev/nvme0n1p2"]
regex = true
```

![Disk filter not ignoring list](./assets/disk_filter_post.png)

This would ignore anything that does not match either of these two conditions. If I instead wish to ignore anything that matches this list, then I can set `is_list_ignored = true` instead:

![Disk filter ignoring list](./assets/disk_filter_post2.png)

Likewise, I can do something similar for `temp_filter`:

![Temp filter before](./assets/temp_filter_pre.png)

If I, say, only wanted to see any entry with the words "cpu" or "wifi" in it, case sensitive:

```toml
[temp_filter]
is_list_ignored = false
list = ["cpu", "wifi"]
case_sensitive = true
```

![Temp filter after](./assets/temp_filter_post.png)

Now, flipping to `case_sensitive = false` would instead show:

![Temp filter after with case sensitivity off](./assets/temp_filter_post2.png)

### Battery

You can get battery statistics (charge, time to fill/discharge, consumption in watts, and battery health) via the battery widget.
Expand Down
Binary file added assets/disk_filter_post.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/disk_filter_post2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/disk_filter_pre.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/summary_and_search.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/temp_filter_post.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/temp_filter_post2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/temp_filter_pre.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 19 additions & 7 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ pub struct AppConfigFields {
pub disable_click: bool,
}

/// For filtering out information
pub struct DataFilters {
pub disk_filter: Option<Filter>,
pub temp_filter: Option<Filter>,
}

#[derive(Debug)]
pub struct Filter {
pub is_list_ignored: bool,
pub list: Vec<regex::Regex>,
}

#[derive(TypedBuilder)]
pub struct App {
#[builder(default = false, setter(skip))]
Expand Down Expand Up @@ -99,6 +111,7 @@ pub struct App {
pub widget_map: HashMap<u64, BottomWidget>,
pub current_widget: BottomWidget,
pub used_widgets: UsedWidgets,
pub filters: DataFilters,
}

impl App {
Expand Down Expand Up @@ -312,10 +325,9 @@ impl App {

pub fn toggle_sort(&mut self) {
match &self.current_widget.widget_type {
// FIXME: [REFACTOR] Remove these @'s if unneeded, they were an idea but they're ultimately useless for me here...?
widget_type @ BottomWidgetType::Proc | widget_type @ BottomWidgetType::ProcSort => {
BottomWidgetType::Proc | BottomWidgetType::ProcSort => {
let widget_id = self.current_widget.widget_id
- match &widget_type {
- match &self.current_widget.widget_type {
BottomWidgetType::Proc => 0,
BottomWidgetType::ProcSort => 2,
_ => 0,
Expand Down Expand Up @@ -348,9 +360,9 @@ impl App {

pub fn invert_sort(&mut self) {
match &self.current_widget.widget_type {
widget_type @ BottomWidgetType::Proc | widget_type @ BottomWidgetType::ProcSort => {
BottomWidgetType::Proc | BottomWidgetType::ProcSort => {
let widget_id = self.current_widget.widget_id
- match &widget_type {
- match &self.current_widget.widget_type {
BottomWidgetType::Proc => 0,
BottomWidgetType::ProcSort => 2,
_ => 0,
Expand Down Expand Up @@ -1571,9 +1583,9 @@ impl App {
}
}
WidgetDirection::Down => match &self.current_widget.widget_type {
proc_type @ BottomWidgetType::Proc | proc_type @ BottomWidgetType::ProcSort => {
BottomWidgetType::Proc | BottomWidgetType::ProcSort => {
let widget_id = self.current_widget.widget_id
- match proc_type {
- match &self.current_widget.widget_type {
BottomWidgetType::ProcSort => 2,
_ => 0,
};
Expand Down
4 changes: 3 additions & 1 deletion src/app/data_harvester/disks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ pub async fn get_sysinfo_disk_usage_list(
name: disk.get_name().to_string_lossy().into(),
mount_point: disk.get_mount_point().to_string_lossy().into(),
free_space: disk.get_available_space(),
used_space: disk.get_total_space() - disk.get_available_space(),
used_space: disk
.get_total_space()
.saturating_sub(disk.get_available_space()),
total_space: disk.get_total_space(),
})
.collect::<Vec<DiskHarvest>>();
Expand Down
8 changes: 3 additions & 5 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ fn main() -> Result<()> {
create_event_thread(
sender,
reset_receiver,
app.app_config_fields.use_current_cpu_total,
app.app_config_fields.update_rate_in_milliseconds,
app.app_config_fields.temperature_type.clone(),
app.app_config_fields.show_average_cpu,
&app.app_config_fields,
app.used_widgets.clone(),
);

Expand Down Expand Up @@ -151,7 +148,8 @@ fn main() -> Result<()> {

// Disk
if app.used_widgets.use_disk {
app.canvas_data.disk_data = convert_disk_row(&app.data_collection);
app.canvas_data.disk_data =
convert_disk_row(&app.data_collection, &app.filters.disk_filter);
}

// Temperatures
Expand Down
4 changes: 2 additions & 2 deletions src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,9 @@ impl Painter {
app_state.current_widget.widget_id,
false,
),
proc_type @ Proc | proc_type @ ProcSearch | proc_type @ ProcSort => {
Proc | ProcSearch | ProcSort => {
let widget_id = app_state.current_widget.widget_id
- match proc_type {
- match &app_state.current_widget.widget_type {
ProcSearch => 1,
ProcSort => 2,
_ => 0,
Expand Down
1 change: 0 additions & 1 deletion src/canvas/widgets/network_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ impl NetworkGraphWidget for Painter {
// Update draw loc in widget map
// Note that in both cases, we always go to the same widget id so it's fine to do it like
// this lol.
debug!("!@#!@");
if let Some(network_widget) = app_state.widget_map.get_mut(&widget_id) {
network_widget.top_left_corner = Some((draw_loc.x, draw_loc.y));
network_widget.bottom_right_corner =
Expand Down
1 change: 1 addition & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ pub const DEFAULT_BATTERY_LAYOUT: &str = r##"
pub const DEFAULT_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";

// Default config file
// FIXME: Update the default config
pub const DEFAULT_CONFIG_CONTENT: &str = r##"
# This is a default config file for bottom. All of the settings are commented
# out by default; if you wish to change them uncomment and modify as you see
Expand Down
83 changes: 60 additions & 23 deletions src/data_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::collections::HashMap;

use crate::{
app::{data_farmer, data_harvester, App},
app::{data_farmer, data_harvester, App, Filter},
utils::gen_util::*,
};

Expand Down Expand Up @@ -83,40 +83,77 @@ pub struct ConvertedCpuData {
}

pub fn convert_temp_row(app: &App) -> Vec<Vec<String>> {
let mut sensor_vector: Vec<Vec<String>> = Vec::new();

let current_data = &app.data_collection;
let temp_type = &app.app_config_fields.temperature_type;
let temp_filter = &app.filters.temp_filter;

if current_data.temp_harvest.is_empty() {
sensor_vector.push(vec!["No Sensors Found".to_string(), "".to_string()])
} else {
for sensor in &current_data.temp_harvest {
sensor_vector.push(vec![
match (&sensor.component_name, &sensor.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(),
},
(sensor.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",
},
]);
}
let mut sensor_vector: Vec<Vec<String>> = 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
}
})
.collect();

if sensor_vector.is_empty() {
sensor_vector.push(vec!["No Sensors Found".to_string(), "".to_string()]);
}

sensor_vector
}

pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<String>> {
pub fn convert_disk_row(
current_data: &data_farmer::DataCollection, disk_filter: &Option<Filter>,
) -> Vec<Vec<String>> {
let mut disk_vector: Vec<Vec<String>> = 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(&current_data.io_labels)
.for_each(|(disk, (io_read, io_write))| {
let converted_free_space = get_simple_byte_values(disk.free_space, false);
Expand Down
11 changes: 8 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,16 +687,21 @@ pub fn create_event_thread(
sender: std::sync::mpsc::Sender<
BottomEvent<crossterm::event::KeyEvent, crossterm::event::MouseEvent>,
>,
reset_receiver: std::sync::mpsc::Receiver<ResetEvent>, use_current_cpu_total: bool,
update_rate_in_milliseconds: u64, temp_type: data_harvester::temperature::TemperatureType,
show_average_cpu: bool, used_widget_set: UsedWidgets,
reset_receiver: std::sync::mpsc::Receiver<ResetEvent>,
app_config_fields: &app::AppConfigFields, used_widget_set: UsedWidgets,
) {
let temp_type = app_config_fields.temperature_type.clone();
let use_current_cpu_total = app_config_fields.use_current_cpu_total;
let show_average_cpu = app_config_fields.show_average_cpu;
let update_rate_in_milliseconds = app_config_fields.update_rate_in_milliseconds;

thread::spawn(move || {
let mut data_state = data_harvester::DataCollector::default();
data_state.set_collected_data(used_widget_set);
data_state.set_temperature_type(temp_type);
data_state.set_use_current_cpu_total(use_current_cpu_total);
data_state.set_show_average_cpu(show_average_cpu);

data_state.init();
loop {
if let Ok(message) = reset_receiver.try_recv() {
Expand Down
Loading

0 comments on commit cef3166

Please sign in to comment.