preserve space by letting to nuon only add quotes when necessary (#6379)

* preserve space by letting `to nuon` only add quotes when necessary

* fix CI, add quotes with colon

* fmt

* add more chars to blacklist
This commit is contained in:
pwygab 2022-08-23 19:51:07 +08:00 committed by GitHub
parent d97975e9fa
commit 884382bac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 4 deletions

View file

@ -104,7 +104,13 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
// Table output
let headers: Vec<String> = headers
.iter()
.map(|string| format!("\"{}\"", string))
.map(|string| {
if needs_quotes(string) {
format!("\"{}\"", string)
} else {
string.to_string()
}
})
.collect();
let headers_output = headers.join(", ");
@ -114,7 +120,7 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
if let Value::Record { vals, .. } = val {
for val in vals {
row.push(value_to_string(val, span)?);
row.push(value_to_string_without_quotes(val, span)?);
}
}
@ -129,7 +135,7 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
} else {
let mut collection = vec![];
for val in vals {
collection.push(value_to_string(val, span)?);
collection.push(value_to_string_without_quotes(val, span)?);
}
Ok(format!("[{}]", collection.join(", ")))
}
@ -148,7 +154,15 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
Value::Record { cols, vals, .. } => {
let mut collection = vec![];
for (col, val) in cols.iter().zip(vals) {
collection.push(format!("\"{}\": {}", col, value_to_string(val, span)?));
collection.push(if needs_quotes(col) {
format!(
"\"{}\": {}",
col,
value_to_string_without_quotes(val, span)?
)
} else {
format!("{}: {}", col, value_to_string_without_quotes(val, span)?)
});
}
Ok(format!("{{{}}}", collection.join(", ")))
}
@ -156,12 +170,39 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
}
}
fn value_to_string_without_quotes(v: &Value, span: Span) -> Result<String, ShellError> {
match v {
Value::String { val, .. } => Ok({
let mut quoted = escape_quote_string(val);
if !needs_quotes(val) {
quoted.remove(0);
quoted.pop();
}
quoted
}),
_ => value_to_string(v, span),
}
}
fn to_nuon(call: &Call, input: PipelineData) -> Result<String, ShellError> {
let v = input.into_value(call.head);
value_to_string(&v, call.head)
}
fn needs_quotes(string: &str) -> bool {
string.contains(' ')
|| string.contains(',')
|| string.contains(':')
|| string.contains(';')
|| string.contains('(')
|| string.contains(')')
|| string.contains('[')
|| string.contains(']')
|| string.contains('{')
|| string.contains('}')
}
#[cfg(test)]
mod test {
#[test]

View file

@ -249,3 +249,21 @@ fn to_nuon_converts_columns_with_spaces() {
));
assert!(actual.err.is_empty());
}
#[test]
fn to_nuon_does_not_quote_unnecessarily() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
let test = [["a", "b", "c d"]; [1 2 3] [4 5 6]]; $test | to nuon
"#
));
assert_eq!(actual.out, "[[a, b, \"c d\"]; [1, 2, 3], [4, 5, 6]]");
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
let a = {"ro name": "sam" rank: 10}; $a | to nuon
"#
));
assert_eq!(actual.out, "{\"ro name\": sam, rank: 10}");
}