feature: Add appox. total mem as an option for processes and basic mem
Adds a way to display the memory value as a column in the processes widget and the basic memory widget, rather than just the percentage.
This commit is contained in:
parent
59ce90f577
commit
3c373d7129
|
@ -20,6 +20,7 @@
|
||||||
"haase",
|
"haase",
|
||||||
"heim",
|
"heim",
|
||||||
"hjkl",
|
"hjkl",
|
||||||
|
"libc",
|
||||||
"markdownlint",
|
"markdownlint",
|
||||||
"minwindef",
|
"minwindef",
|
||||||
"noheader",
|
"noheader",
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
"softirq",
|
"softirq",
|
||||||
"stime",
|
"stime",
|
||||||
"subwidget",
|
"subwidget",
|
||||||
|
"sysconf",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"tokei",
|
"tokei",
|
||||||
"twrite",
|
"twrite",
|
||||||
|
@ -39,6 +41,7 @@
|
||||||
"use",
|
"use",
|
||||||
"use curr usage",
|
"use curr usage",
|
||||||
"utime",
|
"utime",
|
||||||
|
"virt",
|
||||||
"whitespaces",
|
"whitespaces",
|
||||||
"winapi",
|
"winapi",
|
||||||
"winnt",
|
"winnt",
|
||||||
|
|
|
@ -41,8 +41,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- [#114](https://github.com/ClementTsang/bottom/pull/114): Show process state per process (originally in 0.4.0, moved to later). This only
|
- [#114](https://github.com/ClementTsang/bottom/pull/114): Show process state per process (originally in 0.4.0, moved to later). This only shows if the processes are not merged together; I couldn't think of a nice way to show it when grouped together, unfortunately.
|
||||||
shows if the processes are not merged together; I couldn't think of a nice way to show it when grouped together, unfortunately.
|
|
||||||
|
- Add (estimated) memory usage values, toggle this from percent to values for processes with `%`.
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
|
|
|
@ -762,9 +762,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.70"
|
version = "0.2.74"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
|
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
|
|
|
@ -38,6 +38,7 @@ 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"
|
||||||
|
# libc = "0.2.74"
|
||||||
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
|
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
|
||||||
tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
|
tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
|
||||||
|
|
||||||
|
|
|
@ -225,6 +225,7 @@ Run using `btm`.
|
||||||
| `P` | Toggle between showing the full path or just the process name |
|
| `P` | Toggle between showing the full path or just the process name |
|
||||||
| `s, F6` | Open process sort widget |
|
| `s, F6` | Open process sort widget |
|
||||||
| `I` | Invert current sort |
|
| `I` | Invert current sort |
|
||||||
|
| `%` | Toggle between values and percentages for memory usage |
|
||||||
|
|
||||||
#### Process search bindings
|
#### Process search bindings
|
||||||
|
|
||||||
|
@ -260,6 +261,12 @@ Run using `btm`.
|
||||||
| `Left, Alt-h` | Go to the next battery |
|
| `Left, Alt-h` | Go to the next battery |
|
||||||
| `Right, Alt-l` | Go to the previous battery |
|
| `Right, Alt-l` | Go to the previous battery |
|
||||||
|
|
||||||
|
#### Basic memory bindings
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| --- | ------------------------------------------------------ |
|
||||||
|
| `%` | Toggle between values and percentages for memory usage |
|
||||||
|
|
||||||
### Process searching keywords
|
### Process searching keywords
|
||||||
|
|
||||||
- Note none of the keywords are case sensitive.
|
- Note none of the keywords are case sensitive.
|
||||||
|
|
28
src/app.rs
28
src/app.rs
|
@ -80,6 +80,9 @@ pub struct App {
|
||||||
#[builder(default = false, setter(skip))]
|
#[builder(default = false, setter(skip))]
|
||||||
pub is_force_redraw: bool,
|
pub is_force_redraw: bool,
|
||||||
|
|
||||||
|
#[builder(default = false, setter(skip))]
|
||||||
|
pub basic_mode_use_percent: bool,
|
||||||
|
|
||||||
pub cpu_state: CpuState,
|
pub cpu_state: CpuState,
|
||||||
pub mem_state: MemState,
|
pub mem_state: MemState,
|
||||||
pub net_state: NetState,
|
pub net_state: NetState,
|
||||||
|
@ -342,6 +345,30 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_percentages(&mut self) {
|
||||||
|
match &self.current_widget.widget_type {
|
||||||
|
BottomWidgetType::BasicMem => {
|
||||||
|
self.basic_mode_use_percent = !self.basic_mode_use_percent; // Oh god this is so lazy.
|
||||||
|
}
|
||||||
|
BottomWidgetType::Proc => {
|
||||||
|
if let Some(proc_widget_state) = self
|
||||||
|
.proc_state
|
||||||
|
.widget_states
|
||||||
|
.get_mut(&self.current_widget.widget_id)
|
||||||
|
{
|
||||||
|
proc_widget_state
|
||||||
|
.columns
|
||||||
|
.toggle(&processes::ProcessSorting::Mem);
|
||||||
|
proc_widget_state
|
||||||
|
.columns
|
||||||
|
.toggle(&processes::ProcessSorting::MemPercent);
|
||||||
|
self.proc_state.force_update = Some(self.current_widget.widget_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle_ignore_case(&mut self) {
|
pub fn toggle_ignore_case(&mut self) {
|
||||||
let is_in_search_widget = self.is_in_search_widget();
|
let is_in_search_widget = self.is_in_search_widget();
|
||||||
if let Some(proc_widget_state) = self
|
if let Some(proc_widget_state) = self
|
||||||
|
@ -1111,6 +1138,7 @@ impl App {
|
||||||
'e' => self.expand_widget(),
|
'e' => self.expand_widget(),
|
||||||
's' => self.toggle_sort(),
|
's' => self.toggle_sort(),
|
||||||
'I' => self.invert_sort(),
|
'I' => self.invert_sort(),
|
||||||
|
'%' => self.toggle_percentages(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ pub struct DataCollector {
|
||||||
widgets_to_harvest: UsedWidgets,
|
widgets_to_harvest: UsedWidgets,
|
||||||
battery_manager: Option<Manager>,
|
battery_manager: Option<Manager>,
|
||||||
battery_list: Option<Vec<Battery>>,
|
battery_list: Option<Vec<Battery>>,
|
||||||
|
// page_file_size_kb: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DataCollector {
|
impl Default for DataCollector {
|
||||||
|
@ -110,6 +111,11 @@ impl Default for DataCollector {
|
||||||
widgets_to_harvest: UsedWidgets::default(),
|
widgets_to_harvest: UsedWidgets::default(),
|
||||||
battery_manager: None,
|
battery_manager: None,
|
||||||
battery_list: None,
|
battery_list: None,
|
||||||
|
// page_file_size_kb: if cfg!(target_os = "linux") {
|
||||||
|
// unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024 }
|
||||||
|
// } else {
|
||||||
|
// 0
|
||||||
|
// },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,6 +206,7 @@ impl DataCollector {
|
||||||
current_instant
|
current_instant
|
||||||
.duration_since(self.last_collection_time)
|
.duration_since(self.last_collection_time)
|
||||||
.as_secs(),
|
.as_secs(),
|
||||||
|
self.mem_total_kb,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
|
|
@ -53,8 +53,8 @@ pub async fn get_network_data(
|
||||||
(0, 0)
|
(0, 0)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
((total_rx - *prev_net_rx) as f64 / elapsed_time) as u64,
|
((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64,
|
||||||
((total_tx - *prev_net_tx) as f64 / elapsed_time) as u64,
|
((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ pub struct ProcessHarvest {
|
||||||
pub pid: u32,
|
pub pid: u32,
|
||||||
pub cpu_usage_percent: f64,
|
pub cpu_usage_percent: f64,
|
||||||
pub mem_usage_percent: f64,
|
pub mem_usage_percent: f64,
|
||||||
|
pub mem_usage_kb: u64,
|
||||||
|
// pub rss_kb: u64,
|
||||||
|
// pub virt_kb: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub read_bytes_per_sec: u64,
|
pub read_bytes_per_sec: u64,
|
||||||
|
@ -224,12 +227,13 @@ fn get_linux_cpu_usage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn convert_ps<S: core::hash::BuildHasher>(
|
fn convert_ps<S: core::hash::BuildHasher>(
|
||||||
process: &str, cpu_usage: f64, cpu_fraction: f64,
|
process: &str, cpu_usage: f64, cpu_fraction: f64,
|
||||||
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, S>,
|
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, S>,
|
||||||
new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool,
|
new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool,
|
||||||
time_difference_in_secs: u64,
|
time_difference_in_secs: u64, mem_total_kb: u64,
|
||||||
) -> std::io::Result<ProcessHarvest> {
|
) -> std::io::Result<ProcessHarvest> {
|
||||||
let pid = (&process[..10])
|
let pid = (&process[..10])
|
||||||
.trim()
|
.trim()
|
||||||
|
@ -313,6 +317,7 @@ fn convert_ps<S: core::hash::BuildHasher>(
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
mem_usage_percent,
|
mem_usage_percent,
|
||||||
|
mem_usage_kb: (mem_usage_percent * mem_total_kb as f64 / 100.0) as u64,
|
||||||
cpu_usage_percent,
|
cpu_usage_percent,
|
||||||
total_read_bytes,
|
total_read_bytes,
|
||||||
total_write_bytes,
|
total_write_bytes,
|
||||||
|
@ -327,7 +332,7 @@ fn convert_ps<S: core::hash::BuildHasher>(
|
||||||
pub fn linux_get_processes_list(
|
pub fn linux_get_processes_list(
|
||||||
prev_idle: &mut f64, prev_non_idle: &mut f64,
|
prev_idle: &mut f64, prev_non_idle: &mut f64,
|
||||||
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool,
|
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool,
|
||||||
time_difference_in_secs: u64,
|
time_difference_in_secs: u64, mem_total_kb: u64,
|
||||||
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
||||||
let ps_result = Command::new("ps")
|
let ps_result = Command::new("ps")
|
||||||
.args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"])
|
.args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"])
|
||||||
|
@ -336,7 +341,6 @@ pub fn linux_get_processes_list(
|
||||||
let split_string = ps_stdout.split('\n');
|
let split_string = ps_stdout.split('\n');
|
||||||
if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
||||||
let process_list = split_string.collect::<Vec<&str>>();
|
let process_list = split_string.collect::<Vec<&str>>();
|
||||||
|
|
||||||
let mut new_pid_stats = HashMap::new();
|
let mut new_pid_stats = HashMap::new();
|
||||||
|
|
||||||
let process_vector: Vec<ProcessHarvest> = process_list
|
let process_vector: Vec<ProcessHarvest> = process_list
|
||||||
|
@ -352,6 +356,7 @@ pub fn linux_get_processes_list(
|
||||||
&mut new_pid_stats,
|
&mut new_pid_stats,
|
||||||
use_current_cpu_total,
|
use_current_cpu_total,
|
||||||
time_difference_in_secs,
|
time_difference_in_secs,
|
||||||
|
mem_total_kb,
|
||||||
) {
|
) {
|
||||||
if !process_object.name.is_empty() {
|
if !process_object.name.is_empty() {
|
||||||
Some(process_object)
|
Some(process_object)
|
||||||
|
@ -431,6 +436,7 @@ pub fn windows_macos_get_processes_list(
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
},
|
},
|
||||||
|
mem_usage_kb: process_val.memory(),
|
||||||
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,
|
||||||
|
|
|
@ -671,12 +671,12 @@ impl Prefix {
|
||||||
match prefix_type {
|
match prefix_type {
|
||||||
PrefixType::Cpu => matches_condition(
|
PrefixType::Cpu => matches_condition(
|
||||||
&numerical_query.condition,
|
&numerical_query.condition,
|
||||||
process.cpu_usage,
|
process.cpu_percent_usage,
|
||||||
numerical_query.value,
|
numerical_query.value,
|
||||||
),
|
),
|
||||||
PrefixType::Mem => matches_condition(
|
PrefixType::Mem => matches_condition(
|
||||||
&numerical_query.condition,
|
&numerical_query.condition,
|
||||||
process.mem_usage,
|
process.mem_percent_usage,
|
||||||
numerical_query.value,
|
numerical_query.value,
|
||||||
),
|
),
|
||||||
PrefixType::Rps => matches_condition(
|
PrefixType::Rps => matches_condition(
|
||||||
|
|
|
@ -165,6 +165,7 @@ impl Default for ProcColumn {
|
||||||
ProcessName,
|
ProcessName,
|
||||||
Command,
|
Command,
|
||||||
CpuPercent,
|
CpuPercent,
|
||||||
|
Mem,
|
||||||
MemPercent,
|
MemPercent,
|
||||||
ReadPerSecond,
|
ReadPerSecond,
|
||||||
WritePerSecond,
|
WritePerSecond,
|
||||||
|
@ -187,7 +188,7 @@ impl Default for ProcColumn {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
MemPercent | Mem => {
|
MemPercent => {
|
||||||
column_mapping.insert(
|
column_mapping.insert(
|
||||||
column,
|
column,
|
||||||
ColumnInfo {
|
ColumnInfo {
|
||||||
|
@ -196,6 +197,15 @@ impl Default for ProcColumn {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Mem => {
|
||||||
|
column_mapping.insert(
|
||||||
|
column,
|
||||||
|
ColumnInfo {
|
||||||
|
enabled: false,
|
||||||
|
shortcut: Some("m"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
ProcessName => {
|
ProcessName => {
|
||||||
column_mapping.insert(
|
column_mapping.insert(
|
||||||
column,
|
column,
|
||||||
|
@ -250,6 +260,20 @@ impl Default for ProcColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcColumn {
|
impl ProcColumn {
|
||||||
|
pub fn toggle(&mut self, column: &ProcessSorting) {
|
||||||
|
if let Some(mapping) = self.column_mapping.get_mut(column) {
|
||||||
|
mapping.enabled = !(mapping.enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_enabled(&self, column: &ProcessSorting) -> bool {
|
||||||
|
if let Some(mapping) = self.column_mapping.get(column) {
|
||||||
|
mapping.enabled
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_enabled_columns_len(&self) -> usize {
|
pub fn get_enabled_columns_len(&self) -> usize {
|
||||||
self.ordered_columns
|
self.ordered_columns
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -42,8 +42,10 @@ pub struct DisplayableData {
|
||||||
pub process_data: Vec<ConvertedProcessData>,
|
pub process_data: Vec<ConvertedProcessData>,
|
||||||
// What's actually displayed
|
// What's actually displayed
|
||||||
pub finalized_process_data_map: HashMap<u64, Vec<ConvertedProcessData>>,
|
pub finalized_process_data_map: HashMap<u64, Vec<ConvertedProcessData>>,
|
||||||
pub mem_label: String,
|
pub mem_label_percent: String,
|
||||||
pub swap_label: String,
|
pub swap_label_percent: String,
|
||||||
|
pub mem_label_frac: String,
|
||||||
|
pub swap_label_frac: String,
|
||||||
pub mem_data: Vec<(f64, f64)>,
|
pub mem_data: Vec<(f64, f64)>,
|
||||||
pub swap_data: Vec<(f64, f64)>,
|
pub swap_data: Vec<(f64, f64)>,
|
||||||
pub cpu_data: Vec<ConvertedCpuData>,
|
pub cpu_data: Vec<ConvertedCpuData>,
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl HelpDialog for Painter {
|
||||||
|
|
||||||
app_state.help_dialog_state.scroll_state.max_scroll_index =
|
app_state.help_dialog_state.scroll_state.max_scroll_index =
|
||||||
(self.styled_help_text.len() as u16
|
(self.styled_help_text.len() as u16
|
||||||
+ (constants::HELP_TEXT.len() as u16 - 4)
|
+ (constants::HELP_TEXT.len() as u16 - 5)
|
||||||
+ overflow_buffer)
|
+ overflow_buffer)
|
||||||
.saturating_sub(draw_loc.height);
|
.saturating_sub(draw_loc.height);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ impl DiskTableWidget for Painter {
|
||||||
get_variable_intrinsic_widths(width as u16, &width_ratios, &DISK_HEADERS_LENS);
|
get_variable_intrinsic_widths(width as u16, &width_ratios, &DISK_HEADERS_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];
|
||||||
|
|
||||||
|
// TODO: This seems to be bugged? The selected text style gets "stuck"? I think this gets fixed with tui 0.10?
|
||||||
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,
|
||||||
|
|
|
@ -38,8 +38,6 @@ impl MemBasicWidget for Painter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// +9 due to 3 + 4 + 2 + 2 columns for the name & space + percentage + bar bounds + margin spacing
|
|
||||||
let bar_length = usize::from(draw_loc.width.saturating_sub(11));
|
|
||||||
let ram_use_percentage = if let Some(mem) = mem_data.last() {
|
let ram_use_percentage = if let Some(mem) = mem_data.last() {
|
||||||
mem.1
|
mem.1
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,20 +48,63 @@ impl MemBasicWidget for Painter {
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length);
|
|
||||||
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length);
|
// +7 due to 3 + 2 + 2 columns for the name & space + bar bounds + margin spacing
|
||||||
let mem_label = format!(
|
// Then + length of fraction
|
||||||
|
let ram_bar_length = usize::from(
|
||||||
|
draw_loc
|
||||||
|
.width
|
||||||
|
.saturating_sub(7)
|
||||||
|
.saturating_sub(app_state.canvas_data.mem_label_frac.trim().len() as u16),
|
||||||
|
);
|
||||||
|
let swap_bar_length = usize::from(
|
||||||
|
draw_loc
|
||||||
|
.width
|
||||||
|
.saturating_sub(7)
|
||||||
|
.saturating_sub(app_state.canvas_data.swap_label_frac.trim().len() as u16),
|
||||||
|
);
|
||||||
|
|
||||||
|
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, ram_bar_length);
|
||||||
|
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, swap_bar_length);
|
||||||
|
// TODO: Use different styling for the frac.
|
||||||
|
let mem_label = if app_state.basic_mode_use_percent {
|
||||||
|
format!(
|
||||||
"RAM[{}{}{:3.0}%]\n",
|
"RAM[{}{}{:3.0}%]\n",
|
||||||
"|".repeat(num_bars_ram),
|
"|".repeat(num_bars_ram),
|
||||||
" ".repeat(bar_length - num_bars_ram),
|
" ".repeat(
|
||||||
ram_use_percentage.round(),
|
ram_bar_length - num_bars_ram
|
||||||
);
|
+ app_state.canvas_data.mem_label_frac.trim().len()
|
||||||
let swap_label = format!(
|
- 4
|
||||||
|
),
|
||||||
|
ram_use_percentage.round()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"RAM[{}{}{}]\n",
|
||||||
|
"|".repeat(num_bars_ram),
|
||||||
|
" ".repeat(ram_bar_length - num_bars_ram),
|
||||||
|
&app_state.canvas_data.mem_label_frac.trim()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let swap_label = if app_state.basic_mode_use_percent {
|
||||||
|
format!(
|
||||||
"SWP[{}{}{:3.0}%]",
|
"SWP[{}{}{:3.0}%]",
|
||||||
"|".repeat(num_bars_swap),
|
"|".repeat(num_bars_swap),
|
||||||
" ".repeat(bar_length - num_bars_swap),
|
" ".repeat(
|
||||||
swap_use_percentage.round(),
|
swap_bar_length - num_bars_swap
|
||||||
);
|
+ app_state.canvas_data.swap_label_frac.trim().len()
|
||||||
|
- 4
|
||||||
|
),
|
||||||
|
swap_use_percentage.round()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"SWP[{}{}{}]",
|
||||||
|
"|".repeat(num_bars_swap),
|
||||||
|
" ".repeat(swap_bar_length - num_bars_swap),
|
||||||
|
&app_state.canvas_data.swap_label_frac.trim()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let mem_text = [
|
let mem_text = [
|
||||||
Text::styled(mem_label, self.colours.ram_style),
|
Text::styled(mem_label, self.colours.ram_style),
|
||||||
|
|
|
@ -62,10 +62,13 @@ impl MemGraphWidget for Painter {
|
||||||
.labels_style(self.colours.graph_style);
|
.labels_style(self.colours.graph_style);
|
||||||
|
|
||||||
let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
|
let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
|
||||||
|
let mem_label = format!(
|
||||||
|
"RAM:{}{}",
|
||||||
|
app_state.canvas_data.mem_label_percent, app_state.canvas_data.mem_label_frac
|
||||||
|
);
|
||||||
mem_canvas_vec.push(
|
mem_canvas_vec.push(
|
||||||
Dataset::default()
|
Dataset::default()
|
||||||
.name(&app_state.canvas_data.mem_label)
|
.name(&mem_label)
|
||||||
.marker(if app_state.app_config_fields.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,9 +79,13 @@ impl MemGraphWidget for Painter {
|
||||||
.graph_type(tui::widgets::GraphType::Line),
|
.graph_type(tui::widgets::GraphType::Line),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let swap_label = format!(
|
||||||
|
"SWP:{}{}",
|
||||||
|
app_state.canvas_data.swap_label_percent, app_state.canvas_data.swap_label_frac
|
||||||
|
);
|
||||||
mem_canvas_vec.push(
|
mem_canvas_vec.push(
|
||||||
Dataset::default()
|
Dataset::default()
|
||||||
.name(&app_state.canvas_data.swap_label)
|
.name(&swap_label)
|
||||||
.marker(if app_state.app_config_fields.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::{data_harvester::processes::ProcessSorting, App},
|
||||||
canvas::{
|
canvas::{
|
||||||
drawing_utils::{
|
drawing_utils::{
|
||||||
get_search_start_position, get_start_position, get_variable_intrinsic_widths,
|
get_search_start_position, get_start_position, get_variable_intrinsic_widths,
|
||||||
|
@ -152,6 +152,7 @@ impl ProcessTableWidget for Painter {
|
||||||
|
|
||||||
// Draw!
|
// Draw!
|
||||||
let is_proc_widget_grouped = proc_widget_state.is_grouped;
|
let is_proc_widget_grouped = proc_widget_state.is_grouped;
|
||||||
|
let mem_enabled = proc_widget_state.columns.is_enabled(&ProcessSorting::Mem);
|
||||||
let process_rows = sliced_vec.iter().map(|process| {
|
let process_rows = sliced_vec.iter().map(|process| {
|
||||||
Row::Data(
|
Row::Data(
|
||||||
vec![
|
vec![
|
||||||
|
@ -161,8 +162,12 @@ impl ProcessTableWidget for Painter {
|
||||||
process.pid.to_string()
|
process.pid.to_string()
|
||||||
},
|
},
|
||||||
process.name.clone(),
|
process.name.clone(),
|
||||||
format!("{:.1}%", process.cpu_usage),
|
format!("{:.1}%", process.cpu_percent_usage),
|
||||||
format!("{:.1}%", process.mem_usage),
|
if mem_enabled {
|
||||||
|
format!("{:.0}{}", process.mem_usage_str.0, process.mem_usage_str.1)
|
||||||
|
} else {
|
||||||
|
format!("{:.1}%", process.mem_percent_usage)
|
||||||
|
},
|
||||||
process.read_per_sec.to_string(),
|
process.read_per_sec.to_string(),
|
||||||
process.write_per_sec.to_string(),
|
process.write_per_sec.to_string(),
|
||||||
process.total_read.to_string(),
|
process.total_read.to_string(),
|
||||||
|
|
|
@ -42,14 +42,15 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help text
|
// Help text
|
||||||
pub const HELP_CONTENTS_TEXT: [&str; 7] = [
|
pub const HELP_CONTENTS_TEXT: [&str; 8] = [
|
||||||
"Press the corresponding numbers to jump to the section, or scroll:\n",
|
"Press the corresponding numbers to jump to the section, or scroll:\n",
|
||||||
"1 - General\n",
|
"1 - General\n",
|
||||||
"2 - CPU widget\n",
|
"2 - CPU widget\n",
|
||||||
"3 - Process widget\n",
|
"3 - Process widget\n",
|
||||||
"4 - Process search widget\n",
|
"4 - Process search widget\n",
|
||||||
"5 - Process sort widget\n",
|
"5 - Process sort widget\n",
|
||||||
"6 - Battery widget",
|
"6 - Battery widget\n",
|
||||||
|
"7 - Basic memory widget",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const GENERAL_HELP_TEXT: [&str; 29] = [
|
pub const GENERAL_HELP_TEXT: [&str; 29] = [
|
||||||
|
@ -91,7 +92,7 @@ pub const CPU_HELP_TEXT: [&str; 2] = [
|
||||||
|
|
||||||
// TODO [Help]: Search in help?
|
// TODO [Help]: Search in help?
|
||||||
// TODO [Help]: Move to using tables for easier formatting?
|
// TODO [Help]: Move to using tables for easier formatting?
|
||||||
pub const PROCESS_HELP_TEXT: [&str; 11] = [
|
pub const PROCESS_HELP_TEXT: [&str; 12] = [
|
||||||
"3 - Process widget\n",
|
"3 - Process widget\n",
|
||||||
"dd Kill the selected process\n",
|
"dd Kill the selected process\n",
|
||||||
"c Sort by CPU usage, press again to reverse sorting order\n",
|
"c Sort by CPU usage, press again to reverse sorting order\n",
|
||||||
|
@ -102,7 +103,8 @@ pub const PROCESS_HELP_TEXT: [&str; 11] = [
|
||||||
"Ctrl-f, / Open process search widget\n",
|
"Ctrl-f, / Open process search widget\n",
|
||||||
"P Toggle between showing the full path or just the process name\n",
|
"P Toggle between showing the full path or just the process name\n",
|
||||||
"s, F6 Open process sort widget\n",
|
"s, F6 Open process sort widget\n",
|
||||||
"I Invert current sort",
|
"I Invert current sort\n",
|
||||||
|
"% Toggle between values and percentages for memory usage",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const SEARCH_HELP_TEXT: [&str; 43] = [
|
pub const SEARCH_HELP_TEXT: [&str; 43] = [
|
||||||
|
@ -166,6 +168,11 @@ pub const BATTERY_HELP_TEXT: [&str; 3] = [
|
||||||
"Right Go to next battery",
|
"Right Go to next battery",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub const BASIC_MEM_HELP_TEXT: [&str; 2] = [
|
||||||
|
"7 - Basic memory widget\n",
|
||||||
|
"% Toggle between values and percentages for memory usage",
|
||||||
|
];
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref HELP_TEXT: Vec<Vec<&'static str>> = vec![
|
pub static ref HELP_TEXT: Vec<Vec<&'static str>> = vec![
|
||||||
HELP_CONTENTS_TEXT.to_vec(),
|
HELP_CONTENTS_TEXT.to_vec(),
|
||||||
|
@ -175,6 +182,7 @@ lazy_static! {
|
||||||
SEARCH_HELP_TEXT.to_vec(),
|
SEARCH_HELP_TEXT.to_vec(),
|
||||||
SORT_HELP_TEXT.to_vec(),
|
SORT_HELP_TEXT.to_vec(),
|
||||||
BATTERY_HELP_TEXT.to_vec(),
|
BATTERY_HELP_TEXT.to_vec(),
|
||||||
|
BASIC_MEM_HELP_TEXT.to_vec(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,10 @@ pub struct ConvertedNetworkData {
|
||||||
pub struct ConvertedProcessData {
|
pub struct ConvertedProcessData {
|
||||||
pub pid: u32,
|
pub pid: u32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub cpu_usage: f64,
|
pub cpu_percent_usage: f64,
|
||||||
pub mem_usage: f64,
|
pub mem_percent_usage: f64,
|
||||||
|
pub mem_usage_kb: u64,
|
||||||
|
pub mem_usage_str: (f64, String),
|
||||||
pub group_pids: Vec<u32>,
|
pub group_pids: Vec<u32>,
|
||||||
pub read_per_sec: String,
|
pub read_per_sec: String,
|
||||||
pub write_per_sec: String,
|
pub write_per_sec: String,
|
||||||
|
@ -51,8 +53,9 @@ pub struct ConvertedProcessData {
|
||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
pub struct SingleProcessData {
|
pub struct SingleProcessData {
|
||||||
pub pid: u32,
|
pub pid: u32,
|
||||||
pub cpu_usage: f64,
|
pub cpu_percent_usage: f64,
|
||||||
pub mem_usage: f64,
|
pub mem_percent_usage: f64,
|
||||||
|
pub mem_usage_kb: u64,
|
||||||
pub group_pids: Vec<u32>,
|
pub group_pids: Vec<u32>,
|
||||||
pub read_per_sec: u64,
|
pub read_per_sec: u64,
|
||||||
pub write_per_sec: u64,
|
pub write_per_sec: u64,
|
||||||
|
@ -231,9 +234,11 @@ pub fn convert_swap_data_points(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String, String) {
|
pub fn convert_mem_labels(
|
||||||
let mem_label = "RAM:".to_string()
|
current_data: &data_farmer::DataCollection,
|
||||||
+ &format!(
|
) -> (String, String, String, String) {
|
||||||
|
(
|
||||||
|
format!(
|
||||||
"{:3.0}%",
|
"{:3.0}%",
|
||||||
match current_data.memory_harvest.mem_total_in_mb {
|
match current_data.memory_harvest.mem_total_in_mb {
|
||||||
0 => 0.0,
|
0 => 0.0,
|
||||||
|
@ -241,15 +246,13 @@ pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String
|
||||||
current_data.memory_harvest.mem_used_in_mb as f64 * 100.0
|
current_data.memory_harvest.mem_used_in_mb as f64 * 100.0
|
||||||
/ current_data.memory_harvest.mem_total_in_mb as f64,
|
/ current_data.memory_harvest.mem_total_in_mb as f64,
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
+ &format!(
|
format!(
|
||||||
" {:.1}GB/{:.1}GB",
|
" {:.1}GB/{:.1}GB",
|
||||||
current_data.memory_harvest.mem_used_in_mb as f64 / 1024.0,
|
current_data.memory_harvest.mem_used_in_mb as f64 / 1024.0,
|
||||||
(current_data.memory_harvest.mem_total_in_mb as f64 / 1024.0)
|
(current_data.memory_harvest.mem_total_in_mb as f64 / 1024.0)
|
||||||
);
|
),
|
||||||
|
format!(
|
||||||
let swap_label = "SWP:".to_string()
|
|
||||||
+ &format!(
|
|
||||||
"{:3.0}%",
|
"{:3.0}%",
|
||||||
match current_data.swap_harvest.mem_total_in_mb {
|
match current_data.swap_harvest.mem_total_in_mb {
|
||||||
0 => 0.0,
|
0 => 0.0,
|
||||||
|
@ -257,14 +260,13 @@ pub fn convert_mem_labels(current_data: &data_farmer::DataCollection) -> (String
|
||||||
current_data.swap_harvest.mem_used_in_mb as f64 * 100.0
|
current_data.swap_harvest.mem_used_in_mb as f64 * 100.0
|
||||||
/ current_data.swap_harvest.mem_total_in_mb as f64,
|
/ current_data.swap_harvest.mem_total_in_mb as f64,
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
+ &format!(
|
format!(
|
||||||
" {:.1}GB/{:.1}GB",
|
" {:.1}GB/{:.1}GB",
|
||||||
current_data.swap_harvest.mem_used_in_mb as f64 / 1024.0,
|
current_data.swap_harvest.mem_used_in_mb as f64 / 1024.0,
|
||||||
(current_data.swap_harvest.mem_total_in_mb as f64 / 1024.0)
|
(current_data.swap_harvest.mem_total_in_mb as f64 / 1024.0)
|
||||||
);
|
),
|
||||||
|
)
|
||||||
(mem_label, swap_label)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rx_tx_data_points(
|
pub fn get_rx_tx_data_points(
|
||||||
|
@ -398,8 +400,10 @@ pub fn convert_process_data(
|
||||||
ProcessNamingType::Name => process.name.to_string(),
|
ProcessNamingType::Name => process.name.to_string(),
|
||||||
ProcessNamingType::Path => process.path.to_string(),
|
ProcessNamingType::Path => process.path.to_string(),
|
||||||
},
|
},
|
||||||
cpu_usage: process.cpu_usage_percent,
|
cpu_percent_usage: process.cpu_usage_percent,
|
||||||
mem_usage: process.mem_usage_percent,
|
mem_percent_usage: process.mem_usage_percent,
|
||||||
|
mem_usage_kb: process.mem_usage_kb,
|
||||||
|
mem_usage_str: get_exact_byte_values(process.mem_usage_kb * 1024, false),
|
||||||
group_pids: vec![process.pid],
|
group_pids: vec![process.pid],
|
||||||
read_per_sec,
|
read_per_sec,
|
||||||
write_per_sec,
|
write_per_sec,
|
||||||
|
@ -428,8 +432,9 @@ pub fn convert_process_data(
|
||||||
..SingleProcessData::default()
|
..SingleProcessData::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
(*entry).cpu_usage += process.cpu_usage_percent;
|
(*entry).cpu_percent_usage += process.cpu_usage_percent;
|
||||||
(*entry).mem_usage += process.mem_usage_percent;
|
(*entry).mem_percent_usage += process.mem_usage_percent;
|
||||||
|
(*entry).mem_usage_kb += process.mem_usage_kb;
|
||||||
(*entry).group_pids.push(process.pid);
|
(*entry).group_pids.push(process.pid);
|
||||||
(*entry).read_per_sec += process.read_bytes_per_sec;
|
(*entry).read_per_sec += process.read_bytes_per_sec;
|
||||||
(*entry).write_per_sec += process.write_bytes_per_sec;
|
(*entry).write_per_sec += process.write_bytes_per_sec;
|
||||||
|
@ -458,8 +463,10 @@ pub fn convert_process_data(
|
||||||
ConvertedProcessData {
|
ConvertedProcessData {
|
||||||
pid: p.pid,
|
pid: p.pid,
|
||||||
name: identifier.to_string(),
|
name: identifier.to_string(),
|
||||||
cpu_usage: p.cpu_usage,
|
cpu_percent_usage: p.cpu_percent_usage,
|
||||||
mem_usage: p.mem_usage,
|
mem_percent_usage: p.mem_percent_usage,
|
||||||
|
mem_usage_kb: p.mem_usage_kb,
|
||||||
|
mem_usage_str: get_exact_byte_values(p.mem_usage_kb * 1024, false),
|
||||||
group_pids: p.group_pids,
|
group_pids: p.group_pids,
|
||||||
read_per_sec,
|
read_per_sec,
|
||||||
write_per_sec,
|
write_per_sec,
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -213,8 +213,10 @@ fn main() -> error::Result<()> {
|
||||||
app.canvas_data.swap_data =
|
app.canvas_data.swap_data =
|
||||||
convert_swap_data_points(&app.data_collection, false);
|
convert_swap_data_points(&app.data_collection, false);
|
||||||
let memory_and_swap_labels = convert_mem_labels(&app.data_collection);
|
let memory_and_swap_labels = convert_mem_labels(&app.data_collection);
|
||||||
app.canvas_data.mem_label = memory_and_swap_labels.0;
|
app.canvas_data.mem_label_percent = memory_and_swap_labels.0;
|
||||||
app.canvas_data.swap_label = memory_and_swap_labels.1;
|
app.canvas_data.mem_label_frac = memory_and_swap_labels.1;
|
||||||
|
app.canvas_data.swap_label_percent = memory_and_swap_labels.2;
|
||||||
|
app.canvas_data.swap_label_frac = memory_and_swap_labels.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.used_widgets.use_cpu {
|
if app.used_widgets.use_cpu {
|
||||||
|
@ -668,20 +670,26 @@ fn sort_process_data(
|
||||||
ProcessSorting::CpuPercent => {
|
ProcessSorting::CpuPercent => {
|
||||||
to_sort_vec.sort_by(|a, b| {
|
to_sort_vec.sort_by(|a, b| {
|
||||||
utils::gen_util::get_ordering(
|
utils::gen_util::get_ordering(
|
||||||
a.cpu_usage,
|
a.cpu_percent_usage,
|
||||||
b.cpu_usage,
|
b.cpu_percent_usage,
|
||||||
proc_widget_state.process_sorting_reverse,
|
proc_widget_state.process_sorting_reverse,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ProcessSorting::Mem => {
|
ProcessSorting::Mem => {
|
||||||
// TODO: Do when I do mem values in processes
|
to_sort_vec.sort_by(|a, b| {
|
||||||
|
utils::gen_util::get_ordering(
|
||||||
|
a.mem_usage_kb,
|
||||||
|
b.mem_usage_kb,
|
||||||
|
proc_widget_state.process_sorting_reverse,
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ProcessSorting::MemPercent => {
|
ProcessSorting::MemPercent => {
|
||||||
to_sort_vec.sort_by(|a, b| {
|
to_sort_vec.sort_by(|a, b| {
|
||||||
utils::gen_util::get_ordering(
|
utils::gen_util::get_ordering(
|
||||||
a.mem_usage,
|
a.mem_percent_usage,
|
||||||
b.mem_usage,
|
b.mem_percent_usage,
|
||||||
proc_widget_state.process_sorting_reverse,
|
proc_widget_state.process_sorting_reverse,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue