diff options
Diffstat (limited to 'crates/shirabe-symfony-console/src/helper/symfony_question_helper.rs')
| -rw-r--r-- | crates/shirabe-symfony-console/src/helper/symfony_question_helper.rs | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/crates/shirabe-symfony-console/src/helper/symfony_question_helper.rs b/crates/shirabe-symfony-console/src/helper/symfony_question_helper.rs new file mode 100644 index 00000000..9de40dd4 --- /dev/null +++ b/crates/shirabe-symfony-console/src/helper/symfony_question_helper.rs @@ -0,0 +1,163 @@ +//! ref: composer/vendor/symfony/console/Helper/SymfonyQuestionHelper.php + +use crate::formatter::output_formatter::OutputFormatter; +use crate::helper::question_helper::{QuestionHelper, QuestionHelperInterface}; +use crate::output::output_interface; +use crate::output::output_interface::OutputInterface; +use crate::question::QuestionInterface; +use crate::style::style_interface::StyleInterface; +use crate::style::symfony_style::SymfonyStyle; +use shirabe_php_shim::PhpMixed; +use std::ops::{Deref, DerefMut}; + +/// Symfony Style Guide compliant question helper. +#[derive(Debug, Default)] +pub struct SymfonyQuestionHelper { + inner: QuestionHelper, +} + +impl SymfonyQuestionHelper { + pub fn new() -> Self { + Self::default() + } + + fn get_eof_shortcut(&self) -> String { + if shirabe_php_shim::php_os_family() == "Windows" { + return "<comment>Ctrl+Z</comment> then <comment>Enter</comment>".to_string(); + } + + "<comment>Ctrl+D</comment>".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<std::cell::RefCell<dyn OutputInterface>>, + question: &impl QuestionInterface, + ) { + let mut text = OutputFormatter::escape_trailing_backslash(question.get_question()); + let default = question.get_default(); + + if question.is_multiline() { + text += &format!(" (press {} to continue)", self.get_eof_shortcut()); + } + + // switch (true) + if matches!(default, PhpMixed::Null) { + text = format!(" <info>{}</info>:", text); + } else if question.as_confirmation().is_some() { + text = format!( + " <info>{} (yes/no)</info> [<comment>{}</comment>]:", + text, + if shirabe_php_shim::boolval(&default) { + "yes" + } else { + "no" + }, + ); + } else if let Some(choice_question) = question.as_choice().filter(|q| q.is_multiselect()) { + let choices = choice_question.get_choices(); + let default_parts = shirabe_php_shim::explode(",", &default.to_string()); + + let resolved: Vec<String> = default_parts + .iter() + .map(|value| { + choices + .get(&shirabe_php_shim::trim(value, None)) + .map(|v| v.to_string()) + .unwrap() + }) + .collect(); + + text = format!( + " <info>{}</info> [<comment>{}</comment>]:", + text, + OutputFormatter::escape(&resolved.join(", ")).unwrap(), + ); + } else if let Some(choice_question) = question.as_choice() { + let choices = choice_question.get_choices(); + text = format!( + " <info>{}</info> [<comment>{}</comment>]:", + text, + OutputFormatter::escape( + &choices + .get(&default.to_string()) + .cloned() + .unwrap_or(default) + .to_string(), + ) + .unwrap(), + ); + } else { + text = format!( + " <info>{}</info> [<comment>{}</comment>]:", + text, + OutputFormatter::escape(&default.to_string()).unwrap(), + ); + } + + output + .borrow() + .writeln(&[text], output_interface::OUTPUT_NORMAL); + + let mut prompt = " > ".to_string(); + + if let Some(choice_question) = question.as_choice() { + output.borrow().writeln( + &self + .inner + .format_choice_question_choices(choice_question, "comment"), + output_interface::OUTPUT_NORMAL, + ); + + prompt = choice_question.get_prompt().to_string(); + } + + output + .borrow() + .write(&[prompt], false, output_interface::OUTPUT_NORMAL); + } + + /// {@inheritdoc} + fn write_error( + &self, + output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>, + error: &shirabe_php_shim::Exception, + ) { + { + let mut borrowed = output.borrow_mut(); + if let Some(style) = (*borrowed).as_any_mut().downcast_mut::<SymfonyStyle>() { + style.new_line(1); + style.error(PhpMixed::String(error.get_message().to_string())); + + return; + } + } + + self.inner.write_error(output, error); + } +} + +impl Deref for SymfonyQuestionHelper { + type Target = QuestionHelper; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for SymfonyQuestionHelper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} |
