diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-17 07:20:29 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-17 07:20:29 +0900 |
| commit | 6b4ce98f20b3cfc14f1c955565a8acd9abcc16a2 (patch) | |
| tree | 1c752ee23480e71fabad42c3bbe2b7ffc7f6acdc /crates/shirabe-symfony-console/src | |
| parent | c7aa10384a2548167466b4c61f9eff29ed8611f6 (diff) | |
| download | php-shirabe-6b4ce98f20b3cfc14f1c955565a8acd9abcc16a2.tar.gz php-shirabe-6b4ce98f20b3cfc14f1c955565a8acd9abcc16a2.tar.zst php-shirabe-6b4ce98f20b3cfc14f1c955565a8acd9abcc16a2.zip | |
refactor(preg): report unmatched groups as null in the vec-shaped preg_*
preg_match_all() and preg_match_all_set_order() were the last preg_*
functions handing back a bare Vec<String>, where a group that did not
participate is indistinguishable from one that captured "". Hand back
Option<String> as the map-shaped functions already do; php_match_row(),
the last of the truncate-then-pad helpers, goes with them.
preg_split_delim_capture() keeps its Vec<String>. preg_split() accepts
no PREG_UNMATCHED_AS_NULL, so there is no null form to move it to, and
its result interleaves split segments -- which can never be absent --
with the captured delimiters.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-symfony-console/src')
| -rw-r--r-- | crates/shirabe-symfony-console/src/completion/completion_input.rs | 12 | ||||
| -rw-r--r-- | crates/shirabe-symfony-console/src/formatter/output_formatter.rs | 17 |
2 files changed, 25 insertions, 4 deletions
diff --git a/crates/shirabe-symfony-console/src/completion/completion_input.rs b/crates/shirabe-symfony-console/src/completion/completion_input.rs index 2f146a39..aafa7c8a 100644 --- a/crates/shirabe-symfony-console/src/completion/completion_input.rs +++ b/crates/shirabe-symfony-console/src/completion/completion_input.rs @@ -34,7 +34,17 @@ impl CompletionInput { input_str, ); - Self::from_tokens(tokens[0].clone(), current_index) + Self::from_tokens( + tokens[0] + .iter() + .map(|token| { + token + .clone() + .expect("group 0 participates whenever the pattern matches") + }) + .collect(), + current_index, + ) } /// Create an input based on an COMP_WORDS token list. diff --git a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs index 311d50fd..c7c06cf5 100644 --- a/crates/shirabe-symfony-console/src/formatter/output_formatter.rs +++ b/crates/shirabe-symfony-console/src/formatter/output_formatter.rs @@ -109,7 +109,7 @@ impl OutputFormatter { return Ok(Some(style.borrow().clone_box())); } - let mut matches: Vec<Vec<String>> = vec![]; + let mut matches: Vec<Vec<Option<String>>> = vec![]; if preg_match_all_set_order(php_regex!("/([^=]+)=([^;]+)(;|$)/"), string, &mut matches) == 0 { return Ok(None); @@ -117,7 +117,14 @@ impl OutputFormatter { let mut style = OutputFormatterStyle::new(None, None, vec![]); for r#match in &matches { - let mut r#match: Vec<String> = r#match.clone(); + let mut r#match: Vec<String> = r#match + .iter() + .map(|group| { + group + .clone() + .expect("every group participates whenever the pattern matches") + }) + .collect(); shirabe_php_shim::array_shift(&mut r#match); r#match[0] = shirabe_php_shim::strtolower(&r#match[0]); @@ -135,7 +142,11 @@ impl OutputFormatter { ); let options = shirabe_php_shim::array_shift(&mut options).unwrap_or_default(); for option in &options { - style.set_option(option); + style.set_option( + option + .as_deref() + .expect("group 0 participates whenever the pattern matches"), + ); } } else { return Ok(None); |
