mirror of
https://github.com/nushell/nushell.git
synced 2024-11-30 04:14:17 +01:00
Merge pull request #845 from t-hart/from-ssv/headers-as-markers
`from-ssv` logic updated
This commit is contained in:
commit
84a98995bf
@ -46,33 +46,39 @@ fn string_to_table(
|
|||||||
let mut lines = s.lines().filter(|l| !l.trim().is_empty());
|
let mut lines = s.lines().filter(|l| !l.trim().is_empty());
|
||||||
let separator = " ".repeat(std::cmp::max(split_at, 1));
|
let separator = " ".repeat(std::cmp::max(split_at, 1));
|
||||||
|
|
||||||
let headers = lines
|
let headers_raw = lines.next()?;
|
||||||
.next()?
|
|
||||||
.split(&separator)
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.map(|s| s.to_owned())
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
|
|
||||||
let header_row = if headerless {
|
let headers = headers_raw
|
||||||
(1..=headers.len())
|
.trim()
|
||||||
.map(|i| format!("Column{}", i))
|
.split(&separator)
|
||||||
.collect::<Vec<String>>()
|
.map(str::trim)
|
||||||
} else {
|
.filter(|s| !s.is_empty())
|
||||||
|
.map(|s| (headers_raw.find(s).unwrap(), s.to_owned()));
|
||||||
|
|
||||||
|
let columns = if headerless {
|
||||||
headers
|
headers
|
||||||
|
.enumerate()
|
||||||
|
.map(|(header_no, (string_index, _))| {
|
||||||
|
(string_index, format!("Column{}", header_no + 1))
|
||||||
|
})
|
||||||
|
.collect::<Vec<(usize, String)>>()
|
||||||
|
} else {
|
||||||
|
headers.collect::<Vec<(usize, String)>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
lines
|
lines
|
||||||
.map(|l| {
|
.map(|l| {
|
||||||
header_row
|
columns
|
||||||
.iter()
|
.iter()
|
||||||
.zip(
|
.enumerate()
|
||||||
l.split(&separator)
|
.filter_map(|(i, (start, col))| {
|
||||||
.map(|s| s.trim())
|
(match columns.get(i + 1) {
|
||||||
.filter(|s| !s.is_empty()),
|
Some((end, _)) => l.get(*start..*end),
|
||||||
)
|
None => l.get(*start..),
|
||||||
.map(|(a, b)| (String::from(a), String::from(b)))
|
})
|
||||||
|
.and_then(|s| Some((col.clone(), String::from(s.trim()))))
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
@ -171,9 +177,9 @@ mod tests {
|
|||||||
|
|
||||||
a b
|
a b
|
||||||
|
|
||||||
1 2
|
1 2
|
||||||
|
|
||||||
3 4
|
3 4
|
||||||
"#;
|
"#;
|
||||||
let result = string_to_table(input, false, 1);
|
let result = string_to_table(input, false, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -185,6 +191,20 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_deals_with_single_column_input() {
|
||||||
|
let input = r#"
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
"#;
|
||||||
|
let result = string_to_table(input, false, 1);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Some(vec![vec![owned("a", "1")], vec![owned("a", "2")]])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_ignores_headers_when_headerless() {
|
fn it_ignores_headers_when_headerless() {
|
||||||
let input = r#"
|
let input = r#"
|
||||||
@ -206,15 +226,15 @@ mod tests {
|
|||||||
fn it_returns_none_given_an_empty_string() {
|
fn it_returns_none_given_an_empty_string() {
|
||||||
let input = "";
|
let input = "";
|
||||||
let result = string_to_table(input, true, 1);
|
let result = string_to_table(input, true, 1);
|
||||||
assert_eq!(result, None);
|
assert!(result.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_allows_a_predefined_number_of_spaces() {
|
fn it_allows_a_predefined_number_of_spaces() {
|
||||||
let input = r#"
|
let input = r#"
|
||||||
column a column b
|
column a column b
|
||||||
entry 1 entry number 2
|
entry 1 entry number 2
|
||||||
3 four
|
3 four
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = string_to_table(input, false, 3);
|
let result = string_to_table(input, false, 3);
|
||||||
@ -239,12 +259,58 @@ mod tests {
|
|||||||
|
|
||||||
let trimmed = |s: &str| s.trim() == s;
|
let trimmed = |s: &str| s.trim() == s;
|
||||||
|
|
||||||
|
let result = string_to_table(input, false, 2).unwrap();
|
||||||
|
assert!(result
|
||||||
|
.iter()
|
||||||
|
.all(|row| row.iter().all(|(a, b)| trimmed(a) && trimmed(b))))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_keeps_empty_columns() {
|
||||||
|
let input = r#"
|
||||||
|
colA col B col C
|
||||||
|
val2 val3
|
||||||
|
val4 val 5 val 6
|
||||||
|
val7 val8
|
||||||
|
"#;
|
||||||
|
|
||||||
let result = string_to_table(input, false, 2).unwrap();
|
let result = string_to_table(input, false, 2).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
true,
|
result,
|
||||||
result
|
vec![
|
||||||
.iter()
|
vec![
|
||||||
.all(|row| row.iter().all(|(a, b)| trimmed(a) && trimmed(b)))
|
owned("colA", ""),
|
||||||
|
owned("col B", "val2"),
|
||||||
|
owned("col C", "val3")
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
owned("colA", "val4"),
|
||||||
|
owned("col B", "val 5"),
|
||||||
|
owned("col C", "val 6")
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
owned("colA", "val7"),
|
||||||
|
owned("col B", ""),
|
||||||
|
owned("col C", "val8")
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_uses_the_full_final_column() {
|
||||||
|
let input = r#"
|
||||||
|
colA col B
|
||||||
|
val1 val2 trailing value that should be included
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let result = string_to_table(input, false, 2).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
vec![vec![
|
||||||
|
owned("colA", "val1"),
|
||||||
|
owned("col B", "val2 trailing value that should be included"),
|
||||||
|
],]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user