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 {
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();

View File

@ -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;

View File

@ -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),
}
}
}

View File

@ -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(&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.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

View File

@ -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

View File

@ -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),
}
}
}