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:
parent
d7e9fd6be0
commit
a56e7f6cc9
10
CHANGELOG.md
10
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
|
||||
|
|
|
@ -204,7 +204,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bottom"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
12
src/app.rs
12
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
});
|
||||
|
|
|
@ -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(),
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue