diff options
author | ClementTsang <cjhtsang@uwaterloo.ca> | 2020-05-02 21:50:35 -0400 |
---|---|---|
committer | ClementTsang <cjhtsang@uwaterloo.ca> | 2020-05-02 21:50:35 -0400 |
commit | 8307b06c56934aa74985a0fee1271f1bc299b83f (patch) | |
tree | 39ab937261566fea71461b152a6350623a1dad9c | |
parent | e12c2f5212b7898b10f6c01024fa2cbe59c55bc6 (diff) |
bug: fix bug with multiple tokens
-rw-r--r-- | src/app/query.rs | 36 | ||||
-rw-r--r-- | src/app/states.rs | 20 | ||||
-rw-r--r-- | src/canvas/canvas_colours.rs | 2 | ||||
-rw-r--r-- | src/canvas/widgets/process_table.rs | 61 | ||||
-rw-r--r-- | src/constants.rs | 2 | ||||
-rw-r--r-- | src/utils/error.rs | 4 |
6 files changed, 89 insertions, 36 deletions
diff --git a/src/app/query.rs b/src/app/query.rs index 991e5b71..7a890921 100644 --- a/src/app/query.rs +++ b/src/app/query.rs @@ -39,9 +39,25 @@ pub trait ProcessQuery { impl ProcessQuery for ProcWidgetState { fn parse_query(&self) -> Result<Query> { fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> { - Ok(Query { - query: process_and(query)?, - }) + let mut lhs: And = process_and(query)?; + + while query.front().is_some() { + let rhs = Some(Box::new(process_or(query)?)); + + lhs = And { + lhs: Or { + lhs: Prefix { + and: Some(Box::from(lhs)), + compare_prefix: None, + regex_prefix: None, + }, + rhs: None, + }, + rhs, + }; + } + + Ok(Query { query: lhs }) } fn process_and(query: &mut VecDeque<String>) -> Result<And> { @@ -113,6 +129,10 @@ impl ProcessQuery for ProcWidgetState { fn process_prefix(query: &mut VecDeque<String>) -> Result<Prefix> { if let Some(queue_top) = query.pop_front() { if queue_top == "(" { + if query.front().is_none() { + return Err(QueryError("Missing closing parentheses".into())); + } + // Get content within bracket; and check if paren is complete let and = process_and(query)?; if let Some(close_paren) = query.pop_front() { @@ -190,6 +210,8 @@ impl ProcessQuery for ProcWidgetState { condition = Some(QueryComparison::Equal); if let Some(queue_next) = query.pop_front() { value = queue_next.parse::<f64>().ok(); + } else { + return Err(QueryError("Missing value".into())); } } else if content == ">" || content == "<" { // We also have to check if the next string is an "="... @@ -202,6 +224,8 @@ impl ProcessQuery for ProcWidgetState { }); if let Some(queue_next_next) = query.pop_front() { value = queue_next_next.parse::<f64>().ok(); + } else { + return Err(QueryError("Missing value".into())); } } else { condition = Some(if content == ">" { @@ -211,6 +235,8 @@ impl ProcessQuery for ProcWidgetState { }); value = queue_next.parse::<f64>().ok(); } + } else { + return Err(QueryError("Missing value".into())); } } @@ -286,11 +312,13 @@ impl ProcessQuery for ProcWidgetState { } } } + } else { + return Err(QueryError("Missing argument for search prefix".into())); } } } - Err(QueryError("Failed to parse comparator.".into())) + Err(QueryError("Invalid search".into())) } let mut split_query = VecDeque::new(); diff --git a/src/app/states.rs b/src/app/states.rs index 3d45a572..bcd4da40 100644 --- a/src/app/states.rs +++ b/src/app/states.rs @@ -74,6 +74,7 @@ pub struct AppSearchState { pub char_cursor_position: usize, /// The query pub query: Option<Query>, + pub error_message: Option<String>, } impl Default for AppSearchState { @@ -88,6 +89,7 @@ impl Default for AppSearchState { cursor_bar: 0, char_cursor_position: 0, query: None, + error_message: None, } } } @@ -198,15 +200,21 @@ impl ProcWidgetState { .current_search_query .is_empty() { - self.process_search_state.search_state.is_invalid_search = false; self.process_search_state.search_state.is_blank_search = true; - } else if let Ok(parsed_query) = self.parse_query() { - self.process_search_state.search_state.query = Some(parsed_query); - self.process_search_state.search_state.is_blank_search = false; self.process_search_state.search_state.is_invalid_search = false; + self.process_search_state.search_state.error_message = None; } else { - self.process_search_state.search_state.is_blank_search = false; - self.process_search_state.search_state.is_invalid_search = true; + let parsed_query = self.parse_query(); + if let Ok(parsed_query) = parsed_query { + self.process_search_state.search_state.query = Some(parsed_query); + self.process_search_state.search_state.is_blank_search = false; + self.process_search_state.search_state.is_invalid_search = false; + self.process_search_state.search_state.error_message = None; + } else if let Err(err) = parsed_query { + self.process_search_state.search_state.is_blank_search = false; + self.process_search_state.search_state.is_invalid_search = true; + self.process_search_state.search_state.error_message = Some(err.to_string()); + } } self.scroll_state.previous_scroll_position = 0; self.scroll_state.current_scroll_position = 0; diff --git a/src/canvas/canvas_colours.rs b/src/canvas/canvas_colours.rs index 1e1fe236..6be85866 100644 --- a/src/canvas/canvas_colours.rs +++ b/src/canvas/canvas_colours.rs @@ -26,6 +26,7 @@ pub struct CanvasColours { pub graph_style: Style, // Full, Medium, Low pub battery_bar_styles: Vec<Style>, + pub invalid_query_style: Style, } impl Default for CanvasColours { @@ -60,6 +61,7 @@ impl Default for CanvasColours { Style::default().fg(Color::Green), Style::default().fg(Color::Green), ], + invalid_query_style: tui::style::Style::default().fg(tui::style::Color::Red), } } } diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs index 63fb45c3..a495dbdb 100644 --- a/src/canvas/widgets/process_table.rs +++ b/src/canvas/widgets/process_table.rs @@ -44,7 +44,7 @@ impl ProcessTableWidget for Painter { widget_id: u64, ) { if let Some(process_widget_state) = app_state.proc_state.widget_states.get(&widget_id) { - let search_height = if draw_border { 3 } else { 2 }; + let search_height = if draw_border { 4 } else { 3 }; if process_widget_state.is_search_enabled() { let processes_chunk = Layout::default() .direction(Direction::Vertical) @@ -335,9 +335,6 @@ impl ProcessTableWidget for Painter { let search_title = "> "; let num_chars_for_text = search_title.len(); - - let mut search_text = vec![Text::styled(search_title, self.colours.table_header_style)]; - let cursor_position = proc_widget_state.get_cursor_position(); let current_cursor_position = proc_widget_state.get_char_cursor_position(); let is_search_enabled = proc_widget_state.is_search_enabled(); @@ -356,6 +353,14 @@ impl ProcessTableWidget for Painter { app_state.is_force_redraw, ); + let mut search_text = vec![Text::styled( + search_title, + if is_on_widget { + self.colours.table_header_style + } else { + self.colours.text_style + }, + )]; let query = proc_widget_state.get_current_search_query().as_str(); let grapheme_indices = UnicodeSegmentation::grapheme_indices(query, true); let query_with_cursor: Vec<Text<'_>> = build_query( @@ -368,6 +373,8 @@ impl ProcessTableWidget for Painter { self.colours.text_style, ); + // TODO: [QUERY] Make text/border go red if error? + // Text options shamelessly stolen from VS Code. let case_style = if !proc_widget_state.process_search_state.is_ignoring_case { self.colours.currently_selected_text_style @@ -393,31 +400,43 @@ impl ProcessTableWidget for Painter { self.colours.text_style }; - let mut option_text = vec![]; - let case_text = format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" },); - let whole_text = format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" },); - let regex_text = format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" },); - - let option_row = vec![ + let option_text = vec![ Text::raw("\n"), - Text::styled(&case_text, case_style), + Text::styled( + format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }), + case_style, + ), Text::raw(" "), - Text::styled(&whole_text, whole_word_style), + Text::styled( + format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }), + whole_word_style, + ), Text::raw(" "), - Text::styled(®ex_text, regex_style), + Text::styled( + format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }), + regex_style, + ), ]; - option_text.extend(option_row); search_text.extend(query_with_cursor); + search_text.push(Text::styled( + format!( + "\n{}", + if let Some(err) = &proc_widget_state + .process_search_state + .search_state + .error_message + { + err.as_str() + } else { + "" + } + ), + self.colours.invalid_query_style, + )); search_text.extend(option_text); - let current_border_style = if proc_widget_state - .process_search_state - .search_state - .is_invalid_search - { - *INVALID_REGEX_STYLE - } else if is_on_processes { + let current_border_style = if is_on_processes { self.colours.highlighted_border_style } else { self.colours.border_style diff --git a/src/constants.rs b/src/constants.rs index 6920f401..f1cdd520 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -35,8 +35,6 @@ lazy_static! { tui::style::Style::default().fg(tui::style::Color::Gray); pub static ref DEFAULT_HEADER_STYLE: tui::style::Style = tui::style::Style::default().fg(tui::style::Color::LightBlue); - pub static ref INVALID_REGEX_STYLE: tui::style::Style = - tui::style::Style::default().fg(tui::style::Color::Red); } // Help text diff --git a/src/utils/error.rs b/src/utils/error.rs index 22c217bc..227635c3 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -49,9 +49,7 @@ impl std::fmt::Display for BottomError { BottomError::ConversionError(ref message) => { write!(f, "unable to convert: {}", message) } - BottomError::QueryError(ref _message) => { - write!(f, "invalid query - this should not be shown!") - } + BottomError::QueryError(ref message) => write!(f, "{}", message), } } } |