mirror of
https://github.com/nushell/nushell.git
synced 2025-06-06 01:56:54 +02:00
update
This commit is contained in:
parent
425c3d8380
commit
49318b91f3
@ -64,6 +64,8 @@ pub fn nu_value_to_string(val: &Value, cfg: &Config, style: &StyleComputer) -> N
|
|||||||
make_styled_value(text, val, float_precision, style)
|
make_styled_value(text, val, float_precision, style)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: Expose a method which returns just style
|
||||||
|
|
||||||
pub fn nu_value_to_string_clean(val: &Value, cfg: &Config, style_comp: &StyleComputer) -> NuText {
|
pub fn nu_value_to_string_clean(val: &Value, cfg: &Config, style_comp: &StyleComputer) -> NuText {
|
||||||
let (text, style) = nu_value_to_string(val, cfg, style_comp);
|
let (text, style) = nu_value_to_string(val, cfg, style_comp);
|
||||||
let mut text = clean_charset(&text);
|
let mut text = clean_charset(&text);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use nu_ansi_term::Style;
|
||||||
use nu_color_config::StyleComputer;
|
use nu_color_config::StyleComputer;
|
||||||
use nu_protocol::{Config, Record, Value};
|
use nu_protocol::{Config, Record, Value};
|
||||||
use nu_utils::SharedCow;
|
use nu_utils::SharedCow;
|
||||||
@ -46,10 +47,8 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(mut header, mut val)| {
|
.map(|(mut header, mut val)| {
|
||||||
colorize_value(&mut val, config, style_computer);
|
colorize_value(&mut val, config, style_computer);
|
||||||
|
header = colorize_text(&header, style.color_style).unwrap_or(header);
|
||||||
|
|
||||||
if let Some(color) = style.color_style {
|
|
||||||
header = color.paint(header).to_string();
|
|
||||||
}
|
|
||||||
(header, val)
|
(header, val)
|
||||||
})
|
})
|
||||||
.collect::<Record>(),
|
.collect::<Record>(),
|
||||||
@ -62,11 +61,19 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp
|
|||||||
}
|
}
|
||||||
value => {
|
value => {
|
||||||
let (text, style) = nu_value_to_string_clean(value, config, style_computer);
|
let (text, style) = nu_value_to_string_clean(value, config, style_computer);
|
||||||
if let Some(color) = style.color_style {
|
if let Some(text) = colorize_text(&text, style.color_style) {
|
||||||
let text = color.paint(text).to_string();
|
*value = Value::string(text, value.span());
|
||||||
let span = value.span();
|
|
||||||
*value = Value::string(text, span);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn colorize_text(text: &str, color: Option<Style>) -> Option<String> {
|
||||||
|
if let Some(color) = color {
|
||||||
|
if !color.is_plain() {
|
||||||
|
return Some(color.paint(text).to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
@ -2,13 +2,13 @@ use nu_color_config::TextStyle;
|
|||||||
use nu_engine::column::get_columns;
|
use nu_engine::column::get_columns;
|
||||||
use nu_protocol::{Config, Record, ShellError, Value};
|
use nu_protocol::{Config, Record, ShellError, Value};
|
||||||
|
|
||||||
use super::has_index;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clean_charset, colorize_space,
|
clean_charset, colorize_space,
|
||||||
common::{
|
common::{
|
||||||
check_value, create_nu_table_config, get_empty_style, get_header_style, get_index_style,
|
check_value, create_nu_table_config, get_empty_style, get_header_style, get_index_style,
|
||||||
get_value_style, nu_value_to_string_colored, NuText, INDEX_COLUMN_NAME,
|
get_value_style, nu_value_to_string_colored, NuText, INDEX_COLUMN_NAME,
|
||||||
},
|
},
|
||||||
|
types::has_index,
|
||||||
NuRecordsValue, NuTable, StringResult, TableOpts, TableOutput, TableResult,
|
NuRecordsValue, NuTable, StringResult, TableOpts, TableOutput, TableResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@ use nu_protocol::{Config, Record, Span, TableIndent, Value};
|
|||||||
use tabled::{
|
use tabled::{
|
||||||
grid::{
|
grid::{
|
||||||
ansi::ANSIStr,
|
ansi::ANSIStr,
|
||||||
config::{AlignmentHorizontal, Borders, CompactMultilineConfig},
|
config::{Borders, CompactMultilineConfig},
|
||||||
dimension::{DimensionPriority, PoolTableDimension},
|
dimension::{DimensionPriority, PoolTableDimension},
|
||||||
},
|
},
|
||||||
settings::{Color, Padding, TableOption, Theme},
|
settings::{Alignment, Color, Padding, TableOption},
|
||||||
tables::{PoolTable, TableValue},
|
tables::{PoolTable, TableValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ fn build_table(
|
|||||||
theme.set_horizontal_lines(Default::default());
|
theme.set_horizontal_lines(Default::default());
|
||||||
|
|
||||||
table.with(Padding::new(indent.left, indent.right, 0, 0));
|
table.with(Padding::new(indent.left, indent.right, 0, 0));
|
||||||
table.with(SetRawStyle(theme));
|
table.with(*theme.get_borders());
|
||||||
table.with(SetAlignment(AlignmentHorizontal::Left));
|
table.with(Alignment::left());
|
||||||
table.with(PoolTableDimension::new(
|
table.with(PoolTableDimension::new(
|
||||||
DimensionPriority::Last,
|
DimensionPriority::Last,
|
||||||
DimensionPriority::Last,
|
DimensionPriority::Last,
|
||||||
@ -72,14 +72,6 @@ fn build_table(
|
|||||||
table.to_string()
|
table.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_table_with_border_color(mut table: PoolTable, color: Color) -> String {
|
|
||||||
// NOTE: We have this function presizely because of color_into_ansistr internals
|
|
||||||
// color must be alive why we build table
|
|
||||||
|
|
||||||
table.with(SetBorderColor(color_into_ansistr(&color)));
|
|
||||||
table.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
|
fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
|
||||||
match value {
|
match value {
|
||||||
Value::Record { val, .. } => build_vertical_map(val.into_owned(), config),
|
Value::Record { val, .. } => build_vertical_map(val.into_owned(), config),
|
||||||
@ -91,76 +83,74 @@ fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue
|
|||||||
build_vertical_array(vals, config)
|
build_vertical_array(vals, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value => {
|
value => build_string_value(value, config),
|
||||||
let mut text = value.to_abbreviated_string(config);
|
|
||||||
if string_width(&text) > 50 {
|
|
||||||
text = string_wrap(&text, 30, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TableValue::Cell(text)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_vertical_map(record: Record, config: &Config) -> TableValue {
|
fn build_string_value(value: Value, config: &Config) -> TableValue {
|
||||||
let mut rows = Vec::with_capacity(record.len());
|
const MAX_STRING_WIDTH: usize = 50;
|
||||||
for (key, value) in record {
|
const WRAP_STRING_WIDTH: usize = 30;
|
||||||
let val = convert_nu_value_to_table_value(value, config);
|
|
||||||
let row = TableValue::Row(vec![TableValue::Cell(key), val]);
|
let mut text = value.to_abbreviated_string(config);
|
||||||
rows.push(row);
|
if string_width(&text) > MAX_STRING_WIDTH {
|
||||||
|
text = string_wrap(&text, WRAP_STRING_WIDTH, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_key_width = rows
|
TableValue::Cell(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_vertical_map(record: Record, config: &Config) -> TableValue {
|
||||||
|
let max_key_width = record
|
||||||
.iter()
|
.iter()
|
||||||
.map(|row| match row {
|
.map(|(k, _)| string_width(k))
|
||||||
TableValue::Row(list) => match &list[0] {
|
|
||||||
TableValue::Cell(key) => string_width(key),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
rows.iter_mut().for_each(|row| {
|
let mut rows = Vec::with_capacity(record.len());
|
||||||
match row {
|
for (mut key, value) in record {
|
||||||
TableValue::Row(list) => match &mut list[0] {
|
string_append_to_width(&mut key, max_key_width);
|
||||||
TableValue::Cell(key) => {
|
|
||||||
let width = string_width(key);
|
let value = convert_nu_value_to_table_value(value, config);
|
||||||
let rest = max_key_width - width;
|
|
||||||
key.extend(std::iter::repeat(' ').take(rest));
|
let row = TableValue::Row(vec![TableValue::Cell(key), value]);
|
||||||
}
|
rows.push(row);
|
||||||
_ => unreachable!(),
|
}
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
TableValue::Column(rows)
|
TableValue::Column(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn string_append_to_width(key: &mut String, max: usize) {
|
||||||
|
let width = string_width(key);
|
||||||
|
let rest = max - width;
|
||||||
|
key.extend(std::iter::repeat(' ').take(rest));
|
||||||
|
}
|
||||||
|
|
||||||
fn build_vertical_array(vals: Vec<Value>, config: &Config) -> TableValue {
|
fn build_vertical_array(vals: Vec<Value>, config: &Config) -> TableValue {
|
||||||
let map = vals
|
let map = vals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|val| convert_nu_value_to_table_value(val, config))
|
.map(|val| convert_nu_value_to_table_value(val, config))
|
||||||
.collect::<Vec<_>>();
|
.collect();
|
||||||
|
|
||||||
TableValue::Column(map)
|
TableValue::Column(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_record(vals: &[Value]) -> bool {
|
fn is_valid_record(vals: &[Value]) -> bool {
|
||||||
let mut first_record: Option<&Record> = None;
|
if vals.is_empty() {
|
||||||
for val in vals {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_value = match &vals[0] {
|
||||||
|
Value::Record { val, .. } => val,
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
for val in &vals[1..] {
|
||||||
match val {
|
match val {
|
||||||
Value::Record { val, .. } => {
|
Value::Record { val, .. } => {
|
||||||
if let Some(known) = first_record {
|
let equal = val.columns().eq(first_value.columns());
|
||||||
let equal = known.columns().eq(val.columns());
|
if !equal {
|
||||||
if !equal {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
first_record = Some(val)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
_ => return false,
|
_ => return false,
|
||||||
}
|
}
|
||||||
@ -177,30 +167,41 @@ fn count_columns_in_record(vals: &[Value]) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_map_from_record(vals: Vec<Value>, config: &Config) -> TableValue {
|
fn build_map_from_record(vals: Vec<Value>, config: &Config) -> TableValue {
|
||||||
let mut list = vec![];
|
// assumes that we have a valid record structure (checked by is_valid_record)
|
||||||
|
|
||||||
let head = get_columns_in_record(&vals);
|
let head = get_columns_in_record(&vals);
|
||||||
let count_columns = head.len();
|
let mut list = Vec::with_capacity(head.len());
|
||||||
for col in head {
|
for col in head {
|
||||||
list.push(vec![TableValue::Cell(col)]);
|
list.push(TableValue::Column(vec![TableValue::Cell(col)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for val in vals {
|
for val in vals {
|
||||||
match val {
|
let val = get_as_record(val);
|
||||||
Value::Record { val, .. } => {
|
for (i, (_, val)) in val.into_owned().into_iter().enumerate() {
|
||||||
for (i, (_key, val)) in val.into_owned().into_iter().take(count_columns).enumerate()
|
let value = convert_nu_value_to_table_value(val, config);
|
||||||
{
|
let list = get_table_value_column_mut(&mut list[i]);
|
||||||
let cell = convert_nu_value_to_table_value(val, config);
|
|
||||||
list[i].push(cell);
|
list.push(value);
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let columns = list.into_iter().map(TableValue::Column).collect::<Vec<_>>();
|
TableValue::Row(list)
|
||||||
|
}
|
||||||
|
|
||||||
TableValue::Row(columns)
|
fn get_table_value_column_mut(val: &mut TableValue) -> &mut Vec<TableValue> {
|
||||||
|
match val {
|
||||||
|
TableValue::Column(row) => row,
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_as_record(val: Value) -> nu_utils::SharedCow<Record> {
|
||||||
|
match val {
|
||||||
|
Value::Record { val, .. } => val,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_columns_in_record(vals: &[Value]) -> Vec<String> {
|
fn get_columns_in_record(vals: &[Value]) -> Vec<String> {
|
||||||
@ -210,32 +211,6 @@ fn get_columns_in_record(vals: &[Value]) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SetRawStyle(Theme);
|
|
||||||
|
|
||||||
impl<R, D> TableOption<R, CompactMultilineConfig, D> for SetRawStyle {
|
|
||||||
fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
|
|
||||||
let borders = *self.0.get_borders();
|
|
||||||
cfg.set_borders(borders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SetBorderColor(ANSIStr<'static>);
|
|
||||||
|
|
||||||
impl<R, D> TableOption<R, CompactMultilineConfig, D> for SetBorderColor {
|
|
||||||
fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
|
|
||||||
let borders = Borders::filled(self.0);
|
|
||||||
cfg.set_borders_color(borders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SetAlignment(AlignmentHorizontal);
|
|
||||||
|
|
||||||
impl<R, D> TableOption<R, CompactMultilineConfig, D> for SetAlignment {
|
|
||||||
fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
|
|
||||||
cfg.set_alignment_horizontal(self.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn truncate_table_value(
|
fn truncate_table_value(
|
||||||
value: &mut TableValue,
|
value: &mut TableValue,
|
||||||
has_vertical: bool,
|
has_vertical: bool,
|
||||||
@ -341,6 +316,15 @@ fn truncate_table_value(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_table_with_border_color(mut table: PoolTable, color: Color) -> String {
|
||||||
|
// NOTE: We have this function presizely because of color_into_ansistr internals
|
||||||
|
// color must be alive why we build table
|
||||||
|
|
||||||
|
let color = color_into_ansistr(&color);
|
||||||
|
table.with(SetBorderColor(color));
|
||||||
|
table.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
fn color_into_ansistr(color: &Color) -> ANSIStr<'static> {
|
fn color_into_ansistr(color: &Color) -> ANSIStr<'static> {
|
||||||
// # SAFETY
|
// # SAFETY
|
||||||
//
|
//
|
||||||
@ -355,3 +339,12 @@ fn color_into_ansistr(color: &Color) -> ANSIStr<'static> {
|
|||||||
|
|
||||||
ANSIStr::new(prefix, suffix)
|
ANSIStr::new(prefix, suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SetBorderColor(ANSIStr<'static>);
|
||||||
|
|
||||||
|
impl<R, D> TableOption<R, CompactMultilineConfig, D> for SetBorderColor {
|
||||||
|
fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
|
||||||
|
let borders = Borders::filled(self.0);
|
||||||
|
cfg.set_borders_color(borders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user