fix: escape "${"

This commit is contained in:
2026-01-31 17:02:11 +08:00
parent 1aba28d97b
commit db64763d77

View File

@@ -35,7 +35,7 @@ impl Display for Symbol {
if self.normal() { if self.normal() {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} else { } else {
write!(f, r#""{}""#, self.0) write!(f, "{}", escape_quote_string(&self.0))
} }
} }
} }
@@ -221,6 +221,25 @@ pub enum Value {
Repeated, Repeated,
} }
fn escape_quote_string(s: &str) -> String {
let mut ret = String::with_capacity(s.len() + 2);
ret.push('"');
let mut iter = s.chars().peekable();
while let Some(c) = iter.next() {
match c {
'\\' => ret.push_str("\\\\"),
'"' => ret.push_str("\\\""),
'\n' => ret.push_str("\\n"),
'\r' => ret.push_str("\\r"),
'\t' => ret.push_str("\\t"),
'$' if iter.peek() == Some(&'{') => ret.push_str("\\$"),
c => ret.push(c),
}
}
ret.push('"');
ret
}
impl Display for Value { impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
use Value::*; use Value::*;
@@ -229,20 +248,7 @@ impl Display for Value {
&Float(x) => write!(f, "{x}"), &Float(x) => write!(f, "{x}"),
&Bool(x) => write!(f, "{x}"), &Bool(x) => write!(f, "{x}"),
Null => write!(f, "null"), Null => write!(f, "null"),
String(x) => { String(x) => write!(f, "{}", escape_quote_string(x)),
write!(f, "\"")?;
for c in x.chars() {
match c {
'\\' => write!(f, "\\\\")?,
'"' => write!(f, "\\\"")?,
'\n' => write!(f, "\\n")?,
'\r' => write!(f, "\\r")?,
'\t' => write!(f, "\\t")?,
c => write!(f, "{c}")?,
}
}
write!(f, "\"")
}
Path(x) => write!(f, "{x}"), Path(x) => write!(f, "{x}"),
AttrSet(x) => write!(f, "{x}"), AttrSet(x) => write!(f, "{x}"),
List(x) => write!(f, "{x}"), List(x) => write!(f, "{x}"),
@@ -271,20 +277,7 @@ impl Display for ValueCompatDisplay<'_> {
&Float(x) => write!(f, "{x}"), &Float(x) => write!(f, "{x}"),
&Bool(x) => write!(f, "{x}"), &Bool(x) => write!(f, "{x}"),
Null => write!(f, "null"), Null => write!(f, "null"),
String(x) => { String(x) => write!(f, "{}", escape_quote_string(x)),
write!(f, "\"")?;
for c in x.chars() {
match c {
'\\' => write!(f, "\\\\")?,
'"' => write!(f, "\\\"")?,
'\n' => write!(f, "\\n")?,
'\r' => write!(f, "\\r")?,
'\t' => write!(f, "\\t")?,
c => write!(f, "{c}")?,
}
}
write!(f, "\"")
}
Path(x) => write!(f, "{x}"), Path(x) => write!(f, "{x}"),
AttrSet(x) => write!(f, "{}", x.display_compat()), AttrSet(x) => write!(f, "{}", x.display_compat()),
List(x) => write!(f, "{}", x.display_compat()), List(x) => write!(f, "{}", x.display_compat()),