Use record API in describe --detailed (#11075)

For the new stuff from #10795

Added helper to contract `{"type": ...}` records
Use inplace operations if possible for records/lists

Referencing #11027
This commit is contained in:
Stefan Holderbach 2023-11-21 17:49:23 +01:00 committed by GitHub
parent a7e8970383
commit 177e800a07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -256,6 +256,18 @@ fn run(
Ok(description.into_pipeline_data()) Ok(description.into_pipeline_data())
} }
fn compact_primitive_description(mut value: Value) -> Value {
if let Value::Record { ref mut val, .. } = value {
if val.len() != 1 {
return value;
}
if let Some(type_name) = val.get_mut("type") {
return std::mem::take(type_name);
}
}
value
}
fn describe_value( fn describe_value(
value: Value, value: Value,
head: nu_protocol::Span, head: nu_protocol::Span,
@ -285,32 +297,21 @@ fn describe_value(
), ),
head, head,
), ),
Value::Record { val, .. } => { Value::Record { mut val, .. } => {
let mut record = Record::new(); for (_k, v) in val.iter_mut() {
for i in 0..val.len() { *v = compact_primitive_description(describe_value(
let k = val.cols[i].clone(); std::mem::take(v),
let v = val.vals[i].clone(); head,
engine_state,
record.push(k, { call,
if let Value::Record { val, .. } = )?);
describe_value(v.clone(), head, engine_state, call)?
{
if let [Value::String { val: k, .. }] = val.vals.as_slice() {
Value::string(k, head)
} else {
Value::record(val, head)
}
} else {
describe_value(v, head, engine_state, call)?
}
});
} }
Value::record( Value::record(
record!( record!(
"type" => Value::string("record", head), "type" => Value::string("record", head),
"lazy" => Value::bool(false, head), "lazy" => Value::bool(false, head),
"columns" => Value::record(record, head), "columns" => Value::record(val, head),
), ),
head, head,
) )
@ -319,12 +320,12 @@ fn describe_value(
record!( record!(
"type" => Value::string("list", head), "type" => Value::string("list", head),
"length" => Value::int(vals.len() as i64, head), "length" => Value::int(vals.len() as i64, head),
"values" => Value::list(vals.iter().map(|v| "values" => Value::list(vals.into_iter().map(|v|
match describe_value(v.clone(), head, engine_state, call) { Ok(compact_primitive_description(
Ok(Value::Record {val, ..}) => if val.cols.as_slice() == ["type"] {Ok(val.vals[0].clone())} else {Ok(Value::record(val, head))}, describe_value(v, head, engine_state, call)?
x => x ))
} )
).collect::<Result<Vec<_>, _>>()?, head), .collect::<Result<Vec<Value>, ShellError>>()?, head),
), ),
head, head,
), ),
@ -389,19 +390,20 @@ fn describe_value(
if collect_lazyrecords { if collect_lazyrecords {
let collected = val.collect()?; let collected = val.collect()?;
if let Value::Record { val, .. } = if let Value::Record { mut val, .. } =
describe_value(collected, head, engine_state, call)? describe_value(collected, head, engine_state, call)?
{ {
let mut record_cols = Record::new();
record.push("length", Value::int(val.len() as i64, head)); record.push("length", Value::int(val.len() as i64, head));
for (_k, v) in val.iter_mut() {
for i in 0..val.len() { *v = compact_primitive_description(describe_value(
record_cols.push( std::mem::take(v),
val.cols[i].clone(), head,
describe_value(val.vals[i].clone(), head, engine_state, call)?, engine_state,
); call,
)?);
} }
record.push("columns", Value::record(record_cols, head));
record.push("columns", Value::record(val, head));
} else { } else {
let cols = val.column_names(); let cols = val.column_names();
record.push("length", Value::int(cols.len() as i64, head)); record.push("length", Value::int(cols.len() as i64, head));