aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-symfony-console/src/question/confirmation_question.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-09 11:19:03 +0900
committernsfisis <nsfisis@gmail.com>2026-08-09 11:19:03 +0900
commit6051927c8fa32cfffa102d2a170c5a6cf747a1b9 (patch)
tree3fe6769c90cb03ca8f1b9b825e38ad459182361e /crates/shirabe-symfony-console/src/question/confirmation_question.rs
parente3e8806aec771e482899ed3470e920f7b291fa95 (diff)
downloadphp-shirabe-6051927c8fa32cfffa102d2a170c5a6cf747a1b9.tar.gz
php-shirabe-6051927c8fa32cfffa102d2a170c5a6cf747a1b9.tar.zst
php-shirabe-6051927c8fa32cfffa102d2a170c5a6cf747a1b9.zip
refactor(symfony-console): extract symfony/console into the shirabe-symfony-console crate
Move `Symfony\Component\Console` out of shirabe-external-packages and into its own crate, so the path is `shirabe_symfony_console::application::Application` instead of `shirabe_external_packages::symfony::console::application::Application`. The `delegate_to_inner!` and `delegate_command_trait_impls_to_inner!` macros move with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-symfony-console/src/question/confirmation_question.rs')
-rw-r--r--crates/shirabe-symfony-console/src/question/confirmation_question.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/crates/shirabe-symfony-console/src/question/confirmation_question.rs b/crates/shirabe-symfony-console/src/question/confirmation_question.rs
new file mode 100644
index 00000000..34db281b
--- /dev/null
+++ b/crates/shirabe-symfony-console/src/question/confirmation_question.rs
@@ -0,0 +1,113 @@
+//! ref: composer/vendor/symfony/console/Question/ConfirmationQuestion.php
+
+use crate::exception::invalid_argument_exception::InvalidArgumentException;
+use crate::question::Question;
+use crate::question::QuestionInterface;
+use shirabe_php_shim::PhpMixed;
+
+/// Represents a yes/no question.
+#[derive(Debug)]
+pub struct ConfirmationQuestion {
+ inner: Question,
+ true_answer_regex: String,
+}
+
+impl ConfirmationQuestion {
+ /// `$question` The question to ask to the user.
+ /// `$default` The default answer to return, true or false.
+ /// `$trueAnswerRegex` A regex to match the "yes" answer.
+ pub fn new(question: String, default: bool, true_answer_regex: String) -> Self {
+ let mut this = Self {
+ inner: Question::new(question, Some(PhpMixed::Bool(default))),
+ true_answer_regex,
+ };
+
+ let normalizer = this.get_default_normalizer();
+ this.inner.set_normalizer(normalizer);
+
+ this
+ }
+
+ /// Returns the default answer normalizer.
+ fn get_default_normalizer(&self) -> Box<dyn Fn(PhpMixed) -> PhpMixed> {
+ let default = self.inner.get_default();
+ let regex = self.true_answer_regex.clone();
+
+ Box::new(move |answer: PhpMixed| {
+ if let PhpMixed::Bool(_) = answer {
+ return answer;
+ }
+
+ let answer_is_true = {
+ let mut matches: Vec<Option<String>> = Vec::new();
+ shirabe_php_shim::preg_match(
+ &regex,
+ &shirabe_php_shim::strval(&answer),
+ &mut matches,
+ )
+ };
+
+ // false === $default
+ if matches!(default, PhpMixed::Bool(false)) {
+ // $answer && $answerIsTrue
+ return PhpMixed::Bool(!shirabe_php_shim::empty(&answer) && answer_is_true);
+ }
+
+ // '' === $answer || $answerIsTrue
+ let answer_is_empty_string = matches!(&answer, PhpMixed::String(s) if s.is_empty());
+ PhpMixed::Bool(answer_is_empty_string || answer_is_true)
+ })
+ }
+}
+
+impl QuestionInterface for ConfirmationQuestion {
+ fn get_question(&self) -> &str {
+ self.inner.get_question()
+ }
+
+ fn get_default(&self) -> PhpMixed {
+ self.inner.get_default()
+ }
+
+ fn is_multiline(&self) -> bool {
+ self.inner.is_multiline()
+ }
+
+ fn is_hidden(&self) -> bool {
+ self.inner.is_hidden()
+ }
+
+ fn is_hidden_fallback(&self) -> bool {
+ self.inner.is_hidden_fallback()
+ }
+
+ fn get_autocompleter_values(&self) -> Option<Vec<PhpMixed>> {
+ self.inner.get_autocompleter_values()
+ }
+
+ fn get_autocompleter_callback(&self) -> Option<&dyn Fn(&str) -> Option<Vec<PhpMixed>>> {
+ self.inner.get_autocompleter_callback()
+ }
+
+ fn get_validator(
+ &self,
+ ) -> Option<&dyn Fn(Option<PhpMixed>) -> Result<PhpMixed, InvalidArgumentException>> {
+ self.inner.get_validator()
+ }
+
+ fn get_max_attempts(&self) -> Option<i64> {
+ self.inner.get_max_attempts()
+ }
+
+ fn get_normalizer(&self) -> Option<&dyn Fn(PhpMixed) -> PhpMixed> {
+ self.inner.get_normalizer()
+ }
+
+ fn is_trimmable(&self) -> bool {
+ self.inner.is_trimmable()
+ }
+
+ fn as_confirmation(&self) -> Option<&ConfirmationQuestion> {
+ Some(self)
+ }
+}