1use crate::engine::{self, CompiledRegex, EngineFlags, EngineKind, RegexEngine};
2use crate::explain::{self, ExplainNode};
3use crate::input::editor::Editor;
4
5pub struct App {
6 pub regex_editor: Editor,
7 pub test_editor: Editor,
8 pub focused_panel: u8, pub engine_kind: EngineKind,
10 pub flags: EngineFlags,
11 pub matches: Vec<engine::Match>,
12 pub explanation: Vec<ExplainNode>,
13 pub error: Option<String>,
14 pub show_help: bool,
15 pub should_quit: bool,
16 engine: Box<dyn RegexEngine>,
17 compiled: Option<Box<dyn CompiledRegex>>,
18}
19
20impl App {
21 pub fn new(engine_kind: EngineKind, flags: EngineFlags) -> Self {
22 let engine = engine::create_engine(engine_kind);
23 Self {
24 regex_editor: Editor::new(),
25 test_editor: Editor::new(),
26 focused_panel: 0,
27 engine_kind,
28 flags,
29 matches: Vec::new(),
30 explanation: Vec::new(),
31 error: None,
32 show_help: false,
33 should_quit: false,
34 engine,
35 compiled: None,
36 }
37 }
38
39 pub fn set_pattern(&mut self, pattern: &str) {
40 self.regex_editor = Editor::with_content(pattern.to_string());
41 self.recompute();
42 }
43
44 pub fn set_test_string(&mut self, text: &str) {
45 self.test_editor = Editor::with_content(text.to_string());
46 self.rematch();
47 }
48
49 pub fn switch_engine(&mut self) {
50 self.engine_kind = self.engine_kind.next();
51 self.engine = engine::create_engine(self.engine_kind);
52 self.recompute();
53 }
54
55 pub fn recompute(&mut self) {
56 let pattern = self.regex_editor.content().to_string();
57
58 if pattern.is_empty() {
59 self.compiled = None;
60 self.matches.clear();
61 self.explanation.clear();
62 self.error = None;
63 return;
64 }
65
66 match self.engine.compile(&pattern, &self.flags) {
68 Ok(compiled) => {
69 self.compiled = Some(compiled);
70 self.error = None;
71 }
72 Err(e) => {
73 self.compiled = None;
74 self.matches.clear();
75 self.error = Some(e.to_string());
76 }
77 }
78
79 match explain::explain(&pattern) {
81 Ok(nodes) => self.explanation = nodes,
82 Err(e) => {
83 self.explanation.clear();
84 if self.error.is_none() {
85 self.error = Some(e);
86 }
87 }
88 }
89
90 self.rematch();
92 }
93
94 pub fn rematch(&mut self) {
95 if let Some(compiled) = &self.compiled {
96 let text = self.test_editor.content().to_string();
97 if text.is_empty() {
98 self.matches.clear();
99 return;
100 }
101 match compiled.find_matches(&text) {
102 Ok(m) => self.matches = m,
103 Err(e) => {
104 self.matches.clear();
105 self.error = Some(e.to_string());
106 }
107 }
108 } else {
109 self.matches.clear();
110 }
111 }
112}