Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Span::column() with the Style::modern() causes virtual artifact on the intersection in the table #399

Open
fbonin opened this issue Mar 30, 2024 · 8 comments
Labels
question Further information is requested

Comments

@fbonin
Copy link
Contributor

fbonin commented Mar 30, 2024

Using Span::column() with the Style::modern() causes virtual artifact on the intersection in the table

To reproduce :

let mut builder = Builder::default();

let mut title = Vec::with_capacity(1);
title.push("Title");
builder.push_record(title);

let mut header = Vec::with_capacity(4);
header.push("header-1");
header.push("header-2");
header.push("header-3");
header.push("header-4");
builder.push_record(header);

let mut record = Vec::with_capacity(4);
record.push("value-1");
record.push("value-2");
record.push("value-3");
record.push("value-4");
builder.push_record(record);

let mut table = builder.build();
table    
.modify((0, 0), Span::column(4))
    .modify((0, 0), Alignment::center())
    .with(Style::modern())
    .to_string();
println!("{}", table);

Artifacts on the header at the intersection :

image

Expected :

image
@zhiburt zhiburt added the question Further information is requested label Mar 30, 2024
@zhiburt
Copy link
Owner

zhiburt commented Mar 30, 2024

Hi @fbonin

That's actually by design.

Try to use tabled::settings::style::BorderSpanCorrection afterwards.

Let me know if it helped.


Yes I've just noticed it's not stated in README.md.
If you want to you can open a PR

Take care

@fbonin
Copy link
Contributor Author

fbonin commented Mar 30, 2024

Thank you !

@mkatychev
Copy link

mkatychev commented Apr 23, 2024

Just a heads up, BorderSpanCorrection doesn't work on all styles:

use tabled::{
    settings::{
        style::{BorderSpanCorrection, Style},
        Modify, Span,
    },
    Table,
};

fn main() {
    let data = vec![("09", "June", "2022"), ("10", "July", "2022")];

    let mut table = Table::new(&data);
    table
        .with(Modify::new((0, 0)).with("date").with(Span::column(3)))
        .with(BorderSpanCorrection);
    println!("{}", table.to_string());
    table.with(Style::modern());
    println!("{}", table.to_string());
}
$ cargo run

+------------------+
| date             |
+----+------+------+
| 09 | June | 2022 |
+----+------+------+
| 10 | July | 2022 |
+----+------+------+
┌────┬──────┬──────┐
│ date             │
├────┼──────┼──────┤
│ 09 │ June │ 2022 │
├────┼──────┼──────┤
│ 10 │ July │ 2022 │
└────┴──────┴──────┘

@zhiburt
Copy link
Owner

zhiburt commented Apr 23, 2024

Hi @mkatychev

Good observation,
The thing is that you change style after BorderSpanCorrection make its changes.

So essentially you could call it one more time to fix it.
Or if you would make them after applying the style, you'd get a different result.

Yesssssssssss,
Surely this must be noted in documentation (ref #402)

You can help to update the doc yourself if you want to.

Let me know if that helps, and
Take care.

use tabled::{
    settings::{
        style::{BorderSpanCorrection, Style},
        Modify, Span,
    },
    Table,
};

fn main() {
    let data = vec![("09", "June", "2022"), ("10", "July", "2022")];

    let mut table = Table::new(data);
    table
        .with(Modify::new((0, 0)).with("date").with(Span::column(3)))
        .with(Style::modern());

    println!("{table}");
    
    table.with(BorderSpanCorrection);

    println!("{table}");
}
┌────┬──────┬──────┐
│ date             │
├────┼──────┼──────┤
│ 09 │ June │ 2022 │
├────┼──────┼──────┤
│ 10 │ July │ 2022 │
└────┴──────┴──────┘
┌──────────────────┐
│ date             │
├────┬──────┬──────┤
│ 09 │ June │ 2022 │
├────┼──────┼──────┤
│ 10 │ July │ 2022 │
└────┴──────┴──────┘

PS: Once again a good observation.

@zhiburt
Copy link
Owner

zhiburt commented Apr 23, 2024

Note

Could be done with Panel and Disable.

use tabled::{
    settings::{
        object::Rows,
        style::{BorderSpanCorrection, Style},
        Disable, Panel,
    },
    Table,
};

fn main() {
    let data = vec![("09", "June", "2022"), ("10", "July", "2022")];

    let mut table = Table::new(data);
    table
        .with(Disable::row(Rows::first()))
        .with(Panel::header("date"))
        .with(Style::modern());

    println!("{table}");

    table.with(BorderSpanCorrection);

    println!("{table}");
}

@zhiburt
Copy link
Owner

zhiburt commented Apr 23, 2024

Or like this without Disable and using Table::from_iter.

use std::iter::FromIterator;

use tabled::{
    settings::{
        style::{BorderSpanCorrection, Style},
        Panel,
    },
    Table,
};

fn main() {
    let data = vec![["09", "June", "2022"], ["10", "July", "2022"]];

    let mut table = Table::from_iter(data);
    table.with(Panel::header("date")).with(Style::modern());

    println!("{table}");

    table.with(BorderSpanCorrection);

    println!("{table}");
}

@mkatychev
Copy link

I can confirm the first approach worked flawlessly with 3 or more columns, thanks @zhiburt. Panel::corrected_header would be valuable as a convenience method although it seems that one needs a &mut Table to do these inside of Table::with.

@Alexdelia
Copy link
Contributor

@zhiburt , it seems that I found a similar issue with Span::row()

use tabled::{
	builder::Builder,
	settings::{
		object::Cell,
		style::{BorderSpanCorrection, HorizontalLine},
		Alignment, Modify, Span, Style, Theme,
	},
};

type TableRecord<'s> = [&'s str; 7];

const LABEL: &str = "label";
const TRAINING: &str = "training data";
const TESTING: &str = "test data";

const CORRECT: &str = "✓";
const TOTAL: &str = "#";
const PERCENT: &str = "%";
const HEADERS: TableRecord<'static> = ["", CORRECT, TOTAL, PERCENT, CORRECT, TOTAL, PERCENT];

fn main() {
	let mut builder = Builder::default();

	builder.push_record([""]);
	builder.push_record(HEADERS);
	builder.push_record(["Hufflepuff", "346", "348", "99.43%", "179", "181", "98.90%"]);
	builder.push_record(["Gryffindor", "210", "215", "97.67%", "108", "112", "96.43%"]);
	builder.push_record(["Ravenclaw", "304", "308", "98.70%", "131", "135", "97.04%"]);
	builder.push_record(["Slytherin", "190", "194", "97.94%", "103", "107", "96.26%"]);

	let mut table = builder.build();

	let mut theme = Theme::from_style(Style::rounded());
	theme.remove_horizontal_lines();
	theme.insert_horizontal_line(1, HorizontalLine::inherit(Style::modern()));
	theme.insert_horizontal_line(2, HorizontalLine::inherit(Style::modern()));

	table
		.with(
			Modify::new(Cell::new(0, 0))
				.with(Span::row(2))
				.with(Alignment::center_vertical())
				.with(LABEL),
		)
		.with(
			Modify::new(Cell::new(0, 1))
				.with(Span::column(3))
				.with(TRAINING),
		)
		.with(
			Modify::new(Cell::new(0, 4))
				.with(Span::column(3))
				.with(TESTING),
		)
		.with(theme)
		.with(Alignment::center_vertical())
		.with(Alignment::center())
		.with(BorderSpanCorrection);

	println!("{table}");
}

gives:

╭────────────┬────────────────────┬────────────────────╮
│            │   training data    │     test data      │
│   label    ┼─────┬─────┬────────┼─────┬─────┬────────┤
│            │  ✓  │  #  │   %    │  ✓  │  #  │   %    │
├────────────┼─────┼─────┼────────┼─────┼─────┼────────┤
│ Hufflepuff │ 346 │ 348 │ 99.43% │ 179 │ 181 │ 98.90% │
│ Gryffindor │ 210 │ 215 │ 97.67% │ 108 │ 112 │ 96.43% │
│ Ravenclaw  │ 304 │ 308 │ 98.70% │ 131 │ 135 │ 97.04% │
│ Slytherin  │ 190 │ 194 │ 97.94% │ 103 │ 107 │ 96.26% │
╰────────────┴─────┴─────┴────────┴─────┴─────┴────────╯

expected:

╭────────────┬────────────────────┬────────────────────╮
│            │   training data    │     test data      │
│   label    ├─────┬─────┬────────┼─────┬─────┬────────┤
│            │  ✓  │  #  │   %    │  ✓  │  #  │   %    │
├────────────┼─────┼─────┼────────┼─────┼─────┼────────┤
│ Hufflepuff │ 346 │ 348 │ 99.43% │ 179 │ 181 │ 98.90% │
│ Gryffindor │ 210 │ 215 │ 97.67% │ 108 │ 112 │ 96.43% │
│ Ravenclaw  │ 304 │ 308 │ 98.70% │ 131 │ 135 │ 97.04% │
│ Slytherin  │ 190 │ 194 │ 97.94% │ 103 │ 107 │ 96.26% │
╰────────────┴─────┴─────┴────────┴─────┴─────┴────────╯

fyi, Panel::vertical(0, Label) gives:

╭───────┬────────────────────────┬────────────────────┬────────╮
│       │     training data      │     test data      │        │
│       ┼────────────┬─────┬─────┼────────┬─────┬─────┼────────┤
│       │            │  ✓  │  #  │   %    │  ✓  │  #  │   %    │
│ label ┼────────────┼─────┼─────┼────────┼─────┼─────┼────────┤
│       │ Hufflepuff │ 346 │ 348 │ 99.43% │ 179 │ 181 │ 98.90% │
│       │ Gryffindor │ 210 │ 215 │ 97.67% │ 108 │ 112 │ 96.43% │
│       │ Ravenclaw  │ 304 │ 308 │ 98.70% │ 131 │ 135 │ 97.04% │
│       │ Slytherin  │ 190 │ 194 │ 97.94% │ 103 │ 107 │ 96.26% │
╰───────┴────────────┴─────┴─────┴────────┴─────┴─────┴────────╯

also, if I add color on border

example:

.with(BorderColor::filled(Color::new("\u{1b}[2;35m", "\u{1b}[0m")))

"label" inherit the color of the border, like LineText

if it's not a bug, would love to know where I made mistakes

and don't hesitate to point out other elements that I did not do optimally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants