Column width interaction of ansi_term and tabled crates

I've run into a problem formatting terminal output. I'm using the ansi_term and tabled crates together. Here's a minimal example:

use ansi_term::Style;
use tabled::{Table, Tabled};

#[derive(Tabled)]
struct Row {
    column: String,
}

fn main() {
    let normal_text = String::from("Normal text");
    let italic_text: String = Style::new().italic().paint("Italicised").to_string();
    let rows = vec![Row { column: normal_text }, Row { column: italic_text }];
    let table = Table::new(rows);
    println!("{table}");
}

Which produces correctly italicized output, but the columns don't line up.

+--------------------+
| column             |
+--------------------+
| Normal text        |
+--------------------+
| Italicised |
+--------------------+

Any idea what might be happening here?

Thanks again!

The problem is almost certainly that tabled is measuring the string width without expecting there to be ANSI codes (thus including their data, that is invisible when sent to the terminal, in the width). To avoid this problem, you must do one of these things:

  1. Use a width measurement that parses ANSI codes. Checking the documentation and source of tabled, it seems that enabling the ansi feature will do that, but the documentation isn’t clear about what it actually does.
  2. Use a layout algorithm that is aware of styled text before it is formatted as ANSI codes (e.g. use ratatui instead of both libraries).
  3. Measure the original string without any styling, then use that width for layout, but print the styled text. I don’t know if you can do this while still using tabled.