feature: split usage into usage percentage and value (#950)

Denotes both usage and usage percentage. This also redoes the calculation for percentage to be based on the sum of avail + used, rather than on total, as otherwise we get potentially confusing percentages.
This commit is contained in:
Clement Tsang 2023-01-01 05:08:04 -05:00 committed by GitHub
parent d7e9fd6be0
commit a56e7f6cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 19 deletions

View File

@ -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

2
Cargo.lock generated
View File

@ -204,7 +204,7 @@ dependencies = [
[[package]]
name = "bottom"
version = "0.7.0"
version = "0.7.1"
dependencies = [
"anyhow",
"assert_cmd",

View File

@ -1,6 +1,6 @@
[package]
name = "bottom"
version = "0.7.0"
version = "0.7.1"
authors = ["Clement Tsang <cjhtsang@uwaterloo.ca>"]
edition = "2018"
repository = "https://github.com/ClementTsang/bottom"

View File

@ -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

View File

@ -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();
}
}

View File

@ -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(),
});

View File

@ -20,20 +20,12 @@ pub struct DiskWidgetData {
pub free_bytes: Option<u64>,
pub used_bytes: Option<u64>,
pub total_bytes: Option<u64>,
pub summed_total_bytes: Option<u64>,
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<f64> {
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<f64> {
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<DiskWidgetColumn> 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(),
];