diff options
| author | Jonas Maier <jonas@x77.dev> | 2026-06-06 22:55:27 +0200 |
|---|---|---|
| committer | Jonas Maier <jonas@x77.dev> | 2026-06-06 22:55:27 +0200 |
| commit | 2e379710ca4ca1739788beb502a55d8bd596dc16 (patch) | |
| tree | 65461fd6a669e428bbfcb6ae8944f11627e3cb2b | |
| parent | 6b452e817090dba6c80454a42079fa5c9f83b1cd (diff) | |
| download | pish-main.tar.gz | |
| -rw-r--r-- | src/lib.rs | 27 | ||||
| -rw-r--r-- | src/run/mod.rs | 13 | ||||
| -rw-r--r-- | test-cases/case4_submatches/script.sh | 8 | ||||
| -rw-r--r-- | test-cases/case4_submatches/stdout.txt | 1 | ||||
| -rw-r--r-- | tests/scripts.rs | 5 |
5 files changed, 49 insertions, 5 deletions
@@ -18,6 +18,7 @@ use std::sync::{Arc, Mutex}; pub mod ansi; pub mod basedir; +mod bitset; pub mod completion; pub mod consts; pub mod ctrlc; @@ -31,6 +32,7 @@ pub mod panic; pub mod parse; pub mod ps1; pub mod raw; +pub mod regex; pub mod reload; pub mod run; pub mod rw; @@ -38,8 +40,6 @@ pub mod serialization; pub mod syntax_highlighting; pub mod variants; pub mod wait; -pub mod regex; -mod bitset; use raw::*; @@ -49,6 +49,8 @@ use crate::history::HistoryEntry; use crate::line::Line; use crate::parse::{Block, ExpString, Parse, PostExpansion}; use crate::ps1::Prompt; +use crate::regex::bc::RegexCompilationError; +use crate::regex::{CompiledPattern, Pattern, RegexEngine}; macro_rules! print { ($($x:tt)*) => {{ @@ -123,6 +125,8 @@ pub struct Session { prompt: Prompt, terminal_input: Option<ansi::TerminalInput>, + + regex_cache: HashMap<Pattern, Result<Arc<CompiledPattern>, RegexCompilationError>>, } impl Session { @@ -148,6 +152,7 @@ impl Session { prompt, vars, terminal_input: None, + regex_cache: HashMap::new(), } } } @@ -345,6 +350,24 @@ impl Session { self.line.highlight_syntax(&mut self.highlighter)?; Ok(()) } + + fn cached_regex( + se: &Mutex<Self>, + pat: Pattern, + ) -> Result<Arc<CompiledPattern>, RegexCompilationError> { + let mut this = se.lock().unwrap(); + if let Some(re) = this.regex_cache.get(&pat) { + re.clone() + } else { + let res = CompiledPattern::compile(pat.clone()); + let res = match res { + Ok(re) => Ok(Arc::new(re)), + Err(e) => Err(e), + }; + this.regex_cache.insert(pat, res.clone()); + res + } + } } const DEFAULT_PROFILE: &[u8] = include_bytes!("profile"); diff --git a/src/run/mod.rs b/src/run/mod.rs index 64522d9..3420c30 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -457,10 +457,17 @@ impl Executor { stdout: OutputWriter, ) -> SpawnedCmd { for branch in c.branches.into_iter() { - // TODO: do not compile every time - if let Ok(compiled) = branch.pattern.try_compile() - && compiled.matches(&c.discriminant) + if let Ok(compiled) = Session::cached_regex(self.se.as_ref(), branch.pattern) + && let Some(mtch) = compiled.run(&c.discriminant) { + // put submatches into variables + if !mtch.submatches.is_empty() { + let mut se = self.se.lock().unwrap(); + for (var, match_loc) in mtch.submatches.into_iter() { + let val = c.discriminant[match_loc].to_vec(); + se.vars.set(var, val); + } + } return self.execute_block(branch.block, stdin, stdout); } } diff --git a/test-cases/case4_submatches/script.sh b/test-cases/case4_submatches/script.sh new file mode 100644 index 0000000..75e7f6f --- /dev/null +++ b/test-cases/case4_submatches/script.sh @@ -0,0 +1,8 @@ +set file_name = 'taxes.pdf' + +case $file_name { + (?<base>.*)[.](?<ext>.*) { } + .* { echo format error } +} + +echo "file base is $base, file extension is $ext" diff --git a/test-cases/case4_submatches/stdout.txt b/test-cases/case4_submatches/stdout.txt new file mode 100644 index 0000000..570da9d --- /dev/null +++ b/test-cases/case4_submatches/stdout.txt @@ -0,0 +1 @@ +file base is taxes, file extension is pdf diff --git a/tests/scripts.rs b/tests/scripts.rs index 2a7a6f8..69a81ce 100644 --- a/tests/scripts.rs +++ b/tests/scripts.rs @@ -22,6 +22,11 @@ fn case3_negative_lookahead() { } #[test] +fn case4_submatches() { + common::test_case("case4_submatches", include_bytes!("../test-cases/case4_submatches/script.sh"), include_bytes!("../test-cases/case4_submatches/stdout.txt")); +} + +#[test] fn comment() { common::test_case("comment", include_bytes!("../test-cases/comment/script.sh"), include_bytes!("../test-cases/comment/stdout.txt")); } |
