Csv errors (#1490)

* Add error message for csv parsing failures

* Add csv error prettyfier

* Improve readability of the error

Line 2: error is easier to understand than:
Line 2, error

* Remove unnecessary use of the format! macro

Replacing it with .to_string() fixes a clippy warning

* Improve consistency with JSON parsing errors
This commit is contained in:
Sosthene-Guedon 2020-03-16 18:32:02 +01:00 committed by GitHub
parent 22ba4c2a2f
commit d8c4565413
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,5 +1,5 @@
use crate::prelude::*; use crate::prelude::*;
use csv::ReaderBuilder; use csv::{ErrorKind, ReaderBuilder};
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{Primitive, ReturnSuccess, TaggedDictBuilder, UntaggedValue, Value}; use nu_protocol::{Primitive, ReturnSuccess, TaggedDictBuilder, UntaggedValue, Value};
@ -58,8 +58,11 @@ pub fn from_delimited_data(
} }
x => yield ReturnSuccess::value(x), x => yield ReturnSuccess::value(x),
}, },
Err(_) => { Err(err) => {
let line_one = format!("Could not parse as {}", format_name); let line_one = match pretty_csv_error(err) {
Some(pretty) => format!("Could not parse as {} ({})", format_name,pretty),
None => format!("Could not parse as {}", format_name),
};
let line_two = format!("input cannot be parsed as {}", format_name); let line_two = format!("input cannot be parsed as {}", format_name);
yield Err(ShellError::labeled_error_with_secondary( yield Err(ShellError::labeled_error_with_secondary(
line_one, line_one,
@ -74,3 +77,26 @@ pub fn from_delimited_data(
Ok(stream.to_output_stream()) Ok(stream.to_output_stream())
} }
fn pretty_csv_error(err: csv::Error) -> Option<String> {
match err.kind() {
ErrorKind::UnequalLengths {
pos,
expected_len,
len,
} => {
if let Some(pos) = pos {
Some(format!(
"Line {}: expected {} fields, found {}",
pos.line(),
expected_len,
len
))
} else {
Some(format!("Expected {} fields, found {}", expected_len, len))
}
}
ErrorKind::Seek => Some("Internal error while parsing csv".to_string()),
_ => None,
}
}