diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-08 02:44:38 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-08 02:44:38 +0900 |
| commit | 243450fee9853c2fea66ae0642dabb8db5227d6f (patch) | |
| tree | 8a3ee16555d04835ef7afad576942b642bfdcfa6 | |
| parent | 06368584a9277022d9cfc42d22c37f4cc6e580f8 (diff) | |
| download | php-shirabe-243450fee9853c2fea66ae0642dabb8db5227d6f.tar.gz php-shirabe-243450fee9853c2fea66ae0642dabb8db5227d6f.tar.zst php-shirabe-243450fee9853c2fea66ae0642dabb8db5227d6f.zip | |
feat(phase-c): resolve closure-capture phase-b TODOs in config/create-project
Port Config::process() to the real Preg::replace_callback, whose closure
borrows &self/flags and calls get_with_flags; surface get() errors via a
captured cell so process now returns Result. Switch the replace_callback
shim bounds to FnMut to allow the error-capturing closure.
Wire CreateProjectCommand suggestion collection through the
Rc<RefCell> reporter's interior mutation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| -rw-r--r-- | crates/shirabe-external-packages/src/composer/pcre/preg.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/src/command/create_project_command.rs | 7 | ||||
| -rw-r--r-- | crates/shirabe/src/config.rs | 46 |
3 files changed, 35 insertions, 26 deletions
diff --git a/crates/shirabe-external-packages/src/composer/pcre/preg.rs b/crates/shirabe-external-packages/src/composer/pcre/preg.rs index e16643a..ea189eb 100644 --- a/crates/shirabe-external-packages/src/composer/pcre/preg.rs +++ b/crates/shirabe-external-packages/src/composer/pcre/preg.rs @@ -211,7 +211,7 @@ impl Preg { todo!() } - pub fn replace_callback<F: Fn(&indexmap::IndexMap<CaptureKey, String>) -> String>( + pub fn replace_callback<F: FnMut(&indexmap::IndexMap<CaptureKey, String>) -> String>( _pattern: &str, _replacement: F, _subject: &str, @@ -219,7 +219,7 @@ impl Preg { todo!() } - pub fn replace_callback4<F: Fn(&indexmap::IndexMap<CaptureKey, String>) -> String>( + pub fn replace_callback4<F: FnMut(&indexmap::IndexMap<CaptureKey, String>) -> String>( _pattern: &str, _replacement: F, _subject: &str, @@ -228,7 +228,7 @@ impl Preg { todo!() } - pub fn replace_callback5<F: Fn(&indexmap::IndexMap<CaptureKey, String>) -> String>( + pub fn replace_callback5<F: FnMut(&indexmap::IndexMap<CaptureKey, String>) -> String>( _pattern: &str, _replacement: F, _subject: &str, @@ -238,7 +238,7 @@ impl Preg { todo!() } - pub fn replace_callback6<F: Fn(&indexmap::IndexMap<CaptureKey, String>) -> String>( + pub fn replace_callback6<F: FnMut(&indexmap::IndexMap<CaptureKey, String>) -> String>( _pattern: &str, _replacement: F, _subject: &str, diff --git a/crates/shirabe/src/command/create_project_command.rs b/crates/shirabe/src/command/create_project_command.rs index 77cbea7..f8fc511 100644 --- a/crates/shirabe/src/command/create_project_command.rs +++ b/crates/shirabe/src/command/create_project_command.rs @@ -972,8 +972,11 @@ impl CreateProjectCommand { im.notify_installs(io.clone()); // collect suggestions - // TODO(phase-b): self.suggested_packages_reporter is on the outer scope via &self - // self.suggested_packages_reporter.add_suggestions_from_package(&*package); + self.suggested_packages_reporter + .as_ref() + .unwrap() + .borrow_mut() + .add_suggestions_from_package(package.clone()); let installed_from_vcs = package.get_installation_source().as_deref() == Some("source"); diff --git a/crates/shirabe/src/config.rs b/crates/shirabe/src/config.rs index d1f0702..d6bee9e 100644 --- a/crates/shirabe/src/config.rs +++ b/crates/shirabe/src/config.rs @@ -14,7 +14,8 @@ use shirabe_php_shim::{ E_USER_DEPRECATED, FILTER_VALIDATE_URL, PHP_URL_HOST, PHP_URL_SCHEME, PhpMixed, RuntimeException, array_key_exists, array_merge, array_reverse, array_search_mixed, array_unique, current, empty, filter_var, implode, in_array, is_array, is_int, is_string, key, - max, parse_url, reset, rtrim, strtolower, strtoupper, strtr, substr, trigger_error, + max, parse_url, php_to_string, reset, rtrim, strtolower, strtoupper, strtr, substr, + trigger_error, }; use std::cell::RefCell; @@ -618,7 +619,7 @@ impl Config { } else { val }; - let processed = self.process(raw_val, flags); + let processed = self.process(raw_val, flags)?; let mut val_str = rtrim(processed.as_string().unwrap_or(""), Some("/\\")); val_str = Platform::expand_path(&val_str); @@ -740,7 +741,7 @@ impl Config { "home" => { let v = self.config.get(key).cloned().unwrap_or(PhpMixed::Null); let expanded = Platform::expand_path(v.as_string().unwrap_or("")); - let processed = self.process(PhpMixed::String(expanded), flags); + let processed = self.process(PhpMixed::String(expanded), flags)?; Ok(PhpMixed::String(rtrim( processed.as_string().unwrap_or(""), Some("/\\"), @@ -905,7 +906,7 @@ impl Config { return Ok(PhpMixed::Null); } - Ok(self.process(v, flags)) + self.process(v, flags) } "audit" => { @@ -981,7 +982,7 @@ impl Config { } let v = self.config.get(key).cloned().unwrap_or(PhpMixed::Null); - Ok(self.process(v, flags)) + self.process(v, flags) } } } @@ -1073,26 +1074,31 @@ impl Config { /// @param int $flags Options (see class constants) /// /// @return string|mixed - fn process(&self, value: PhpMixed, flags: i64) -> PhpMixed { + fn process(&self, value: PhpMixed, flags: i64) -> Result<PhpMixed> { if !is_string(&value) { - return value; + return Ok(value); } let value_str = value.as_string().unwrap_or("").to_string(); - // TODO(phase-b): Preg::replace_callback with a closure that calls &mut self.get_with_flags - let mut result = value_str.clone(); - let mut m: IndexMap<CaptureKey, String> = IndexMap::new(); - if Preg::is_match_strict_groups3(r"#\{\$(.+)\}#", &value_str, Some(&mut m)).unwrap_or(false) - { - let key_match = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); - let replacement = self - .get_with_flags(&key_match, flags) - .ok() - .and_then(|v| v.as_string().map(|s| s.to_string())) - .unwrap_or_default(); - result = result.replace(&format!("{{${}}}", key_match), &replacement); + let mut error = None; + let result = Preg::replace_callback( + r"#\{\$(.+)\}#", + |m: &IndexMap<CaptureKey, String>| -> String { + let key_match = m.get(&CaptureKey::ByIndex(1)).cloned().unwrap_or_default(); + match self.get_with_flags(&key_match, flags) { + Ok(v) => php_to_string(&v), + Err(e) => { + error = Some(e); + String::new() + } + } + }, + &value_str, + )?; + if let Some(e) = error { + return Err(e); } - PhpMixed::String(result) + Ok(PhpMixed::String(result)) } /// Turns relative paths in absolute paths without realpath() |
