mirror of
https://github.com/nushell/nushell.git
synced 2025-01-11 08:48:23 +01:00
allow Range to expand to array-like when converting to json (#8047)
# Description Fixes #8002, which expands ranges `1..3` to expand to array-like when saving and converting to json. Now, ``` > 1..3 | save foo.json # foo.json [ 1, 2, 3 ] > 1..3 | to json [ 1, 2, 3 ] ``` # User-Facing Changes _(List of all changes that impact the user experience here. This helps us keep track of breaking changes.)_ # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - [X] `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - [X] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - [X] `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
parent
253b223e65
commit
42f0b55de0
@ -48,6 +48,8 @@ impl Command for ToJson {
|
||||
let use_tabs = call.has_flag("tabs");
|
||||
|
||||
let span = call.head;
|
||||
// allow ranges to expand and turn into array
|
||||
let input = input.try_expand_range()?;
|
||||
let value = input.into_value(span);
|
||||
let json_value = value_to_json_value(&value)?;
|
||||
|
||||
|
@ -34,6 +34,7 @@ impl Command for ToNuon {
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let input = input.try_expand_range()?;
|
||||
Ok(Value::String {
|
||||
val: to_nuon(call, input)?,
|
||||
span: call.head,
|
||||
|
@ -39,6 +39,7 @@ impl Command for ToText {
|
||||
} else {
|
||||
"\n"
|
||||
};
|
||||
let input = input.try_expand_range()?;
|
||||
|
||||
if let PipelineData::ListStream(stream, _) = input {
|
||||
Ok(PipelineData::ExternalStream {
|
||||
|
@ -64,6 +64,7 @@ impl Command for ToXml {
|
||||
let head = call.head;
|
||||
let config = engine_state.get_config();
|
||||
let pretty: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "pretty")?;
|
||||
let input = input.try_expand_range()?;
|
||||
to_xml(input, head, pretty, config)
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ impl Command for ToYaml {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
let input = input.try_expand_range()?;
|
||||
to_yaml(input, head)
|
||||
}
|
||||
}
|
||||
|
@ -283,3 +283,21 @@ fn save_list_stream() {
|
||||
assert_eq!(actual, "a\nb\nc\nd\n")
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn writes_out_range() {
|
||||
Playground::setup("save_test_14", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![]);
|
||||
|
||||
let expected_file = dirs.test().join("list_sample.json");
|
||||
|
||||
nu!(
|
||||
cwd: dirs.root(),
|
||||
r#"1..3 | save save_test_14/list_sample.json"#,
|
||||
);
|
||||
|
||||
let actual = file_contents(expected_file);
|
||||
println!("{actual}");
|
||||
assert_eq!(actual, "[\n 1,\n 2,\n 3\n]")
|
||||
})
|
||||
}
|
||||
|
@ -108,3 +108,26 @@ fn top_level_values_from_json() {
|
||||
assert_eq!(actual.out, type_name);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ranges_to_json_as_array() {
|
||||
let value = r#"[ 1, 2, 3]"#;
|
||||
let actual = nu!(r#"1..3 | to json"#);
|
||||
assert_eq!(actual.out, value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unbounded_from_in_range_fails() {
|
||||
let actual = nu!(r#"1.. | to json"#);
|
||||
assert!(actual.err.contains("Cannot create range"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inf_in_range_fails() {
|
||||
let actual = nu!(r#"inf..5 | to json"#);
|
||||
assert!(actual.err.contains("Cannot create range"));
|
||||
let actual = nu!(r#"5..inf | to json"#);
|
||||
assert!(actual.err.contains("Cannot create range"));
|
||||
let actual = nu!(r#"-inf..inf | to json"#);
|
||||
assert!(actual.err.contains("Cannot create range"));
|
||||
}
|
||||
|
@ -604,6 +604,53 @@ impl PipelineData {
|
||||
(self, false)
|
||||
}
|
||||
}
|
||||
/// Try to convert Value from Value::Range to Value::List.
|
||||
/// This is useful to expand Value::Range into array notation, specifically when
|
||||
/// converting `to json` or `to nuon`.
|
||||
/// `1..3 | to XX -> [1,2,3]`
|
||||
pub fn try_expand_range(self) -> Result<PipelineData, ShellError> {
|
||||
let input = match self {
|
||||
PipelineData::Value(Value::Range { val, span }, ..) => {
|
||||
match (&val.to, &val.from) {
|
||||
(Value::Float { val, .. }, _) | (_, Value::Float { val, .. }) => {
|
||||
if *val == f64::INFINITY || *val == f64::NEG_INFINITY {
|
||||
return Err(ShellError::GenericError(
|
||||
"Cannot create range".into(),
|
||||
"Infinity is not allowed when converting to json".into(),
|
||||
Some(span),
|
||||
Some("Consider removing infinity".into()),
|
||||
vec![],
|
||||
));
|
||||
}
|
||||
}
|
||||
(Value::Int { val, span }, _) => {
|
||||
if *val == i64::MAX || *val == i64::MIN {
|
||||
return Err(ShellError::GenericError(
|
||||
"Cannot create range".into(),
|
||||
"Unbounded ranges are not allowed when converting to json".into(),
|
||||
Some(*span),
|
||||
Some(
|
||||
"Consider using ranges with valid start and end point.".into(),
|
||||
),
|
||||
vec![],
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
let range_values: Vec<Value> = val.into_range_iter(None)?.collect();
|
||||
PipelineData::Value(
|
||||
Value::List {
|
||||
vals: range_values,
|
||||
span,
|
||||
},
|
||||
None,
|
||||
)
|
||||
}
|
||||
_ => self,
|
||||
};
|
||||
Ok(input)
|
||||
}
|
||||
|
||||
/// Consume and print self data immediately.
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user