bug: fix bug with multiple tokens

This commit is contained in:
ClementTsang 2020-05-02 21:50:35 -04:00
parent e12c2f5212
commit 8307b06c56
6 changed files with 89 additions and 36 deletions

View File

@ -39,9 +39,25 @@ pub trait ProcessQuery {
impl ProcessQuery for ProcWidgetState { impl ProcessQuery for ProcWidgetState {
fn parse_query(&self) -> Result<Query> { fn parse_query(&self) -> Result<Query> {
fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> { fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> {
Ok(Query { let mut lhs: And = process_and(query)?;
query: 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> { 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> { fn process_prefix(query: &mut VecDeque<String>) -> Result<Prefix> {
if let Some(queue_top) = query.pop_front() { if let Some(queue_top) = query.pop_front() {
if queue_top == "(" { 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 // Get content within bracket; and check if paren is complete
let and = process_and(query)?; let and = process_and(query)?;
if let Some(close_paren) = query.pop_front() { if let Some(close_paren) = query.pop_front() {
@ -190,6 +210,8 @@ impl ProcessQuery for ProcWidgetState {
condition = Some(QueryComparison::Equal); condition = Some(QueryComparison::Equal);
if let Some(queue_next) = query.pop_front() { if let Some(queue_next) = query.pop_front() {
value = queue_next.parse::<f64>().ok(); value = queue_next.parse::<f64>().ok();
} else {
return Err(QueryError("Missing value".into()));
} }
} else if content == ">" || content == "<" { } else if content == ">" || content == "<" {
// We also have to check if the next string is an "="... // 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() { if let Some(queue_next_next) = query.pop_front() {
value = queue_next_next.parse::<f64>().ok(); value = queue_next_next.parse::<f64>().ok();
} else {
return Err(QueryError("Missing value".into()));
} }
} else { } else {
condition = Some(if content == ">" { condition = Some(if content == ">" {
@ -211,6 +235,8 @@ impl ProcessQuery for ProcWidgetState {
}); });
value = queue_next.parse::<f64>().ok(); 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(); let mut split_query = VecDeque::new();

View File

@ -74,6 +74,7 @@ pub struct AppSearchState {
pub char_cursor_position: usize, pub char_cursor_position: usize,
/// The query /// The query
pub query: Option<Query>, pub query: Option<Query>,
pub error_message: Option<String>,
} }
impl Default for AppSearchState { impl Default for AppSearchState {
@ -88,6 +89,7 @@ impl Default for AppSearchState {
cursor_bar: 0, cursor_bar: 0,
char_cursor_position: 0, char_cursor_position: 0,
query: None, query: None,
error_message: None,
} }
} }
} }
@ -198,15 +200,21 @@ impl ProcWidgetState {
.current_search_query .current_search_query
.is_empty() .is_empty()
{ {
self.process_search_state.search_state.is_invalid_search = false;
self.process_search_state.search_state.is_blank_search = true; 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.is_invalid_search = false;
self.process_search_state.search_state.error_message = None;
} else { } else {
self.process_search_state.search_state.is_blank_search = false; let parsed_query = self.parse_query();
self.process_search_state.search_state.is_invalid_search = true; 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.previous_scroll_position = 0;
self.scroll_state.current_scroll_position = 0; self.scroll_state.current_scroll_position = 0;

View File

@ -26,6 +26,7 @@ pub struct CanvasColours {
pub graph_style: Style, pub graph_style: Style,
// Full, Medium, Low // Full, Medium, Low
pub battery_bar_styles: Vec<Style>, pub battery_bar_styles: Vec<Style>,
pub invalid_query_style: Style,
} }
impl Default for CanvasColours { impl Default for CanvasColours {
@ -60,6 +61,7 @@ impl Default for CanvasColours {
Style::default().fg(Color::Green), Style::default().fg(Color::Green),
Style::default().fg(Color::Green), Style::default().fg(Color::Green),
], ],
invalid_query_style: tui::style::Style::default().fg(tui::style::Color::Red),
} }
} }
} }

View File

@ -44,7 +44,7 @@ impl ProcessTableWidget for Painter {
widget_id: u64, widget_id: u64,
) { ) {
if let Some(process_widget_state) = app_state.proc_state.widget_states.get(&widget_id) { 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() { if process_widget_state.is_search_enabled() {
let processes_chunk = Layout::default() let processes_chunk = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
@ -335,9 +335,6 @@ impl ProcessTableWidget for Painter {
let search_title = "> "; let search_title = "> ";
let num_chars_for_text = search_title.len(); 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 cursor_position = proc_widget_state.get_cursor_position();
let current_cursor_position = proc_widget_state.get_char_cursor_position(); let current_cursor_position = proc_widget_state.get_char_cursor_position();
let is_search_enabled = proc_widget_state.is_search_enabled(); let is_search_enabled = proc_widget_state.is_search_enabled();
@ -356,6 +353,14 @@ impl ProcessTableWidget for Painter {
app_state.is_force_redraw, 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 query = proc_widget_state.get_current_search_query().as_str();
let grapheme_indices = UnicodeSegmentation::grapheme_indices(query, true); let grapheme_indices = UnicodeSegmentation::grapheme_indices(query, true);
let query_with_cursor: Vec<Text<'_>> = build_query( let query_with_cursor: Vec<Text<'_>> = build_query(
@ -368,6 +373,8 @@ impl ProcessTableWidget for Painter {
self.colours.text_style, self.colours.text_style,
); );
// TODO: [QUERY] Make text/border go red if error?
// Text options shamelessly stolen from VS Code. // Text options shamelessly stolen from VS Code.
let case_style = if !proc_widget_state.process_search_state.is_ignoring_case { let case_style = if !proc_widget_state.process_search_state.is_ignoring_case {
self.colours.currently_selected_text_style self.colours.currently_selected_text_style
@ -393,31 +400,43 @@ impl ProcessTableWidget for Painter {
self.colours.text_style self.colours.text_style
}; };
let mut option_text = vec![]; let 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![
Text::raw("\n"), 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::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::raw(" "),
Text::styled(&regex_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.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); search_text.extend(option_text);
let current_border_style = if proc_widget_state let current_border_style = if is_on_processes {
.process_search_state
.search_state
.is_invalid_search
{
*INVALID_REGEX_STYLE
} else if is_on_processes {
self.colours.highlighted_border_style self.colours.highlighted_border_style
} else { } else {
self.colours.border_style self.colours.border_style

View File

@ -35,8 +35,6 @@ lazy_static! {
tui::style::Style::default().fg(tui::style::Color::Gray); tui::style::Style::default().fg(tui::style::Color::Gray);
pub static ref DEFAULT_HEADER_STYLE: tui::style::Style = pub static ref DEFAULT_HEADER_STYLE: tui::style::Style =
tui::style::Style::default().fg(tui::style::Color::LightBlue); 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 // Help text

View File

@ -49,9 +49,7 @@ impl std::fmt::Display for BottomError {
BottomError::ConversionError(ref message) => { BottomError::ConversionError(ref message) => {
write!(f, "unable to convert: {}", message) write!(f, "unable to convert: {}", message)
} }
BottomError::QueryError(ref _message) => { BottomError::QueryError(ref message) => write!(f, "{}", message),
write!(f, "invalid query - this should not be shown!")
}
} }
} }
} }