mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
Make stream info visible to users in describe
(#7589)
Closes #7581. After this PR, `describe` shows `(stream)` next to input that arrived at `describe` as a `ListStream`: ```bash 〉ls | describe table<name: string, type: string, size: filesize, modified: date> (stream) 〉[1 2 3] | each {|i| $i} | describe list<int> (stream) ``` `describe` must collect all items of the stream to display type information for lists and tables. If users need to avoid collecting input, they can use the `-n`/`--no-collect` flag: ```bash 〉[1 2 3] | each {|i| $i} | describe --no-collect stream ```
This commit is contained in:
parent
bdd52f0111
commit
95d4922e44
@ -19,6 +19,11 @@ impl Command for Describe {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("describe")
|
||||
.input_output_types(vec![(Type::Any, Type::String)])
|
||||
.switch(
|
||||
"no-collect",
|
||||
"do not collect streams of structured data",
|
||||
Some('n'),
|
||||
)
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
||||
@ -30,32 +35,58 @@ impl Command for Describe {
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let head = call.head;
|
||||
if matches!(input, PipelineData::ExternalStream { .. }) {
|
||||
Ok(PipelineData::Value(
|
||||
Value::string("raw input", call.head),
|
||||
None,
|
||||
))
|
||||
} else {
|
||||
let value = input.into_value(call.head);
|
||||
let description = match value {
|
||||
Value::CustomValue { val, .. } => val.value_string(),
|
||||
_ => value.get_type().to_string(),
|
||||
};
|
||||
|
||||
Ok(Value::String {
|
||||
val: description,
|
||||
span: head,
|
||||
let no_collect: bool = call.has_flag("no-collect");
|
||||
|
||||
let description = match input {
|
||||
PipelineData::ExternalStream { .. } => "raw input".into(),
|
||||
PipelineData::ListStream(_, _) => {
|
||||
if no_collect {
|
||||
"stream".into()
|
||||
} else {
|
||||
let value = input.into_value(head);
|
||||
let base_description = match value {
|
||||
Value::CustomValue { val, .. } => val.value_string(),
|
||||
_ => value.get_type().to_string(),
|
||||
};
|
||||
|
||||
format!("{base_description} (stream)")
|
||||
}
|
||||
}
|
||||
.into_pipeline_data())
|
||||
_ => {
|
||||
let value = input.into_value(head);
|
||||
match value {
|
||||
Value::CustomValue { val, .. } => val.value_string(),
|
||||
_ => value.get_type().to_string(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Value::String {
|
||||
val: description,
|
||||
span: head,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
description: "Describe the type of a string",
|
||||
example: "'hello' | describe",
|
||||
result: Some(Value::test_string("string")),
|
||||
}]
|
||||
vec![
|
||||
Example {
|
||||
description: "Describe the type of a string",
|
||||
example: "'hello' | describe",
|
||||
result: Some(Value::test_string("string")),
|
||||
},
|
||||
Example {
|
||||
description: "Describe a stream of data, collecting it first",
|
||||
example: "[1 2 3] | each {|i| $i} | describe",
|
||||
result: Some(Value::test_string("list<int> (stream)")),
|
||||
},
|
||||
Example {
|
||||
description: "Describe the input but do not collect streams",
|
||||
example: "[1 2 3] | each {|i| $i} | describe --no-collect",
|
||||
result: Some(Value::test_string("stream")),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
|
@ -13,7 +13,7 @@ mod test_examples {
|
||||
MathRound, Path, Random, Split, SplitColumn, SplitRow, Str, StrJoin, StrLength, StrReplace,
|
||||
Url, Values, Wrap,
|
||||
};
|
||||
use crate::{Break, Mut, To};
|
||||
use crate::{Break, Each, Mut, To};
|
||||
use itertools::Itertools;
|
||||
use nu_protocol::{
|
||||
ast::Block,
|
||||
@ -61,6 +61,7 @@ mod test_examples {
|
||||
// Base functions that are needed for testing
|
||||
// Try to keep this working set small to keep tests running as fast as possible
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
working_set.add_decl(Box::new(Each));
|
||||
working_set.add_decl(Box::new(Let));
|
||||
working_set.add_decl(Box::new(Str));
|
||||
working_set.add_decl(Box::new(StrJoin));
|
||||
|
@ -375,7 +375,7 @@ mod test {
|
||||
r#"[7,8,9,10] | par-each {|el ind| $ind } | describe"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<int>");
|
||||
assert_eq!(actual.out, "list<int> (stream)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -77,7 +77,7 @@ fn gets_first_row_as_list_when_amount_given() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<int>");
|
||||
assert_eq!(actual.out, "list<int> (stream)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -76,7 +76,7 @@ fn gets_last_row_as_list_when_amount_given() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<int>");
|
||||
assert_eq!(actual.out, "list<int> (stream)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -9,7 +9,7 @@ fn float_in_seq_leads_to_lists_of_floats() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<float>");
|
||||
assert_eq!(actual.out, "list<float> (stream)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -21,5 +21,5 @@ fn ints_in_seq_leads_to_lists_of_ints() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "list<int>");
|
||||
assert_eq!(actual.out, "list<int> (stream)");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user