perl_dap/command_args/
mod.rs1#[must_use]
5pub fn format_command_args(args: &[String]) -> Vec<String> {
6 args.iter()
7 .map(|arg| {
8 if arg.is_empty() || arg.chars().any(char::is_whitespace) {
9 #[cfg(windows)]
10 {
11 format!("\"{}\"", arg.replace('"', "\\\""))
12 }
13 #[cfg(not(windows))]
14 {
15 if arg.contains('\'') {
16 format!("\"{}\"", arg.replace('"', "\\\""))
17 } else {
18 format!("'{}'", arg)
19 }
20 }
21 } else {
22 arg.clone()
23 }
24 })
25 .collect()
26}
27
28#[cfg(test)]
29mod tests {
30 use super::format_command_args;
31
32 #[test]
33 fn leaves_simple_args_unmodified() {
34 let args = vec!["plain".to_string(), "--flag".to_string()];
35 let formatted = format_command_args(&args);
36 assert_eq!(formatted, args);
37 }
38
39 #[test]
40 fn quotes_args_with_spaces() {
41 let args = vec!["file with spaces.txt".to_string()];
42 let formatted = format_command_args(&args);
43 assert_eq!(formatted.len(), 1);
44 assert!(formatted[0].contains("file with spaces.txt"));
45 assert_ne!(formatted[0], "file with spaces.txt");
46 }
47
48 #[test]
49 fn empty_slice_returns_empty_vec() {
50 let args: Vec<String> = vec![];
51 let formatted = format_command_args(&args);
52 assert!(formatted.is_empty());
53 }
54
55 #[test]
56 fn empty_arg_is_preserved_via_quotes() {
57 let args = vec![String::new()];
58 let formatted = format_command_args(&args);
59 assert_eq!(formatted.len(), 1);
60 #[cfg(windows)]
61 assert_eq!(formatted[0], "\"\"");
62 #[cfg(not(windows))]
63 assert_eq!(formatted[0], "''");
64 }
65
66 #[cfg(not(windows))]
67 #[test]
68 fn double_quote_escapes_arg_with_space_and_single_quote() {
69 let args = vec!["it's a file".to_string()];
72 let formatted = format_command_args(&args);
73 assert_eq!(formatted.len(), 1);
74 assert!(
76 formatted[0].starts_with('"'),
77 "expected double-quote prefix, got: {}",
78 formatted[0]
79 );
80 assert!(formatted[0].ends_with('"'), "expected double-quote suffix, got: {}", formatted[0]);
81 assert!(
83 formatted[0].contains("it's a file"),
84 "original text not found in: {}",
85 formatted[0]
86 );
87 }
88
89 #[cfg(not(windows))]
90 #[test]
91 fn mixed_args_are_each_handled_independently() {
92 let args = vec![
93 "plain".to_string(), "has spaces".to_string(), "it's here now".to_string(), ];
97 let formatted = format_command_args(&args);
98 assert_eq!(formatted.len(), 3);
99
100 assert_eq!(formatted[0], "plain");
102
103 assert_eq!(formatted[1], "'has spaces'");
105
106 assert!(
108 formatted[2].starts_with('"'),
109 "expected double-quote prefix, got: {}",
110 formatted[2]
111 );
112 assert!(formatted[2].ends_with('"'), "expected double-quote suffix, got: {}", formatted[2]);
113 assert!(
114 formatted[2].contains("it's here now"),
115 "original text not found in: {}",
116 formatted[2]
117 );
118 }
119}