Stream lazy default output (#15955)

It was brought up in the Discord that `default { open -r foo.txt }`
results in a string instead of streaming output. This changes `default`
such that closures now stream when given simple input.

# Description
If the value isn't expected to be cached, `default` just runs the
closure without caching the value, which allows its output to be
streamed

# User-Facing Changes


# Tests + Formatting
👍 

# After Submitting
This commit is contained in:
Firegem
2025-06-24 19:17:33 -04:00
committed by GitHub
parent a6b8e2f95c
commit cb7ac9199d
2 changed files with 16 additions and 4 deletions

View File

@ -213,7 +213,7 @@ fn default(
|| (default_when_empty
&& matches!(input, PipelineData::Value(ref value, _) if value.is_empty()))
{
default_value.pipeline_data()
default_value.single_run_pipeline_data()
} else if default_when_empty && matches!(input, PipelineData::ListStream(..)) {
let PipelineData::ListStream(ls, metadata) = input else {
unreachable!()
@ -221,7 +221,7 @@ fn default(
let span = ls.span();
let mut stream = ls.into_inner().peekable();
if stream.peek().is_none() {
return default_value.pipeline_data();
return default_value.single_run_pipeline_data();
}
// stream's internal state already preserves the original signals config, so if this
@ -278,8 +278,14 @@ impl DefaultValue {
}
}
fn pipeline_data(&mut self) -> Result<PipelineData, ShellError> {
self.value().map(|x| x.into_pipeline_data())
/// Used when we know the value won't need to be cached to allow streaming.
fn single_run_pipeline_data(self) -> Result<PipelineData, ShellError> {
match self {
DefaultValue::Uncalculated(mut closure) => {
closure.item.run_with_input(PipelineData::Empty)
}
DefaultValue::Calculated(val) => Ok(val.into_pipeline_data()),
}
}
}

View File

@ -244,3 +244,9 @@ fn return_closure_value() {
let actual = nu!(r#"null | default { {||} }"#);
assert!(actual.out.starts_with("closure"));
}
#[test]
fn lazy_output_streams() {
let actual = nu!(r#"default { nu --testbin cococo 'hello' } | describe"#);
assert!(actual.out.contains("byte stream"));
}