mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-10 22:54:21 +00: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
3 changed files with 106 additions and 94 deletions
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).
|
||||
pub struct AppSearchState {
|
||||
is_enabled: bool,
|
||||
pub is_enabled: bool,
|
||||
current_search_query: String,
|
||||
current_regex: Option<std::result::Result<regex::Regex, regex::Error>>,
|
||||
current_cursor_position: usize,
|
||||
|
@ -117,10 +117,6 @@ impl ProcessSearchState {
|
|||
pub fn toggle_search_regex(&mut self) {
|
||||
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)]
|
||||
|
@ -333,10 +329,15 @@ impl App {
|
|||
}
|
||||
|
||||
fn is_filtering_or_searching(&self) -> bool {
|
||||
self.cpu_state.is_showing_tray
|
||||
|| self.mem_state.is_showing_tray
|
||||
|| self.net_state.is_showing_tray
|
||||
|| self.process_search_state.search_state.is_enabled
|
||||
match self.current_widget_selected {
|
||||
WidgetPosition::Cpu => self.cpu_state.is_showing_tray,
|
||||
WidgetPosition::Mem => self.mem_state.is_showing_tray,
|
||||
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) {
|
||||
|
@ -360,13 +361,21 @@ impl App {
|
|||
|
||||
pub fn on_tab(&mut self) {
|
||||
match self.current_widget_selected {
|
||||
WidgetPosition::Process => self.toggle_grouping(),
|
||||
WidgetPosition::Disk => {}
|
||||
WidgetPosition::ProcessSearch => {
|
||||
if self.process_search_state.is_searching_with_pid {
|
||||
WidgetPosition::Process => {
|
||||
self.toggle_grouping();
|
||||
if self.is_grouped() {
|
||||
self.search_with_name();
|
||||
} 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
|
||||
self.process_search_state.search_state.is_enabled = true;
|
||||
self.current_widget_selected = WidgetPosition::ProcessSearch;
|
||||
if self.is_grouped() {
|
||||
self.search_with_name();
|
||||
}
|
||||
}
|
||||
WidgetPosition::Cpu => {
|
||||
self.cpu_state.is_showing_tray = true;
|
||||
|
@ -432,17 +444,15 @@ impl App {
|
|||
|
||||
pub fn search_with_pid(&mut self) {
|
||||
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) {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
if self
|
||||
.process_search_state
|
||||
|
@ -473,9 +473,9 @@ impl App {
|
|||
let regex_string = &self.process_search_state.search_state.current_search_query;
|
||||
let escaped_regex: String;
|
||||
let final_regex_string = &format!(
|
||||
"{}{}{}",
|
||||
"{}{}{}{}",
|
||||
if self.process_search_state.is_searching_whole_word {
|
||||
"^$"
|
||||
"^"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
|
@ -489,7 +489,12 @@ impl App {
|
|||
&escaped_regex
|
||||
} else {
|
||||
regex_string
|
||||
}
|
||||
},
|
||||
if self.process_search_state.is_searching_whole_word {
|
||||
"$"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
);
|
||||
|
||||
let new_regex = regex::Regex::new(final_regex_string);
|
||||
|
@ -784,7 +789,6 @@ impl App {
|
|||
.current_cursor_position += 1;
|
||||
|
||||
self.update_regex();
|
||||
|
||||
self.update_process_gui = true;
|
||||
} else {
|
||||
match caught_char {
|
||||
|
|
|
@ -536,20 +536,26 @@ impl Painter {
|
|||
.iter()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.filter(|(itx, _)| app_state.cpu_state.core_show_vec[*itx])
|
||||
.map(|(itx, cpu)| {
|
||||
Dataset::default()
|
||||
.marker(if app_state.app_config_fields.use_dot {
|
||||
Marker::Dot
|
||||
} else {
|
||||
Marker::Braille
|
||||
})
|
||||
.style(
|
||||
self.colours.cpu_colour_styles[itx % self.colours.cpu_colour_styles.len()],
|
||||
.filter_map(|(itx, cpu)| {
|
||||
if app_state.cpu_state.core_show_vec[itx] {
|
||||
Some(
|
||||
Dataset::default()
|
||||
.marker(if app_state.app_config_fields.use_dot {
|
||||
Marker::Dot
|
||||
} else {
|
||||
Marker::Braille
|
||||
})
|
||||
.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 {
|
||||
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 mut stringified_cpu_data: Vec<Vec<String>> = Vec::new();
|
||||
|
||||
// TODO: [OPT] Reduce this instead...
|
||||
if app_state.cpu_state.is_showing_tray {
|
||||
for (itx, cpu) in sliced_cpu_data.iter().enumerate() {
|
||||
for (itx, cpu) in sliced_cpu_data.iter().enumerate() {
|
||||
if app_state.cpu_state.is_showing_tray {
|
||||
stringified_cpu_data.push(vec![
|
||||
cpu.cpu_name.clone(),
|
||||
if app_state.cpu_state.core_show_vec[itx + start_position as usize] {
|
||||
|
@ -619,10 +624,10 @@ impl Painter {
|
|||
"[ ]".to_string()
|
||||
},
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
for cpu in sliced_cpu_data.iter() {
|
||||
if let Some(cpu_data) = cpu.cpu_data.last() {
|
||||
} else if let Some(cpu_data) = cpu.cpu_data.last() {
|
||||
if app_state.app_config_fields.show_disabled_data
|
||||
|| app_state.cpu_state.core_show_vec[itx]
|
||||
{
|
||||
stringified_cpu_data.push(vec![
|
||||
cpu.cpu_name.clone(),
|
||||
format!("{:.0}%", cpu_data.1.round()),
|
||||
|
@ -634,15 +639,6 @@ impl Painter {
|
|||
let cpu_rows = stringified_cpu_data
|
||||
.iter()
|
||||
.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)| {
|
||||
Row::StyledData(
|
||||
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(
|
||||
"Search by PID (Tab for Name): ",
|
||||
self.colours.table_header_style,
|
||||
|
@ -1369,21 +1367,22 @@ impl Painter {
|
|||
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 title = if app_state.is_expanded {
|
||||
const TITLE_BASE: &str = " Processes ── Esc to go back ";
|
||||
let repeat_num = max(
|
||||
0,
|
||||
draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2,
|
||||
);
|
||||
let result_title = format!(
|
||||
" Processes ─{}─ Esc to go back ",
|
||||
"─".repeat(repeat_num as usize)
|
||||
);
|
||||
let title =
|
||||
if app_state.is_expanded && !app_state.process_search_state.search_state.is_enabled {
|
||||
const TITLE_BASE: &str = " Processes ── Esc to go back ";
|
||||
let repeat_num = max(
|
||||
0,
|
||||
draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2,
|
||||
);
|
||||
let result_title = format!(
|
||||
" Processes ─{}─ Esc to go back ",
|
||||
"─".repeat(repeat_num as usize)
|
||||
);
|
||||
|
||||
result_title
|
||||
} else {
|
||||
" Processes ".to_string()
|
||||
};
|
||||
result_title
|
||||
} else {
|
||||
" Processes ".to_string()
|
||||
};
|
||||
|
||||
Table::new(process_headers.iter(), process_rows)
|
||||
.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() {
|
||||
app.process_search_state.toggle_ignore_case();
|
||||
app.update_regex();
|
||||
app.update_process_gui = true;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('w') => {
|
||||
if app.is_in_search_widget() {
|
||||
app.process_search_state.toggle_search_whole_word();
|
||||
app.update_regex();
|
||||
app.update_process_gui = true;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('r') => {
|
||||
if app.is_in_search_widget() {
|
||||
app.process_search_state.toggle_search_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
|
||||
.process_data
|
||||
.iter()
|
||||
.filter(|(_pid, process)| {
|
||||
if app
|
||||
.filter_map(|(_pid, process)| {
|
||||
let mut result = true;
|
||||
|
||||
if !app
|
||||
.process_search_state
|
||||
.search_state
|
||||
.is_invalid_or_blank_search()
|
||||
{
|
||||
return true;
|
||||
} else if let Some(matcher_result) = app.get_current_regex_matcher() {
|
||||
if let Ok(matcher) = matcher_result {
|
||||
if app.process_search_state.is_searching_with_pid {
|
||||
return matcher.is_match(&process.pid.to_string());
|
||||
} else {
|
||||
return matcher.is_match(&process.name);
|
||||
if let Some(matcher_result) = app.get_current_regex_matcher() {
|
||||
if let Ok(matcher) = matcher_result {
|
||||
if app.process_search_state.is_searching_with_pid {
|
||||
result = matcher.is_match(&process.pid.to_string());
|
||||
} else {
|
||||
result = matcher.is_match(&process.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.map(|(_pid, process)| ConvertedProcessData {
|
||||
pid: process.pid,
|
||||
name: process.name.clone(),
|
||||
cpu_usage: process.cpu_usage_percent,
|
||||
mem_usage: process.mem_usage_percent,
|
||||
group_pids: vec![process.pid],
|
||||
|
||||
if result {
|
||||
return Some(ConvertedProcessData {
|
||||
pid: process.pid,
|
||||
name: process.name.clone(),
|
||||
cpu_usage: process.cpu_usage_percent,
|
||||
mem_usage: process.mem_usage_percent,
|
||||
group_pids: vec![process.pid],
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue