mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-09-22 17:28:19 +02:00
Tons of refactoring and fixes.
* Fixed a bunch of previously introduced bugs. Oops. * Some minor refactoring/efficiency changes that *should* help. Should.
This commit is contained in:
parent
d9364410e8
commit
2f59af412d
72
src/app.rs
72
src/app.rs
@ -57,7 +57,7 @@ impl Default for AppScrollState {
|
|||||||
|
|
||||||
/// AppSearchState deals with generic searching (I might do this in the future).
|
/// AppSearchState deals with generic searching (I might do this in the future).
|
||||||
pub struct AppSearchState {
|
pub struct AppSearchState {
|
||||||
is_enabled: bool,
|
pub is_enabled: bool,
|
||||||
current_search_query: String,
|
current_search_query: String,
|
||||||
current_regex: Option<std::result::Result<regex::Regex, regex::Error>>,
|
current_regex: Option<std::result::Result<regex::Regex, regex::Error>>,
|
||||||
current_cursor_position: usize,
|
current_cursor_position: usize,
|
||||||
@ -117,10 +117,6 @@ impl ProcessSearchState {
|
|||||||
pub fn toggle_search_regex(&mut self) {
|
pub fn toggle_search_regex(&mut self) {
|
||||||
self.is_searching_with_regex = !self.is_searching_with_regex;
|
self.is_searching_with_regex = !self.is_searching_with_regex;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_search_with_pid(&mut self) {
|
|
||||||
self.is_searching_with_pid = !self.is_searching_with_pid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -333,10 +329,15 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_filtering_or_searching(&self) -> bool {
|
fn is_filtering_or_searching(&self) -> bool {
|
||||||
self.cpu_state.is_showing_tray
|
match self.current_widget_selected {
|
||||||
|| self.mem_state.is_showing_tray
|
WidgetPosition::Cpu => self.cpu_state.is_showing_tray,
|
||||||
|| self.net_state.is_showing_tray
|
WidgetPosition::Mem => self.mem_state.is_showing_tray,
|
||||||
|| self.process_search_state.search_state.is_enabled
|
WidgetPosition::Network => self.net_state.is_showing_tray,
|
||||||
|
WidgetPosition::Process | WidgetPosition::ProcessSearch => {
|
||||||
|
self.process_search_state.search_state.is_enabled
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_multi_tap_keys(&mut self) {
|
fn reset_multi_tap_keys(&mut self) {
|
||||||
@ -360,13 +361,21 @@ impl App {
|
|||||||
|
|
||||||
pub fn on_tab(&mut self) {
|
pub fn on_tab(&mut self) {
|
||||||
match self.current_widget_selected {
|
match self.current_widget_selected {
|
||||||
WidgetPosition::Process => self.toggle_grouping(),
|
WidgetPosition::Process => {
|
||||||
WidgetPosition::Disk => {}
|
self.toggle_grouping();
|
||||||
WidgetPosition::ProcessSearch => {
|
if self.is_grouped() {
|
||||||
if self.process_search_state.is_searching_with_pid {
|
|
||||||
self.search_with_name();
|
self.search_with_name();
|
||||||
} else {
|
} else {
|
||||||
self.search_with_pid();
|
self.update_process_gui = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WidgetPosition::ProcessSearch => {
|
||||||
|
if !self.is_grouped() {
|
||||||
|
if self.process_search_state.is_searching_with_pid {
|
||||||
|
self.search_with_name();
|
||||||
|
} else {
|
||||||
|
self.search_with_pid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -403,6 +412,9 @@ impl App {
|
|||||||
// Toggle on
|
// Toggle on
|
||||||
self.process_search_state.search_state.is_enabled = true;
|
self.process_search_state.search_state.is_enabled = true;
|
||||||
self.current_widget_selected = WidgetPosition::ProcessSearch;
|
self.current_widget_selected = WidgetPosition::ProcessSearch;
|
||||||
|
if self.is_grouped() {
|
||||||
|
self.search_with_name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WidgetPosition::Cpu => {
|
WidgetPosition::Cpu => {
|
||||||
self.cpu_state.is_showing_tray = true;
|
self.cpu_state.is_showing_tray = true;
|
||||||
@ -432,17 +444,15 @@ impl App {
|
|||||||
|
|
||||||
pub fn search_with_pid(&mut self) {
|
pub fn search_with_pid(&mut self) {
|
||||||
if !self.is_in_dialog() && self.is_searching() {
|
if !self.is_in_dialog() && self.is_searching() {
|
||||||
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
self.process_search_state.is_searching_with_pid = true;
|
||||||
self.process_search_state.is_searching_with_pid = true;
|
self.update_process_gui = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_with_name(&mut self) {
|
pub fn search_with_name(&mut self) {
|
||||||
if !self.is_in_dialog() && self.is_searching() {
|
if !self.is_in_dialog() && self.is_searching() {
|
||||||
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
self.process_search_state.is_searching_with_pid = false;
|
||||||
self.process_search_state.is_searching_with_pid = false;
|
self.update_process_gui = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,16 +460,6 @@ impl App {
|
|||||||
&self.process_search_state.search_state.current_search_query
|
&self.process_search_state.search_state.current_search_query
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_ignore_case(&mut self) {
|
|
||||||
if !self.is_in_dialog() && self.is_searching() {
|
|
||||||
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
|
||||||
self.process_search_state.toggle_ignore_case();
|
|
||||||
self.update_regex();
|
|
||||||
self.update_process_gui = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_regex(&mut self) {
|
pub fn update_regex(&mut self) {
|
||||||
if self
|
if self
|
||||||
.process_search_state
|
.process_search_state
|
||||||
@ -473,9 +473,9 @@ impl App {
|
|||||||
let regex_string = &self.process_search_state.search_state.current_search_query;
|
let regex_string = &self.process_search_state.search_state.current_search_query;
|
||||||
let escaped_regex: String;
|
let escaped_regex: String;
|
||||||
let final_regex_string = &format!(
|
let final_regex_string = &format!(
|
||||||
"{}{}{}",
|
"{}{}{}{}",
|
||||||
if self.process_search_state.is_searching_whole_word {
|
if self.process_search_state.is_searching_whole_word {
|
||||||
"^$"
|
"^"
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
@ -489,7 +489,12 @@ impl App {
|
|||||||
&escaped_regex
|
&escaped_regex
|
||||||
} else {
|
} else {
|
||||||
regex_string
|
regex_string
|
||||||
}
|
},
|
||||||
|
if self.process_search_state.is_searching_whole_word {
|
||||||
|
"$"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_regex = regex::Regex::new(final_regex_string);
|
let new_regex = regex::Regex::new(final_regex_string);
|
||||||
@ -784,7 +789,6 @@ impl App {
|
|||||||
.current_cursor_position += 1;
|
.current_cursor_position += 1;
|
||||||
|
|
||||||
self.update_regex();
|
self.update_regex();
|
||||||
|
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
} else {
|
} else {
|
||||||
match caught_char {
|
match caught_char {
|
||||||
|
@ -536,20 +536,26 @@ impl Painter {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|(itx, _)| app_state.cpu_state.core_show_vec[*itx])
|
.filter_map(|(itx, cpu)| {
|
||||||
.map(|(itx, cpu)| {
|
if app_state.cpu_state.core_show_vec[itx] {
|
||||||
Dataset::default()
|
Some(
|
||||||
.marker(if app_state.app_config_fields.use_dot {
|
Dataset::default()
|
||||||
Marker::Dot
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
} else {
|
Marker::Dot
|
||||||
Marker::Braille
|
} else {
|
||||||
})
|
Marker::Braille
|
||||||
.style(
|
})
|
||||||
self.colours.cpu_colour_styles[itx % self.colours.cpu_colour_styles.len()],
|
.style(
|
||||||
|
self.colours.cpu_colour_styles
|
||||||
|
[itx % self.colours.cpu_colour_styles.len()],
|
||||||
|
)
|
||||||
|
.data(&cpu.cpu_data[..]),
|
||||||
)
|
)
|
||||||
.data(&cpu.cpu_data[..])
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect();
|
||||||
|
|
||||||
let title = if app_state.is_expanded && !app_state.cpu_state.is_showing_tray {
|
let title = if app_state.is_expanded && !app_state.cpu_state.is_showing_tray {
|
||||||
const TITLE_BASE: &str = " CPU ── Esc to go back ";
|
const TITLE_BASE: &str = " CPU ── Esc to go back ";
|
||||||
@ -608,9 +614,8 @@ impl Painter {
|
|||||||
let sliced_cpu_data = &cpu_data[start_position as usize..];
|
let sliced_cpu_data = &cpu_data[start_position as usize..];
|
||||||
let mut stringified_cpu_data: Vec<Vec<String>> = Vec::new();
|
let mut stringified_cpu_data: Vec<Vec<String>> = Vec::new();
|
||||||
|
|
||||||
// TODO: [OPT] Reduce this instead...
|
for (itx, cpu) in sliced_cpu_data.iter().enumerate() {
|
||||||
if app_state.cpu_state.is_showing_tray {
|
if app_state.cpu_state.is_showing_tray {
|
||||||
for (itx, cpu) in sliced_cpu_data.iter().enumerate() {
|
|
||||||
stringified_cpu_data.push(vec![
|
stringified_cpu_data.push(vec![
|
||||||
cpu.cpu_name.clone(),
|
cpu.cpu_name.clone(),
|
||||||
if app_state.cpu_state.core_show_vec[itx + start_position as usize] {
|
if app_state.cpu_state.core_show_vec[itx + start_position as usize] {
|
||||||
@ -619,10 +624,10 @@ impl Painter {
|
|||||||
"[ ]".to_string()
|
"[ ]".to_string()
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
} else if let Some(cpu_data) = cpu.cpu_data.last() {
|
||||||
} else {
|
if app_state.app_config_fields.show_disabled_data
|
||||||
for cpu in sliced_cpu_data.iter() {
|
|| app_state.cpu_state.core_show_vec[itx]
|
||||||
if let Some(cpu_data) = cpu.cpu_data.last() {
|
{
|
||||||
stringified_cpu_data.push(vec![
|
stringified_cpu_data.push(vec![
|
||||||
cpu.cpu_name.clone(),
|
cpu.cpu_name.clone(),
|
||||||
format!("{:.0}%", cpu_data.1.round()),
|
format!("{:.0}%", cpu_data.1.round()),
|
||||||
@ -634,15 +639,6 @@ impl Painter {
|
|||||||
let cpu_rows = stringified_cpu_data
|
let cpu_rows = stringified_cpu_data
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(itx, _)| {
|
|
||||||
if app_state.cpu_state.is_showing_tray
|
|
||||||
|| app_state.app_config_fields.show_disabled_data
|
|
||||||
{
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
app_state.cpu_state.core_show_vec[*itx]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|(itx, cpu_string_row)| {
|
.map(|(itx, cpu_string_row)| {
|
||||||
Row::StyledData(
|
Row::StyledData(
|
||||||
cpu_string_row.iter(),
|
cpu_string_row.iter(),
|
||||||
@ -1179,7 +1175,9 @@ impl Painter {
|
|||||||
)]
|
)]
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut search_text = vec![if app_state.process_search_state.is_searching_with_pid {
|
let mut search_text = vec![if app_state.is_grouped() {
|
||||||
|
Text::styled("Search by Name: ", self.colours.table_header_style)
|
||||||
|
} else if app_state.process_search_state.is_searching_with_pid {
|
||||||
Text::styled(
|
Text::styled(
|
||||||
"Search by PID (Tab for Name): ",
|
"Search by PID (Tab for Name): ",
|
||||||
self.colours.table_header_style,
|
self.colours.table_header_style,
|
||||||
@ -1369,21 +1367,22 @@ impl Painter {
|
|||||||
get_variable_intrinsic_widths(width as u16, &width_ratios, &process_headers_lens);
|
get_variable_intrinsic_widths(width as u16, &width_ratios, &process_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];
|
||||||
|
|
||||||
let title = if app_state.is_expanded {
|
let title =
|
||||||
const TITLE_BASE: &str = " Processes ── Esc to go back ";
|
if app_state.is_expanded && !app_state.process_search_state.search_state.is_enabled {
|
||||||
let repeat_num = max(
|
const TITLE_BASE: &str = " Processes ── Esc to go back ";
|
||||||
0,
|
let repeat_num = max(
|
||||||
draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2,
|
0,
|
||||||
);
|
draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2,
|
||||||
let result_title = format!(
|
);
|
||||||
" Processes ─{}─ Esc to go back ",
|
let result_title = format!(
|
||||||
"─".repeat(repeat_num as usize)
|
" Processes ─{}─ Esc to go back ",
|
||||||
);
|
"─".repeat(repeat_num as usize)
|
||||||
|
);
|
||||||
|
|
||||||
result_title
|
result_title
|
||||||
} else {
|
} else {
|
||||||
" Processes ".to_string()
|
" Processes ".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
Table::new(process_headers.iter(), process_rows)
|
Table::new(process_headers.iter(), process_rows)
|
||||||
.block(
|
.block(
|
||||||
|
43
src/main.rs
43
src/main.rs
@ -376,18 +376,21 @@ fn handle_key_event_or_break(
|
|||||||
if app.is_in_search_widget() {
|
if app.is_in_search_widget() {
|
||||||
app.process_search_state.toggle_ignore_case();
|
app.process_search_state.toggle_ignore_case();
|
||||||
app.update_regex();
|
app.update_regex();
|
||||||
|
app.update_process_gui = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Char('w') => {
|
KeyCode::Char('w') => {
|
||||||
if app.is_in_search_widget() {
|
if app.is_in_search_widget() {
|
||||||
app.process_search_state.toggle_search_whole_word();
|
app.process_search_state.toggle_search_whole_word();
|
||||||
app.update_regex();
|
app.update_regex();
|
||||||
|
app.update_process_gui = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Char('r') => {
|
KeyCode::Char('r') => {
|
||||||
if app.is_in_search_widget() {
|
if app.is_in_search_widget() {
|
||||||
app.process_search_state.toggle_search_regex();
|
app.process_search_state.toggle_search_regex();
|
||||||
app.update_regex();
|
app.update_regex();
|
||||||
|
app.update_process_gui = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -785,30 +788,36 @@ fn update_final_process_list(app: &mut app::App) {
|
|||||||
app.canvas_data
|
app.canvas_data
|
||||||
.process_data
|
.process_data
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_pid, process)| {
|
.filter_map(|(_pid, process)| {
|
||||||
if app
|
let mut result = true;
|
||||||
|
|
||||||
|
if !app
|
||||||
.process_search_state
|
.process_search_state
|
||||||
.search_state
|
.search_state
|
||||||
.is_invalid_or_blank_search()
|
.is_invalid_or_blank_search()
|
||||||
{
|
{
|
||||||
return true;
|
if let Some(matcher_result) = app.get_current_regex_matcher() {
|
||||||
} else if let Some(matcher_result) = app.get_current_regex_matcher() {
|
if let Ok(matcher) = matcher_result {
|
||||||
if let Ok(matcher) = matcher_result {
|
if app.process_search_state.is_searching_with_pid {
|
||||||
if app.process_search_state.is_searching_with_pid {
|
result = matcher.is_match(&process.pid.to_string());
|
||||||
return matcher.is_match(&process.pid.to_string());
|
} else {
|
||||||
} else {
|
result = matcher.is_match(&process.name);
|
||||||
return matcher.is_match(&process.name);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
|
||||||
})
|
if result {
|
||||||
.map(|(_pid, process)| ConvertedProcessData {
|
return Some(ConvertedProcessData {
|
||||||
pid: process.pid,
|
pid: process.pid,
|
||||||
name: process.name.clone(),
|
name: process.name.clone(),
|
||||||
cpu_usage: process.cpu_usage_percent,
|
cpu_usage: process.cpu_usage_percent,
|
||||||
mem_usage: process.mem_usage_percent,
|
mem_usage: process.mem_usage_percent,
|
||||||
group_pids: vec![process.pid],
|
group_pids: vec![process.pid],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user