[DRAFT] Check fix for emojie, wrap issues (#13430)

Hi there

Here I am using latest tabled.

My tests shows it does fixes panics, but I am wanna be sure.

@fdncred could you verify that it does fixes those panics/errors?

Closes #13405 
Closes #12786
This commit is contained in:
Maxim Zhiburt 2024-08-24 01:35:42 +03:00 committed by GitHub
parent 7003b007d5
commit 525eac1afd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 917 additions and 822 deletions

1292
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -156,7 +156,7 @@ sha2 = "0.10"
strip-ansi-escapes = "0.2.0"
syn = "2.0"
sysinfo = "0.30"
tabled = { version = "0.14.0", default-features = false }
tabled = { version = "0.16.0", default-features = false }
tempfile = "3.10"
terminal_size = "0.3"
titlecase = "2.0"

View File

@ -83,7 +83,7 @@ serde_urlencoded = { workspace = true }
serde_yaml = { workspace = true }
sha2 = { workspace = true }
sysinfo = { workspace = true }
tabled = { workspace = true, features = ["color"], default-features = false }
tabled = { workspace = true, features = ["ansi"], default-features = false }
terminal_size = { workspace = true }
titlecase = { workspace = true }
toml = { workspace = true, features = ["preserve_order"] }

View File

@ -57,7 +57,7 @@ pub fn build_table(value: Value, description: String, termsize: usize) -> String
Settings::default()
.with(Style::rounded().corner_top_left('├').corner_top_right('┤'))
.with(SetWidths(widths))
.with(Wrap::new(width).priority::<PriorityMax>())
.with(Wrap::new(width).priority(PriorityMax))
.with(SetHorizontalChar::new('┼', '┴', 11 + 2 + 1)),
);
@ -308,7 +308,7 @@ mod global_horizontal_char {
}
}
impl<R: Records + ExactRecords> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig>
impl<R: Records + ExactRecords> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>>
for SetHorizontalChar
{
fn change(
@ -377,7 +377,7 @@ mod set_widths {
pub struct SetWidths(pub Vec<usize>);
impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetWidths {
impl<R> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetWidths {
fn change(
self,
_: &mut R,

View File

@ -18,7 +18,7 @@ nu-color-config = { path = "../nu-color-config", version = "0.97.2" }
nu-ansi-term = { workspace = true }
once_cell = { workspace = true }
fancy-regex = { workspace = true }
tabled = { workspace = true, features = ["color"], default-features = false }
tabled = { workspace = true, features = ["ansi"], default-features = false }
[dev-dependencies]
# nu-test-support = { path="../nu-test-support", version = "0.97.2" }

View File

@ -1,7 +1,7 @@
use nu_ansi_term::{Color, Style};
use nu_color_config::TextStyle;
use nu_table::{NuTable, NuTableConfig, TableTheme};
use tabled::grid::records::vec_records::CellInfo;
use tabled::grid::records::vec_records::Text;
fn main() {
let args: Vec<_> = std::env::args().collect();
@ -80,10 +80,10 @@ fn make_table_data() -> (Vec<&'static str>, Vec<&'static str>) {
(table_headers, row_data)
}
fn to_cell_info_vec(data: &[&str]) -> Vec<CellInfo<String>> {
fn to_cell_info_vec(data: &[&str]) -> Vec<Text<String>> {
let mut v = vec![];
for x in data {
v.push(CellInfo::new(String::from(*x)));
v.push(Text::new(String::from(*x)));
}
v

View File

@ -7,12 +7,12 @@ use std::{cmp::min, collections::HashMap};
use tabled::{
builder::Builder,
grid::{
color::AnsiColor,
ansi::ANSIBuf,
colors::Colors,
config::{AlignmentHorizontal, ColoredConfig, Entity, EntityMap, Position},
dimension::CompleteDimensionVecRecords,
records::{
vec_records::{Cell, CellInfo, VecRecords},
vec_records::{Cell, Text, VecRecords},
ExactRecords, PeekableRecords, Records, Resizable,
},
},
@ -22,7 +22,7 @@ use tabled::{
peaker::Peaker,
themes::ColumnNames,
width::Truncate,
Color, Modify, Padding, Settings, TableOption, Width,
Alignment, Color, Modify, Padding, Settings, TableOption, Width,
},
Table,
};
@ -37,13 +37,13 @@ pub struct NuTable {
}
pub type NuRecords = VecRecords<NuTableCell>;
pub type NuTableCell = CellInfo<String>;
pub type NuTableCell = Text<String>;
#[derive(Debug, Default, Clone)]
struct Styles {
index: AnsiColor<'static>,
header: AnsiColor<'static>,
data: EntityMap<AnsiColor<'static>>,
index: ANSIBuf,
header: ANSIBuf,
data: EntityMap<ANSIBuf>,
data_is_set: bool,
}
@ -60,7 +60,7 @@ impl NuTable {
/// Creates an empty [`NuTable`] instance.
pub fn new(count_rows: usize, count_columns: usize) -> Self {
Self {
data: VecRecords::new(vec![vec![CellInfo::default(); count_columns]; count_rows]),
data: VecRecords::new(vec![vec![Text::default(); count_columns]; count_rows]),
styles: Styles::default(),
indent: (1, 1),
alignments: Alignments {
@ -84,12 +84,12 @@ impl NuTable {
}
pub fn insert(&mut self, pos: Position, text: String) {
self.data[pos.0][pos.1] = CellInfo::new(text);
self.data[pos.0][pos.1] = Text::new(text);
}
pub fn set_column_style(&mut self, column: usize, style: TextStyle) {
if let Some(style) = style.color_style {
let style = AnsiColor::from(convert_style(style));
let style = ANSIBuf::from(convert_style(style));
self.styles.data.insert(Entity::Column(column), style);
self.styles.data_is_set = true;
}
@ -102,7 +102,7 @@ impl NuTable {
pub fn insert_style(&mut self, pos: Position, style: TextStyle) {
if let Some(style) = style.color_style {
let style = AnsiColor::from(convert_style(style));
let style = ANSIBuf::from(convert_style(style));
self.styles.data.insert(Entity::Cell(pos.0, pos.1), style);
self.styles.data_is_set = true;
}
@ -115,7 +115,7 @@ impl NuTable {
pub fn set_header_style(&mut self, style: TextStyle) {
if let Some(style) = style.color_style {
let style = AnsiColor::from(convert_style(style));
let style = ANSIBuf::from(convert_style(style));
self.styles.header = style;
}
@ -124,7 +124,7 @@ impl NuTable {
pub fn set_index_style(&mut self, style: TextStyle) {
if let Some(style) = style.color_style {
let style = AnsiColor::from(convert_style(style));
let style = ANSIBuf::from(convert_style(style));
self.styles.index = style;
}
@ -133,7 +133,7 @@ impl NuTable {
pub fn set_data_style(&mut self, style: TextStyle) {
if let Some(style) = style.color_style {
let style = AnsiColor::from(convert_style(style));
let style = ANSIBuf::from(convert_style(style));
self.styles.data.insert(Entity::Global, style);
self.styles.data_is_set = true;
}
@ -171,8 +171,8 @@ impl NuTable {
}
}
impl From<Vec<Vec<CellInfo<String>>>> for NuTable {
fn from(value: Vec<Vec<CellInfo<String>>>) -> Self {
impl From<Vec<Vec<Text<String>>>> for NuTable {
fn from(value: Vec<Vec<Text<String>>>) -> Self {
let mut nutable = Self::new(0, 0);
nutable.data = VecRecords::new(value);
@ -352,7 +352,7 @@ impl TableWidthCtrl {
}
}
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for TableWidthCtrl {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for TableWidthCtrl {
fn change(
self,
rec: &mut NuRecords,
@ -374,8 +374,8 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
)
.change(rec, cfg, dim);
} else if self.cfg.expand && self.width_max > total_width {
Settings::new(SetDimensions(self.width), Width::increase(self.width_max))
.change(rec, cfg, dim)
let opt = (SetDimensions(self.width), Width::increase(self.width_max));
TableOption::<VecRecords<_>, _, _>::change(opt, rec, cfg, dim)
} else {
SetDimensions(self.width).change(rec, cfg, dim);
}
@ -408,7 +408,7 @@ impl TableTrim {
}
}
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for TableTrim {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for TableTrim {
fn change(
self,
recs: &mut NuRecords,
@ -424,27 +424,28 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
match self.strategy {
TrimStrategy::Wrap { try_to_keep_words } => {
let mut wrap = Width::wrap(self.width_max).priority::<PriorityMax>();
if try_to_keep_words {
wrap = wrap.keep_words();
}
let wrap = Width::wrap(self.width_max)
.keep_words(try_to_keep_words)
.priority(PriorityMax);
Settings::new(SetDimensions(self.width), wrap).change(recs, cfg, dims);
let opt = (SetDimensions(self.width), wrap);
TableOption::<NuRecords, _, _>::change(opt, recs, cfg, dims);
}
TrimStrategy::Truncate { suffix } => {
let mut truncate = Width::truncate(self.width_max).priority::<PriorityMax>();
let mut truncate = Width::truncate(self.width_max).priority(PriorityMax);
if let Some(suffix) = suffix {
truncate = truncate.suffix(suffix).suffix_try_color(true);
}
Settings::new(SetDimensions(self.width), truncate).change(recs, cfg, dims);
let opt = (SetDimensions(self.width), truncate);
TableOption::<NuRecords, _, _>::change(opt, recs, cfg, dims);
}
}
}
}
fn trim_as_header(
recs: &mut VecRecords<CellInfo<String>>,
recs: &mut VecRecords<Text<String>>,
cfg: &mut ColoredConfig,
dims: &mut CompleteDimensionVecRecords,
trim: TableTrim,
@ -456,7 +457,7 @@ fn trim_as_header(
let headers = recs[0].to_owned();
let headers_widths = headers
.iter()
.map(CellInfo::width)
.map(Text::width)
.map(|v| v + trim.pad)
.collect::<Vec<_>>();
let min_width_use = get_total_width2(&headers_widths, cfg);
@ -481,14 +482,10 @@ fn trim_as_header(
match &trim.strategy {
TrimStrategy::Wrap { try_to_keep_words } => {
let mut wrap = Width::wrap(use_width);
if *try_to_keep_words {
wrap = wrap.keep_words();
}
let wrap = Width::wrap(use_width).keep_words(*try_to_keep_words);
Modify::new(Columns::single(i))
.with(wrap)
.change(recs, cfg, dims);
let opt = Modify::new(Columns::single(i)).with(wrap);
TableOption::<VecRecords<Text<String>>, _, _>::change(opt, recs, cfg, dims);
}
TrimStrategy::Truncate { suffix } => {
let mut truncate = Width::truncate(use_width);
@ -496,9 +493,8 @@ fn trim_as_header(
truncate = truncate.suffix(suffix).suffix_try_color(true);
}
Modify::new(Columns::single(i))
.with(truncate)
.change(recs, cfg, dims);
let opt = Modify::new(Columns::single(i)).with(truncate);
TableOption::<VecRecords<Text<String>>, _, _>::change(opt, recs, cfg, dims);
}
}
}
@ -579,19 +575,21 @@ fn load_theme(
let mut theme = theme.get_theme();
if !with_header {
theme.set_horizontals(std::collections::HashMap::new());
} else if with_footer && table.count_rows() > 2 {
if let Some(line) = theme.get_horizontal(1) {
theme.insert_horizontal(table.count_rows() - 1, line);
}
theme.set_horizontal_lines(Default::default());
}
table.with(theme);
if let Some(style) = sep_color {
let color = convert_style(style);
let color = AnsiColor::from(color);
table.get_config_mut().set_border_color_global(color);
let color = ANSIBuf::from(color);
table.get_config_mut().set_border_color_default(color);
}
if !with_header {
table.with(RemoveHorizontalLine);
} else if with_footer {
table.with(CopyFirstHorizontalLineAtLast);
}
}
@ -853,10 +851,6 @@ fn truncate_columns_by_head(
pub struct PriorityMax;
impl Peaker for PriorityMax {
fn create() -> Self {
Self
}
fn peak(&mut self, _: &[usize], widths: &[usize]) -> Option<usize> {
let col = (0..widths.len()).rev().max_by_key(|&i| widths[i]);
col.filter(|&col| widths[col] != 0)
@ -881,7 +875,7 @@ fn push_empty_column(data: &mut NuRecords) {
let records = std::mem::take(data);
let mut inner: Vec<Vec<_>> = records.into();
let empty_cell = CellInfo::new(String::from("..."));
let empty_cell = Text::new(String::from("..."));
for row in &mut inner {
row.push(empty_cell.clone());
}
@ -920,7 +914,7 @@ fn convert_alignment(alignment: nu_color_config::Alignment) -> AlignmentHorizont
struct SetAlignment(AlignmentHorizontal, Entity);
impl<R, D> TableOption<R, D, ColoredConfig> for SetAlignment {
impl<R, D> TableOption<R, ColoredConfig, D> for SetAlignment {
fn change(self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
cfg.set_alignment_horizontal(self.1, self.0);
}
@ -928,7 +922,7 @@ impl<R, D> TableOption<R, D, ColoredConfig> for SetAlignment {
struct SetDimensions(Vec<usize>);
impl<R> TableOption<R, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetDimensions {
impl<R> TableOption<R, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetDimensions {
fn change(self, _: &mut R, _: &mut ColoredConfig, dims: &mut CompleteDimensionVecRecords<'_>) {
dims.set_widths(self.0);
}
@ -951,7 +945,7 @@ fn build_width(records: &NuRecords, pad: usize) -> Vec<usize> {
struct GetRow(usize, Vec<String>);
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for &mut GetRow {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for &mut GetRow {
fn change(
self,
recs: &mut NuRecords,
@ -965,7 +959,7 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
struct GetRowSettings(usize, AlignmentHorizontal, Option<Color>);
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig>
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>>
for &mut GetRowSettings
{
fn change(
@ -1007,7 +1001,7 @@ impl SetLineHeaders {
}
}
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for SetLineHeaders {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for SetLineHeaders {
fn change(
self,
recs: &mut NuRecords,
@ -1020,7 +1014,7 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
columns = columns
.into_iter()
.zip(widths.iter().map(|w| w.checked_sub(2).unwrap_or(*w))) // exclude padding; which is generally 2
.map(|(s, width)| Truncate::truncate_text(&s, width).into_owned())
.map(|(s, width)| Truncate::truncate(&s, width).into_owned())
.collect();
}
None => {
@ -1065,7 +1059,7 @@ impl MoveRowPrev {
}
}
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for MoveRowNext {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for MoveRowNext {
fn change(
self,
recs: &mut NuRecords,
@ -1076,7 +1070,7 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
}
}
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for MoveRowPrev {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for MoveRowPrev {
fn change(
self,
recs: &mut NuRecords,
@ -1193,9 +1187,11 @@ fn set_column_names(
align: AlignmentHorizontal,
color: Option<Color>,
) {
let mut names = ColumnNames::new(head).set_line(line).set_alignment(align);
let mut names = ColumnNames::new(head)
.line(line)
.alignment(Alignment::from(align));
if let Some(color) = color {
names = names.set_color(color);
names = names.color(color);
}
ColumnNames::change(names, records, cfg, dims)
@ -1214,7 +1210,7 @@ fn remove_row(recs: &mut NuRecords, row: usize) -> Vec<String> {
struct StripColorFromRow(usize);
impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for StripColorFromRow {
impl TableOption<NuRecords, ColoredConfig, CompleteDimensionVecRecords<'_>> for StripColorFromRow {
fn change(
self,
recs: &mut NuRecords,
@ -1222,7 +1218,32 @@ impl TableOption<NuRecords, CompleteDimensionVecRecords<'_>, ColoredConfig> for
_: &mut CompleteDimensionVecRecords<'_>,
) {
for cell in &mut recs[self.0] {
*cell = CellInfo::new(strip_ansi_unlikely(cell.as_ref()).into_owned());
*cell = Text::new(strip_ansi_unlikely(cell.as_ref()).into_owned());
}
}
}
struct RemoveHorizontalLine;
impl<D> TableOption<NuRecords, ColoredConfig, D> for RemoveHorizontalLine {
fn change(self, recs: &mut NuRecords, cfg: &mut ColoredConfig, _: &mut D) {
cfg.remove_horizontal_line(1, recs.count_rows());
}
}
struct CopyFirstHorizontalLineAtLast;
impl<D> TableOption<NuRecords, ColoredConfig, D> for CopyFirstHorizontalLineAtLast {
fn change(self, recs: &mut NuRecords, cfg: &mut ColoredConfig, _: &mut D) {
if recs.count_rows() <= 2 {
return;
}
let line = match cfg.get_horizontal_line(1) {
Some(line) => *line,
None => return,
};
cfg.insert_horizontal_line(recs.count_rows() - 1, line);
}
}

View File

@ -1,107 +1,78 @@
use tabled::settings::style::{HorizontalLine, Line, RawStyle, Style};
use tabled::settings::style::{HorizontalLine, Style};
use tabled::settings::themes::Theme;
#[derive(Debug, Clone)]
pub struct TableTheme {
theme: RawStyle,
full_theme: RawStyle,
theme: Theme,
full_theme: Theme,
has_inner: bool,
}
impl TableTheme {
pub fn basic() -> TableTheme {
pub fn new(theme: impl Into<Theme>, full_theme: impl Into<Theme>, has_inner: bool) -> Self {
Self {
theme: Style::ascii().into(),
full_theme: Style::ascii().into(),
has_inner: true,
theme: theme.into(),
full_theme: full_theme.into(),
has_inner,
}
}
pub fn basic() -> TableTheme {
Self::new(Style::ascii(), Style::ascii(), true)
}
pub fn thin() -> TableTheme {
Self {
theme: Style::modern().into(),
full_theme: Style::modern().into(),
has_inner: true,
}
Self::new(Style::modern(), Style::modern(), true)
}
pub fn light() -> TableTheme {
let theme = Style::blank()
.horizontals([HorizontalLine::new(
1,
Line::new(Some('─'), Some('─'), None, None),
)])
.into();
Self {
theme,
full_theme: Style::modern().into(),
has_inner: true,
}
let mut theme = Theme::from_style(Style::blank());
theme.insert_horizontal_line(1, HorizontalLine::new('─').intersection('─'));
Self::new(theme, Style::modern(), true)
}
pub fn psql() -> TableTheme {
Self {
theme: Style::psql().into(),
full_theme: Style::psql().into(),
has_inner: true,
}
Self::new(Style::psql(), Style::psql(), true)
}
pub fn markdown() -> TableTheme {
Self {
theme: Style::markdown().into(),
full_theme: Style::markdown().into(),
has_inner: true,
}
Self::new(Style::markdown(), Style::markdown(), true)
}
pub fn dots() -> TableTheme {
let theme = Style::dots().remove_horizontal().into();
Self {
theme,
full_theme: Style::dots().into(),
has_inner: true,
}
let theme = Style::dots().remove_horizontal();
Self::new(theme, Style::dots(), true)
}
pub fn restructured() -> TableTheme {
Self {
theme: Style::re_structured_text().into(),
full_theme: Style::re_structured_text().into(),
has_inner: true,
}
Self::new(
Style::re_structured_text(),
Style::re_structured_text(),
true,
)
}
pub fn ascii_rounded() -> TableTheme {
Self {
theme: Style::ascii_rounded().into(),
full_theme: Style::ascii_rounded().into(),
has_inner: true,
}
Self::new(Style::ascii_rounded(), Style::ascii_rounded(), true)
}
pub fn basic_compact() -> TableTheme {
let theme = Style::ascii().remove_horizontal().into();
Self {
theme,
full_theme: Style::ascii().into(),
has_inner: true,
}
let theme = Style::ascii().remove_horizontal();
Self::new(theme, Style::ascii(), true)
}
pub fn compact() -> TableTheme {
let hline = HorizontalLine::inherit(Style::modern().remove_left().remove_right());
let theme = Style::modern()
.remove_left()
.remove_right()
.remove_horizontal()
.horizontals([HorizontalLine::new(1, Style::modern().get_horizontal())
.left(None)
.right(None)])
.into();
Self {
theme,
full_theme: Style::modern().into(),
has_inner: true,
}
.horizontals([(1, hline)]);
Self::new(theme, Style::modern(), true)
}
pub fn with_love() -> TableTheme {
@ -109,10 +80,7 @@ impl TableTheme {
.top('❤')
.bottom('❤')
.vertical('❤')
.horizontals([HorizontalLine::new(
1,
Line::new(Some('❤'), Some('❤'), None, None),
)]);
.horizontals([(1, HorizontalLine::new('❤').intersection('❤'))]);
let full_theme = Style::empty()
.top('❤')
@ -131,53 +99,40 @@ impl TableTheme {
.intersection_left('❤')
.intersection('❤');
Self {
theme: theme.into(),
full_theme: full_theme.into(),
has_inner: true,
}
Self::new(theme, full_theme, true)
}
pub fn compact_double() -> TableTheme {
let hline = HorizontalLine::inherit(Style::extended())
.remove_left()
.remove_right();
let theme = Style::extended()
.remove_left()
.remove_right()
.remove_horizontal()
.horizontals([HorizontalLine::new(1, Style::extended().get_horizontal())
.left(None)
.right(None)])
.into();
Self {
theme,
full_theme: Style::extended().into(),
has_inner: true,
}
.horizontals([(1, hline)]);
Self::new(theme, Style::extended(), true)
}
pub fn rounded() -> TableTheme {
Self {
theme: Style::rounded().into(),
full_theme: Style::modern()
let full = Style::modern()
.corner_top_left('╭')
.corner_top_right('╮')
.corner_bottom_left('╰')
.corner_bottom_right('╯')
.into(),
has_inner: true,
}
.corner_bottom_right('╯');
Self::new(Style::rounded(), full, true)
}
pub fn reinforced() -> TableTheme {
let full_theme = Style::modern()
let full = Style::modern()
.corner_top_left('┏')
.corner_top_right('┓')
.corner_bottom_left('┗')
.corner_bottom_right('┛');
Self {
theme: full_theme.clone().remove_horizontal().into(),
full_theme: full_theme.into(),
has_inner: true,
}
Self::new(full.clone().remove_horizontal(), full, true)
}
pub fn heavy() -> TableTheme {
@ -193,48 +148,32 @@ impl TableTheme {
.corner_top_right('┓')
.corner_bottom_left('┗')
.corner_bottom_right('┛')
.horizontals([HorizontalLine::new(1, Line::full('━', '╋', '┣', '┫'))]);
let full_theme = theme
.horizontals([(1, HorizontalLine::full('━', '╋', '┣', '┫'))]);
let full = theme
.clone()
.remove_horizontals()
.horizontal('━')
.intersection_left('┣')
.intersection_right('┫')
.intersection('╋');
Self {
theme: theme.into(),
full_theme: full_theme.into(),
has_inner: true,
}
Self::new(theme, full, true)
}
pub fn none() -> TableTheme {
Self {
theme: Style::blank().into(),
full_theme: Style::blank().into(),
has_inner: true,
}
Self::new(Style::blank(), Style::blank(), true)
}
pub fn has_top_line(&self) -> bool {
self.theme.get_top().is_some()
|| self.theme.get_top_intersection().is_some()
|| self.theme.get_top_left().is_some()
|| self.theme.get_top_right().is_some()
pub fn has_top(&self) -> bool {
self.theme.borders_has_top()
}
pub fn has_left(&self) -> bool {
self.theme.get_left().is_some()
|| self.theme.get_left_intersection().is_some()
|| self.theme.get_top_left().is_some()
|| self.theme.get_bottom_left().is_some()
self.theme.borders_has_left()
}
pub fn has_right(&self) -> bool {
self.theme.get_right().is_some()
|| self.theme.get_right_intersection().is_some()
|| self.theme.get_top_right().is_some()
|| self.theme.get_bottom_right().is_some()
self.theme.borders_has_right()
}
pub fn has_inner(&self) -> bool {
@ -245,11 +184,11 @@ impl TableTheme {
self.full_theme.get_borders().has_horizontal()
}
pub fn get_theme_full(&self) -> RawStyle {
pub fn get_theme_full(&self) -> Theme {
self.full_theme.clone()
}
pub fn get_theme(&self) -> RawStyle {
pub fn get_theme(&self) -> Theme {
self.theme.clone()
}
}

View File

@ -358,7 +358,7 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> StringResult {
// we could use Padding for it but,
// the easiest way to do so is just push a new_line char before
let mut key = key.to_owned();
if !key.is_empty() && is_expanded && theme.has_top_line() {
if !key.is_empty() && is_expanded && theme.has_top() {
key.insert(0, '\n');
}

View File

@ -3,11 +3,11 @@ use nu_color_config::StyleComputer;
use nu_protocol::{Config, Record, Span, Value};
use tabled::{
grid::{
color::{AnsiColor, StaticColor},
ansi::{ANSIBuf, ANSIStr},
config::{AlignmentHorizontal, Borders, CompactMultilineConfig},
dimension::{DimensionPriority, PoolTableDimension},
},
settings::{style::RawStyle, Color, Padding, TableOption},
settings::{Color, Padding, TableOption, Theme},
tables::{PoolTable, TableValue},
};
@ -53,7 +53,7 @@ fn build_table(
let mut table = PoolTable::from(val);
let mut theme = theme.get_theme_full();
theme.set_horizontals(std::collections::HashMap::default());
theme.set_horizontal_lines(Default::default());
table.with(Padding::new(indent.0, indent.1, 0, 0));
table.with(SetRawStyle(theme));
@ -73,12 +73,13 @@ fn build_table(
// We just need this unsafe section to cope with some limitations of [`PoolTable`].
// Mitigation of this is definitely on a todo list.
let color: AnsiColor<'_> = color.into();
let color: ANSIBuf = color.into();
let prefix = color.get_prefix();
let suffix = color.get_suffix();
let prefix: &'static str = unsafe { std::mem::transmute(prefix) };
let suffix: &'static str = unsafe { std::mem::transmute(suffix) };
table.with(SetBorderColor(StaticColor::new(prefix, suffix)));
table.with(SetBorderColor(ANSIStr::new(prefix, suffix)));
let table = table.to_string();
return table;
@ -217,29 +218,29 @@ fn get_columns_in_record(vals: &[Value]) -> Vec<String> {
}
}
struct SetRawStyle(RawStyle);
struct SetRawStyle(Theme);
impl<R, D> TableOption<R, D, CompactMultilineConfig> for SetRawStyle {
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 = cfg.set_borders(borders);
let borders = *self.0.get_borders();
cfg.set_borders(borders);
}
}
struct SetBorderColor(StaticColor);
struct SetBorderColor(ANSIStr<'static>);
impl<R, D> TableOption<R, D, CompactMultilineConfig> for SetBorderColor {
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 = cfg.set_borders_color(borders);
cfg.set_borders_color(borders);
}
}
struct SetAlignment(AlignmentHorizontal);
impl<R, D> TableOption<R, D, CompactMultilineConfig> for SetAlignment {
impl<R, D> TableOption<R, CompactMultilineConfig, D> for SetAlignment {
fn change(self, _: &mut R, cfg: &mut CompactMultilineConfig, _: &mut D) {
*cfg = cfg.set_alignment_horizontal(self.0);
cfg.set_alignment_horizontal(self.0);
}
}

View File

@ -2,7 +2,9 @@ use nu_color_config::StyleComputer;
use tabled::{
builder::Builder,
grid::{
color::AnsiColor, records::vec_records::CellInfo, util::string::string_width_multiline,
ansi::{ANSIBuf, ANSIStr},
records::vec_records::Text,
util::string::get_text_width,
},
settings::{width::Truncate, Color, Modify, Padding, Style, Width},
};
@ -10,7 +12,7 @@ use tabled::{
use crate::common::get_leading_trailing_space_style;
pub fn string_width(text: &str) -> usize {
string_width_multiline(text)
get_text_width(text)
}
pub fn string_wrap(text: &str, width: usize, keep_words: bool) -> String {
@ -24,7 +26,7 @@ pub fn string_wrap(text: &str, width: usize, keep_words: bool) -> String {
}
let wrap = if keep_words {
Width::wrap(width).keep_words()
Width::wrap(width).keep_words(true)
} else {
Width::wrap(width)
};
@ -45,7 +47,7 @@ pub fn string_truncate(text: &str, width: usize) -> String {
None => return String::new(),
};
Truncate::truncate_text(line, width).into_owned()
Truncate::truncate(line, width).into_owned()
}
pub fn clean_charset(text: &str) -> String {
@ -53,24 +55,26 @@ pub fn clean_charset(text: &str) -> String {
text.replace('\t', " ").replace('\r', "")
}
pub fn colorize_space(data: &mut [Vec<CellInfo<String>>], style_computer: &StyleComputer<'_>) {
pub fn colorize_space(data: &mut [Vec<Text<String>>], style_computer: &StyleComputer<'_>) {
if let Some(style) = get_leading_trailing_space_style(style_computer).color_style {
let style = convert_style(style).into();
colorize_lead_trail_space(data, Some(&style), Some(&style));
let style = ANSIBuf::from(convert_style(style));
let style = style.as_ref();
colorize_lead_trail_space(data, Some(style), Some(style));
}
}
pub fn colorize_space_str(text: &mut String, style_computer: &StyleComputer<'_>) {
if let Some(style) = get_leading_trailing_space_style(style_computer).color_style {
let style = convert_style(style).into();
*text = colorize_space_one(text, Some(&style), Some(&style));
let style = ANSIBuf::from(convert_style(style));
let style = style.as_ref();
*text = colorize_space_one(text, Some(style), Some(style));
}
}
fn colorize_lead_trail_space(
data: &mut [Vec<CellInfo<String>>],
lead: Option<&AnsiColor<'_>>,
trail: Option<&AnsiColor<'_>>,
data: &mut [Vec<Text<String>>],
lead: Option<ANSIStr<'_>>,
trail: Option<ANSIStr<'_>>,
) {
if lead.is_none() && trail.is_none() {
return;
@ -79,16 +83,12 @@ fn colorize_lead_trail_space(
for row in data.iter_mut() {
for cell in row {
let buf = colorize_space_one(cell.as_ref(), lead, trail);
*cell = CellInfo::new(buf);
*cell = Text::new(buf);
}
}
}
fn colorize_space_one(
text: &str,
lead: Option<&AnsiColor<'_>>,
trail: Option<&AnsiColor<'_>>,
) -> String {
fn colorize_space_one(text: &str, lead: Option<ANSIStr<'_>>, trail: Option<ANSIStr<'_>>) -> String {
use fancy_regex::Captures;
use fancy_regex::Regex;
use once_cell::sync::Lazy;

View File

@ -1,7 +1,7 @@
#![allow(dead_code)]
use nu_table::{string_width, NuTable, NuTableConfig};
use tabled::grid::records::vec_records::CellInfo;
use tabled::grid::records::vec_records::Text;
pub struct TestCase {
cfg: NuTableConfig,
@ -19,7 +19,7 @@ impl TestCase {
}
}
type Data = Vec<Vec<CellInfo<String>>>;
type Data = Vec<Vec<Text<String>>>;
pub fn test_table<I: IntoIterator<Item = TestCase>>(data: Data, tests: I) {
for (i, test) in tests.into_iter().enumerate() {
@ -42,15 +42,15 @@ pub fn create_table(data: Data, config: NuTableConfig, termwidth: usize) -> Opti
table.draw(config, termwidth)
}
pub fn create_row(count_columns: usize) -> Vec<CellInfo<String>> {
pub fn create_row(count_columns: usize) -> Vec<Text<String>> {
let mut row = Vec::with_capacity(count_columns);
for i in 0..count_columns {
row.push(CellInfo::new(i.to_string()));
row.push(Text::new(i.to_string()));
}
row
}
pub fn cell(text: &str) -> CellInfo<String> {
CellInfo::new(text.to_string())
pub fn cell(text: &str) -> Text<String> {
Text::new(text.to_string())
}

View File

@ -3,7 +3,7 @@ mod common;
use common::{create_row, test_table, TestCase};
use nu_protocol::TrimStrategy;
use nu_table::{NuTable, NuTableConfig, TableTheme as theme};
use tabled::grid::records::vec_records::CellInfo;
use tabled::grid::records::vec_records::Text;
#[test]
fn data_and_header_has_different_size_doesnt_work() {
@ -194,7 +194,7 @@ fn width_control_test_0() {
test_width(data, &tests);
}
fn test_width(data: Vec<Vec<CellInfo<String>>>, tests: &[(usize, &str)]) {
fn test_width(data: Vec<Vec<Text<String>>>, tests: &[(usize, &str)]) {
let config = NuTableConfig {
theme: theme::heavy(),
trim: TrimStrategy::truncate(Some(String::from("..."))),

View File

@ -2,7 +2,7 @@ mod common;
use common::create_row as row;
use nu_table::{NuTable, NuTableConfig, TableTheme as theme};
use tabled::grid::records::vec_records::CellInfo;
use tabled::grid::records::vec_records::Text;
#[test]
fn test_rounded() {
@ -451,7 +451,7 @@ fn test_with_love() {
assert_eq!(create_table_with_size(vec![], true, theme::with_love()), "");
}
fn create_table(data: Vec<Vec<CellInfo<String>>>, with_header: bool, theme: theme) -> String {
fn create_table(data: Vec<Vec<Text<String>>>, with_header: bool, theme: theme) -> String {
let config = NuTableConfig {
theme,
with_header,
@ -463,11 +463,7 @@ fn create_table(data: Vec<Vec<CellInfo<String>>>, with_header: bool, theme: them
out.expect("not expected to get None")
}
fn create_table_with_size(
data: Vec<Vec<CellInfo<String>>>,
with_header: bool,
theme: theme,
) -> String {
fn create_table_with_size(data: Vec<Vec<Text<String>>>, with_header: bool, theme: theme) -> String {
let config = NuTableConfig {
theme,
with_header,