mirror of
https://github.com/nushell/nushell.git
synced 2025-01-11 16:58:41 +01:00
Fix error message for headers
(#11809)
# Description Fixes #11780: `headers`: incorrect error
This commit is contained in:
parent
d77eeeb5dd
commit
779a3c075e
@ -1,8 +1,8 @@
|
|||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
record, Category, Config, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type,
|
record, Category, Config, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span,
|
||||||
Value,
|
Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -69,66 +69,38 @@ impl Command for Headers {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let config = engine_state.get_config();
|
let config = engine_state.get_config();
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
let value = input.into_value(call.head);
|
let span = input.span().unwrap_or(call.head);
|
||||||
let (old_headers, new_headers) = extract_headers(&value, config)?;
|
let value = input.into_value(span);
|
||||||
let new_headers = replace_headers(value, &old_headers, &new_headers)?;
|
let Value::List { vals: table, .. } = value else {
|
||||||
|
return Err(ShellError::TypeMismatch {
|
||||||
|
err_message: "not a table".to_string(),
|
||||||
|
span,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Ok(new_headers.into_pipeline_data_with_metadata(metadata))
|
let (old_headers, new_headers) = extract_headers(&table, span, config)?;
|
||||||
|
let value = replace_headers(table, span, &old_headers, &new_headers)?;
|
||||||
|
|
||||||
|
Ok(value.into_pipeline_data_with_metadata(metadata))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_headers(
|
|
||||||
value: Value,
|
|
||||||
old_headers: &[String],
|
|
||||||
new_headers: &[String],
|
|
||||||
) -> Result<Value, ShellError> {
|
|
||||||
let span = value.span();
|
|
||||||
match value {
|
|
||||||
Value::Record { val, .. } => Ok(Value::record(
|
|
||||||
val.into_iter()
|
|
||||||
.filter_map(|(col, val)| {
|
|
||||||
old_headers
|
|
||||||
.iter()
|
|
||||||
.position(|c| c == &col)
|
|
||||||
.map(|i| (new_headers[i].clone(), val))
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
span,
|
|
||||||
)),
|
|
||||||
Value::List { vals, .. } => {
|
|
||||||
let vals = vals
|
|
||||||
.into_iter()
|
|
||||||
.skip(1)
|
|
||||||
.map(|value| replace_headers(value, old_headers, new_headers))
|
|
||||||
.collect::<Result<Vec<Value>, ShellError>>()?;
|
|
||||||
|
|
||||||
Ok(Value::list(vals, span))
|
|
||||||
}
|
|
||||||
_ => Err(ShellError::TypeMismatch {
|
|
||||||
err_message: "record".to_string(),
|
|
||||||
span: value.span(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid_header(value: &Value) -> bool {
|
|
||||||
matches!(
|
|
||||||
value,
|
|
||||||
Value::Nothing { .. }
|
|
||||||
| Value::String { val: _, .. }
|
|
||||||
| Value::Bool { val: _, .. }
|
|
||||||
| Value::Float { val: _, .. }
|
|
||||||
| Value::Int { val: _, .. }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_headers(
|
fn extract_headers(
|
||||||
value: &Value,
|
table: &[Value],
|
||||||
|
span: Span,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
) -> Result<(Vec<String>, Vec<String>), ShellError> {
|
) -> Result<(Vec<String>, Vec<String>), ShellError> {
|
||||||
let span = value.span();
|
table
|
||||||
match value {
|
.first()
|
||||||
Value::Record { val: record, .. } => {
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Found empty list".into(),
|
||||||
|
msg: "unable to extract headers".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})
|
||||||
|
.and_then(Value::as_record)
|
||||||
|
.and_then(|record| {
|
||||||
for v in record.values() {
|
for v in record.values() {
|
||||||
if !is_valid_header(v) {
|
if !is_valid_header(v) {
|
||||||
return Err(ShellError::TypeMismatch {
|
return Err(ShellError::TypeMismatch {
|
||||||
@ -151,26 +123,57 @@ fn extract_headers(
|
|||||||
col
|
col
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>();
|
.collect();
|
||||||
|
|
||||||
Ok((old_headers, new_headers))
|
Ok((old_headers, new_headers))
|
||||||
}
|
})
|
||||||
Value::List { vals, .. } => vals
|
}
|
||||||
.iter()
|
|
||||||
.map(|value| extract_headers(value, config))
|
fn is_valid_header(value: &Value) -> bool {
|
||||||
.next()
|
matches!(
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
value,
|
||||||
error: "Found empty list".into(),
|
Value::Nothing { .. }
|
||||||
msg: "unable to extract headers".into(),
|
| Value::String { val: _, .. }
|
||||||
span: Some(span),
|
| Value::Bool { val: _, .. }
|
||||||
help: None,
|
| Value::Float { val: _, .. }
|
||||||
inner: vec![],
|
| Value::Int { val: _, .. }
|
||||||
})?,
|
)
|
||||||
_ => Err(ShellError::TypeMismatch {
|
}
|
||||||
err_message: "record".to_string(),
|
|
||||||
span: value.span(),
|
fn replace_headers(
|
||||||
}),
|
rows: Vec<Value>,
|
||||||
}
|
span: Span,
|
||||||
|
old_headers: &[String],
|
||||||
|
new_headers: &[String],
|
||||||
|
) -> Result<Value, ShellError> {
|
||||||
|
rows.into_iter()
|
||||||
|
.skip(1)
|
||||||
|
.map(|value| {
|
||||||
|
let span = value.span();
|
||||||
|
if let Value::Record { val: record, .. } = value {
|
||||||
|
Ok(Value::record(
|
||||||
|
record
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(col, val)| {
|
||||||
|
old_headers
|
||||||
|
.iter()
|
||||||
|
.position(|c| c == &col)
|
||||||
|
.map(|i| (new_headers[i].clone(), val))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
span,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(ShellError::CantConvert {
|
||||||
|
to_type: "record".into(),
|
||||||
|
from_type: value.get_type().to_string(),
|
||||||
|
span,
|
||||||
|
help: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.map(|rows| Value::list(rows, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user