aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-symfony-console/src/command/help_command.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/command/help_command.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/command/help_command.rs')
-rw-r--r--crates/shirabe-symfony-console/src/command/help_command.rs171
1 files changed, 171 insertions, 0 deletions
diff --git a/crates/shirabe-symfony-console/src/command/help_command.rs b/crates/shirabe-symfony-console/src/command/help_command.rs
new file mode 100644
index 00000000..9472d144
--- /dev/null
+++ b/crates/shirabe-symfony-console/src/command/help_command.rs
@@ -0,0 +1,171 @@
+//! ref: composer/vendor/symfony/console/Command/HelpCommand.php
+
+use crate::command::command::{Command, CommandData, SetDefinitionArg};
+use crate::completion::completion_input::CompletionInput;
+use crate::completion::completion_suggestions::{CompletionSuggestions, StringOrSuggestion};
+use crate::descriptor::application_description::ApplicationDescription;
+use crate::descriptor::descriptor_interface::DescribableObject;
+use crate::helper::descriptor_helper::DescriptorHelper;
+use crate::input::input_argument::InputArgument;
+use crate::input::input_definition::DefinitionItem;
+use crate::input::input_interface::InputInterface;
+use crate::input::input_option::InputOption;
+use crate::output::output_interface::OutputInterface;
+use shirabe_php_shim::{PhpMixed, impl_php_class};
+use std::ops::{Deref, DerefMut};
+
+/// HelpCommand displays the help for a given command.
+#[derive(Debug)]
+pub struct HelpCommand {
+ inner: CommandData,
+ command: std::cell::RefCell<Option<std::rc::Rc<std::cell::RefCell<dyn Command>>>>,
+}
+
+impl_php_class!(
+ HelpCommand,
+ r"Symfony\Component\Console\Command\HelpCommand"
+);
+
+impl Deref for HelpCommand {
+ type Target = CommandData;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl DerefMut for HelpCommand {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+}
+
+impl Default for HelpCommand {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl HelpCommand {
+ pub fn new() -> Self {
+ let command = HelpCommand {
+ inner: CommandData::new(None),
+ command: std::cell::RefCell::new(None),
+ };
+ command
+ .configure()
+ .expect("HelpCommand::configure uses static, valid metadata");
+ command
+ }
+
+ pub fn set_command(&self, command: std::rc::Rc<std::cell::RefCell<dyn Command>>) {
+ *self.command.borrow_mut() = Some(command);
+ }
+
+ pub fn complete_impl(&self, input: &CompletionInput, suggestions: &mut CompletionSuggestions) {
+ if input.must_suggest_argument_values_for("command_name") {
+ let application = self.get_application().unwrap();
+ let mut descriptor = ApplicationDescription::new(application, None, false);
+ suggestions.suggest_values(
+ descriptor
+ .get_commands()
+ .keys()
+ .cloned()
+ .map(StringOrSuggestion::String)
+ .collect(),
+ );
+
+ return;
+ }
+
+ if input.must_suggest_option_values_for("format") {
+ let helper = DescriptorHelper::new();
+ suggestions.suggest_values(
+ helper
+ .get_formats()
+ .into_iter()
+ .map(StringOrSuggestion::String)
+ .collect(),
+ );
+ }
+ }
+}
+
+impl Command for HelpCommand {
+ fn configure(&self) -> anyhow::Result<()> {
+ self.inner.ignore_validation_errors();
+
+ self.inner.set_name("help")?;
+ self.inner.set_definition(SetDefinitionArg::Array(vec![
+ DefinitionItem::InputArgument(InputArgument::new(
+ "command_name".to_string(),
+ Some(InputArgument::OPTIONAL),
+ "The command name".to_string(),
+ PhpMixed::from("help".to_string()),
+ )?),
+ DefinitionItem::InputOption(InputOption::new(
+ "format",
+ PhpMixed::Null,
+ Some(InputOption::VALUE_REQUIRED),
+ "The output format (txt, xml, json, or md)".to_string(),
+ PhpMixed::from("txt".to_string()),
+ )?),
+ DefinitionItem::InputOption(InputOption::new(
+ "raw",
+ PhpMixed::Null,
+ Some(InputOption::VALUE_NONE),
+ "To output raw command help".to_string(),
+ PhpMixed::Null,
+ )?),
+ ]));
+ self.inner.set_description("Display help for a command");
+ self.inner.set_help(
+ "The <info>%command.name%</info> command displays help for a given command:\n\
+ \n\
+ \x20\x20<info>%command.full_name% list</info>\n\
+ \n\
+ You can also output the help in other formats by using the <comment>--format</comment> option:\n\
+ \n\
+ \x20\x20<info>%command.full_name% --format=xml list</info>\n\
+ \n\
+ To display the list of available commands, please use the <info>list</info> command.",
+ );
+
+ Ok(())
+ }
+
+ fn execute(
+ &self,
+ input: std::rc::Rc<std::cell::RefCell<dyn InputInterface>>,
+ output: std::rc::Rc<std::cell::RefCell<dyn OutputInterface>>,
+ ) -> anyhow::Result<i64> {
+ if self.command.borrow().is_none() {
+ let application = self.get_application().unwrap();
+ let command_name = input.borrow().get_argument("command_name")?.to_string();
+ let found = application.borrow_mut().find(&command_name)?;
+ *self.command.borrow_mut() = Some(found);
+ }
+
+ let mut helper = DescriptorHelper::new();
+ let object = DescribableObject::Command(self.command.borrow().clone().unwrap());
+ let mut options = indexmap::IndexMap::new();
+ options.insert("format".to_string(), input.borrow().get_option("format")?);
+ options.insert("raw_text".to_string(), input.borrow().get_option("raw")?);
+ helper.describe2(output.clone(), object, options)?;
+
+ *self.command.borrow_mut() = None;
+
+ Ok(0)
+ }
+
+ fn complete(
+ &self,
+ input: &CompletionInput,
+ suggestions: &mut CompletionSuggestions,
+ ) -> anyhow::Result<()> {
+ self.complete_impl(input, suggestions);
+ Ok(())
+ }
+
+ crate::delegate_command_trait_impls_to_inner!(inner);
+}