Skip to main content

moon_task/
task_arg.rs

1use moon_common::cacheable;
2use std::ops::Deref;
3
4cacheable!(
5    #[derive(Clone, Debug, Eq, PartialEq)]
6    #[serde(into = "String", from = "String")]
7    pub struct TaskArg {
8        // For use in sub-shells
9        pub quoted_value: Option<String>,
10
11        // For use in processes
12        pub value: String, // unquoted
13    }
14);
15
16impl TaskArg {
17    pub fn new(base_value: impl AsRef<str>) -> Self {
18        let base_value = base_value.as_ref();
19        let mut is_quoted = false;
20        let mut quoted_value = None;
21        let mut value = String::new();
22
23        // Keep in sync with starbase!
24        for (start, end) in [
25            ("\"", "\""),
26            ("'", "'"),
27            ("$\"", "\""),
28            ("$'", "'"),
29            ("%(", ")"),
30            ("r#'", "'#"),
31        ] {
32            if base_value.starts_with(start) && base_value.ends_with(end) {
33                value.push_str(base_value.trim_start_matches(start).trim_end_matches(end));
34                quoted_value = Some(base_value.to_owned());
35                is_quoted = true;
36                break;
37            }
38        }
39
40        if !is_quoted {
41            value.push_str(base_value);
42        }
43
44        Self {
45            quoted_value,
46            value,
47        }
48    }
49
50    pub fn new_quoted(
51        value_without_quotes: impl AsRef<str>,
52        value_with_quotes: impl AsRef<str>,
53    ) -> Self {
54        Self {
55            quoted_value: Some(value_with_quotes.as_ref().into()),
56            value: value_without_quotes.as_ref().into(),
57        }
58    }
59
60    pub fn new_unquoted(value: impl AsRef<str>) -> Self {
61        Self {
62            quoted_value: None,
63            value: value.as_ref().into(),
64        }
65    }
66
67    pub fn is_empty(&self) -> bool {
68        self.value.is_empty()
69    }
70
71    pub fn is_quoted(&self) -> bool {
72        self.quoted_value.is_some()
73    }
74
75    pub fn get_value(&self) -> &str {
76        self.quoted_value.as_deref().unwrap_or(&self.value)
77    }
78}
79
80impl From<TaskArg> for String {
81    fn from(arg: TaskArg) -> Self {
82        // Preserve quotes when serializing
83        arg.get_value().into()
84    }
85}
86
87impl From<String> for TaskArg {
88    fn from(value: String) -> Self {
89        // Handle quotes when deserializing
90        Self::new(value)
91    }
92}
93
94impl From<&str> for TaskArg {
95    fn from(value: &str) -> Self {
96        // Handle quotes when deserializing
97        Self::new(value)
98    }
99}
100
101impl PartialEq<&str> for TaskArg {
102    fn eq(&self, other: &&str) -> bool {
103        &self.value == other
104    }
105}
106
107impl AsRef<str> for TaskArg {
108    fn as_ref(&self) -> &str {
109        &self.value
110    }
111}
112
113impl Deref for TaskArg {
114    type Target = String;
115
116    fn deref(&self) -> &Self::Target {
117        &self.value
118    }
119}