mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-10 14:44:18 +00:00
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:
parent
a074808a00
commit
12e4777d97
16 changed files with 690 additions and 856 deletions
|
@ -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: ~~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
|
||||
|
||||
|
|
1030
Cargo.lock
generated
1030
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -38,15 +38,12 @@ backtrace = "0.3"
|
|||
serde = {version = "1.0", features = ["derive"] }
|
||||
unicode-segmentation = "1.6.0"
|
||||
unicode-width = "0.1.7"
|
||||
tui = {version = "0.9", features = ["crossterm"], default-features = false }
|
||||
|
||||
# For debugging only...
|
||||
fern = "0.6.0"
|
||||
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]
|
||||
winapi = "0.3.8"
|
||||
|
||||
|
|
14
README.md
14
README.md
|
@ -3,7 +3,6 @@
|
|||
[![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)
|
||||
[![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).
|
||||
|
||||
|
@ -135,7 +134,7 @@ Run using `btm`.
|
|||
|
||||
```
|
||||
-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
|
||||
-c, --celsius Displays the temperature type in Celsius [default]
|
||||
-f, --fahrenheit Displays the temperature type in Fahrenheit
|
||||
|
@ -192,11 +191,9 @@ Run using `btm`.
|
|||
|
||||
#### CPU bindings
|
||||
|
||||
| | |
|
||||
| ------- | -------------------------------------------- |
|
||||
| `/` | Open filtering for showing certain CPU cores |
|
||||
| `Space` | Toggle enabled/disabled cores |
|
||||
| `Esc` | Exit filtering mode |
|
||||
| | |
|
||||
| ------------ | --------------------------------------------------------------------- |
|
||||
| Mouse scroll | Scrolling over an CPU core/average shows only that entry on the chart |
|
||||
|
||||
#### 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:
|
||||
| Field | Type |
|
||||
|------------------------|---------------------------------------------------------------------------------------|
|
||||
| `avg_cpu` | Boolean |
|
||||
| `hide_avg_cpu` | Boolean |
|
||||
| `dot_marker` | Boolean |
|
||||
| `left_legend` | 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"` |
|
||||
| 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"` |
|
||||
| All CPUs colour | The colour for the "All" CPU label | `all_cpu_color="White"` |
|
||||
| RAM | The colour RAM will use | `ram_color="#ffffff"` |
|
||||
| SWAP | The colour SWAP will use | `swap_color="#ffffff"` |
|
||||
| RX | The colour rx will use | `rx_color="#ffffff"` |
|
||||
|
|
197
src/app.rs
197
src/app.rs
|
@ -33,7 +33,6 @@ pub struct AppConfigFields {
|
|||
pub left_legend: bool,
|
||||
pub show_average_cpu: bool,
|
||||
pub use_current_cpu_total: bool,
|
||||
pub show_disabled_data: bool,
|
||||
pub use_basic_mode: bool,
|
||||
pub default_time_value: u64,
|
||||
pub time_interval: u64,
|
||||
|
@ -115,14 +114,6 @@ impl App {
|
|||
});
|
||||
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
|
||||
self.to_delete_process_list = None;
|
||||
self.dd_err = None;
|
||||
|
@ -155,42 +146,6 @@ impl App {
|
|||
self.is_force_redraw = true;
|
||||
} else if self.is_filtering_or_searching() {
|
||||
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 => {
|
||||
if let Some(current_proc_state) = self
|
||||
.proc_state
|
||||
|
@ -239,28 +194,6 @@ impl App {
|
|||
|
||||
fn is_filtering_or_searching(&self) -> bool {
|
||||
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 => {
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
|
@ -305,17 +238,30 @@ impl App {
|
|||
pub fn on_tab(&mut self) {
|
||||
// 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 is_in_search_widget {
|
||||
} else if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.widget_states
|
||||
.get_mut(&self.current_widget.widget_id)
|
||||
{
|
||||
// Toggles process widget grouping state
|
||||
proc_widget_state.is_grouped = !(proc_widget_state.is_grouped);
|
||||
self.proc_state.force_update = Some(self.current_widget.widget_id);
|
||||
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_multi_graph_mode =
|
||||
!cpu_widget_state.is_multi_graph_mode;
|
||||
}
|
||||
}
|
||||
BottomWidgetType::Proc => {
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.widget_states
|
||||
.get_mut(&self.current_widget.widget_id)
|
||||
{
|
||||
// Toggles process widget grouping state
|
||||
proc_widget_state.is_grouped = !(proc_widget_state.is_grouped);
|
||||
self.proc_state.force_update = Some(self.current_widget.widget_id);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,78 +277,23 @@ impl App {
|
|||
}
|
||||
|
||||
/// "On space" if we don't want to treat is as a character.
|
||||
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_space(&mut self) {}
|
||||
|
||||
pub fn on_slash(&mut self) {
|
||||
if !self.is_in_dialog() {
|
||||
match self.current_widget.widget_type {
|
||||
BottomWidgetType::Proc => {
|
||||
// Toggle on
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.widget_states
|
||||
.get_mut(&self.current_widget.widget_id)
|
||||
{
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.is_enabled = true;
|
||||
self.move_widget_selection_down();
|
||||
}
|
||||
if let BottomWidgetType::Proc = self.current_widget.widget_type {
|
||||
// Toggle on
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.widget_states
|
||||
.get_mut(&self.current_widget.widget_id)
|
||||
{
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.is_enabled = true;
|
||||
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 => {
|
||||
let is_filtering_or_searching = self.is_filtering_or_searching();
|
||||
if let Some(cpu_widget_state) = self
|
||||
.cpu_state
|
||||
.widget_states
|
||||
.get_mut(&(self.current_widget.widget_id - 1))
|
||||
{
|
||||
let cap = if is_filtering_or_searching {
|
||||
self.canvas_data.cpu_data.len()
|
||||
} else {
|
||||
cpu_widget_state.num_cpus_shown
|
||||
} as u64;
|
||||
|
||||
let cap = self.canvas_data.cpu_data.len() as u64;
|
||||
if cap > 0 {
|
||||
cpu_widget_state.scroll_state.current_scroll_position = cap - 1;
|
||||
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) {
|
||||
let is_filtering_or_searching = self.is_filtering_or_searching();
|
||||
if let Some(cpu_widget_state) = self
|
||||
.cpu_state
|
||||
.widget_states
|
||||
|
@ -1661,12 +1545,7 @@ impl App {
|
|||
{
|
||||
let current_posn = cpu_widget_state.scroll_state.current_scroll_position;
|
||||
|
||||
let cap = if is_filtering_or_searching {
|
||||
self.canvas_data.cpu_data.len()
|
||||
} else {
|
||||
cpu_widget_state.num_cpus_shown
|
||||
};
|
||||
|
||||
let cap = self.canvas_data.cpu_data.len();
|
||||
if current_posn as i64 + num_to_change_by >= 0
|
||||
&& current_posn as i64 + num_to_change_by < cap as i64
|
||||
{
|
||||
|
|
|
@ -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_name: cpu.get_name().to_uppercase(),
|
||||
cpu_name: format!("CPU{}", itx),
|
||||
cpu_usage: f64::from(cpu.get_cpu_usage()),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -330,7 +330,6 @@ pub fn windows_macos_get_processes_list(
|
|||
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64,
|
||||
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
||||
let mut process_vector: Vec<ProcessHarvest> = Vec::new();
|
||||
|
||||
let process_hashmap = sys.get_processes();
|
||||
let cpu_usage = sys.get_global_processor_info().get_cpu_usage() as f64 / 100.0;
|
||||
let num_cpus = sys.get_processors().len() as f64;
|
||||
|
@ -372,7 +371,11 @@ pub fn windows_macos_get_processes_list(
|
|||
process_vector.push(ProcessHarvest {
|
||||
pid: process_val.pid() as u32,
|
||||
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,
|
||||
read_bytes_per_sec: disk_usage.read_bytes,
|
||||
write_bytes_per_sec: disk_usage.written_bytes,
|
||||
|
|
|
@ -296,11 +296,9 @@ impl NetState {
|
|||
pub struct CpuWidgetState {
|
||||
pub current_display_time: u64,
|
||||
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 scroll_state: AppScrollWidgetState,
|
||||
pub is_multi_graph_mode: bool,
|
||||
}
|
||||
|
||||
impl CpuWidgetState {
|
||||
|
@ -308,11 +306,9 @@ impl CpuWidgetState {
|
|||
CpuWidgetState {
|
||||
current_display_time,
|
||||
is_legend_hidden: false,
|
||||
is_showing_tray: false,
|
||||
core_show_vec: Vec::new(),
|
||||
num_cpus_shown: 0,
|
||||
autohide_timer,
|
||||
scroll_state: AppScrollWidgetState::default(),
|
||||
is_multi_graph_mode: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +316,6 @@ impl CpuWidgetState {
|
|||
pub struct CpuState {
|
||||
pub force_update: Option<u64>,
|
||||
pub widget_states: HashMap<u64, CpuWidgetState>,
|
||||
pub num_cpus_total: usize,
|
||||
}
|
||||
|
||||
impl CpuState {
|
||||
|
@ -328,7 +323,6 @@ impl CpuState {
|
|||
CpuState {
|
||||
force_update: None,
|
||||
widget_states,
|
||||
num_cpus_total: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ pub struct CanvasColours {
|
|||
pub tx_style: Style,
|
||||
pub total_rx_style: Style,
|
||||
pub total_tx_style: Style,
|
||||
pub all_colour_style: Style,
|
||||
pub avg_colour_style: Style,
|
||||
pub cpu_colour_styles: Vec<Style>,
|
||||
pub border_style: Style,
|
||||
|
@ -46,6 +47,7 @@ impl Default for CanvasColours {
|
|||
tx_style: Style::default().fg(STANDARD_SECOND_COLOUR),
|
||||
total_rx_style: Style::default().fg(STANDARD_THIRD_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),
|
||||
cpu_colour_styles: Vec::new(),
|
||||
border_style: Style::default().fg(text_colour),
|
||||
|
@ -122,6 +124,11 @@ impl CanvasColours {
|
|||
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<()> {
|
||||
let max_amount = std::cmp::min(colours.len(), NUM_COLOURS as usize);
|
||||
for (itx, colour) in colours.iter().enumerate() {
|
||||
|
|
|
@ -13,6 +13,7 @@ pub const STANDARD_THIRD_COLOUR: Color = Color::LightCyan;
|
|||
pub const STANDARD_FOURTH_COLOUR: Color = Color::LightGreen;
|
||||
pub const STANDARD_HIGHLIGHT_COLOUR: Color = Color::LightBlue;
|
||||
pub const AVG_COLOUR: Color = Color::Red;
|
||||
pub const ALL_COLOUR: Color = Color::Green;
|
||||
|
||||
lazy_static! {
|
||||
static ref COLOR_NAME_LOOKUP_TABLE: HashMap<&'static str, Color> = [
|
||||
|
|
|
@ -22,6 +22,9 @@ use tui::{
|
|||
|
||||
const CPU_SELECT_LEGEND_HEADER: [&str; 2] = ["CPU", "Show"];
|
||||
const CPU_LEGEND_HEADER: [&str; 2] = ["CPU", "Use%"];
|
||||
const AVG_POSITION: usize = 1;
|
||||
const ALL_POSITION: usize = 0;
|
||||
|
||||
lazy_static! {
|
||||
static ref CPU_LEGEND_HEADER_LENS: Vec<usize> = CPU_LEGEND_HEADER
|
||||
.iter()
|
||||
|
@ -97,6 +100,8 @@ impl CpuGraphWidget for Painter {
|
|||
fn draw_cpu_graph<B: Backend>(
|
||||
&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) {
|
||||
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 show_avg_cpu = app_state.app_config_fields.show_average_cpu;
|
||||
let dataset_vector: Vec<Dataset<'_>> = cpu_data
|
||||
.iter()
|
||||
.zip(&cpu_widget_state.core_show_vec)
|
||||
.enumerate()
|
||||
.rev()
|
||||
.filter_map(|(itx, (cpu, cpu_show_vec))| {
|
||||
if *cpu_show_vec {
|
||||
Some(
|
||||
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()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.map(|(itx, cpu)| {
|
||||
Dataset::default()
|
||||
.marker(if use_dot {
|
||||
Marker::Dot
|
||||
} else {
|
||||
Marker::Braille
|
||||
})
|
||||
.style(if show_avg_cpu && itx == 0 {
|
||||
.style(if show_avg_cpu && itx == AVG_POSITION {
|
||||
self.colours.avg_colour_style
|
||||
} else {
|
||||
self.colours.cpu_colour_styles
|
||||
[itx % self.colours.cpu_colour_styles.len()]
|
||||
})
|
||||
.data(&cpu.cpu_data[..])
|
||||
.graph_type(tui::widgets::GraphType::Line),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let title = if app_state.is_expanded && !cpu_widget_state.is_showing_tray {
|
||||
const TITLE_BASE: &str = " CPU ── Esc to go back ";
|
||||
format!(
|
||||
" CPU ─{}─ Esc to go back ",
|
||||
"─".repeat(
|
||||
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
|
||||
)
|
||||
)
|
||||
.graph_type(tui::widgets::GraphType::Line)
|
||||
})
|
||||
.collect()
|
||||
} else if let Some(cpu) = cpu_data.get(current_scroll_position) {
|
||||
vec![Dataset::default()
|
||||
.marker(if use_dot {
|
||||
Marker::Dot
|
||||
} else {
|
||||
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 {
|
||||
" CPU ".to_string()
|
||||
vec![]
|
||||
};
|
||||
|
||||
let title = " CPU ".to_string();
|
||||
|
||||
let border_style = if app_state.current_widget.widget_id == widget_id {
|
||||
self.colours.highlighted_border_style
|
||||
} else {
|
||||
|
@ -231,35 +247,13 @@ impl CpuGraphWidget for Painter {
|
|||
|
||||
let mut offset_scroll_index =
|
||||
(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 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) =
|
||||
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.legend_value),
|
||||
]
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let cpu_string_row: Vec<Cow<'_, str>> = vec![
|
||||
Cow::Borrowed(&cpu.cpu_name),
|
||||
Cow::Borrowed(&cpu.legend_value),
|
||||
];
|
||||
|
||||
if cpu_string_row.is_empty() {
|
||||
offset_scroll_index += 1;
|
||||
|
@ -267,21 +261,22 @@ impl CpuGraphWidget for Painter {
|
|||
} else {
|
||||
Some(Row::StyledData(
|
||||
cpu_string_row.into_iter(),
|
||||
if is_on_widget {
|
||||
if itx == offset_scroll_index {
|
||||
self.colours.currently_selected_text_style
|
||||
} else if show_avg_cpu && itx == 0 {
|
||||
if is_on_widget && itx == offset_scroll_index {
|
||||
self.colours.currently_selected_text_style
|
||||
} else if itx == ALL_POSITION {
|
||||
self.colours.all_colour_style
|
||||
} else if show_avg_cpu {
|
||||
if itx == AVG_POSITION {
|
||||
self.colours.avg_colour_style
|
||||
} else {
|
||||
self.colours.cpu_colour_styles[itx
|
||||
+ start_position as usize
|
||||
% self.colours.cpu_colour_styles.len()]
|
||||
self.colours.cpu_colour_styles[itx + start_position as usize
|
||||
- AVG_POSITION
|
||||
- 1 % self.colours.cpu_colour_styles.len()]
|
||||
}
|
||||
} else if show_avg_cpu && itx == 0 {
|
||||
self.colours.avg_colour_style
|
||||
} else {
|
||||
self.colours.cpu_colour_styles[itx
|
||||
+ start_position as usize % self.colours.cpu_colour_styles.len()]
|
||||
self.colours.cpu_colour_styles[itx + start_position as usize
|
||||
- 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_ratios = vec![0.5, 0.5];
|
||||
|
||||
let variable_intrinsic_results = get_variable_intrinsic_widths(
|
||||
width as u16,
|
||||
&width_ratios,
|
||||
if cpu_widget_state.is_showing_tray {
|
||||
&CPU_SELECT_LEGEND_HEADER_LENS
|
||||
} else {
|
||||
&CPU_LEGEND_HEADER_LENS
|
||||
},
|
||||
);
|
||||
let variable_intrinsic_results =
|
||||
get_variable_intrinsic_widths(width as u16, &width_ratios, &CPU_LEGEND_HEADER_LENS);
|
||||
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 {
|
||||
(
|
||||
self.colours.highlighted_border_style,
|
||||
|
@ -325,31 +301,22 @@ impl CpuGraphWidget for Painter {
|
|||
|
||||
// Draw
|
||||
f.render_widget(
|
||||
Table::new(
|
||||
if cpu_widget_state.is_showing_tray {
|
||||
CPU_SELECT_LEGEND_HEADER
|
||||
} else {
|
||||
CPU_LEGEND_HEADER
|
||||
}
|
||||
.iter(),
|
||||
cpu_rows,
|
||||
)
|
||||
.block(
|
||||
Block::default()
|
||||
.title(&title)
|
||||
.title_style(border_and_title_style)
|
||||
.borders(Borders::ALL)
|
||||
.border_style(border_and_title_style),
|
||||
)
|
||||
.header_style(self.colours.table_header_style)
|
||||
.highlight_style(highlight_style)
|
||||
.widths(
|
||||
&(intrinsic_widths
|
||||
.iter()
|
||||
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
|
||||
.collect::<Vec<_>>()),
|
||||
)
|
||||
.header_gap(app_state.app_config_fields.table_gap),
|
||||
Table::new(CPU_LEGEND_HEADER.iter(), cpu_rows)
|
||||
.block(
|
||||
Block::default()
|
||||
.title_style(border_and_title_style)
|
||||
.borders(Borders::ALL)
|
||||
.border_style(border_and_title_style),
|
||||
)
|
||||
.header_style(self.colours.table_header_style)
|
||||
.highlight_style(highlight_style)
|
||||
.widths(
|
||||
&(intrinsic_widths
|
||||
.iter()
|
||||
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
|
||||
.collect::<Vec<_>>()),
|
||||
)
|
||||
.header_gap(app_state.app_config_fields.table_gap),
|
||||
draw_loc,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
];
|
||||
|
||||
pub const CPU_HELP_TEXT: [&str; 4] = [
|
||||
pub const CPU_HELP_TEXT: [&str; 2] = [
|
||||
"2 - CPU widget\n",
|
||||
"/ Open filtering for showing certain CPU cores\n",
|
||||
"Space Toggle enabled/disabled cores\n",
|
||||
"Esc Exit filtering mode",
|
||||
"Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart",
|
||||
];
|
||||
|
||||
pub const PROCESS_HELP_TEXT: [&str; 8] = [
|
||||
|
@ -170,8 +168,8 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
|
|||
# is also set here.
|
||||
[flags]
|
||||
|
||||
# Whether to display an average cpu entry.
|
||||
#avg_cpu = false
|
||||
# Whether to hide the average cpu entry.
|
||||
#hide_avg_cpu = false
|
||||
|
||||
# Whether to use dot markers rather than braille.
|
||||
#dot_marker = false
|
||||
|
@ -197,9 +195,6 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
|
|||
# Whether to make process searching use regex by default.
|
||||
#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:
|
||||
#temperature_type = "k"
|
||||
#temperature_type = "f"
|
||||
|
|
|
@ -66,6 +66,7 @@ pub struct ConvertedCpuData {
|
|||
pub cpu_name: String,
|
||||
/// Tuple is time, value
|
||||
pub cpu_data: Vec<Point>,
|
||||
/// Represents the value displayed on the legend.
|
||||
pub legend_value: String,
|
||||
}
|
||||
|
||||
|
@ -153,7 +154,7 @@ pub fn convert_cpu_data_points(
|
|||
let mut new_cpu_data = ConvertedCpuData::default();
|
||||
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 {
|
||||
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(
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -67,7 +67,7 @@ fn get_matches() -> clap::ArgMatches<'static> {
|
|||
(version: crate_version!())
|
||||
(author: crate_authors!())
|
||||
(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.")
|
||||
(@group TEMPERATURE_TYPE =>
|
||||
(@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 WHOLE_WORD: -W --whole_word "Match whole word when 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 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")
|
||||
|
@ -158,7 +157,6 @@ fn main() -> error::Result<()> {
|
|||
// Set panic hook
|
||||
panic::set_hook(Box::new(|info| panic_hook(info)));
|
||||
|
||||
let mut first_run = true;
|
||||
loop {
|
||||
if let Ok(recv) = receiver.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) {
|
||||
match recv {
|
||||
|
@ -219,18 +217,7 @@ fn main() -> error::Result<()> {
|
|||
app.canvas_data.swap_label = memory_and_swap_labels.1;
|
||||
}
|
||||
|
||||
// Pre-fill CPU if needed
|
||||
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
|
||||
app.canvas_data.cpu_data =
|
||||
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)?;
|
||||
}
|
||||
|
||||
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 {
|
||||
painter.colours.set_cpu_colours(cpu_core_colors)?;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ pub struct Config {
|
|||
|
||||
#[derive(Default, Deserialize)]
|
||||
pub struct ConfigFlags {
|
||||
pub avg_cpu: Option<bool>,
|
||||
pub hide_avg_cpu: Option<bool>,
|
||||
pub dot_marker: Option<bool>,
|
||||
pub temperature_type: Option<String>,
|
||||
pub rate: Option<u64>,
|
||||
|
@ -32,7 +32,6 @@ pub struct ConfigFlags {
|
|||
pub whole_word: Option<bool>,
|
||||
pub regex: Option<bool>,
|
||||
pub default_widget: Option<String>,
|
||||
pub show_disabled_data: Option<bool>,
|
||||
pub basic: Option<bool>,
|
||||
pub default_time_value: Option<u64>,
|
||||
pub time_delta: Option<u64>,
|
||||
|
@ -48,6 +47,7 @@ pub struct ConfigFlags {
|
|||
#[derive(Default, Deserialize)]
|
||||
pub struct ConfigColours {
|
||||
pub table_header_color: Option<String>,
|
||||
pub all_cpu_color: Option<String>,
|
||||
pub avg_cpu_color: Option<String>,
|
||||
pub cpu_core_colors: Option<Vec<String>>,
|
||||
pub ram_color: Option<String>,
|
||||
|
@ -208,11 +208,10 @@ pub fn build_app(
|
|||
let app_config_fields = AppConfigFields {
|
||||
update_rate_in_milliseconds: get_update_rate_in_milliseconds(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),
|
||||
left_legend: get_use_left_legend(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,
|
||||
default_time_value,
|
||||
time_interval: get_time_interval(matches, config)?,
|
||||
|
@ -356,16 +355,19 @@ fn get_temperature(
|
|||
Ok(data_harvester::temperature::TemperatureType::Celsius)
|
||||
}
|
||||
|
||||
fn get_avg_cpu(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||
if matches.is_present("AVG_CPU") {
|
||||
return true;
|
||||
/// Yes, this function gets whether to show average CPU (true) or not (false)
|
||||
fn get_show_average_cpu(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||
// 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 {
|
||||
if let Some(avg_cpu) = flags.avg_cpu {
|
||||
if let Some(avg_cpu) = flags.hide_avg_cpu {
|
||||
return avg_cpu;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
true
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
if matches.is_present("BASIC_MODE") {
|
||||
return true;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[flags]
|
||||
avg_cpu = "test"
|
||||
basic = "test"
|
Loading…
Reference in a new issue