change: remove slash, change scroll behaviour on cpu

- Removal of the old slash-space-to-hide behaviour of CPU widget
- Scrolling onto a specific entry will only show that entry
- Showing average is now default
This commit is contained in:
Clement Tsang 2020-05-16 22:38:19 -04:00 committed by GitHub
parent a074808a00
commit 12e4777d97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 690 additions and 856 deletions

View file

@ -11,7 +11,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- TODO: ~~[#114](https://github.com/ClementTsang/bottom/pull/114): Process state per process (originally in 0.4.0, moved to later).~~ - TODO: ~~[#114](https://github.com/ClementTsang/bottom/pull/114): Process state per process (originally in 0.4.0, moved to later).~~
- TODO: ~~Moving down the CPU list will show only the corresponding graph.~~ ### Changes
- Removal of the `/` CPU core showing in the chart. It felt clunky to use, was not really useful, and hard to work with with large core counts.
Furthermore:
- `show_disabled_data` option and flag is removed.
- Average CPU is now on by _default_. You can disable it via `-a, --hide_avg_cpu` or `hide_avg_cpu = true`.
## [0.4.3] - 2020-05-15 ## [0.4.3] - 2020-05-15

1030
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -38,15 +38,12 @@ backtrace = "0.3"
serde = {version = "1.0", features = ["derive"] } serde = {version = "1.0", features = ["derive"] }
unicode-segmentation = "1.6.0" unicode-segmentation = "1.6.0"
unicode-width = "0.1.7" unicode-width = "0.1.7"
tui = {version = "0.9", features = ["crossterm"], default-features = false }
# For debugging only... # For debugging only...
fern = "0.6.0" fern = "0.6.0"
log = "0.4.8" log = "0.4.8"
tui = {version = "0.9", features = ["crossterm"], default-features = false }
# tui = {git = "https://github.com/ClementTsang/tui-rs", features = ["crossterm"], default-features = false }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = "0.3.8" winapi = "0.3.8"

View file

@ -3,7 +3,6 @@
[![Build Status](https://travis-ci.com/ClementTsang/bottom.svg?token=1wvzVgp94E1TZyPNs8JF&branch=master)](https://travis-ci.com/ClementTsang/bottom) [![Build Status](https://travis-ci.com/ClementTsang/bottom.svg?token=1wvzVgp94E1TZyPNs8JF&branch=master)](https://travis-ci.com/ClementTsang/bottom)
[![crates.io link](https://img.shields.io/crates/v/bottom.svg)](https://crates.io/crates/bottom) [![crates.io link](https://img.shields.io/crates/v/bottom.svg)](https://crates.io/crates/bottom)
[![tokei](https://tokei.rs/b1/github/ClementTsang/bottom?category=code)](https://github.com/ClementTsang/bottom) [![tokei](https://tokei.rs/b1/github/ClementTsang/bottom?category=code)](https://github.com/ClementTsang/bottom)
[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors)
A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop). A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop).
@ -135,7 +134,7 @@ Run using `btm`.
``` ```
-h, --help Prints help information, including flags and options -h, --help Prints help information, including flags and options
-a, --avg_cpu Shows the average CPU usage in addition to per-core -a, --hide_avg_cpu Hides the average CPU usage
-m, --dot-marker Uses a dot marker instead of the default braille marker -m, --dot-marker Uses a dot marker instead of the default braille marker
-c, --celsius Displays the temperature type in Celsius [default] -c, --celsius Displays the temperature type in Celsius [default]
-f, --fahrenheit Displays the temperature type in Fahrenheit -f, --fahrenheit Displays the temperature type in Fahrenheit
@ -193,10 +192,8 @@ Run using `btm`.
#### CPU bindings #### CPU bindings
| | | | | |
| ------- | -------------------------------------------- | | ------------ | --------------------------------------------------------------------- |
| `/` | Open filtering for showing certain CPU cores | | Mouse scroll | Scrolling over an CPU core/average shows only that entry on the chart |
| `Space` | Toggle enabled/disabled cores |
| `Esc` | Exit filtering mode |
#### Process bindings #### Process bindings
@ -375,7 +372,7 @@ The following options can be set under `[flags]` to achieve the same effect as p
These are the following supported flag config values: These are the following supported flag config values:
| Field | Type | | Field | Type |
|------------------------|---------------------------------------------------------------------------------------| |------------------------|---------------------------------------------------------------------------------------|
| `avg_cpu` | Boolean | | `hide_avg_cpu` | Boolean |
| `dot_marker` | Boolean | | `dot_marker` | Boolean |
| `left_legend` | Boolean | | `left_legend` | Boolean |
| `current_usage` | Boolean | | `current_usage` | Boolean |
@ -405,6 +402,7 @@ Supported named colours are one of the following strings: `Reset, Black, Red, Gr
| Table header colours | Colour of table headers | `table_header_color="255, 255, 255"` | | Table header colours | Colour of table headers | `table_header_color="255, 255, 255"` |
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "white", "255, 255, 255"]` | | CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "white", "255, 255, 255"]` |
| Average CPU colour | The average CPU color | `avg_cpu_color="White"` | | Average CPU colour | The average CPU color | `avg_cpu_color="White"` |
| All CPUs colour | The colour for the "All" CPU label | `all_cpu_color="White"` |
| RAM | The colour RAM will use | `ram_color="#ffffff"` | | RAM | The colour RAM will use | `ram_color="#ffffff"` |
| SWAP | The colour SWAP will use | `swap_color="#ffffff"` | | SWAP | The colour SWAP will use | `swap_color="#ffffff"` |
| RX | The colour rx will use | `rx_color="#ffffff"` | | RX | The colour rx will use | `rx_color="#ffffff"` |

View file

@ -33,7 +33,6 @@ pub struct AppConfigFields {
pub left_legend: bool, pub left_legend: bool,
pub show_average_cpu: bool, pub show_average_cpu: bool,
pub use_current_cpu_total: bool, pub use_current_cpu_total: bool,
pub show_disabled_data: bool,
pub use_basic_mode: bool, pub use_basic_mode: bool,
pub default_time_value: u64, pub default_time_value: u64,
pub time_interval: u64, pub time_interval: u64,
@ -115,14 +114,6 @@ impl App {
}); });
self.proc_state.force_update_all = true; self.proc_state.force_update_all = true;
// Reset all CPU filter states
self.cpu_state.widget_states.values_mut().for_each(|state| {
for show_vec_state in &mut state.core_show_vec {
*show_vec_state = true;
}
state.num_cpus_shown = state.core_show_vec.len();
});
// Clear current delete list // Clear current delete list
self.to_delete_process_list = None; self.to_delete_process_list = None;
self.dd_err = None; self.dd_err = None;
@ -155,42 +146,6 @@ impl App {
self.is_force_redraw = true; self.is_force_redraw = true;
} else if self.is_filtering_or_searching() { } else if self.is_filtering_or_searching() {
match self.current_widget.widget_type { match self.current_widget.widget_type {
BottomWidgetType::Cpu => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&self.current_widget.widget_id)
{
cpu_widget_state.is_showing_tray = false;
if cpu_widget_state.scroll_state.current_scroll_position
>= cpu_widget_state.num_cpus_shown as u64
{
let new_position =
cpu_widget_state.num_cpus_shown.saturating_sub(1) as u64;
cpu_widget_state.scroll_state.current_scroll_position = new_position;
cpu_widget_state.scroll_state.previous_scroll_position = 0;
}
self.is_force_redraw = true;
}
}
BottomWidgetType::CpuLegend => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&(self.current_widget.widget_id - 1))
{
cpu_widget_state.is_showing_tray = false;
if cpu_widget_state.scroll_state.current_scroll_position
>= cpu_widget_state.num_cpus_shown as u64
{
let new_position =
cpu_widget_state.num_cpus_shown.saturating_sub(1) as u64;
cpu_widget_state.scroll_state.current_scroll_position = new_position;
cpu_widget_state.scroll_state.previous_scroll_position = 0;
}
self.is_force_redraw = true;
}
}
BottomWidgetType::Proc => { BottomWidgetType::Proc => {
if let Some(current_proc_state) = self if let Some(current_proc_state) = self
.proc_state .proc_state
@ -239,28 +194,6 @@ impl App {
fn is_filtering_or_searching(&self) -> bool { fn is_filtering_or_searching(&self) -> bool {
match self.current_widget.widget_type { match self.current_widget.widget_type {
BottomWidgetType::Cpu => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get(&self.current_widget.widget_id)
{
cpu_widget_state.is_showing_tray
} else {
false
}
}
BottomWidgetType::CpuLegend => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get(&(self.current_widget.widget_id - 1))
{
cpu_widget_state.is_showing_tray
} else {
false
}
}
BottomWidgetType::Proc => { BottomWidgetType::Proc => {
if let Some(proc_widget_state) = self if let Some(proc_widget_state) = self
.proc_state .proc_state
@ -305,10 +238,20 @@ impl App {
pub fn on_tab(&mut self) { pub fn on_tab(&mut self) {
// Disallow usage whilst in a dialog and only in processes // Disallow usage whilst in a dialog and only in processes
let is_in_search_widget = self.is_in_search_widget();
if !self.is_in_dialog() { if !self.is_in_dialog() {
if is_in_search_widget { match self.current_widget.widget_type {
} else if let Some(proc_widget_state) = self BottomWidgetType::Cpu => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&self.current_widget.widget_id)
{
cpu_widget_state.is_multi_graph_mode =
!cpu_widget_state.is_multi_graph_mode;
}
}
BottomWidgetType::Proc => {
if let Some(proc_widget_state) = self
.proc_state .proc_state
.widget_states .widget_states
.get_mut(&self.current_widget.widget_id) .get_mut(&self.current_widget.widget_id)
@ -318,6 +261,9 @@ impl App {
self.proc_state.force_update = Some(self.current_widget.widget_id); self.proc_state.force_update = Some(self.current_widget.widget_id);
} }
} }
_ => {}
}
}
} }
/// I don't like this, but removing it causes a bunch of breakage. /// I don't like this, but removing it causes a bunch of breakage.
@ -331,36 +277,11 @@ impl App {
} }
/// "On space" if we don't want to treat is as a character. /// "On space" if we don't want to treat is as a character.
pub fn on_space(&mut self) { pub fn on_space(&mut self) {}
if let BottomWidgetType::CpuLegend = self.current_widget.widget_type {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&(self.current_widget.widget_id - 1))
{
let curr_posn = cpu_widget_state.scroll_state.current_scroll_position;
if cpu_widget_state.is_showing_tray
&& curr_posn < self.data_collection.cpu_harvest.len() as u64
{
cpu_widget_state.core_show_vec[curr_posn as usize] =
!cpu_widget_state.core_show_vec[curr_posn as usize];
if !self.app_config_fields.show_disabled_data {
if !cpu_widget_state.core_show_vec[curr_posn as usize] {
cpu_widget_state.num_cpus_shown -= 1;
} else {
cpu_widget_state.num_cpus_shown += 1;
}
}
}
}
}
}
pub fn on_slash(&mut self) { pub fn on_slash(&mut self) {
if !self.is_in_dialog() { if !self.is_in_dialog() {
match self.current_widget.widget_type { if let BottomWidgetType::Proc = self.current_widget.widget_type {
BottomWidgetType::Proc => {
// Toggle on // Toggle on
if let Some(proc_widget_state) = self if let Some(proc_widget_state) = self
.proc_state .proc_state
@ -374,36 +295,6 @@ impl App {
self.move_widget_selection_down(); self.move_widget_selection_down();
} }
} }
BottomWidgetType::Cpu => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&self.current_widget.widget_id)
{
cpu_widget_state.is_showing_tray = true;
if self.app_config_fields.left_legend {
self.move_widget_selection_left();
} else {
self.move_widget_selection_right();
}
}
}
BottomWidgetType::CpuLegend => {
if let Some(cpu_widget_state) = self
.cpu_state
.widget_states
.get_mut(&(self.current_widget.widget_id - 1))
{
cpu_widget_state.is_showing_tray = true;
if self.app_config_fields.left_legend {
self.move_widget_selection_left();
} else {
self.move_widget_selection_right();
}
}
}
_ => {}
}
} }
} }
@ -1598,18 +1489,12 @@ impl App {
} }
} }
BottomWidgetType::CpuLegend => { BottomWidgetType::CpuLegend => {
let is_filtering_or_searching = self.is_filtering_or_searching();
if let Some(cpu_widget_state) = self if let Some(cpu_widget_state) = self
.cpu_state .cpu_state
.widget_states .widget_states
.get_mut(&(self.current_widget.widget_id - 1)) .get_mut(&(self.current_widget.widget_id - 1))
{ {
let cap = if is_filtering_or_searching { let cap = self.canvas_data.cpu_data.len() as u64;
self.canvas_data.cpu_data.len()
} else {
cpu_widget_state.num_cpus_shown
} as u64;
if cap > 0 { if cap > 0 {
cpu_widget_state.scroll_state.current_scroll_position = cap - 1; cpu_widget_state.scroll_state.current_scroll_position = cap - 1;
cpu_widget_state.scroll_state.scroll_direction = ScrollDirection::DOWN; cpu_widget_state.scroll_state.scroll_direction = ScrollDirection::DOWN;
@ -1653,7 +1538,6 @@ impl App {
} }
fn change_cpu_table_position(&mut self, num_to_change_by: i64) { fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
let is_filtering_or_searching = self.is_filtering_or_searching();
if let Some(cpu_widget_state) = self if let Some(cpu_widget_state) = self
.cpu_state .cpu_state
.widget_states .widget_states
@ -1661,12 +1545,7 @@ impl App {
{ {
let current_posn = cpu_widget_state.scroll_state.current_scroll_position; let current_posn = cpu_widget_state.scroll_state.current_scroll_position;
let cap = if is_filtering_or_searching { let cap = self.canvas_data.cpu_data.len();
self.canvas_data.cpu_data.len()
} else {
cpu_widget_state.num_cpus_shown
};
if current_posn as i64 + num_to_change_by >= 0 if current_posn as i64 + num_to_change_by >= 0
&& current_posn as i64 + num_to_change_by < cap as i64 && current_posn as i64 + num_to_change_by < cap as i64
{ {

View file

@ -20,9 +20,9 @@ pub fn get_cpu_data_list(sys: &System, show_average_cpu: bool) -> CPUHarvest {
}); });
} }
for cpu in cpu_data { for (itx, cpu) in cpu_data.iter().enumerate() {
cpu_vec.push(CPUData { cpu_vec.push(CPUData {
cpu_name: cpu.get_name().to_uppercase(), cpu_name: format!("CPU{}", itx),
cpu_usage: f64::from(cpu.get_cpu_usage()), cpu_usage: f64::from(cpu.get_cpu_usage()),
}); });
} }

View file

@ -330,7 +330,6 @@ pub fn windows_macos_get_processes_list(
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, sys: &System, use_current_cpu_total: bool, mem_total_kb: u64,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> { ) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
let mut process_vector: Vec<ProcessHarvest> = Vec::new(); let mut process_vector: Vec<ProcessHarvest> = Vec::new();
let process_hashmap = sys.get_processes(); let process_hashmap = sys.get_processes();
let cpu_usage = sys.get_global_processor_info().get_cpu_usage() as f64 / 100.0; let cpu_usage = sys.get_global_processor_info().get_cpu_usage() as f64 / 100.0;
let num_cpus = sys.get_processors().len() as f64; let num_cpus = sys.get_processors().len() as f64;
@ -372,7 +371,11 @@ pub fn windows_macos_get_processes_list(
process_vector.push(ProcessHarvest { process_vector.push(ProcessHarvest {
pid: process_val.pid() as u32, pid: process_val.pid() as u32,
name, name,
mem_usage_percent: process_val.memory() as f64 * 100.0 / mem_total_kb as f64, mem_usage_percent: if mem_total_kb > 0 {
process_val.memory() as f64 * 100.0 / mem_total_kb as f64
} else {
0.0
},
cpu_usage_percent: process_cpu_usage, cpu_usage_percent: process_cpu_usage,
read_bytes_per_sec: disk_usage.read_bytes, read_bytes_per_sec: disk_usage.read_bytes,
write_bytes_per_sec: disk_usage.written_bytes, write_bytes_per_sec: disk_usage.written_bytes,

View file

@ -296,11 +296,9 @@ impl NetState {
pub struct CpuWidgetState { pub struct CpuWidgetState {
pub current_display_time: u64, pub current_display_time: u64,
pub is_legend_hidden: bool, pub is_legend_hidden: bool,
pub is_showing_tray: bool,
pub core_show_vec: Vec<bool>,
pub num_cpus_shown: usize,
pub autohide_timer: Option<Instant>, pub autohide_timer: Option<Instant>,
pub scroll_state: AppScrollWidgetState, pub scroll_state: AppScrollWidgetState,
pub is_multi_graph_mode: bool,
} }
impl CpuWidgetState { impl CpuWidgetState {
@ -308,11 +306,9 @@ impl CpuWidgetState {
CpuWidgetState { CpuWidgetState {
current_display_time, current_display_time,
is_legend_hidden: false, is_legend_hidden: false,
is_showing_tray: false,
core_show_vec: Vec::new(),
num_cpus_shown: 0,
autohide_timer, autohide_timer,
scroll_state: AppScrollWidgetState::default(), scroll_state: AppScrollWidgetState::default(),
is_multi_graph_mode: false,
} }
} }
} }
@ -320,7 +316,6 @@ impl CpuWidgetState {
pub struct CpuState { pub struct CpuState {
pub force_update: Option<u64>, pub force_update: Option<u64>,
pub widget_states: HashMap<u64, CpuWidgetState>, pub widget_states: HashMap<u64, CpuWidgetState>,
pub num_cpus_total: usize,
} }
impl CpuState { impl CpuState {
@ -328,7 +323,6 @@ impl CpuState {
CpuState { CpuState {
force_update: None, force_update: None,
widget_states, widget_states,
num_cpus_total: 0,
} }
} }
} }

View file

@ -17,6 +17,7 @@ pub struct CanvasColours {
pub tx_style: Style, pub tx_style: Style,
pub total_rx_style: Style, pub total_rx_style: Style,
pub total_tx_style: Style, pub total_tx_style: Style,
pub all_colour_style: Style,
pub avg_colour_style: Style, pub avg_colour_style: Style,
pub cpu_colour_styles: Vec<Style>, pub cpu_colour_styles: Vec<Style>,
pub border_style: Style, pub border_style: Style,
@ -46,6 +47,7 @@ impl Default for CanvasColours {
tx_style: Style::default().fg(STANDARD_SECOND_COLOUR), tx_style: Style::default().fg(STANDARD_SECOND_COLOUR),
total_rx_style: Style::default().fg(STANDARD_THIRD_COLOUR), total_rx_style: Style::default().fg(STANDARD_THIRD_COLOUR),
total_tx_style: Style::default().fg(STANDARD_FOURTH_COLOUR), total_tx_style: Style::default().fg(STANDARD_FOURTH_COLOUR),
all_colour_style: Style::default().fg(ALL_COLOUR),
avg_colour_style: Style::default().fg(AVG_COLOUR), avg_colour_style: Style::default().fg(AVG_COLOUR),
cpu_colour_styles: Vec::new(), cpu_colour_styles: Vec::new(),
border_style: Style::default().fg(text_colour), border_style: Style::default().fg(text_colour),
@ -122,6 +124,11 @@ impl CanvasColours {
Ok(()) Ok(())
} }
pub fn set_all_cpu_colour(&mut self, colour: &str) -> error::Result<()> {
self.all_colour_style = get_style_from_config(colour)?;
Ok(())
}
pub fn set_cpu_colours(&mut self, colours: &[String]) -> error::Result<()> { pub fn set_cpu_colours(&mut self, colours: &[String]) -> error::Result<()> {
let max_amount = std::cmp::min(colours.len(), NUM_COLOURS as usize); let max_amount = std::cmp::min(colours.len(), NUM_COLOURS as usize);
for (itx, colour) in colours.iter().enumerate() { for (itx, colour) in colours.iter().enumerate() {

View file

@ -13,6 +13,7 @@ pub const STANDARD_THIRD_COLOUR: Color = Color::LightCyan;
pub const STANDARD_FOURTH_COLOUR: Color = Color::LightGreen; pub const STANDARD_FOURTH_COLOUR: Color = Color::LightGreen;
pub const STANDARD_HIGHLIGHT_COLOUR: Color = Color::LightBlue; pub const STANDARD_HIGHLIGHT_COLOUR: Color = Color::LightBlue;
pub const AVG_COLOUR: Color = Color::Red; pub const AVG_COLOUR: Color = Color::Red;
pub const ALL_COLOUR: Color = Color::Green;
lazy_static! { lazy_static! {
static ref COLOR_NAME_LOOKUP_TABLE: HashMap<&'static str, Color> = [ static ref COLOR_NAME_LOOKUP_TABLE: HashMap<&'static str, Color> = [

View file

@ -22,6 +22,9 @@ use tui::{
const CPU_SELECT_LEGEND_HEADER: [&str; 2] = ["CPU", "Show"]; const CPU_SELECT_LEGEND_HEADER: [&str; 2] = ["CPU", "Show"];
const CPU_LEGEND_HEADER: [&str; 2] = ["CPU", "Use%"]; const CPU_LEGEND_HEADER: [&str; 2] = ["CPU", "Use%"];
const AVG_POSITION: usize = 1;
const ALL_POSITION: usize = 0;
lazy_static! { lazy_static! {
static ref CPU_LEGEND_HEADER_LENS: Vec<usize> = CPU_LEGEND_HEADER static ref CPU_LEGEND_HEADER_LENS: Vec<usize> = CPU_LEGEND_HEADER
.iter() .iter()
@ -97,6 +100,8 @@ impl CpuGraphWidget for Painter {
fn draw_cpu_graph<B: Backend>( fn draw_cpu_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64, &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64,
) { ) {
use std::convert::TryFrom;
if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) { if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) {
let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data; let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data;
@ -142,47 +147,58 @@ impl CpuGraphWidget for Painter {
let use_dot = app_state.app_config_fields.use_dot; let use_dot = app_state.app_config_fields.use_dot;
let show_avg_cpu = app_state.app_config_fields.show_average_cpu; let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
let dataset_vector: Vec<Dataset<'_>> = cpu_data let dataset_vector: Vec<Dataset<'_>> = if let Ok(current_scroll_position) =
usize::try_from(cpu_widget_state.scroll_state.current_scroll_position)
{
if current_scroll_position == ALL_POSITION {
cpu_data
.iter() .iter()
.zip(&cpu_widget_state.core_show_vec)
.enumerate() .enumerate()
.rev() .rev()
.filter_map(|(itx, (cpu, cpu_show_vec))| { .map(|(itx, cpu)| {
if *cpu_show_vec {
Some(
Dataset::default() Dataset::default()
.marker(if use_dot { .marker(if use_dot {
Marker::Dot Marker::Dot
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(if show_avg_cpu && itx == 0 { .style(if show_avg_cpu && itx == AVG_POSITION {
self.colours.avg_colour_style self.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles self.colours.cpu_colour_styles
[itx % self.colours.cpu_colour_styles.len()] [itx % self.colours.cpu_colour_styles.len()]
}) })
.data(&cpu.cpu_data[..]) .data(&cpu.cpu_data[..])
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line)
)
} else {
None
}
}) })
.collect(); .collect()
} else if let Some(cpu) = cpu_data.get(current_scroll_position) {
let title = if app_state.is_expanded && !cpu_widget_state.is_showing_tray { vec![Dataset::default()
const TITLE_BASE: &str = " CPU ── Esc to go back "; .marker(if use_dot {
format!( Marker::Dot
" CPU ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else { } else {
" CPU ".to_string() Marker::Braille
})
.style(if show_avg_cpu && current_scroll_position == AVG_POSITION {
self.colours.avg_colour_style
} else {
self.colours.cpu_colour_styles[cpu_widget_state
.scroll_state
.current_scroll_position
as usize
% self.colours.cpu_colour_styles.len()]
})
.data(&cpu.cpu_data[..])
.graph_type(tui::widgets::GraphType::Line)]
} else {
vec![]
}
} else {
vec![]
}; };
let title = " CPU ".to_string();
let border_style = if app_state.current_widget.widget_id == widget_id { let border_style = if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style self.colours.highlighted_border_style
} else { } else {
@ -231,35 +247,13 @@ impl CpuGraphWidget for Painter {
let mut offset_scroll_index = let mut offset_scroll_index =
(cpu_widget_state.scroll_state.current_scroll_position - start_position) as usize; (cpu_widget_state.scroll_state.current_scroll_position - start_position) as usize;
let show_disabled_data = app_state.app_config_fields.show_disabled_data;
let show_avg_cpu = app_state.app_config_fields.show_average_cpu; let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
let cpu_rows = sliced_cpu_data.iter().enumerate().filter_map(|(itx, cpu)| { let cpu_rows = sliced_cpu_data.iter().enumerate().filter_map(|(itx, cpu)| {
let cpu_string_row: Vec<Cow<'_, str>> = if let Some(cpu_core_show_vec) = let cpu_string_row: Vec<Cow<'_, str>> = vec![
cpu_widget_state
.core_show_vec
.get(itx + start_position as usize)
{
if cpu_widget_state.is_showing_tray {
vec![
Cow::Borrowed(&cpu.cpu_name),
if *cpu_core_show_vec {
"[*]".into()
} else {
"[ ]".into()
},
]
} else if show_disabled_data || *cpu_core_show_vec {
vec![
Cow::Borrowed(&cpu.cpu_name), Cow::Borrowed(&cpu.cpu_name),
Cow::Borrowed(&cpu.legend_value), Cow::Borrowed(&cpu.legend_value),
] ];
} else {
Vec::new()
}
} else {
Vec::new()
};
if cpu_string_row.is_empty() { if cpu_string_row.is_empty() {
offset_scroll_index += 1; offset_scroll_index += 1;
@ -267,21 +261,22 @@ impl CpuGraphWidget for Painter {
} else { } else {
Some(Row::StyledData( Some(Row::StyledData(
cpu_string_row.into_iter(), cpu_string_row.into_iter(),
if is_on_widget { if is_on_widget && itx == offset_scroll_index {
if itx == offset_scroll_index {
self.colours.currently_selected_text_style self.colours.currently_selected_text_style
} else if show_avg_cpu && itx == 0 { } else if itx == ALL_POSITION {
self.colours.all_colour_style
} else if show_avg_cpu {
if itx == AVG_POSITION {
self.colours.avg_colour_style self.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles[itx self.colours.cpu_colour_styles[itx + start_position as usize
+ start_position as usize - AVG_POSITION
% self.colours.cpu_colour_styles.len()] - 1 % self.colours.cpu_colour_styles.len()]
} }
} else if show_avg_cpu && itx == 0 {
self.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles[itx self.colours.cpu_colour_styles[itx + start_position as usize
+ start_position as usize % self.colours.cpu_colour_styles.len()] - ALL_POSITION
- 1 % self.colours.cpu_colour_styles.len()]
}, },
)) ))
} }
@ -291,29 +286,10 @@ impl CpuGraphWidget for Painter {
let width = f64::from(draw_loc.width); let width = f64::from(draw_loc.width);
let width_ratios = vec![0.5, 0.5]; let width_ratios = vec![0.5, 0.5];
let variable_intrinsic_results = get_variable_intrinsic_widths( let variable_intrinsic_results =
width as u16, get_variable_intrinsic_widths(width as u16, &width_ratios, &CPU_LEGEND_HEADER_LENS);
&width_ratios,
if cpu_widget_state.is_showing_tray {
&CPU_SELECT_LEGEND_HEADER_LENS
} else {
&CPU_LEGEND_HEADER_LENS
},
);
let intrinsic_widths = &(variable_intrinsic_results.0)[0..variable_intrinsic_results.1]; let intrinsic_widths = &(variable_intrinsic_results.0)[0..variable_intrinsic_results.1];
let title = if cpu_widget_state.is_showing_tray {
const TITLE_BASE: &str = " Esc to close ";
format!(
"{} Esc to close ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else {
"".to_string()
};
let (border_and_title_style, highlight_style) = if is_on_widget { let (border_and_title_style, highlight_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, self.colours.highlighted_border_style,
@ -325,18 +301,9 @@ impl CpuGraphWidget for Painter {
// Draw // Draw
f.render_widget( f.render_widget(
Table::new( Table::new(CPU_LEGEND_HEADER.iter(), cpu_rows)
if cpu_widget_state.is_showing_tray {
CPU_SELECT_LEGEND_HEADER
} else {
CPU_LEGEND_HEADER
}
.iter(),
cpu_rows,
)
.block( .block(
Block::default() Block::default()
.title(&title)
.title_style(border_and_title_style) .title_style(border_and_title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style), .border_style(border_and_title_style),

View file

@ -74,11 +74,9 @@ pub const GENERAL_HELP_TEXT: [&str; 20] = [
"Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down", "Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down",
]; ];
pub const CPU_HELP_TEXT: [&str; 4] = [ pub const CPU_HELP_TEXT: [&str; 2] = [
"2 - CPU widget\n", "2 - CPU widget\n",
"/ Open filtering for showing certain CPU cores\n", "Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart",
"Space Toggle enabled/disabled cores\n",
"Esc Exit filtering mode",
]; ];
pub const PROCESS_HELP_TEXT: [&str; 8] = [ pub const PROCESS_HELP_TEXT: [&str; 8] = [
@ -170,8 +168,8 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
# is also set here. # is also set here.
[flags] [flags]
# Whether to display an average cpu entry. # Whether to hide the average cpu entry.
#avg_cpu = false #hide_avg_cpu = false
# Whether to use dot markers rather than braille. # Whether to use dot markers rather than braille.
#dot_marker = false #dot_marker = false
@ -197,9 +195,6 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
# Whether to make process searching use regex by default. # Whether to make process searching use regex by default.
#regex = false #regex = false
# Whether to show CPU entries in the legend when they are hidden.
#show_disabled_data = false
# Defaults to Celsius. Temperature is one of: # Defaults to Celsius. Temperature is one of:
#temperature_type = "k" #temperature_type = "k"
#temperature_type = "f" #temperature_type = "f"

View file

@ -66,6 +66,7 @@ pub struct ConvertedCpuData {
pub cpu_name: String, pub cpu_name: String,
/// Tuple is time, value /// Tuple is time, value
pub cpu_data: Vec<Point>, pub cpu_data: Vec<Point>,
/// Represents the value displayed on the legend.
pub legend_value: String, pub legend_value: String,
} }
@ -153,7 +154,7 @@ pub fn convert_cpu_data_points(
let mut new_cpu_data = ConvertedCpuData::default(); let mut new_cpu_data = ConvertedCpuData::default();
new_cpu_data.cpu_name = if let Some(cpu_harvest) = current_data.cpu_harvest.get(itx) new_cpu_data.cpu_name = if let Some(cpu_harvest) = current_data.cpu_harvest.get(itx)
{ {
cpu_harvest.cpu_name.clone() cpu_harvest.cpu_name.to_string()
} else { } else {
String::default() String::default()
}; };
@ -171,7 +172,13 @@ pub fn convert_cpu_data_points(
} }
} }
cpu_data_vector let mut extended_vec = vec![ConvertedCpuData {
cpu_name: "All".to_string(),
cpu_data: vec![],
legend_value: String::new(),
}];
extended_vec.extend(cpu_data_vector);
extended_vec
} }
pub fn convert_mem_data_points( pub fn convert_mem_data_points(

View file

@ -67,7 +67,7 @@ fn get_matches() -> clap::ArgMatches<'static> {
(version: crate_version!()) (version: crate_version!())
(author: crate_authors!()) (author: crate_authors!())
(about: crate_description!()) (about: crate_description!())
(@arg AVG_CPU: -a --avg_cpu "Enables showing the average CPU usage.") (@arg HIDE_AVG_CPU: -a --hide_avg_cpu "Hides the average CPU usage.")
(@arg DOT_MARKER: -m --dot_marker "Use a dot marker instead of the default braille marker.") (@arg DOT_MARKER: -m --dot_marker "Use a dot marker instead of the default braille marker.")
(@group TEMPERATURE_TYPE => (@group TEMPERATURE_TYPE =>
(@arg KELVIN : -k --kelvin "Sets the temperature type to Kelvin.") (@arg KELVIN : -k --kelvin "Sets the temperature type to Kelvin.")
@ -83,7 +83,6 @@ fn get_matches() -> clap::ArgMatches<'static> {
(@arg CASE_SENSITIVE: -S --case_sensitive "Match case when searching by default.") (@arg CASE_SENSITIVE: -S --case_sensitive "Match case when searching by default.")
(@arg WHOLE_WORD: -W --whole_word "Match whole word when searching by default.") (@arg WHOLE_WORD: -W --whole_word "Match whole word when searching by default.")
(@arg REGEX_DEFAULT: -R --regex "Use regex in searching by default.") (@arg REGEX_DEFAULT: -R --regex "Use regex in searching by default.")
(@arg SHOW_DISABLED_DATA: -s --show_disabled_data "Show disabled data entries.")
(@arg DEFAULT_TIME_VALUE: -t --default_time_value +takes_value "Default time value for graphs in milliseconds; minimum is 30s, defaults to 60s.") (@arg DEFAULT_TIME_VALUE: -t --default_time_value +takes_value "Default time value for graphs in milliseconds; minimum is 30s, defaults to 60s.")
(@arg TIME_DELTA: -d --time_delta +takes_value "The amount changed upon zooming in/out in milliseconds; minimum is 1s, defaults to 15s.") (@arg TIME_DELTA: -d --time_delta +takes_value "The amount changed upon zooming in/out in milliseconds; minimum is 1s, defaults to 15s.")
(@arg HIDE_TIME: --hide_time "Completely hide the time scaling") (@arg HIDE_TIME: --hide_time "Completely hide the time scaling")
@ -158,7 +157,6 @@ fn main() -> error::Result<()> {
// Set panic hook // Set panic hook
panic::set_hook(Box::new(|info| panic_hook(info))); panic::set_hook(Box::new(|info| panic_hook(info)));
let mut first_run = true;
loop { loop {
if let Ok(recv) = receiver.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) { if let Ok(recv) = receiver.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) {
match recv { match recv {
@ -219,18 +217,7 @@ fn main() -> error::Result<()> {
app.canvas_data.swap_label = memory_and_swap_labels.1; app.canvas_data.swap_label = memory_and_swap_labels.1;
} }
// Pre-fill CPU if needed
if app.used_widgets.use_cpu { if app.used_widgets.use_cpu {
if first_run {
let cpu_len = app.data_collection.cpu_harvest.len();
app.cpu_state.widget_states.values_mut().for_each(|state| {
state.core_show_vec = vec![true; cpu_len];
state.num_cpus_shown = cpu_len;
});
app.cpu_state.num_cpus_total = cpu_len;
first_run = false;
}
// CPU // CPU
app.canvas_data.cpu_data = app.canvas_data.cpu_data =
convert_cpu_data_points(&app.data_collection, false); convert_cpu_data_points(&app.data_collection, false);
@ -446,6 +433,10 @@ fn generate_config_colours(config: &Config, painter: &mut canvas::Painter) -> er
painter.colours.set_avg_cpu_colour(avg_cpu_color)?; painter.colours.set_avg_cpu_colour(avg_cpu_color)?;
} }
if let Some(all_cpu_color) = &colours.all_cpu_color {
painter.colours.set_all_cpu_colour(all_cpu_color)?;
}
if let Some(cpu_core_colors) = &colours.cpu_core_colors { if let Some(cpu_core_colors) = &colours.cpu_core_colors {
painter.colours.set_cpu_colours(cpu_core_colors)?; painter.colours.set_cpu_colours(cpu_core_colors)?;
} }

View file

@ -21,7 +21,7 @@ pub struct Config {
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct ConfigFlags { pub struct ConfigFlags {
pub avg_cpu: Option<bool>, pub hide_avg_cpu: Option<bool>,
pub dot_marker: Option<bool>, pub dot_marker: Option<bool>,
pub temperature_type: Option<String>, pub temperature_type: Option<String>,
pub rate: Option<u64>, pub rate: Option<u64>,
@ -32,7 +32,6 @@ pub struct ConfigFlags {
pub whole_word: Option<bool>, pub whole_word: Option<bool>,
pub regex: Option<bool>, pub regex: Option<bool>,
pub default_widget: Option<String>, pub default_widget: Option<String>,
pub show_disabled_data: Option<bool>,
pub basic: Option<bool>, pub basic: Option<bool>,
pub default_time_value: Option<u64>, pub default_time_value: Option<u64>,
pub time_delta: Option<u64>, pub time_delta: Option<u64>,
@ -48,6 +47,7 @@ pub struct ConfigFlags {
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct ConfigColours { pub struct ConfigColours {
pub table_header_color: Option<String>, pub table_header_color: Option<String>,
pub all_cpu_color: Option<String>,
pub avg_cpu_color: Option<String>, pub avg_cpu_color: Option<String>,
pub cpu_core_colors: Option<Vec<String>>, pub cpu_core_colors: Option<Vec<String>>,
pub ram_color: Option<String>, pub ram_color: Option<String>,
@ -208,11 +208,10 @@ pub fn build_app(
let app_config_fields = AppConfigFields { let app_config_fields = AppConfigFields {
update_rate_in_milliseconds: get_update_rate_in_milliseconds(matches, config)?, update_rate_in_milliseconds: get_update_rate_in_milliseconds(matches, config)?,
temperature_type: get_temperature(matches, config)?, temperature_type: get_temperature(matches, config)?,
show_average_cpu: get_avg_cpu(matches, config), show_average_cpu: get_show_average_cpu(matches, config),
use_dot: get_use_dot(matches, config), use_dot: get_use_dot(matches, config),
left_legend: get_use_left_legend(matches, config), left_legend: get_use_left_legend(matches, config),
use_current_cpu_total: get_use_current_cpu_total(matches, config), use_current_cpu_total: get_use_current_cpu_total(matches, config),
show_disabled_data: get_show_disabled_data(matches, config),
use_basic_mode, use_basic_mode,
default_time_value, default_time_value,
time_interval: get_time_interval(matches, config)?, time_interval: get_time_interval(matches, config)?,
@ -356,16 +355,19 @@ fn get_temperature(
Ok(data_harvester::temperature::TemperatureType::Celsius) Ok(data_harvester::temperature::TemperatureType::Celsius)
} }
fn get_avg_cpu(matches: &clap::ArgMatches<'static>, config: &Config) -> bool { /// Yes, this function gets whether to show average CPU (true) or not (false)
if matches.is_present("AVG_CPU") { fn get_show_average_cpu(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
return true; // FIXME: Update the demo config file and default config files! Need to remove
// old options and change to hide_avg_cpu option.
if matches.is_present("HIDE_AVG_CPU") {
return false;
} else if let Some(flags) = &config.flags { } else if let Some(flags) = &config.flags {
if let Some(avg_cpu) = flags.avg_cpu { if let Some(avg_cpu) = flags.hide_avg_cpu {
return avg_cpu; return avg_cpu;
} }
} }
false true
} }
fn get_use_dot(matches: &clap::ArgMatches<'static>, config: &Config) -> bool { fn get_use_dot(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
@ -403,18 +405,6 @@ fn get_use_current_cpu_total(matches: &clap::ArgMatches<'static>, config: &Confi
false false
} }
fn get_show_disabled_data(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("SHOW_DISABLED_DATA") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(show_disabled_data) = flags.show_disabled_data {
return show_disabled_data;
}
}
false
}
fn get_use_basic_mode(matches: &clap::ArgMatches<'static>, config: &Config) -> bool { fn get_use_basic_mode(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("BASIC_MODE") { if matches.is_present("BASIC_MODE") {
return true; return true;

View file

@ -1,2 +1,2 @@
[flags] [flags]
avg_cpu = "test" basic = "test"