summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2020-05-02 21:50:35 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2020-05-02 21:50:35 -0400
commit8307b06c56934aa74985a0fee1271f1bc299b83f (patch)
tree39ab937261566fea71461b152a6350623a1dad9c
parente12c2f5212b7898b10f6c01024fa2cbe59c55bc6 (diff)
bug: fix bug with multiple tokens
-rw-r--r--src/app/query.rs36
-rw-r--r--src/app/states.rs20
-rw-r--r--src/canvas/canvas_colours.rs2
-rw-r--r--src/canvas/widgets/process_table.rs61
-rw-r--r--src/constants.rs2
-rw-r--r--src/utils/error.rs4
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(&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
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),
}
}
}