diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ab87f41..b7858102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.1] - ??? + +## Bug Fixes + +## Changes + +## Features + +- [#950](https://github.com/ClementTsang/bottom/pull/950): Split usage into usage percentage and value. + ## [0.7.0] - 2022-12-31 ## Bug Fixes diff --git a/Cargo.lock b/Cargo.lock index 74aac16c..60cced73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,7 +204,7 @@ dependencies = [ [[package]] name = "bottom" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_cmd", diff --git a/Cargo.toml b/Cargo.toml index 19100110..b2384432 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bottom" -version = "0.7.0" +version = "0.7.1" authors = ["Clement Tsang "] edition = "2018" repository = "https://github.com/ClementTsang/bottom" diff --git a/README.md b/README.md index 9851aa35..d3f558cb 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ cargo install bottom ### Arch Linux -There is an official package that can be installed with `pacman`: +There is an [official package](https://archlinux.org/packages/community/x86_64/bottom/) that can be installed with `pacman`: ```bash sudo pacman -Syu bottom diff --git a/src/app.rs b/src/app.rs index 78a64b00..2cfa4ebe 100644 --- a/src/app.rs +++ b/src/app.rs @@ -379,9 +379,9 @@ impl App { .get_mut(&self.current_widget.widget_id) { proc_widget_state.toggle_mem_percentage(); - proc_widget_state.force_data_update(); } } + _ => {} } } @@ -1219,6 +1219,12 @@ impl App { { proc_widget_state.select_column(ProcWidget::PID_OR_COUNT); } + } else if let Some(disk) = self + .disk_state + .get_mut_widget_state(self.current_widget.widget_id) + { + disk.table.set_sort_index(5); + disk.force_data_update(); } } 'P' => { @@ -1302,7 +1308,7 @@ impl App { .disk_state .get_mut_widget_state(self.current_widget.widget_id) { - disk.table.set_sort_index(5); + disk.table.set_sort_index(6); disk.force_data_update(); } } @@ -1311,7 +1317,7 @@ impl App { .disk_state .get_mut_widget_state(self.current_widget.widget_id) { - disk.table.set_sort_index(6); + disk.table.set_sort_index(7); disk.force_data_update(); } } diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 3e9f650f..257157ee 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -90,12 +90,18 @@ impl ConvertedData { .iter() .zip(&data.io_labels) .for_each(|(disk, (io_read, io_write))| { + let summed_total_bytes = match (disk.used_space, disk.free_space) { + (Some(used), Some(free)) => Some(used + free), + _ => None, + }; + self.disk_data.push(DiskWidgetData { name: KString::from_ref(&disk.name), mount_point: KString::from_ref(&disk.mount_point), free_bytes: disk.free_space, used_bytes: disk.used_space, total_bytes: disk.total_space, + summed_total_bytes, io_read: io_read.into(), io_write: io_write.into(), }); diff --git a/src/widgets/disk_table.rs b/src/widgets/disk_table.rs index b2a6db74..b168ac91 100644 --- a/src/widgets/disk_table.rs +++ b/src/widgets/disk_table.rs @@ -20,20 +20,12 @@ pub struct DiskWidgetData { pub free_bytes: Option, pub used_bytes: Option, pub total_bytes: Option, + pub summed_total_bytes: Option, pub io_read: KString, pub io_write: KString, } impl DiskWidgetData { - pub fn free_space(&self) -> KString { - if let Some(free_bytes) = self.free_bytes { - let converted_free_space = get_decimal_bytes(free_bytes); - format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1).into() - } else { - "N/A".into() - } - } - pub fn total_space(&self) -> KString { if let Some(total_bytes) = self.total_bytes { let converted_total_space = get_decimal_bytes(total_bytes); @@ -47,13 +39,57 @@ impl DiskWidgetData { } } - pub fn usage(&self) -> KString { - if let (Some(used_bytes), Some(total_bytes)) = (self.used_bytes, self.total_bytes) { - format!("{:.0}%", used_bytes as f64 / total_bytes as f64 * 100_f64).into() + pub fn free_space(&self) -> KString { + if let Some(free_bytes) = self.free_bytes { + let converted_free_space = get_decimal_bytes(free_bytes); + format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1).into() } else { "N/A".into() } } + + pub fn used_space(&self) -> KString { + if let Some(used_bytes) = self.used_bytes { + let converted_free_space = get_decimal_bytes(used_bytes); + format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1).into() + } else { + "N/A".into() + } + } + + pub fn free_percent(&self) -> Option { + if let (Some(free_bytes), Some(summed_total_bytes)) = + (self.free_bytes, self.summed_total_bytes) + { + Some(free_bytes as f64 / summed_total_bytes as f64 * 100_f64) + } else { + None + } + } + + pub fn free_percent_string(&self) -> KString { + match self.free_percent() { + Some(val) => format!("{:.1}%", val).into(), + None => "N/A".into(), + } + } + + pub fn used_percent(&self) -> Option { + if let (Some(used_bytes), Some(summed_total_bytes)) = + (self.used_bytes, self.summed_total_bytes) + { + Some(used_bytes as f64 / summed_total_bytes as f64 * 100_f64) + } else { + None + } + } + + pub fn used_percent_string(&self) -> KString { + match self.used_percent() { + Some(val) => format!("{:.1}%", val).into(), + None => "N/A".into(), + } + } } pub enum DiskWidgetColumn { @@ -62,6 +98,8 @@ pub enum DiskWidgetColumn { Used, Free, Total, + UsedPercent, + FreePercent, IoRead, IoWrite, } @@ -73,6 +111,8 @@ impl ColumnHeader for DiskWidgetColumn { DiskWidgetColumn::Mount => "Mount(m)", DiskWidgetColumn::Used => "Used(u)", DiskWidgetColumn::Free => "Free(n)", + DiskWidgetColumn::UsedPercent => "Used%(p)", + DiskWidgetColumn::FreePercent => "Free%", DiskWidgetColumn::Total => "Total(t)", DiskWidgetColumn::IoRead => "R/s(r)", DiskWidgetColumn::IoWrite => "W/s(w)", @@ -86,8 +126,14 @@ impl DataToCell for DiskWidgetData { let text = match column { DiskWidgetColumn::Disk => truncate_to_text(&self.name, calculated_width), DiskWidgetColumn::Mount => truncate_to_text(&self.mount_point, calculated_width), - DiskWidgetColumn::Used => truncate_to_text(&self.usage(), calculated_width), + DiskWidgetColumn::Used => truncate_to_text(&self.used_space(), calculated_width), DiskWidgetColumn::Free => truncate_to_text(&self.free_space(), calculated_width), + DiskWidgetColumn::UsedPercent => { + truncate_to_text(&self.used_percent_string(), calculated_width) + } + DiskWidgetColumn::FreePercent => { + truncate_to_text(&self.free_percent_string(), calculated_width) + } DiskWidgetColumn::Total => truncate_to_text(&self.total_space(), calculated_width), DiskWidgetColumn::IoRead => truncate_to_text(&self.io_read, calculated_width), DiskWidgetColumn::IoWrite => truncate_to_text(&self.io_write, calculated_width), @@ -132,9 +178,19 @@ impl SortsRow for DiskWidgetColumn { DiskWidgetColumn::Used => { data.sort_by(|a, b| sort_partial_fn(descending)(&a.used_bytes, &b.used_bytes)); } + DiskWidgetColumn::UsedPercent => { + data.sort_by(|a, b| { + sort_partial_fn(descending)(&a.used_percent(), &b.used_percent()) + }); + } DiskWidgetColumn::Free => { data.sort_by(|a, b| sort_partial_fn(descending)(&a.free_bytes, &b.free_bytes)); } + DiskWidgetColumn::FreePercent => { + data.sort_by(|a, b| { + sort_partial_fn(descending)(&a.free_percent(), &b.free_percent()) + }); + } DiskWidgetColumn::Total => { data.sort_by(|a, b| sort_partial_fn(descending)(&a.total_bytes, &b.total_bytes)); } @@ -156,6 +212,7 @@ impl DiskTableWidget { SortColumn::hard(DiskWidgetColumn::Used, 8).default_descending(), SortColumn::hard(DiskWidgetColumn::Free, 8).default_descending(), SortColumn::hard(DiskWidgetColumn::Total, 9).default_descending(), + SortColumn::hard(DiskWidgetColumn::UsedPercent, 9).default_descending(), SortColumn::hard(DiskWidgetColumn::IoRead, 10).default_descending(), SortColumn::hard(DiskWidgetColumn::IoWrite, 11).default_descending(), ];