aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-12 01:01:35 +0900
committernsfisis <nsfisis@gmail.com>2026-06-12 01:01:43 +0900
commit1e44f5723e4c0e0903d00a61f254901e612fe5e1 (patch)
tree9c2e1eec364bbf6418a4072ee7767b04c3df0297 /crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
parentddf0a624145b618c05c2ee47414545b99b685f37 (diff)
downloadphp-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.tar.gz
php-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.tar.zst
php-shirabe-1e44f5723e4c0e0903d00a61f254901e612fe5e1.zip
feat(symfony-console): port Symfony Console and make the workspace compile
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-external-packages/src/symfony/console/input/input_option.rs')
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/input/input_option.rs194
1 files changed, 178 insertions, 16 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs b/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
index 673ca07..c929d03 100644
--- a/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/input/input_option.rs
@@ -1,7 +1,15 @@
+use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
+use crate::symfony::console::exception::logic_exception::LogicException;
use shirabe_php_shim::PhpMixed;
#[derive(Debug)]
-pub struct InputOption;
+pub struct InputOption {
+ name: String,
+ shortcut: Option<String>,
+ mode: i64,
+ default: PhpMixed,
+ description: String,
+}
impl InputOption {
pub const VALUE_NONE: i64 = 1;
@@ -11,36 +19,190 @@ impl InputOption {
pub const VALUE_NEGATABLE: i64 = 16;
pub fn new(
- _name: &str,
- _shortcut: Option<&str>,
- _mode: Option<i64>,
- _description: &str,
- _default: PhpMixed,
- ) -> Self {
- todo!()
+ name: &str,
+ shortcut: PhpMixed,
+ mode: Option<i64>,
+ description: String,
+ default: PhpMixed,
+ ) -> anyhow::Result<Self> {
+ let name = if name.starts_with("--") {
+ name[2..].to_string()
+ } else {
+ name.to_string()
+ };
+
+ if name.is_empty() {
+ return Err(
+ InvalidArgumentException(shirabe_php_shim::InvalidArgumentException {
+ message: "An option name cannot be empty.".to_string(),
+ code: 0,
+ })
+ .into(),
+ );
+ }
+
+ let shortcut = match shortcut {
+ PhpMixed::String(ref s) if s.is_empty() => None,
+ PhpMixed::List(ref v) if v.is_empty() => None,
+ PhpMixed::Bool(false) => None,
+ PhpMixed::Null => None,
+ PhpMixed::List(ref arr) => {
+ let parts: Vec<String> = arr
+ .iter()
+ .filter_map(|v| {
+ if let PhpMixed::String(s) = v.as_ref() {
+ Some(s.clone())
+ } else {
+ None
+ }
+ })
+ .collect();
+ let joined = shirabe_php_shim::implode("|", &parts);
+ Self::normalize_shortcut(joined)?
+ }
+ PhpMixed::String(s) => Self::normalize_shortcut(s)?,
+ _ => None,
+ };
+
+ let mode = match mode {
+ None => Self::VALUE_NONE,
+ Some(m) if m >= (Self::VALUE_NEGATABLE << 1) || m < 1 => {
+ return Err(
+ InvalidArgumentException(shirabe_php_shim::InvalidArgumentException {
+ message: format!("Option mode \"{}\" is not valid.", m),
+ code: 0,
+ })
+ .into(),
+ );
+ }
+ Some(m) => m,
+ };
+
+ let mut option = InputOption {
+ name,
+ shortcut,
+ mode,
+ description,
+ default: PhpMixed::Null,
+ };
+
+ if option.is_array() && !option.accept_value() {
+ return Err(InvalidArgumentException(shirabe_php_shim::InvalidArgumentException {
+ message: "Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.".to_string(),
+ code: 0,
+ })
+ .into());
+ }
+ if option.is_negatable() && option.accept_value() {
+ return Err(InvalidArgumentException(shirabe_php_shim::InvalidArgumentException {
+ message: "Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.".to_string(),
+ code: 0,
+ })
+ .into());
+ }
+
+ option.set_default(default)?;
+
+ Ok(option)
+ }
+
+ fn normalize_shortcut(s: String) -> anyhow::Result<Option<String>> {
+ let stripped = shirabe_php_shim::ltrim(&s, Some("-"));
+ let parts = shirabe_php_shim::preg_split(r"\|(-?)", &stripped).unwrap_or_default();
+ let filtered: Vec<String> =
+ shirabe_php_shim::array_filter(&parts, |s: &String| !s.is_empty());
+ let result = shirabe_php_shim::implode("|", &filtered);
+ if result.is_empty() {
+ return Err(
+ InvalidArgumentException(shirabe_php_shim::InvalidArgumentException {
+ message: "An option shortcut cannot be empty.".to_string(),
+ code: 0,
+ })
+ .into(),
+ );
+ }
+ Ok(Some(result))
+ }
+
+ pub fn get_shortcut(&self) -> Option<&str> {
+ self.shortcut.as_deref()
}
- pub fn get_name(&self) -> String {
- todo!()
+ pub fn get_name(&self) -> &str {
+ &self.name
}
pub fn accept_value(&self) -> bool {
- todo!()
+ self.is_value_required() || self.is_value_optional()
}
pub fn is_value_required(&self) -> bool {
- todo!()
+ Self::VALUE_REQUIRED == (Self::VALUE_REQUIRED & self.mode)
}
pub fn is_value_optional(&self) -> bool {
- todo!()
+ Self::VALUE_OPTIONAL == (Self::VALUE_OPTIONAL & self.mode)
}
pub fn is_array(&self) -> bool {
- todo!()
+ Self::VALUE_IS_ARRAY == (Self::VALUE_IS_ARRAY & self.mode)
+ }
+
+ pub fn is_negatable(&self) -> bool {
+ Self::VALUE_NEGATABLE == (Self::VALUE_NEGATABLE & self.mode)
+ }
+
+ pub fn set_default(&mut self, default: PhpMixed) -> anyhow::Result<()> {
+ if Self::VALUE_NONE == (Self::VALUE_NONE & self.mode) && !matches!(default, PhpMixed::Null)
+ {
+ return Err(LogicException(shirabe_php_shim::LogicException {
+ message: "Cannot set a default value when using InputOption::VALUE_NONE mode."
+ .to_string(),
+ code: 0,
+ })
+ .into());
+ }
+
+ let default = if self.is_array() {
+ match default {
+ PhpMixed::Null => PhpMixed::List(vec![]),
+ PhpMixed::List(_) => default,
+ _ => {
+ return Err(LogicException(shirabe_php_shim::LogicException {
+ message: "A default value for an array option must be an array."
+ .to_string(),
+ code: 0,
+ })
+ .into());
+ }
+ }
+ } else {
+ default
+ };
+
+ self.default = if self.accept_value() || self.is_negatable() {
+ default
+ } else {
+ PhpMixed::Bool(false)
+ };
+ Ok(())
+ }
+
+ pub fn get_default(&self) -> &PhpMixed {
+ &self.default
+ }
+
+ pub fn get_description(&self) -> &str {
+ &self.description
}
- pub fn get_default(&self) -> PhpMixed {
- todo!()
+ pub fn equals(&self, option: &InputOption) -> bool {
+ option.get_name() == self.get_name()
+ && option.get_shortcut() == self.get_shortcut()
+ && option.get_default() == self.get_default()
+ && option.is_negatable() == self.is_negatable()
+ && option.is_array() == self.is_array()
+ && option.is_value_required() == self.is_value_required()
+ && option.is_value_optional() == self.is_value_optional()
}
}