mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-24 21:23:08 +00:00
feat: add option to move avg CPU to another row (#1487)
Adds an `average_cpu_row` option to move the average CPU usage to its own row when using basic mode.
This commit is contained in:
parent
9379c03595
commit
d6c2ef3e22
7 changed files with 147 additions and 58 deletions
|
@ -14,39 +14,40 @@ hide_avg_cpu = true
|
|||
Most of the [command line flags](../command-line-options.md) have config file equivalents to avoid having to type them out
|
||||
each time:
|
||||
|
||||
| Field | Type | Functionality |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
|
||||
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
|
||||
| `cpu_left_legend` | Boolean | Puts the CPU chart legend to the left side. |
|
||||
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
|
||||
| `group_processes` | Boolean | Groups processes with the same name by default. |
|
||||
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
|
||||
| `whole_word` | Boolean | Enables whole-word matching by default. |
|
||||
| `regex` | Boolean | Enables regex by default. |
|
||||
| `basic` | Boolean | Hides graphs and uses a more basic look. |
|
||||
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
|
||||
| `battery` | Boolean | Shows the battery widget. |
|
||||
| `rate` | Unsigned Int (represents milliseconds) or String (represents human time) | Sets a refresh rate in ms. |
|
||||
| `default_time_value` | Unsigned Int (represents milliseconds) or String (represents human time) | Default time value for graphs in ms. |
|
||||
| `time_delta` | Unsigned Int (represents milliseconds) or String (represents human time) | The amount in ms changed upon zooming. |
|
||||
| `hide_time` | Boolean | Hides the time scale. |
|
||||
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
|
||||
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
|
||||
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
|
||||
| `disable_click` | Boolean | Disables mouse clicks. |
|
||||
| `enable_cache_memory` | Boolean | Enable cache and buffer memory stats (not available on Windows). |
|
||||
| `process_memory_as_value` | Boolean | Defaults to showing process memory usage by value. |
|
||||
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
|
||||
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
|
||||
| `process_command` | Boolean | Show processes as their commands by default. |
|
||||
| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. |
|
||||
| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. |
|
||||
| `network_use_bytes` | Boolean | Displays the network widget using bytes. |
|
||||
| `network_use_log` | Boolean | Displays the network widget with a log scale. |
|
||||
| `enable_gpu` | Boolean | Shows the GPU widgets. |
|
||||
| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. |
|
||||
| `unnormalized_cpu` | Boolean | Show process CPU% without normalizing over the number of cores. |
|
||||
| `expanded` | Boolean | Expand the default widget upon starting the app. |
|
||||
| `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the memory widget. |
|
||||
| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the network widget. |
|
||||
| Field | Type | Functionality |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
|
||||
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
|
||||
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
|
||||
| `cpu_left_legend` | Boolean | Puts the CPU chart legend to the left side. |
|
||||
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
|
||||
| `group_processes` | Boolean | Groups processes with the same name by default. |
|
||||
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
|
||||
| `whole_word` | Boolean | Enables whole-word matching by default. |
|
||||
| `regex` | Boolean | Enables regex by default. |
|
||||
| `basic` | Boolean | Hides graphs and uses a more basic look. |
|
||||
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
|
||||
| `battery` | Boolean | Shows the battery widget. |
|
||||
| `rate` | Unsigned Int (represents milliseconds) or String (represents human time) | Sets a refresh rate in ms. |
|
||||
| `default_time_value` | Unsigned Int (represents milliseconds) or String (represents human time) | Default time value for graphs in ms. |
|
||||
| `time_delta` | Unsigned Int (represents milliseconds) or String (represents human time) | The amount in ms changed upon zooming. |
|
||||
| `hide_time` | Boolean | Hides the time scale. |
|
||||
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
|
||||
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
|
||||
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
|
||||
| `disable_click` | Boolean | Disables mouse clicks. |
|
||||
| `enable_cache_memory` | Boolean | Enable cache and buffer memory stats (not available on Windows). |
|
||||
| `process_memory_as_value` | Boolean | Defaults to showing process memory usage by value. |
|
||||
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
|
||||
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
|
||||
| `process_command` | Boolean | Show processes as their commands by default. |
|
||||
| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. |
|
||||
| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. |
|
||||
| `network_use_bytes` | Boolean | Displays the network widget using bytes. |
|
||||
| `network_use_log` | Boolean | Displays the network widget with a log scale. |
|
||||
| `enable_gpu` | Boolean | Shows the GPU widgets. |
|
||||
| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. |
|
||||
| `unnormalized_cpu` | Boolean | Show process CPU% without normalizing over the number of cores. |
|
||||
| `expanded` | Boolean | Expand the default widget upon starting the app. |
|
||||
| `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the memory widget. |
|
||||
| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the network widget. |
|
||||
| `average_cpu_row` | Boolean | Moves the average CPU usage entry to its own row when using basic mode. |
|
|
@ -246,6 +246,12 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"average_cpu_row": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"basic": {
|
||||
"type": [
|
||||
"boolean",
|
||||
|
|
|
@ -68,6 +68,7 @@ pub struct AppConfigFields {
|
|||
pub network_scale_type: AxisScaling,
|
||||
pub network_use_binary_prefix: bool,
|
||||
pub retention_ms: u64,
|
||||
pub dedicated_average_row: bool,
|
||||
}
|
||||
|
||||
/// For filtering out information
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
impl Painter {
|
||||
/// Inspired by htop.
|
||||
pub fn draw_basic_cpu(
|
||||
&self, f: &mut Frame<'_>, app_state: &mut App, draw_loc: Rect, widget_id: u64,
|
||||
&self, f: &mut Frame<'_>, app_state: &mut App, mut draw_loc: Rect, widget_id: u64,
|
||||
) {
|
||||
// Skip the first element, it's the "all" element
|
||||
if app_state.converted_data.cpu_data.len() > 1 {
|
||||
|
@ -45,6 +45,32 @@ impl Painter {
|
|||
);
|
||||
}
|
||||
|
||||
let (cpu_data, avg_data) =
|
||||
maybe_split_avg(cpu_data, app_state.app_config_fields.dedicated_average_row);
|
||||
|
||||
if let Some(avg) = avg_data {
|
||||
let (outer, inner, ratio, style) = self.cpu_info(&avg);
|
||||
let [cores_loc, mut avg_loc] =
|
||||
Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).areas(draw_loc);
|
||||
|
||||
// The cores section all have horizontal margin, so to line up with the cores we
|
||||
// need to add some margin ourselves.
|
||||
avg_loc.x += 1;
|
||||
avg_loc.width -= 2;
|
||||
|
||||
f.render_widget(
|
||||
PipeGauge::default()
|
||||
.gauge_style(style)
|
||||
.label_style(style)
|
||||
.inner_label(inner)
|
||||
.start_label(outer)
|
||||
.ratio(ratio),
|
||||
avg_loc,
|
||||
);
|
||||
|
||||
draw_loc = cores_loc;
|
||||
}
|
||||
|
||||
if draw_loc.height > 0 {
|
||||
let remaining_height = usize::from(draw_loc.height);
|
||||
const REQUIRED_COLUMNS: usize = 4;
|
||||
|
@ -56,27 +82,7 @@ impl Painter {
|
|||
.direction(Direction::Horizontal)
|
||||
.split(draw_loc);
|
||||
|
||||
let mut gauge_info = cpu_data.iter().map(|cpu| match cpu {
|
||||
CpuWidgetData::All => unreachable!(),
|
||||
CpuWidgetData::Entry {
|
||||
data_type,
|
||||
data: _,
|
||||
last_entry,
|
||||
} => {
|
||||
let (outer, style) = match data_type {
|
||||
CpuDataType::Avg => ("AVG".to_string(), self.colours.avg_cpu_colour),
|
||||
CpuDataType::Cpu(index) => (
|
||||
format!("{index:<3}",),
|
||||
self.colours.cpu_colour_styles
|
||||
[index % self.colours.cpu_colour_styles.len()],
|
||||
),
|
||||
};
|
||||
let inner = format!("{:>3.0}%", last_entry.round());
|
||||
let ratio = last_entry / 100.0;
|
||||
|
||||
(outer, inner, ratio, style)
|
||||
}
|
||||
});
|
||||
let mut gauge_info = cpu_data.iter().map(|cpu| self.cpu_info(cpu));
|
||||
|
||||
// Very ugly way to sync the gauge limit across all gauges.
|
||||
let hide_parts = columns
|
||||
|
@ -138,4 +144,64 @@ impl Painter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cpu_info(&self, cpu: &CpuWidgetData) -> (String, String, f64, tui::style::Style) {
|
||||
let CpuWidgetData::Entry {
|
||||
data_type,
|
||||
last_entry,
|
||||
..
|
||||
} = cpu
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let (outer, style) = match data_type {
|
||||
CpuDataType::Avg => ("AVG".to_string(), self.colours.avg_cpu_colour),
|
||||
CpuDataType::Cpu(index) => (
|
||||
format!("{index:<3}",),
|
||||
self.colours.cpu_colour_styles[index % self.colours.cpu_colour_styles.len()],
|
||||
),
|
||||
};
|
||||
let inner = format!("{:>3.0}%", last_entry.round());
|
||||
let ratio = last_entry / 100.0;
|
||||
|
||||
(outer, inner, ratio, style)
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_split_avg(
|
||||
data: &[CpuWidgetData], separate_avg: bool,
|
||||
) -> (Vec<CpuWidgetData>, Option<CpuWidgetData>) {
|
||||
let mut cpu_data = vec![];
|
||||
let mut avg_data = None;
|
||||
|
||||
for cpu in data {
|
||||
let CpuWidgetData::Entry {
|
||||
data_type,
|
||||
data,
|
||||
last_entry,
|
||||
} = cpu
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
match data_type {
|
||||
CpuDataType::Avg if separate_avg => {
|
||||
avg_data = Some(CpuWidgetData::Entry {
|
||||
data_type: *data_type,
|
||||
data: data.clone(),
|
||||
last_entry: *last_entry,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
cpu_data.push(CpuWidgetData::Entry {
|
||||
data_type: *data_type,
|
||||
data: data.clone(),
|
||||
last_entry: *last_entry,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(cpu_data, avg_data)
|
||||
}
|
||||
|
|
|
@ -269,6 +269,7 @@ pub(crate) fn init_app(
|
|||
network_unit_type,
|
||||
network_use_binary_prefix,
|
||||
retention_ms,
|
||||
dedicated_average_row: get_dedicated_avg_row(args, config),
|
||||
};
|
||||
|
||||
let table_config = ProcTableConfig {
|
||||
|
@ -677,6 +678,17 @@ fn get_show_average_cpu(args: &BottomArgs, config: &Config) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
fn get_dedicated_avg_row(_args: &BottomArgs, config: &Config) -> bool {
|
||||
let conf = config
|
||||
.flags
|
||||
.as_ref()
|
||||
.and_then(|flags| flags.average_cpu_row)
|
||||
.unwrap_or(false);
|
||||
|
||||
// args.cpu.average_cpu_row || conf
|
||||
conf
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_default_time_value(
|
||||
args: &BottomArgs, config: &Config, retention_ms: u64,
|
||||
|
|
|
@ -428,6 +428,8 @@ pub struct CpuArgs {
|
|||
help = "Puts the CPU chart legend on the left side."
|
||||
)]
|
||||
pub cpu_left_legend: bool,
|
||||
// #[arg(short = 'A', long, action = ArgAction::SetTrue, help = "Moves the average CPU usage entry to its own row when using basic mode.")]
|
||||
// pub average_cpu_row: bool,
|
||||
}
|
||||
|
||||
/// Memory argument/config options.
|
||||
|
|
|
@ -43,4 +43,5 @@ pub(crate) struct FlagConfig {
|
|||
pub(crate) enable_gpu: Option<bool>,
|
||||
pub(crate) enable_cache_memory: Option<bool>,
|
||||
pub(crate) retention: Option<StringOrNum>,
|
||||
pub(crate) average_cpu_row: Option<bool>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue