mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 08:23:24 +01:00
add "to nuon" enumeration of possible styles (#12591)
# Description
in order to change the style of the _serialized_ NUON data,
`nuon::to_nuon` takes three mutually exclusive arguments, `raw: bool`,
`tabs: Option<usize>` and `indent: Option<usize>` 🤔
this begs to use an enumeration with all possible alternatives, right?
this PR changes the signature of `nuon::to_nuon` to use `nuon::ToStyle`
which has three variants
- `Raw`: no newlines
- `Tabs(n: usize)`: newlines and `n` tabulations as indent
- `Spaces(n: usize)`: newlines and `n` spaces as indent
# User-Facing Changes
the signature of `nuon::to_nuon` changes from
```rust
to_nuon(
input: &Value,
raw: bool,
tabs: Option<usize>,
indent: Option<usize>,
span: Option<Span>,
) -> Result<String, ShellError>
```
to
```rust
to_nuon(
input: &Value,
style: ToStyle,
span: Option<Span>
) -> Result<String, ShellError>
```
# Tests + Formatting
# After Submitting
This commit is contained in:
parent
187b87c61c
commit
be5ed3290c
@ -215,7 +215,7 @@ fn sort_attributes(val: Value) -> Value {
|
|||||||
|
|
||||||
fn generate_key(item: &ValueCounter) -> Result<String, ShellError> {
|
fn generate_key(item: &ValueCounter) -> Result<String, ShellError> {
|
||||||
let value = sort_attributes(item.val_to_compare.clone()); //otherwise, keys could be different for Records
|
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<ValueCounter>) -> Vec<Value> {
|
fn generate_results_with_count(head: Span, uniq_values: Vec<ValueCounter>) -> Vec<Value> {
|
||||||
|
@ -42,14 +42,20 @@ impl Command for ToNuon {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let raw = call.has_flag(engine_state, stack, "raw")?;
|
let style = if call.has_flag(engine_state, stack, "raw")? {
|
||||||
let tabs: Option<usize> = call.get_flag(engine_state, stack, "tabs")?;
|
nuon::ToStyle::Raw
|
||||||
let indent: Option<usize> = call.get_flag(engine_state, stack, "indent")?;
|
} 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 span = call.head;
|
||||||
let value = input.into_value(span);
|
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(serde_nuon_string) => {
|
||||||
Ok(Value::string(serde_nuon_string, span).into_pipeline_data())
|
Ok(Value::string(serde_nuon_string, span).into_pipeline_data())
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ fn into_sqlite_big_insert() {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.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();
|
+ &line_ending();
|
||||||
|
|
||||||
nuon_file.write_all(nuon.as_bytes()).unwrap();
|
nuon_file.write_all(nuon.as_bytes()).unwrap();
|
||||||
|
@ -9,13 +9,14 @@ mod to;
|
|||||||
|
|
||||||
pub use from::from_nuon;
|
pub use from::from_nuon;
|
||||||
pub use to::to_nuon;
|
pub use to::to_nuon;
|
||||||
|
pub use to::ToStyle;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use nu_protocol::{ast::RangeInclusion, engine::Closure, record, IntRange, Range, Span, Value};
|
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
|
/// test something of the form
|
||||||
/// ```nushell
|
/// ```nushell
|
||||||
@ -29,7 +30,7 @@ mod tests {
|
|||||||
if let Some(m) = middle {
|
if let Some(m) = middle {
|
||||||
assert_eq!(val, m);
|
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]
|
#[test]
|
||||||
@ -178,9 +179,7 @@ mod tests {
|
|||||||
block_id: 0,
|
block_id: 0,
|
||||||
captures: vec![]
|
captures: vec![]
|
||||||
}),
|
}),
|
||||||
true,
|
ToStyle::Raw,
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
@ -199,14 +198,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn binary_roundtrip() {
|
fn binary_roundtrip() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_nuon(
|
to_nuon(&from_nuon("0x[1f ff]", None).unwrap(), ToStyle::Raw, None).unwrap(),
|
||||||
&from_nuon("0x[1f ff]", None).unwrap(),
|
|
||||||
true,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"0x[1FFF]"
|
"0x[1FFF]"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -247,7 +239,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn float_doesnt_become_int() {
|
fn float_doesnt_become_int() {
|
||||||
assert_eq!(
|
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"
|
"1.0"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -255,7 +247,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn float_inf_parsed_properly() {
|
fn float_inf_parsed_properly() {
|
||||||
assert_eq!(
|
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"
|
"inf"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -263,14 +255,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn float_neg_inf_parsed_properly() {
|
fn float_neg_inf_parsed_properly() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_nuon(
|
to_nuon(&Value::test_float(f64::NEG_INFINITY), ToStyle::Raw, None).unwrap(),
|
||||||
&Value::test_float(f64::NEG_INFINITY),
|
|
||||||
true,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"-inf"
|
"-inf"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -278,7 +263,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn float_nan_parsed_properly() {
|
fn float_nan_parsed_properly() {
|
||||||
assert_eq!(
|
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"
|
"NaN"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -299,9 +284,7 @@ mod tests {
|
|||||||
"c d" => Value::test_int(6)
|
"c d" => Value::test_int(6)
|
||||||
))
|
))
|
||||||
]),
|
]),
|
||||||
true,
|
ToStyle::Raw,
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@ -312,7 +295,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_nuon_quotes_empty_string() {
|
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!(res.is_ok());
|
||||||
assert_eq!(res.unwrap(), r#""""#);
|
assert_eq!(res.unwrap(), r#""""#);
|
||||||
}
|
}
|
||||||
@ -358,9 +341,7 @@ mod tests {
|
|||||||
"c d" => Value::test_int(6)
|
"c d" => Value::test_int(6)
|
||||||
))
|
))
|
||||||
]),
|
]),
|
||||||
true,
|
ToStyle::Raw,
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
@ -373,9 +354,7 @@ mod tests {
|
|||||||
"ro name" => Value::test_string("sam"),
|
"ro name" => Value::test_string("sam"),
|
||||||
"rank" => Value::test_int(10)
|
"rank" => Value::test_int(10)
|
||||||
)),
|
)),
|
||||||
true,
|
ToStyle::Raw,
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -8,39 +8,54 @@ use nu_protocol::{Range, ShellError, Span, Value};
|
|||||||
|
|
||||||
use std::ops::Bound;
|
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
|
/// 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**
|
/// > **Note**
|
||||||
/// > a [`Span`] can be passed to [`to_nuon`] if there is context available to the caller, e.g. when
|
/// > 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).
|
/// > 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
|
/// also see [`super::from_nuon`] for the inverse operation
|
||||||
pub fn to_nuon(
|
pub fn to_nuon(input: &Value, style: ToStyle, span: Option<Span>) -> Result<String, ShellError> {
|
||||||
input: &Value,
|
|
||||||
raw: bool,
|
|
||||||
tabs: Option<usize>,
|
|
||||||
indent: Option<usize>,
|
|
||||||
span: Option<Span>,
|
|
||||||
) -> Result<String, ShellError> {
|
|
||||||
let span = span.unwrap_or(Span::unknown());
|
let span = span.unwrap_or(Span::unknown());
|
||||||
|
|
||||||
let nuon_result = if raw {
|
let indentation = match style {
|
||||||
value_to_string(input, span, 0, None)?
|
ToStyle::Raw => None,
|
||||||
} else if let Some(tab_count) = tabs {
|
ToStyle::Tabs(t) => Some("\t".repeat(t)),
|
||||||
value_to_string(input, span, 0, Some(&"\t".repeat(tab_count)))?
|
ToStyle::Spaces(s) => Some(" ".repeat(s)),
|
||||||
} else if let Some(indent) = indent {
|
|
||||||
value_to_string(input, span, 0, Some(&" ".repeat(indent)))?
|
|
||||||
} else {
|
|
||||||
value_to_string(input, span, 0, None)?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(nuon_result)
|
let res = value_to_string(input, span, 0, indentation.as_deref())?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value_to_string(
|
fn value_to_string(
|
||||||
|
Loading…
Reference in New Issue
Block a user