Merged heterogeneous tables (#536)

* Merged heterogeneous tables

* switch emoji
This commit is contained in:
JT 2021-12-21 08:03:47 +11:00 committed by GitHub
parent 152467a858
commit 0571a6ee34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 38 deletions

View File

@ -148,7 +148,7 @@ pub fn write_xml_events<W: Write>(
}
}
_ => {
let s = current.clone().into_abbreviated_string(config);
let s = current.into_abbreviated_string(config);
writer
.write_event(Event::Text(BytesText::from_plain_str(s.as_str())))
.expect("Couldn't write XML text");

View File

@ -52,7 +52,7 @@ impl Command for Table {
match input {
PipelineData::Value(Value::List { vals, .. }, ..) => {
let table = convert_to_table(0, vals, ctrlc, &config, call.head)?;
let table = convert_to_table(0, &vals, ctrlc, &config, call.head)?;
if let Some(table) = table {
let result = nu_table::draw_table(&table, term_width, &color_hm, &config);
@ -215,20 +215,35 @@ impl Command for Table {
}
}
fn get_columns(input: &[Value]) -> Vec<String> {
let mut columns = vec![];
for item in input {
if let Value::Record { cols, vals: _, .. } = item {
for col in cols {
if !columns.contains(col) {
columns.push(col.to_string());
}
}
}
}
columns
}
fn convert_to_table(
row_offset: usize,
iter: impl IntoIterator<Item = Value>,
input: &[Value],
ctrlc: Option<Arc<AtomicBool>>,
config: &Config,
head: Span,
) -> Result<Option<nu_table::Table>, ShellError> {
let mut iter = iter.into_iter().peekable();
let mut headers = get_columns(input);
let mut input = input.iter().peekable();
let color_hm = get_color_config(config);
let float_precision = config.float_precision as usize;
if let Some(first) = iter.peek() {
let mut headers = first.columns();
if input.peek().is_some() {
if !headers.is_empty() {
headers.insert(0, "#".into());
}
@ -236,41 +251,34 @@ fn convert_to_table(
// Vec of Vec of String1, String2 where String1 is datatype and String2 is value
let mut data: Vec<Vec<(String, String)>> = Vec::new();
for (row_num, item) in iter.enumerate() {
for (row_num, item) in input.enumerate() {
if let Some(ctrlc) = &ctrlc {
if ctrlc.load(Ordering::SeqCst) {
return Ok(None);
}
}
if let Value::Error { error } = item {
return Err(error);
return Err(error.clone());
}
// String1 = datatype, String2 = value as string
let mut row: Vec<(String, String)> =
vec![("string".to_string(), (row_num + row_offset).to_string())];
if headers.is_empty() {
// if header row is empty, this is probably a list so format it that way
row.push(("list".to_string(), item.into_abbreviated_string(config)))
} else {
for header in headers.iter().skip(1) {
let result = match item {
Value::Record { .. } => {
item.clone().follow_cell_path(&[PathMember::String {
val: header.into(),
span: head,
}])
}
_ => Ok(item.clone()),
};
for header in headers.iter().skip(1) {
let result = match item {
Value::Record { .. } => item.clone().follow_cell_path(&[PathMember::String {
val: header.into(),
span: head,
}]),
_ => Ok(item.clone()),
};
match result {
Ok(value) => row.push((
(&value.get_type()).to_string(),
value.into_abbreviated_string(config),
)),
Err(_) => row.push(("empty".to_string(), String::new())),
}
match result {
Ok(value) => row.push((
(&value.get_type()).to_string(),
value.into_abbreviated_string(config),
)),
Err(_) => row.push(("empty".to_string(), "".into())),
}
}
@ -397,7 +405,7 @@ impl Iterator for PagingTableCreator {
let table = convert_to_table(
self.row_offset,
batch.into_iter(),
&batch,
self.ctrlc.clone(),
&self.config,
self.head,

View File

@ -386,22 +386,22 @@ impl Value {
}
/// Convert Value into string. Note that Streams will be consumed.
pub fn into_abbreviated_string(self, config: &Config) -> String {
pub fn into_abbreviated_string(&self, config: &Config) -> String {
match self {
Value::Bool { val, .. } => val.to_string(),
Value::Int { val, .. } => val.to_string(),
Value::Float { val, .. } => val.to_string(),
Value::Filesize { val, .. } => format_filesize(val, config),
Value::Duration { val, .. } => format_duration(val),
Value::Date { val, .. } => HumanTime::from(val).to_string(),
Value::Filesize { val, .. } => format_filesize(*val, config),
Value::Duration { val, .. } => format_duration(*val),
Value::Date { val, .. } => HumanTime::from(*val).to_string(),
Value::Range { val, .. } => {
format!(
"{}..{}",
val.from.into_string(", ", config),
val.to.into_string(", ", config)
val.from.clone().into_string(", ", config),
val.to.clone().into_string(", ", config)
)
}
Value::String { val, .. } => val,
Value::String { val, .. } => val.to_string(),
Value::List { ref vals, .. } => match &vals[..] {
[Value::Record { .. }, _end @ ..] => format!(
"[table {} row{}]",