From bdf8db4890991da45e99a449d0c031d74d648ad4 Mon Sep 17 00:00:00 2001 From: ggemre Date: Sun, 11 Feb 2024 21:15:27 -0700 Subject: [PATCH] feat: add selectable & hidden props --- src/external/model.rs | 41 ++++++++++++++++++++++++++++----- src/external/widget.rs | 5 +++-- src/interface/window.rs | 50 ++++++++++++++++++----------------------- src/main.rs | 16 +++++++++++++ 4 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/external/model.rs b/src/external/model.rs index 69a237d..2393e68 100644 --- a/src/external/model.rs +++ b/src/external/model.rs @@ -30,6 +30,7 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { let param_regex = Regex::new(r#"(\w+)\s*=\s*\"?([^\",]+)\"?,?\s*"#).unwrap(); let text_regex = Regex::new(r#"TEXT\("(.*)"\)"#).unwrap(); + let text_v2_regex = Regex::new(r"TEXT\s*\((.*?)\)").unwrap(); let data_regex = Regex::new(r#"DATA\("(.*)"\)"#).unwrap(); let quit_regex = Regex::new(r#"QUIT\("([^"]*)"\)"#).unwrap(); @@ -41,11 +42,11 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { if let Some(captures) = input_regex.captures(line) { // found input widget, initialize parameters to default values let params_str = captures.get(1).unwrap().as_str(); - let mut max_width = 32; let mut filter = Filter::Off; let mut label = String::new(); - let mut placeholder = String::new(); let mut content = String::new(); + let mut selectable = true; + let mut hidden = false; for param_match in param_regex.captures_iter(params_str) { let param = param_match.get(1).unwrap().as_str(); @@ -53,7 +54,6 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { // set parameter variable for each valid parameter match param { - | "max_width" => max_width = value.parse().unwrap_or(32), | "filter" => { filter = value.parse().unwrap_or_else(|_| { eprintln!( @@ -64,8 +64,9 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { }) } | "label" => label = value.to_string(), - | "placeholder" => placeholder = value.to_string(), | "content" => content = value.to_string(), + | "selectable" => selectable = value.eq("true"), + | "hidden" => hidden = value.eq("true"), | _ => {} } } @@ -73,11 +74,11 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { // add a new input widget to the model widgets.push(Widget::Input { y: level, - max_width, filter, label, - placeholder, content, + selectable, + hidden, id: unique_id, }); } else if let Some(captures) = text_regex.captures(line) { @@ -89,6 +90,34 @@ pub fn parse_stdout(stdout: &str) -> (Vec, String) { y: level, content, show: true, + selectable: true, + id: unique_id, + }); + } else if let Some(captures) = text_v2_regex.captures(line) { + // TODO: merge text_v2 with text one day... + // found parameterized text widget, initialize parameters to default values + let params_str = captures.get(1).unwrap().as_str(); + let mut content = String::new(); + let mut selectable = true; + + for param_match in param_regex.captures_iter(params_str) { + let param = param_match.get(1).unwrap().as_str(); + let value = param_match.get(2).unwrap().as_str(); + + // set parameter variable for each valid parameter + match param { + | "content" => content = value.to_string(), + | "selectable" => selectable = value.eq("true"), + | _ => {} + } + } + + // add a new input widget to the model + widgets.push(Widget::Text { + y: level, + content, + show: true, + selectable, id: unique_id, }); } else if let Some(captures) = data_regex.captures(line) { diff --git a/src/external/widget.rs b/src/external/widget.rs index c1ef179..76472ff 100644 --- a/src/external/widget.rs +++ b/src/external/widget.rs @@ -24,16 +24,17 @@ impl FromStr for Filter { pub enum Widget { Input { y: i32, - max_width: usize, filter: Filter, label: String, - placeholder: String, content: String, + selectable: bool, + hidden: bool, id: usize, }, Text { y: i32, content: String, + selectable: bool, show: bool, id: usize, }, diff --git a/src/interface/window.rs b/src/interface/window.rs index db7f777..bd57e95 100644 --- a/src/interface/window.rs +++ b/src/interface/window.rs @@ -206,35 +206,24 @@ fn wait_for_input( break; } | Some(Input::KeyEnter) | Some(Input::Character('\n')) => { - // enter/return pressed, prepare program to quit - break_condition = BreakCondition::QUIT; - - for widget in model { - match widget { - | Widget::Input { y, id, .. } - if *y == (cursor.y as i32) => - { - // selected widget is input, set break condition and selected id - current_widget = *id; - break_condition = BreakCondition::INPUT; - break; - } - | Widget::Text { y, id, .. } - if *y == (cursor.y as i32) => - { - // selected widget is text, set break condition and selected id - current_widget = *id; - break_condition = BreakCondition::SELECTION; - break; - } - | _ => { - break_condition = BreakCondition::QUIT; - } + if let Some(Widget::Input { id, selectable, .. }) = + find_widget_by_y(model, cursor.y as i32) + { + if *selectable { + current_widget = *id; + break_condition = BreakCondition::INPUT; + break; + } + } + if let Some(Widget::Text { id, selectable, .. }) = + find_widget_by_y(model, cursor.y as i32) + { + if *selectable { + current_widget = *id; + break_condition = BreakCondition::SELECTION; + break; } } - - // conditions have been set, exit loop - break; } | Some(Input::KeyUp) => { // up arrow pressed, move cursor up @@ -372,28 +361,33 @@ fn wait_for_input( let mut content; let filter; + let hidden; let current_level = cursor.y; let mut label_len = 0; if let Some(Widget::Input { content: ref_content, filter: ref_filter, + hidden: ref_hidden, .. }) = find_widget_by_y(model, cursor.y as i32).cloned() { // current row is input, get its content and filter type content = ref_content.clone(); filter = ref_filter.clone(); + hidden = ref_hidden.clone(); } else { // current row is text, nothing to type so skip continue; } + let display_char = if hidden { '*' } else { c }; + // insert typed character to screen window.mvinsch( cursor.y as i32, (cursor.x + left_margin) as i32, - c as chtype, + display_char as chtype, ); cursor.x += 1; diff --git a/src/main.rs b/src/main.rs index de3f0d1..37611d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,6 +53,22 @@ fn main() { data = new_data; } + // for widget in model { + // match widget { + // | Widget::Input { + // y, selectable, .. + // } => { + // println!("{}", selectable); + // } + // | Widget::Text { + // y, selectable, .. + // } => { + // println!("{}", selectable); + // } + // } + // } + // exit(1); + let (break_condition, match_id) = init(&mut model); if break_condition == BreakCondition::SELECTION {