forked from extern/nushell
Updates the table creation logic.
The table parsing/creation logic has changed from treating every line the same to processing each line in context of the column header's placement. Previously, lines on separate rows would go towards the same column as long as they were the same index based on separator alone. Now, each item's index is based on vertical alignment to the column header. This may seem brittle, but it solves the problem of some tables operating with empty cells that would cause remaining values to be paired with the wrong column. Based on kubernetes output (get pods, events), the new method has shown to have much greater success rates for parsing.
This commit is contained in:
parent
a0ed6ea3c8
commit
9b1ff9b566
@ -46,33 +46,39 @@ fn string_to_table(
|
||||
let mut lines = s.lines().filter(|l| !l.trim().is_empty());
|
||||
let separator = " ".repeat(std::cmp::max(split_at, 1));
|
||||
|
||||
let headers = lines
|
||||
.next()?
|
||||
.split(&separator)
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.to_owned())
|
||||
.collect::<Vec<String>>();
|
||||
let headers_raw = lines.next()?;
|
||||
|
||||
let header_row = if headerless {
|
||||
(1..=headers.len())
|
||||
.map(|i| format!("Column{}", i))
|
||||
.collect::<Vec<String>>()
|
||||
} else {
|
||||
let headers = headers_raw
|
||||
.trim()
|
||||
.split(&separator)
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| (headers_raw.find(s).unwrap(), s.to_owned()));
|
||||
|
||||
let columns = if headerless {
|
||||
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(
|
||||
lines
|
||||
.map(|l| {
|
||||
header_row
|
||||
columns
|
||||
.iter()
|
||||
.zip(
|
||||
l.split(&separator)
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty()),
|
||||
)
|
||||
.map(|(a, b)| (String::from(a), String::from(b)))
|
||||
.enumerate()
|
||||
.filter_map(|(i, (start, col))| {
|
||||
(match columns.get(i + 1) {
|
||||
Some((end, _)) => l.get(*start..*end),
|
||||
None => l.get(*start..)?.split(&separator).next(),
|
||||
})
|
||||
.and_then(|s| Some((col.clone(), String::from(s.trim()))))
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
|
Loading…
Reference in New Issue
Block a user