Skip to content

Commit

Permalink
feature: add the ability to configure the disk widget's table columns (
Browse files Browse the repository at this point in the history
…#1625)

* a bit of refactoring here...

* some refactoring, add columns

* cleanup

* add disk column feature

* update changelog
  • Loading branch information
ClementTsang authored Nov 18, 2024
1 parent c8cba49 commit 196d6d1
Show file tree
Hide file tree
Showing 21 changed files with 413 additions and 154 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ That said, these are more guidelines rather than hardset rules, though the proje

## [0.11.0] - Unreleased

### Features

- [#1625](https://github.com/ClementTsang/bottom/pull/1625): Add the ability to configure the disk widget's table columns.

### Bug Fixes

- [#1551](https://github.com/ClementTsang/bottom/pull/1551): Fix missing parent section names in default config.
Expand Down
63 changes: 59 additions & 4 deletions sample_configs/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,156 +8,211 @@
[flags]
# Whether to hide the average cpu entry.
#hide_avg_cpu = false

# Whether to use dot markers rather than braille.
#dot_marker = false

# The update rate of the application.
#rate = "1s"

# Whether to put the CPU legend to the left.
#cpu_left_legend = false

# Whether to set CPU% on a process to be based on the total CPU or just current usage.
#current_usage = false

# Whether to set CPU% on a process to be based on the total CPU or per-core CPU% (not divided by the number of cpus).
#unnormalized_cpu = false

# Whether to group processes with the same name together by default.
#group_processes = false

# Whether to make process searching case sensitive by default.
#case_sensitive = false

# Whether to make process searching look for matching the entire word by default.
#whole_word = false

# Whether to make process searching use regex by default.
#regex = false

# The temperature unit. One of the following, defaults to "c" for Celsius:
#temperature_type = "c"
##temperature_type = "k"
##temperature_type = "f"
##temperature_type = "kelvin"
##temperature_type = "fahrenheit"
##temperature_type = "celsius"

# The default time interval (in milliseconds).
#default_time_value = "60s"

# The time delta on each zoom in/out action (in milliseconds).
#time_delta = 15000

# Hides the time scale.
#hide_time = false

# Override layout default widget
#default_widget_type = "proc"
#default_widget_count = 1

# Expand selected widget upon starting the app
#expanded = true

# Use basic mode
#basic = false

# Use the old network legend style
#use_old_network_legend = false

# Remove space in tables
#hide_table_gap = false

# Show the battery widgets
#battery = false

# Disable mouse clicks
#disable_click = false

# Show memory values in the processes widget as values by default
#process_memory_as_value = false

# Show tree mode by default in the processes widget.
#tree = false

# Shows an indicator in table widgets tracking where in the list you are.
#show_table_scroll_position = false

# Show processes as their commands by default in the process widget.
#process_command = false

# Displays the network widget with binary prefixes.
#network_use_binary_prefix = false

# Displays the network widget using bytes.
#network_use_bytes = false

# Displays the network widget with a log scale.
#network_use_log = false

# Hides advanced options to stop a process on Unix-like systems.
#disable_advanced_kill = false

# Hide GPU(s) information
#disable_gpu = false

# Shows cache and buffer memory
#enable_cache_memory = false

# How much data is stored at once in terms of time.
#retention = "10m"

# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
#memory_legend = "top-right"

# 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):
# PID, Name, CPU%, Mem%, R/s, W/s, T.Read, T.Write, User, State, Time, GMem%, GPU%
#columns = ["PID", "Name", "CPU%", "Mem%", "R/s", "W/s", "T.Read", "T.Write", "User", "State", "GMem%", "GPU%"]


# CPU widget configuration
#[cpu]
# One of "all" (default), "average"/"avg"
# default = "average"
#default = "average"


# Disk widget configuration
#[disk]
# The columns shown by the process widget. The following columns are supported:
# Disk, Mount, Used, Free, Total, Used%, Free%, R/s, W/s
#columns = ["Disk", "Mount", "Used", "Free", "Total", "Used%", "R/s", "W/s"]

# By default, there are no disk name filters enabled. These can be turned on to filter out specific data entries if you
# don't want to see them. An example use case is provided below.
#[disk.name_filter]
# Whether to ignore any matches. Defaults to true.
#is_list_ignored = true

# A list of filters to try and match.
#list = ["/dev/sda\\d+", "/dev/nvme0n1p2"]

# Whether to use regex. Defaults to false.
#regex = true

# Whether to be case-sensitive. Defaults to false.
#case_sensitive = false

# Whether to be require matching the whole word. Defaults to false.
#whole_word = false

# By default, there are no mount name filters enabled. An example use case is provided below.
#[disk.mount_filter]
# Whether to ignore any matches. Defaults to true.
#is_list_ignored = true

# A list of filters to try and match.
#list = ["/mnt/.*", "/boot"]

# Whether to use regex. Defaults to false.
#regex = true

# Whether to be case-sensitive. Defaults to false.
#case_sensitive = false

# Whether to be require matching the whole word. Defaults to false.
#whole_word = false


# Temperature widget configuration
#[temperature]

# By default, there are no temperature sensor filters enabled. An example use case is provided below.
#[temperature.sensor_filter]
# Whether to ignore any matches. Defaults to true.
#is_list_ignored = true

# A list of filters to try and match.
#list = ["cpu", "wifi"]

# Whether to use regex. Defaults to false.
#regex = false

# Whether to be case-sensitive. Defaults to false.
#case_sensitive = false

# Whether to be require matching the whole word. Defaults to false.
#whole_word = false


# Network widget configuration
#[network]

# By default, there are no network interface filters enabled. An example use case is provided below.
#[network.interface_filter]
# Whether to ignore any matches. Defaults to true.
#is_list_ignored = true

# A list of filters to try and match.
#list = ["virbr0.*"]

# Whether to use regex. Defaults to false.
#regex = true

# Whether to be case-sensitive. Defaults to false.
#case_sensitive = false

# Whether to be 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

# Built-in themes. Valid values are:
# - "default"
# - "default-light"
Expand Down
25 changes: 25 additions & 0 deletions schema/nightly/bottom.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,35 @@
}
}
},
"DiskColumn": {
"type": "string",
"enum": [
"Disk",
"Free",
"Free%",
"Mount",
"R/s",
"Read",
"Rps",
"Total",
"Used",
"Used%",
"W/s",
"Wps",
"Write"
]
},
"DiskConfig": {
"description": "Disk configuration.",
"type": "object",
"properties": {
"columns": {
"description": "A list of disk widget columns.",
"type": "array",
"items": {
"$ref": "#/definitions/DiskColumn"
}
},
"mount_filter": {
"description": "A filter over the mount names.",
"anyOf": [
Expand Down
2 changes: 1 addition & 1 deletion scripts/schema/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def main():
read_file = re.sub(
r"^#(\s\s+)([a-zA-Z\[])", r"\2", read_file, flags=re.MULTILINE
)
print(f"uncommented file: \n{read_file}")
print(f"uncommented file: \n{read_file}\n=====\n")

toml_str = tomllib.loads(read_file)
else:
Expand Down
17 changes: 4 additions & 13 deletions src/app/data_farmer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
processes::{Pid, ProcessHarvest},
temperature, Data,
},
utils::data_prefixes::*,
dec_bytes_per_second_string,
};

pub type TimeOffset = f64;
Expand Down Expand Up @@ -423,20 +423,11 @@ impl DataCollection {
*io_curr = (r_rate, w_rate);
*io_prev = (io_r_pt, io_w_pt);

// TODO: idk why I'm generating this here tbh
if let Some(io_labels) = self.io_labels.get_mut(itx) {
let converted_read = get_decimal_bytes(r_rate);
let converted_write = get_decimal_bytes(w_rate);
*io_labels = (
if r_rate >= GIGA_LIMIT {
format!("{:.*}{}/s", 1, converted_read.0, converted_read.1)
} else {
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1)
},
if w_rate >= GIGA_LIMIT {
format!("{:.*}{}/s", 1, converted_write.0, converted_write.1)
} else {
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1)
},
dec_bytes_per_second_string(r_rate),
dec_bytes_per_second_string(w_rate),
);
}
}
Expand Down
17 changes: 11 additions & 6 deletions src/canvas/components/data_table/sortable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ impl SortOrder {
SortOrder::Descending => SortOrder::Ascending,
}
}

/// A hack to get a const default.
pub const fn const_default() -> Self {
Self::Ascending
}
}

impl Default for SortOrder {
fn default() -> Self {
Self::Ascending
Self::const_default()
}
}

Expand Down Expand Up @@ -195,26 +200,26 @@ where

/// Creates a new [`SortColumn`] with a hard width, which has no shortcut
/// and sorts by default in ascending order ([`SortOrder::Ascending`]).
pub fn hard(inner: T, width: u16) -> Self {
pub const fn hard(inner: T, width: u16) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::Hard(width),
is_hidden: false,
default_order: SortOrder::default(),
default_order: SortOrder::const_default(),
}
}

/// Creates a new [`SortColumn`] with a soft width, which has no shortcut
/// and sorts by default in ascending order ([`SortOrder::Ascending`]).
pub fn soft(inner: T, max_percentage: Option<f32>) -> Self {
pub const fn soft(inner: T, max_percentage: Option<f32>) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::Soft {
desired: 0,
max_percentage,
},
is_hidden: false,
default_order: SortOrder::default(),
default_order: SortOrder::const_default(),
}
}

Expand All @@ -225,7 +230,7 @@ where
}

/// Sets the default sort order to [`SortOrder::Descending`].
pub fn default_descending(mut self) -> Self {
pub const fn default_descending(mut self) -> Self {
self.default_order = SortOrder::Descending;
self
}
Expand Down
Loading

0 comments on commit 196d6d1

Please sign in to comment.