1use nu_utils::escape_quote_string;
2
3fn string_should_be_quoted(input: &str) -> bool {
4 input.is_empty()
5 || input.starts_with('$')
6 || input.chars().any(|c| {
7 c.is_whitespace()
8 || c == '('
9 || c == '['
10 || c == '{'
11 || c == '}'
12 || c == '\''
13 || c == '`'
14 || c == '"'
15 || c == '\\'
16 || c == ';'
17 || c == '|'
18 || c == '#'
22 })
23}
24
25pub fn escape_for_script_arg(input: &str) -> String {
33 if input.starts_with("--") {
35 if let Some((arg_name, arg_val)) = input.split_once('=') {
36 let arg_val = if string_should_be_quoted(arg_val) {
38 escape_quote_string(arg_val)
39 } else {
40 arg_val.into()
41 };
42
43 return format!("{arg_name}={arg_val}");
44 } else {
45 return input.into();
46 }
47 }
48 if string_should_be_quoted(input) {
49 escape_quote_string(input)
50 } else {
51 input.into()
52 }
53}
54
55#[cfg(test)]
56mod test {
57 use super::escape_for_script_arg;
58
59 #[test]
60 fn test_not_extra_quote() {
61 assert_eq!(escape_for_script_arg("word"), "word".to_string());
64 assert_eq!(escape_for_script_arg("8"), "8".to_string());
65 }
66
67 #[test]
68 fn test_quote_special() {
69 let cases = vec![
70 ("two words", r#""two words""#),
71 ("$nake", r#""$nake""#),
72 ("`123", r#""`123""#),
73 ("this|cat", r#""this|cat""#),
74 ("this;cat", r#""this;cat""#),
75 ("#000000", r##""#000000""##),
77 ("#", r##""#""##),
78 ("foo#bar", r##""foo#bar""##),
79 ];
80
81 for (input, expected) in cases {
82 assert_eq!(escape_for_script_arg(input).as_str(), expected);
83 }
84 }
85
86 #[test]
87 fn test_flag_value_with_hash() {
88 assert_eq!(
89 escape_for_script_arg("--color=#000000"),
90 r##"--color="#000000""##.to_string()
91 );
92 }
93
94 #[test]
95 fn test_quote_newline() {
96 assert_eq!(escape_for_script_arg("c\nd"), format!("\"c\nd\""));
97 }
98
99 #[test]
100 fn test_arg_with_flag() {
101 assert_eq!(escape_for_script_arg("--linux"), "--linux".to_string());
104 assert_eq!(
105 escape_for_script_arg("--version=v5.2"),
106 "--version=v5.2".to_string()
107 );
108
109 assert_eq!(escape_for_script_arg("--version"), "--version".to_string());
112 assert_eq!(escape_for_script_arg("v5.2"), "v5.2".to_string());
113 }
114
115 #[test]
116 fn test_flag_arg_with_values_contains_special() {
117 assert_eq!(
120 escape_for_script_arg("--version='xx yy'"),
121 r#"--version="'xx yy'""#.to_string()
122 );
123 assert_eq!(
124 escape_for_script_arg("--separator=`"),
125 r#"--separator="`""#.to_string()
126 );
127 }
128
129 #[test]
130 fn test_escape() {
131 assert_eq!(escape_for_script_arg(r"\"), r#""\\""#.to_string());
134 assert_eq!(
135 escape_for_script_arg(r#"--arg=""#),
136 r#"--arg="\"""#.to_string()
137 );
138 }
139}