diff --git a/crates/nu-command/src/filters/uniq.rs b/crates/nu-command/src/filters/uniq.rs index 1734b4dc10..7d71d868f0 100644 --- a/crates/nu-command/src/filters/uniq.rs +++ b/crates/nu-command/src/filters/uniq.rs @@ -215,7 +215,7 @@ fn sort_attributes(val: Value) -> Value { fn generate_key(item: &ValueCounter) -> Result { let value = sort_attributes(item.val_to_compare.clone()); //otherwise, keys could be different for Records - nuon::to_nuon(&value, true, None, None, Some(Span::unknown())) + nuon::to_nuon(&value, nuon::ToStyle::Raw, Some(Span::unknown())) } fn generate_results_with_count(head: Span, uniq_values: Vec) -> Vec { diff --git a/crates/nu-command/src/formats/to/nuon.rs b/crates/nu-command/src/formats/to/nuon.rs index 6352ade30a..e747ac58f6 100644 --- a/crates/nu-command/src/formats/to/nuon.rs +++ b/crates/nu-command/src/formats/to/nuon.rs @@ -42,14 +42,20 @@ impl Command for ToNuon { call: &Call, input: PipelineData, ) -> Result { - let raw = call.has_flag(engine_state, stack, "raw")?; - let tabs: Option = call.get_flag(engine_state, stack, "tabs")?; - let indent: Option = call.get_flag(engine_state, stack, "indent")?; + let style = if call.has_flag(engine_state, stack, "raw")? { + nuon::ToStyle::Raw + } else if let Some(t) = call.get_flag(engine_state, stack, "tabs")? { + nuon::ToStyle::Tabs(t) + } else if let Some(i) = call.get_flag(engine_state, stack, "indent")? { + nuon::ToStyle::Spaces(i) + } else { + nuon::ToStyle::Raw + }; let span = call.head; let value = input.into_value(span); - match nuon::to_nuon(&value, raw, tabs, indent, Some(span)) { + match nuon::to_nuon(&value, style, Some(span)) { Ok(serde_nuon_string) => { Ok(Value::string(serde_nuon_string, span).into_pipeline_data()) } diff --git a/crates/nu-command/tests/commands/database/into_sqlite.rs b/crates/nu-command/tests/commands/database/into_sqlite.rs index e30d7d2f8f..6c25be1f9a 100644 --- a/crates/nu-command/tests/commands/database/into_sqlite.rs +++ b/crates/nu-command/tests/commands/database/into_sqlite.rs @@ -330,7 +330,7 @@ fn into_sqlite_big_insert() { ) .unwrap(); - let nuon = nuon::to_nuon(&value, true, None, None, Some(Span::unknown())).unwrap() + let nuon = nuon::to_nuon(&value, nuon::ToStyle::Raw, Some(Span::unknown())).unwrap() + &line_ending(); nuon_file.write_all(nuon.as_bytes()).unwrap(); diff --git a/crates/nuon/src/lib.rs b/crates/nuon/src/lib.rs index 60817ca2d8..22153a174f 100644 --- a/crates/nuon/src/lib.rs +++ b/crates/nuon/src/lib.rs @@ -9,13 +9,14 @@ mod to; pub use from::from_nuon; pub use to::to_nuon; +pub use to::ToStyle; #[cfg(test)] mod tests { use chrono::DateTime; use nu_protocol::{ast::RangeInclusion, engine::Closure, record, IntRange, Range, Span, Value}; - use crate::{from_nuon, to_nuon}; + use crate::{from_nuon, to_nuon, ToStyle}; /// test something of the form /// ```nushell @@ -29,7 +30,7 @@ mod tests { if let Some(m) = middle { assert_eq!(val, m); } - assert_eq!(to_nuon(&val, true, None, None, None).unwrap(), input); + assert_eq!(to_nuon(&val, ToStyle::Raw, None).unwrap(), input); } #[test] @@ -178,9 +179,7 @@ mod tests { block_id: 0, captures: vec![] }), - true, - None, - None, + ToStyle::Raw, None, ) .unwrap_err() @@ -199,14 +198,7 @@ mod tests { #[test] fn binary_roundtrip() { assert_eq!( - to_nuon( - &from_nuon("0x[1f ff]", None).unwrap(), - true, - None, - None, - None - ) - .unwrap(), + to_nuon(&from_nuon("0x[1f ff]", None).unwrap(), ToStyle::Raw, None).unwrap(), "0x[1FFF]" ); } @@ -247,7 +239,7 @@ mod tests { #[test] fn float_doesnt_become_int() { assert_eq!( - to_nuon(&Value::test_float(1.0), true, None, None, None).unwrap(), + to_nuon(&Value::test_float(1.0), ToStyle::Raw, None).unwrap(), "1.0" ); } @@ -255,7 +247,7 @@ mod tests { #[test] fn float_inf_parsed_properly() { assert_eq!( - to_nuon(&Value::test_float(f64::INFINITY), true, None, None, None).unwrap(), + to_nuon(&Value::test_float(f64::INFINITY), ToStyle::Raw, None).unwrap(), "inf" ); } @@ -263,14 +255,7 @@ mod tests { #[test] fn float_neg_inf_parsed_properly() { assert_eq!( - to_nuon( - &Value::test_float(f64::NEG_INFINITY), - true, - None, - None, - None - ) - .unwrap(), + to_nuon(&Value::test_float(f64::NEG_INFINITY), ToStyle::Raw, None).unwrap(), "-inf" ); } @@ -278,7 +263,7 @@ mod tests { #[test] fn float_nan_parsed_properly() { assert_eq!( - to_nuon(&Value::test_float(-f64::NAN), true, None, None, None).unwrap(), + to_nuon(&Value::test_float(-f64::NAN), ToStyle::Raw, None).unwrap(), "NaN" ); } @@ -299,9 +284,7 @@ mod tests { "c d" => Value::test_int(6) )) ]), - true, - None, - None, + ToStyle::Raw, None ) .unwrap(), @@ -312,7 +295,7 @@ mod tests { #[test] fn to_nuon_quotes_empty_string() { - let res = to_nuon(&Value::test_string(""), true, None, None, None); + let res = to_nuon(&Value::test_string(""), ToStyle::Raw, None); assert!(res.is_ok()); assert_eq!(res.unwrap(), r#""""#); } @@ -358,9 +341,7 @@ mod tests { "c d" => Value::test_int(6) )) ]), - true, - None, - None, + ToStyle::Raw, None ) .unwrap(), @@ -373,9 +354,7 @@ mod tests { "ro name" => Value::test_string("sam"), "rank" => Value::test_int(10) )), - true, - None, - None, + ToStyle::Raw, None ) .unwrap(), diff --git a/crates/nuon/src/to.rs b/crates/nuon/src/to.rs index 39c89fb0a5..cf1098e768 100644 --- a/crates/nuon/src/to.rs +++ b/crates/nuon/src/to.rs @@ -8,39 +8,54 @@ use nu_protocol::{Range, ShellError, Span, Value}; use std::ops::Bound; +/// control the way Nushell [`Value`] is converted to NUON data +pub enum ToStyle { + /// no indentation at all + /// + /// `{ a: 1, b: 2 }` will be converted to `{: 1, b: 2}` + Raw, + #[allow(clippy::tabs_in_doc_comments)] + /// tabulation-based indentation + /// + /// using 2 as the variant value, `{ a: 1, b: 2 }` will be converted to + /// ```text + /// { + /// a: 1, + /// b: 2 + /// } + /// ``` + Tabs(usize), + /// space-based indentation + /// + /// using 3 as the variant value, `{ a: 1, b: 2 }` will be converted to + /// ```text + /// { + /// a: 1, + /// b: 2 + /// } + /// ``` + Spaces(usize), +} + /// convert an actual Nushell [`Value`] to a raw string representation of the NUON data /// -/// ## Arguments -/// - `tabs` and `indent` control the level of indentation, expressed in _tabulations_ and _spaces_ -/// respectively. `tabs` has higher precedence over `indent`. -/// - `raw` has the highest precedence and will for the output to be _raw_, i.e. the [`Value`] will -/// be _serialized_ on a single line, without extra whitespaces. -/// /// > **Note** /// > a [`Span`] can be passed to [`to_nuon`] if there is context available to the caller, e.g. when /// > using this function in a command implementation such as [`to nuon`](https://www.nushell.sh/commands/docs/to_nuon.html). /// /// also see [`super::from_nuon`] for the inverse operation -pub fn to_nuon( - input: &Value, - raw: bool, - tabs: Option, - indent: Option, - span: Option, -) -> Result { +pub fn to_nuon(input: &Value, style: ToStyle, span: Option) -> Result { let span = span.unwrap_or(Span::unknown()); - let nuon_result = if raw { - value_to_string(input, span, 0, None)? - } else if let Some(tab_count) = tabs { - value_to_string(input, span, 0, Some(&"\t".repeat(tab_count)))? - } else if let Some(indent) = indent { - value_to_string(input, span, 0, Some(&" ".repeat(indent)))? - } else { - value_to_string(input, span, 0, None)? + let indentation = match style { + ToStyle::Raw => None, + ToStyle::Tabs(t) => Some("\t".repeat(t)), + ToStyle::Spaces(s) => Some(" ".repeat(s)), }; - Ok(nuon_result) + let res = value_to_string(input, span, 0, indentation.as_deref())?; + + Ok(res) } fn value_to_string(