diff --git a/CHANGELOG.md b/CHANGELOG.md index 7aecdc8c..fa4428b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,8 @@ That said, these are more guidelines rather than hard rules, though the project - [#2239](https://github.com/ClementTsang/bottom/pull/2239): Initial Intel GPU support for Linux to get process GPU usage. - [#2245](https://github.com/ClementTsang/bottom/pull/2245): Support solid bars using block and square characters via `styles.widgets.bar_type`. -- [#2236](https://github.com/ClementTsang/bottom/pull/2236): Add configurable binary disk capacity units for usage. +- [#2236](https://github.com/ClementTsang/bottom/pull/2236): Add configurable binary disk capacity units for disk widget usage. +- [#2251](https://github.com/ClementTsang/bottom/pull/2251): Add configurable binary disk capacity units for disk widget I/O. ### Other diff --git a/docs/content/configuration/command-line-options.md b/docs/content/configuration/command-line-options.md index bd85bd50..00162ac9 100644 --- a/docs/content/configuration/command-line-options.md +++ b/docs/content/configuration/command-line-options.md @@ -27,9 +27,9 @@ see information on these options by running `btm -h`, or run `btm --help` to dis ## Disk Options -| Option | Behaviour | -| -------------------------- | --------------------------------------------------------------- | -| `--disk_use_binary_prefix` | Displays used, free, and total disk space with binary prefixes. | +| Option | Behaviour | +| -------------------------- | -------------------------------------------------------------------------------------------------------- | +| `--disk_use_binary_prefix` | Displays the disk widget with binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB). | ## Process Options @@ -77,15 +77,15 @@ see information on these options by running `btm -h`, or run `btm --help` to dis ## Network Options -| Option | Behaviour | -| ----------------------------- | -------------------------------------------------------------- | -| `--network_legend ` | Where to place the legend for the network chart widget. | -| `--network_use_bytes` | Displays the network widget using bytes. | -| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. | -| `--network_use_log` | Displays the network widget with a log scale. | -| `--show_packets` | Displays packet rate and average packet size info. | -| `--use_old_network_legend` | Uses a separate network legend. | -| `--network_start_zeroed` | Show total network usage from app startup rather than on boot. | +| Option | Behaviour | +| ----------------------------- | ------------------------------------------------------------------------------------------------------ | +| `--network_legend ` | Where to place the legend for the network chart widget. | +| `--network_use_bytes` | Displays the network widget using bytes. | +| `--network_use_binary_prefix` | Displays the network widget binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB). | +| `--network_use_log` | Displays the network widget with a log scale. | +| `--show_packets` | Displays packet rate and average packet size info. | +| `--use_old_network_legend` | Uses a separate network legend. | +| `--network_start_zeroed` | Show total network usage from app startup rather than on boot. | ## Battery Options diff --git a/docs/content/configuration/config-file/disk-table.md b/docs/content/configuration/config-file/disk-table.md index 8c8d789a..c7ff97bb 100644 --- a/docs/content/configuration/config-file/disk-table.md +++ b/docs/content/configuration/config-file/disk-table.md @@ -30,10 +30,10 @@ You can also set the sort order by changing `disk.sort_order` with `"Ascending"` sort_order = "Ascending" ``` -## Disk Space Units +## Using Binary Prefixes -Disk space uses decimal prefixes (KB, MB, GB, TB) by default. To display the Used, Free, and Total columns -with binary prefixes (KiB, MiB, GiB, TiB), enable `use_binary_prefix`: +Disk space uses decimal prefixes (e.g. KB, MB, GB, TB) by default. To display using binary prefixes instead +(e.g. KiB, MiB, GiB, TiB), enable `use_binary_prefix`: ```toml [disk] diff --git a/sample_configs/default_config.toml b/sample_configs/default_config.toml index e79ad8b2..c75fd97d 100644 --- a/sample_configs/default_config.toml +++ b/sample_configs/default_config.toml @@ -155,7 +155,6 @@ # Where to place the legend for the network widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right". #network_legend = "top-right" - # Processes widget configuration #[processes] # The columns shown by the process widget. The following columns are supported (the GPU columns are only available if the GPU feature is enabled when built): @@ -209,7 +208,6 @@ # Show process CPU% usage without averaging over the number of CPU cores. #unnormalized_cpu = false - # CPU widget configuration #[cpu] # One of "all" (default), "average"/"avg" @@ -218,11 +216,10 @@ # Whether to show a decimal place for CPU usage values. #show_decimal = false - # Disk widget configuration #[disk] -# Whether to display used, free, and total disk space with binary prefixes (e.g. GiB instead of GB). +# Whether to display disk widget data with binary prefixes (e.g. GiB instead of GB). #use_binary_prefix = false # The columns shown by the process widget. The following columns are supported: @@ -277,7 +274,6 @@ # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Disk I/O graph widget configuration #[disk_io_graph] @@ -316,7 +312,6 @@ # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Temperature widget configuration #[temperature] @@ -347,7 +342,6 @@ # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Temperature graph widget configuration #[temperature_graph] @@ -375,7 +369,6 @@ # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Memory widget configuration #[memory_graph] @@ -391,7 +384,6 @@ # Use short GPU names (e.g. "GPU" or "GPU0", "GPU1") instead of full GPU names. Only available if the GPU feature is enabled when built. #short_gpu_names = false - # Network widget configuration #[network_graph] @@ -418,7 +410,6 @@ # Whether to require matching the whole word. Defaults to false. #whole_word = false - # These are all the components that support custom theming. Note that colour support # will depend on terminal support. #[styles] # Uncomment if you want to use custom styling diff --git a/schema/nightly/bottom.json b/schema/nightly/bottom.json index ab988680..da0fd0cb 100644 --- a/schema/nightly/bottom.json +++ b/schema/nightly/bottom.json @@ -301,7 +301,7 @@ "$ref": "#/$defs/SortOrder" }, "use_binary_prefix": { - "description": "Displays used, free, and total disk space with binary prefixes (e.g. GiB).\nDefaults to decimal prefixes (e.g. GB).", + "description": "Use binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB).\n\nDefaults to decimal prefixes.", "type": [ "boolean", "null" diff --git a/src/constants.rs b/src/constants.rs index f9553e6b..d6a29a66 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -404,7 +404,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Where to place the legend for the network widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right". #network_legend = "top-right" - # Processes widget configuration #[processes] # The columns shown by the process widget. The following columns are supported (the GPU columns are only available if the GPU feature is enabled when built): @@ -458,7 +457,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Show process CPU% usage without averaging over the number of CPU cores. #unnormalized_cpu = false - # CPU widget configuration #[cpu] # One of "all" (default), "average"/"avg" @@ -467,11 +465,10 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to show a decimal place for CPU usage values. #show_decimal = false - # Disk widget configuration #[disk] -# Whether to display used, free, and total disk space with binary prefixes (e.g. GiB instead of GB). +# Whether to display disk widget data with binary prefixes (e.g. GiB instead of GB). #use_binary_prefix = false # The columns shown by the process widget. The following columns are supported: @@ -526,7 +523,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Disk I/O graph widget configuration #[disk_io_graph] @@ -565,7 +561,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Temperature widget configuration #[temperature] @@ -596,7 +591,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Temperature graph widget configuration #[temperature_graph] @@ -624,7 +618,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to require matching the whole word. Defaults to false. #whole_word = false - # Memory widget configuration #[memory_graph] @@ -640,7 +633,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Use short GPU names (e.g. "GPU" or "GPU0", "GPU1") instead of full GPU names. Only available if the GPU feature is enabled when built. #short_gpu_names = false - # Network widget configuration #[network_graph] @@ -667,7 +659,6 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott # Whether to require matching the whole word. Defaults to false. #whole_word = false - # These are all the components that support custom theming. Note that colour support # will depend on terminal support. #[styles] # Uncomment if you want to use custom styling diff --git a/src/options/args.rs b/src/options/args.rs index 93371694..a6ca0cad 100644 --- a/src/options/args.rs +++ b/src/options/args.rs @@ -562,9 +562,8 @@ pub struct DiskArgs { #[arg( long, action = ArgAction::SetTrue, - help = "Displays disk space with binary prefixes.", - long_help = "Displays used, free, and total disk space with binary prefixes (e.g. KiB, MiB, GiB) \ - rather than decimal prefixes (e.g. KB, MB, GB). Defaults to decimal prefixes.", + help = "Displays the disk widget with binary prefixes.", + long_help = "Displays the disk widget with binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB).", alias = "disk-use-binary-prefix" )] pub disk_use_binary_prefix: bool, @@ -598,8 +597,7 @@ pub struct NetworkArgs { long, action = ArgAction::SetTrue, help = "Displays the network widget with binary prefixes.", - long_help = "Displays the network widget with binary prefixes (e.g. kibibits, mebibits) rather than a decimal \ - prefixes (e.g. kilobits, megabits). Defaults to decimal prefixes.", + long_help = "Displays the network widget binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB).", alias = "network-use-binary-prefix" )] pub network_use_binary_prefix: bool, diff --git a/src/options/config/disk.rs b/src/options/config/disk.rs index 03c940c5..db7102f8 100644 --- a/src/options/config/disk.rs +++ b/src/options/config/disk.rs @@ -8,8 +8,9 @@ use crate::{canvas::components::data_table::SortOrder, options::DiskWidgetColumn #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] #[cfg_attr(test, serde(deny_unknown_fields), derive(PartialEq, Eq))] pub(crate) struct DiskConfig { - /// Displays used, free, and total disk space with binary prefixes (e.g. GiB). - /// Defaults to decimal prefixes (e.g. GB). + /// Use binary prefixes (e.g. GiB, MiB) instead of decimal prefixes (e.g. GB, MB). + /// + /// Defaults to decimal prefixes. pub(crate) use_binary_prefix: Option, /// A filter over the disk names. diff --git a/src/utils/conversion.rs b/src/utils/conversion.rs index b720a1a3..795435cf 100644 --- a/src/utils/conversion.rs +++ b/src/utils/conversion.rs @@ -20,9 +20,9 @@ pub(crate) fn get_binary_unit_and_denominator(bytes: u64) -> (&'static str, f64) } } -/// Returns a string given a value that is converted to the closest SI-variant, -/// per second. If the value is greater than a giga-X, then it will return a -/// decimal place. +/// Returns a decimal-prefixed string given a value that is converted to the +/// closest SI-variant, per second. If the value is greater than a giga-X, +/// then it will return a decimal place. #[inline] pub(crate) fn dec_bytes_per_second_string(value: u64) -> String { let converted_values = get_decimal_bytes(value); @@ -33,6 +33,19 @@ pub(crate) fn dec_bytes_per_second_string(value: u64) -> String { } } +/// Returns a binary-prefixed string given a value that is converted to the +/// closest IEC-variant, per second. If the value is greater than a gibi-X, +/// then it will return a decimal place. +#[inline] +pub(crate) fn bin_bytes_per_second_string(value: u64) -> String { + let converted_values = get_binary_bytes(value); + if value >= GIBI_LIMIT { + format!("{:.1}{}/s", converted_values.0, converted_values.1) + } else { + format!("{:.0}{}/s", converted_values.0, converted_values.1) + } +} + #[cfg(test)] mod test { use super::*; @@ -71,4 +84,59 @@ mod test { "10.4TB/s".to_string() ); } + + #[test] + fn test_bin_bytes_per_second_string() { + assert_eq!(bin_bytes_per_second_string(0), "0B/s".to_string()); + assert_eq!(bin_bytes_per_second_string(1), "1B/s".to_string()); + assert_eq!(bin_bytes_per_second_string(900), "900B/s".to_string()); + assert_eq!( + bin_bytes_per_second_string(KILO_LIMIT), + "1000B/s".to_string() + ); + assert_eq!(bin_bytes_per_second_string(1023), "1023B/s".to_string()); + assert_eq!( + bin_bytes_per_second_string(KIBI_LIMIT), + "1KiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string(KIBI_LIMIT + 1), + "1KiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string(MEBI_LIMIT), + "1MiB/s".to_string() + ); + + // The decimal place is added past a gibibyte, not a gigabyte. + assert_eq!( + bin_bytes_per_second_string(GIGA_LIMIT), + "954MiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string(GIBI_LIMIT - 1), + "1024MiB/s".to_string() + ); + + assert_eq!( + bin_bytes_per_second_string(GIBI_LIMIT), + "1.0GiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string(2 * GIBI_LIMIT), + "2.0GiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string((2.5 * GIBI_LIMIT as f64) as u64), + "2.5GiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string((10.34 * TEBI_LIMIT as f64) as u64), + "10.3TiB/s".to_string() + ); + assert_eq!( + bin_bytes_per_second_string((10.36 * TEBI_LIMIT as f64) as u64), + "10.4TiB/s".to_string() + ); + } } diff --git a/src/widgets/disk_table.rs b/src/widgets/disk_table.rs index d52d9256..1ace4d76 100644 --- a/src/widgets/disk_table.rs +++ b/src/widgets/disk_table.rs @@ -10,13 +10,16 @@ use crate::{ }, options::config::style::Styles, utils::{ - conversion::dec_bytes_per_second_string, data_units::convert_bytes, + conversion::{bin_bytes_per_second_string, dec_bytes_per_second_string}, + data_units::convert_bytes, general::sort_partial_fn, }, }; #[derive(Clone, Debug)] pub struct DiskWidgetData { + // TODO: Remove this field, carry it through the widget configuration + // rather than data (requires some refactoring) pub use_binary_prefix: bool, pub name: String, pub mount_point: String, @@ -86,13 +89,21 @@ impl DiskWidgetData { fn io_read(&self) -> Cow<'static, str> { self.io_read_rate_bytes.map_or("N/A".into(), |r_rate| { - dec_bytes_per_second_string(r_rate).into() + if self.use_binary_prefix { + bin_bytes_per_second_string(r_rate).into() + } else { + dec_bytes_per_second_string(r_rate).into() + } }) } fn io_write(&self) -> Cow<'static, str> { self.io_write_rate_bytes.map_or("N/A".into(), |w_rate| { - dec_bytes_per_second_string(w_rate).into() + if self.use_binary_prefix { + bin_bytes_per_second_string(w_rate).into() + } else { + dec_bytes_per_second_string(w_rate).into() + } }) } } @@ -431,7 +442,7 @@ mod test { } } - fn cell(data: &DiskWidgetData, column: DiskWidgetColumn) -> Cow<'static, str> { + fn render_cell(data: &DiskWidgetData, column: DiskWidgetColumn) -> Cow<'static, str> { data.to_cell_text(&column, NonZeroU16::new(10).unwrap()) .unwrap() } @@ -455,7 +466,7 @@ mod test { DiskWidgetColumn::Free, DiskWidgetColumn::Total, ] { - assert_eq!(cell(&data, column), expected); + assert_eq!(render_cell(&data, column), expected); } } } @@ -474,15 +485,20 @@ mod test { DiskWidgetColumn::IoRead, DiskWidgetColumn::IoWrite, ] { - assert_eq!(cell(&missing, column), "N/A"); + assert_eq!(render_cell(&missing, column), "N/A"); } let data = disk(Some(500 * GIBI_LIMIT), use_binary_prefix); - assert_eq!(cell(&data, DiskWidgetColumn::UsedPercent), "50.0%"); - assert_eq!(cell(&data, DiskWidgetColumn::FreePercent), "50.0%"); - assert_eq!(cell(&data, DiskWidgetColumn::IoRead), "536.9GB/s"); - assert_eq!(cell(&data, DiskWidgetColumn::IoWrite), "536.9GB/s"); + assert_eq!(render_cell(&data, DiskWidgetColumn::UsedPercent), "50.0%"); + assert_eq!(render_cell(&data, DiskWidgetColumn::FreePercent), "50.0%"); + if use_binary_prefix { + assert_eq!(render_cell(&data, DiskWidgetColumn::IoRead), "500.0GiB/s"); + assert_eq!(render_cell(&data, DiskWidgetColumn::IoWrite), "500.0GiB/s"); + } else { + assert_eq!(render_cell(&data, DiskWidgetColumn::IoRead), "536.9GB/s"); + assert_eq!(render_cell(&data, DiskWidgetColumn::IoWrite), "536.9GB/s"); + } assert_eq!( - cell( + render_cell( &disk(Some(0), use_binary_prefix), DiskWidgetColumn::UsedPercent ),