Skip to content

Commit 1cc9b24

Browse files
committed
fix: correct shell quotes for Unicode on Windows (#2285)
1 parent c41f2e2 commit 1cc9b24

1 file changed

Lines changed: 16 additions & 14 deletions

File tree

yazi-shared/src/shell/windows.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use std::{borrow::Cow, iter::repeat};
1+
use std::{borrow::Cow, iter::repeat_n};
22

33
pub fn escape_str(s: &str) -> Cow<str> {
44
let bytes = s.as_bytes();
55
if !bytes.is_empty() && !bytes.iter().any(|&c| matches!(c, b' ' | b'"' | b'\n' | b'\t')) {
66
return Cow::Borrowed(s);
77
}
88

9-
let mut escaped = String::with_capacity(bytes.len() + 2);
10-
escaped.push('"');
9+
let mut escaped = Vec::with_capacity(bytes.len() + 2);
10+
escaped.push(b'"');
1111

1212
let mut chars = bytes.iter().copied().peekable();
1313
loop {
@@ -18,24 +18,24 @@ pub fn escape_str(s: &str) -> Cow<str> {
1818
match chars.next() {
1919
Some(b'"') => {
2020
escaped.reserve(slashes * 2 + 2);
21-
escaped.extend(repeat('\\').take(slashes * 2 + 1));
22-
escaped.push('"');
21+
escaped.extend(repeat_n(b'\\', slashes * 2 + 1));
22+
escaped.push(b'"');
2323
}
24-
Some(c) => {
24+
Some(b) => {
2525
escaped.reserve(slashes + 1);
26-
escaped.extend(repeat('\\').take(slashes));
27-
escaped.push(c as _);
26+
escaped.extend(repeat_n(b'\\', slashes));
27+
escaped.push(b);
2828
}
2929
None => {
3030
escaped.reserve(slashes * 2);
31-
escaped.extend(repeat('\\').take(slashes * 2));
31+
escaped.extend(repeat_n(b'\\', slashes * 2));
3232
break;
3333
}
3434
}
3535
}
3636

37-
escaped.push('"');
38-
escaped.into()
37+
escaped.push(b'"');
38+
Cow::Owned(unsafe { String::from_utf8_unchecked(escaped) })
3939
}
4040

4141
#[cfg(windows)]
@@ -59,17 +59,17 @@ pub fn escape_os_str(s: &std::ffi::OsStr) -> Cow<std::ffi::OsStr> {
5959
match chars.next() {
6060
Some(c) if c == b'"' as _ => {
6161
escaped.reserve(slashes * 2 + 2);
62-
escaped.extend(repeat(b'\\' as u16).take(slashes * 2 + 1));
62+
escaped.extend(repeat_n(b'\\' as u16, slashes * 2 + 1));
6363
escaped.push(b'"' as _);
6464
}
6565
Some(c) => {
6666
escaped.reserve(slashes + 1);
67-
escaped.extend(repeat(b'\\' as u16).take(slashes));
67+
escaped.extend(repeat_n(b'\\' as u16, slashes));
6868
escaped.push(c);
6969
}
7070
None => {
7171
escaped.reserve(slashes * 2);
72-
escaped.extend(repeat(b'\\' as u16).take(slashes * 2));
72+
escaped.extend(repeat_n(b'\\' as u16, slashes * 2));
7373
break;
7474
}
7575
}
@@ -137,6 +137,8 @@ mod tests {
137137
assert_eq!(escape_str(r#"--features="default""#), r#""--features=\"default\"""#);
138138
assert_eq!(escape_str(r#""--features=\"default\"""#), r#""\"--features=\\\"default\\\"\"""#);
139139
assert_eq!(escape_str("linker=gcc -L/foo -Wl,bar"), r#""linker=gcc -L/foo -Wl,bar""#);
140+
141+
assert_eq!(escape_str("이것은 테스트"), r#""이것은 테스트""#);
140142
}
141143

142144
#[cfg(windows)]

0 commit comments

Comments
 (0)