[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
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,