nu_table/types/
collapse.rs

1use nu_ansi_term::Style;
2use nu_color_config::StyleComputer;
3use nu_protocol::{Config, Value};
4use nu_utils::SharedCow;
5
6use crate::{
7    common::{get_index_style, load_theme, nu_value_to_string_clean},
8    StringResult, TableOpts, UnstructuredTable,
9};
10
11pub struct CollapsedTable;
12
13impl CollapsedTable {
14    pub fn build(value: Value, opts: TableOpts<'_>) -> StringResult {
15        collapsed_table(value, opts)
16    }
17}
18
19fn collapsed_table(mut value: Value, opts: TableOpts<'_>) -> StringResult {
20    colorize_value(&mut value, opts.config, &opts.style_computer);
21
22    let mut table = UnstructuredTable::new(value, opts.config);
23
24    let theme = load_theme(opts.mode);
25    let is_empty = table.truncate(&theme, opts.width);
26    if is_empty {
27        return Ok(None);
28    }
29
30    let table = table.draw(&theme, opts.config.table.padding, &opts.style_computer);
31
32    Ok(Some(table))
33}
34
35fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComputer) {
36    // todo: Remove recursion?
37
38    match value {
39        Value::Record { ref mut val, .. } => {
40            let style = get_index_style(style_computer);
41            // Take ownership of the record and reassign to &mut
42            // We do this to have owned keys through `.into_iter`
43            let record = std::mem::take(val);
44            *val = SharedCow::new(
45                record
46                    .into_owned()
47                    .into_iter()
48                    .map(|(mut header, mut val)| {
49                        colorize_value(&mut val, config, style_computer);
50                        header = colorize_text(&header, style.color_style).unwrap_or(header);
51
52                        (header, val)
53                    })
54                    .collect(),
55            );
56        }
57        Value::List { vals, .. } => {
58            for val in vals {
59                colorize_value(val, config, style_computer);
60            }
61        }
62        value => {
63            let (text, style) = nu_value_to_string_clean(value, config, style_computer);
64            if let Some(text) = colorize_text(&text, style.color_style) {
65                *value = Value::string(text, value.span());
66            }
67        }
68    }
69}
70
71fn colorize_text(text: &str, color: Option<Style>) -> Option<String> {
72    if let Some(color) = color {
73        if !color.is_plain() {
74            return Some(color.paint(text).to_string());
75        }
76    }
77
78    None
79}