From e5e6cc6807c9fbbef883ffe0eec9eed477d5bee3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 1 Aug 2026 20:51:40 +0900 Subject: feat(symfony-console): implement interactive question/style helpers Resolve the remaining todo!()s in SymfonyStyle, OutputStyle, QuestionHelper and SymfonyQuestionHelper: * Wire up the virtual dispatch PHP performs for the protected writePrompt()/writeError() overrides, following the codebase's established inheritance idiom (Command, ArchiveDownloader): the base class becomes a trait (QuestionHelperInterface, named after the QuestionInterface precedent) whose provided methods ask/do_ask/ validate_attempts carry the template logic and late-bind the write_prompt/write_error hooks through Self, with inner()/inner_mut() reaching the base-class state. SymfonyQuestionHelper overrides the hooks as plain trait-impl methods, mirroring PHP's protected-method overriding, so SymfonyStyle-driven questions now render the Symfony Style Guide prompt. * Type definition_list input as an enum (string|array|TableSeparator) because PhpMixed intentionally cannot carry objects; the InvalidArgumentException branch (a LogicException) becomes unrepresentable. horizontal_table now takes typed Cells/Rows. * Propagate the MissingInputException thrown inside autocomplete() through a Result instead of aborting. * Implement as_console_output_interface via Ref::filter_map on ConsoleOutput, the interface's only implementor. * Port progressIterate eagerly, following ProgressBar::iterate. * Map __FILE__ to current_exe(): a native binary never runs from a phar, so the hiddeninput.exe relocation branch correctly never fires. Co-Authored-By: Claude Fable 5 --- .../console/helper/symfony_question_helper.rs | 56 ++++++++++++---------- 1 file changed, 32 insertions(+), 24 deletions(-) (limited to 'crates/shirabe-external-packages/src/symfony/console/helper/symfony_question_helper.rs') diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/symfony_question_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/symfony_question_helper.rs index 086f9c1c..cae3434d 100644 --- a/crates/shirabe-external-packages/src/symfony/console/helper/symfony_question_helper.rs +++ b/crates/shirabe-external-packages/src/symfony/console/helper/symfony_question_helper.rs @@ -1,10 +1,11 @@ //! ref: composer/vendor/symfony/console/Helper/SymfonyQuestionHelper.php use crate::symfony::console::formatter::output_formatter::OutputFormatter; -use crate::symfony::console::helper::question_helper::QuestionHelper; +use crate::symfony::console::helper::question_helper::{QuestionHelper, QuestionHelperInterface}; use crate::symfony::console::output::output_interface; use crate::symfony::console::output::output_interface::OutputInterface; use crate::symfony::console::question::QuestionInterface; +use crate::symfony::console::style::style_interface::StyleInterface; use crate::symfony::console::style::symfony_style::SymfonyStyle; use shirabe_php_shim::PhpMixed; use std::ops::{Deref, DerefMut}; @@ -20,7 +21,26 @@ impl SymfonyQuestionHelper { Self::default() } - pub(crate) fn write_prompt( + fn get_eof_shortcut(&self) -> String { + if shirabe_php_shim::php_os_family() == "Windows" { + return "Ctrl+Z then Enter".to_string(); + } + + "Ctrl+D".to_string() + } +} + +impl QuestionHelperInterface for SymfonyQuestionHelper { + fn inner(&self) -> &QuestionHelper { + &self.inner + } + + fn inner_mut(&mut self) -> &mut QuestionHelper { + &mut self.inner + } + + /// {@inheritdoc} + fn write_prompt( &self, output: std::rc::Rc>, question: &impl QuestionInterface, @@ -108,36 +128,24 @@ impl SymfonyQuestionHelper { .write(&[prompt], false, output_interface::OUTPUT_NORMAL); } - pub(crate) fn write_error( + /// {@inheritdoc} + fn write_error( &self, output: std::rc::Rc>, error: &shirabe_php_shim::Exception, ) { - let is_symfony_style = { - let borrowed = output.borrow(); - (*borrowed) - .as_any() - .downcast_ref::() - .is_some() - }; - if is_symfony_style { - // $output->newLine(); $output->error($error->getMessage()); - // SymfonyStyle's newLine()/error() require mutable access to the - // concrete type; mutable downcasting through the trait object is - // resolved in a later phase. - todo!("SymfonyStyle newLine()/error() require &mut SymfonyStyle"); + { + let mut borrowed = output.borrow_mut(); + if let Some(style) = (*borrowed).as_any_mut().downcast_mut::() { + style.new_line(1); + style.error(PhpMixed::String(error.message.clone())); + + return; + } } self.inner.write_error(output, error); } - - fn get_eof_shortcut(&self) -> String { - if shirabe_php_shim::php_os_family() == "Windows" { - return "Ctrl+Z then Enter".to_string(); - } - - "Ctrl+D".to_string() - } } impl Deref for SymfonyQuestionHelper { -- cgit v1.3.1