other: some cleanup in proc widget (#903)

This commit is contained in:
Clement Tsang 2022-11-20 01:13:24 -05:00 committed by GitHub
parent fd1badaf36
commit 6a0bf10760
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 53 deletions

21
Cargo.lock generated
View file

@ -215,6 +215,7 @@ dependencies = [
"clap_complete", "clap_complete",
"clap_mangen", "clap_mangen",
"concat-string", "concat-string",
"const_format",
"crossterm", "crossterm",
"ctrlc", "ctrlc",
"dirs", "dirs",
@ -360,6 +361,26 @@ dependencies = [
"cache-padded", "cache-padded",
] ]
[[package]]
name = "const_format"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.7.0" version = "0.7.0"

View file

@ -64,6 +64,7 @@ anyhow = "1.0.57"
backtrace = "0.3.65" backtrace = "0.3.65"
cfg-if = "1.0.0" cfg-if = "1.0.0"
clap = { version = "3.1.12", features = ["default", "cargo", "wrap_help"] } clap = { version = "3.1.12", features = ["default", "cargo", "wrap_help"] }
const_format = "0.2.30"
concat-string = "1.0.1" concat-string = "1.0.1"
crossterm = "0.25.0" crossterm = "0.25.0"
ctrlc = { version = "3.1.9", features = ["termination"] } ctrlc = { version = "3.1.9", features = ["termination"] }

View file

@ -1,5 +1,6 @@
use std::{borrow::Cow, collections::BTreeMap}; use std::{borrow::Cow, collections::BTreeMap};
use const_format::formatcp;
use fxhash::{FxHashMap, FxHashSet}; use fxhash::{FxHashMap, FxHashSet};
use itertools::Itertools; use itertools::Itertools;
@ -385,7 +386,10 @@ impl ProcWidget {
.collect_vec(); .collect_vec();
stack.sort_unstable_by_key(|p| p.pid); stack.sort_unstable_by_key(|p| p.pid);
self.try_sort_skip_pid_asc(&mut stack);
let column = self.table.columns.get(self.table.sort_index()).unwrap();
sort_skip_pid_asc(column.inner(), &mut stack, self.table.order());
stack.reverse(); stack.reverse();
let mut length_stack = vec![stack.len()]; let mut length_stack = vec![stack.len()];
@ -449,14 +453,13 @@ impl ProcWidget {
data.push(process.prefix(Some(prefix)).disabled(disabled)); data.push(process.prefix(Some(prefix)).disabled(disabled));
if let Some(children_pids) = filtered_tree.get(&pid) { if let Some(children_pids) = filtered_tree.get(&pid) {
// TODO: Can probably use static strings for prefixes rather than allocating.
if prefixes.is_empty() { if prefixes.is_empty() {
prefixes.push(String::default()); prefixes.push("");
} else { } else {
prefixes.push(if is_last { prefixes.push(if is_last {
" ".to_string() " "
} else { } else {
format!("{} ", BRANCH_VERTICAL) formatcp!("{} ", BRANCH_VERTICAL)
}); });
} }
@ -468,7 +471,9 @@ impl ProcWidget {
}) })
}) })
.collect_vec(); .collect_vec();
self.try_rev_sort(&mut children);
column.sort_by(&mut children, self.table.order().rev());
length_stack.push(children.len()); length_stack.push(children.len());
stack.extend(children); stack.extend(children);
} }
@ -548,33 +553,14 @@ impl ProcWidget {
}; };
self.id_pid_map = id_pid_map; self.id_pid_map = id_pid_map;
self.try_sort_skip_pid_asc(&mut filtered_data);
if let Some(column) = self.table.columns.get(self.table.sort_index()) {
sort_skip_pid_asc(column.inner(), &mut filtered_data, self.table.order());
}
filtered_data filtered_data
} }
#[inline(always)]
fn try_rev_sort(&self, filtered_data: &mut [ProcWidgetData]) {
if let Some(column) = self.table.columns.get(self.table.sort_index()) {
column.sort_by(
filtered_data,
match self.table.order() {
SortOrder::Ascending => SortOrder::Descending,
SortOrder::Descending => SortOrder::Ascending,
},
);
}
}
#[inline(always)]
fn try_sort_skip_pid_asc(&self, filtered_data: &mut [ProcWidgetData]) {
if let Some(column) = self.table.columns.get(self.table.sort_index()) {
let column = column.inner();
let descending = matches!(self.table.order(), SortOrder::Descending);
sort_skip_pid_asc(column, filtered_data, descending);
}
}
#[inline(always)] #[inline(always)]
fn get_mut_proc_col(&mut self, index: usize) -> Option<&mut ProcColumn> { fn get_mut_proc_col(&mut self, index: usize) -> Option<&mut ProcColumn> {
self.table.columns.get_mut(index).map(|col| col.inner_mut()) self.table.columns.get_mut(index).map(|col| col.inner_mut())
@ -862,7 +848,9 @@ impl ProcWidget {
} }
} }
fn sort_skip_pid_asc(column: &ProcColumn, data: &mut [ProcWidgetData], descending: bool) { #[inline]
fn sort_skip_pid_asc(column: &ProcColumn, data: &mut [ProcWidgetData], order: SortOrder) {
let descending = matches!(order, SortOrder::Descending);
match column { match column {
ProcColumn::Pid if !descending => {} ProcColumn::Pid if !descending => {}
_ => { _ => {
@ -876,11 +864,6 @@ mod test {
use super::*; use super::*;
use crate::app::widgets::MemUsage; use crate::app::widgets::MemUsage;
#[test]
fn sorting_trees() {
// FIXME: Add a test for this...
}
#[test] #[test]
fn test_proc_sort() { fn test_proc_sort() {
let a = ProcWidgetData { let a = ProcWidgetData {
@ -903,6 +886,7 @@ mod test {
let b = ProcWidgetData { let b = ProcWidgetData {
pid: 2, pid: 2,
ppid: Some(1),
id: "B".into(), id: "B".into(),
cpu_usage_percent: 1.1, cpu_usage_percent: 1.1,
mem_usage: MemUsage::Percent(2.2), mem_usage: MemUsage::Percent(2.2),
@ -911,6 +895,7 @@ mod test {
let c = ProcWidgetData { let c = ProcWidgetData {
pid: 3, pid: 3,
ppid: Some(1),
id: "C".into(), id: "C".into(),
cpu_usage_percent: 2.2, cpu_usage_percent: 2.2,
mem_usage: MemUsage::Percent(0.0), mem_usage: MemUsage::Percent(0.0),
@ -919,17 +904,17 @@ mod test {
let d = ProcWidgetData { let d = ProcWidgetData {
pid: 4, pid: 4,
ppid: Some(2),
id: "D".into(), id: "D".into(),
cpu_usage_percent: 0.0, cpu_usage_percent: 0.0,
mem_usage: MemUsage::Percent(0.0), mem_usage: MemUsage::Percent(0.0),
..(a.clone()) ..(a.clone())
}; };
let mut data = vec![d.clone(), b.clone(), c.clone(), a.clone()]; let mut data = vec![d.clone(), b.clone(), c.clone(), a.clone()];
// Assume we had sorted over by pid. // Assume we had sorted over by pid.
data.sort_by_key(|p| p.pid); data.sort_by_key(|p| p.pid);
sort_skip_pid_asc(&ProcColumn::CpuPercent, &mut data, true); sort_skip_pid_asc(&ProcColumn::CpuPercent, &mut data, SortOrder::Descending);
assert_eq!( assert_eq!(
vec![&c, &b, &a, &d] vec![&c, &b, &a, &d]
.iter() .iter()
@ -940,7 +925,7 @@ mod test {
// Note that the PID ordering for ties is still ascending. // Note that the PID ordering for ties is still ascending.
data.sort_by_key(|p| p.pid); data.sort_by_key(|p| p.pid);
sort_skip_pid_asc(&ProcColumn::CpuPercent, &mut data, false); sort_skip_pid_asc(&ProcColumn::CpuPercent, &mut data, SortOrder::Ascending);
assert_eq!( assert_eq!(
vec![&a, &d, &b, &c] vec![&a, &d, &b, &c]
.iter() .iter()
@ -950,7 +935,7 @@ mod test {
); );
data.sort_by_key(|p| p.pid); data.sort_by_key(|p| p.pid);
sort_skip_pid_asc(&ProcColumn::MemoryPercent, &mut data, true); sort_skip_pid_asc(&ProcColumn::MemoryPercent, &mut data, SortOrder::Descending);
assert_eq!( assert_eq!(
vec![&b, &a, &c, &d] vec![&b, &a, &c, &d]
.iter() .iter()
@ -961,7 +946,7 @@ mod test {
// Note that the PID ordering for ties is still ascending. // Note that the PID ordering for ties is still ascending.
data.sort_by_key(|p| p.pid); data.sort_by_key(|p| p.pid);
sort_skip_pid_asc(&ProcColumn::MemoryPercent, &mut data, false); sort_skip_pid_asc(&ProcColumn::MemoryPercent, &mut data, SortOrder::Ascending);
assert_eq!( assert_eq!(
vec![&c, &d, &a, &b] vec![&c, &d, &a, &b]
.iter() .iter()

View file

@ -213,21 +213,17 @@ impl Painter {
// TODO: [MOUSE] Mouse support for these in search // TODO: [MOUSE] Mouse support for these in search
// TODO: [MOVEMENT] Movement support for these in search // TODO: [MOVEMENT] Movement support for these in search
let (case, whole, regex) = if self.is_mac_os {
("Case(F1)", "Whole(F2)", "Regex(F3)")
} else {
("Case(Alt+C)", "Whole(Alt+W)", "Regex(Alt+R)")
};
let option_text = Spans::from(vec![ let option_text = Spans::from(vec![
Span::styled( Span::styled(case, case_style),
format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }),
case_style,
),
Span::raw(" "), Span::raw(" "),
Span::styled( Span::styled(whole, whole_word_style),
format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }),
whole_word_style,
),
Span::raw(" "), Span::raw(" "),
Span::styled( Span::styled(regex, regex_style),
format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }),
regex_style,
),
]); ]);
search_text.push(Spans::from(Span::styled( search_text.push(Spans::from(Span::styled(

View file

@ -17,6 +17,16 @@ pub enum SortOrder {
Descending, Descending,
} }
impl SortOrder {
/// Returns the reverse [`SortOrder`].
pub fn rev(&self) -> SortOrder {
match self {
SortOrder::Ascending => SortOrder::Descending,
SortOrder::Descending => SortOrder::Ascending,
}
}
}
impl Default for SortOrder { impl Default for SortOrder {
fn default() -> Self { fn default() -> Self {
Self::Ascending Self::Ascending