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

handle ansi style in cell content #93

Merged
merged 13 commits into from
May 26, 2023
Merged
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ path = "examples/readme_table_no_tty.rs"
name = "readme_table"
path = "examples/readme_table.rs"

[[example]]
name = "inner_style"
path = "examples/inner_style.rs"
required-features = ["ansi"]

[features]
default = ["tty"]
tty = ["crossterm"]
ansi = ["console"]
# This flag is for library debugging only!
debug = []
# This feature is used to expose internal functionality for integration testing.
Expand All @@ -44,6 +50,7 @@ crossterm = { version = "0.25", optional = true }
strum = "0.24"
strum_macros = "0.24"
unicode-width = "0.1"
console = { version = "0.15.1", optional = true }

[dev-dependencies]
criterion = "0.4"
Expand Down
33 changes: 33 additions & 0 deletions examples/inner_style.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use comfy_table::{Cell, ContentArrangement, Row, Table};

fn main() {
let mut table = Table::new();
//table.load_preset(comfy_table::presets::NOTHING);
table.set_content_arrangement(ContentArrangement::Dynamic);
table.set_width(85);

let mut row = Row::new();
row.add_cell(Cell::new(format!(
"hello{}cell1",
console::style("123\n456").dim().blue()
)));
row.add_cell(Cell::new("cell2"));

table.add_row(row);

let mut row = Row::new();
row.add_cell(Cell::new(
format!(r"cell sys-devices-pci00:00-0000:000:07:00.1-usb2-2\x2d1-2\x2d1.3-2\x2d1.3:1.0-host2-target2:0:0-2:0:0:1-block-sdb{}", console::style(".device").bold().red())
));
row.add_cell(Cell::new(
"cell4 asdfasfsad asdfasdf sad fas df asdf as df asdf asdfasdfasdfasdfasdfasdfa dsfa sdf asdf asd f asdf as df sadf asd fas df "
));
table.add_row(row);

let mut row = Row::new();
row.add_cell(Cell::new("cell5"));
row.add_cell(Cell::new("cell6"));
table.add_row(row);

println!("{}", table);
}
17 changes: 12 additions & 5 deletions src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use crossterm::style::{Attribute, Color};

use crate::style::CellAlignment;

#[cfg(feature = "ansi")]
use crate::utils::fix_style_in_split_str;

/// A stylable table cell with content.
#[derive(Clone, Debug)]
pub struct Cell {
Expand All @@ -26,12 +29,16 @@ impl Cell {
/// Create a new Cell
#[allow(clippy::needless_pass_by_value)]
pub fn new<T: ToString>(content: T) -> Self {
let content = content.to_string();
#[cfg_attr(not(feature = "ansi"), allow(unused_mut))]
let mut split_content: Vec<String> = content.split('\n').map(ToString::to_string).collect();

// corrects ansi codes so style is terminated and resumed around the split
#[cfg(feature = "ansi")]
fix_style_in_split_str(&mut split_content);

Self {
content: content
.to_string()
.split('\n')
.map(ToString::to_string)
.collect(),
content: split_content,
delimiter: None,
alignment: None,
#[cfg(feature = "tty")]
Expand Down
13 changes: 9 additions & 4 deletions src/row.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::slice::Iter;

use unicode_width::UnicodeWidthStr;

use crate::cell::{Cell, Cells};
use crate::{
cell::{Cell, Cells},
utils::formatting::content_split::measure_text_width,
};

/// Each row contains [Cells](crate::Cell) and can be added to a [Table](crate::Table).
#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -63,7 +64,11 @@ impl Row {
// Each entry represents the longest string width for a cell.
cell.content
.iter()
.map(|string| string.width())
.map(|string| {
//let width = console::measure_text_width(string);
//println!("{} {} {}", width, &string, string.escape_debug());
measure_text_width(string)
})
.max()
.unwrap_or(0)
})
Expand Down
16 changes: 14 additions & 2 deletions src/utils/formatting/content_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
use crossterm::style::{style, Stylize};
use unicode_width::UnicodeWidthStr;

use super::content_split::measure_text_width;
use super::content_split::split_line;

use crate::cell::Cell;
use crate::row::Row;
use crate::style::CellAlignment;
use crate::table::Table;
use crate::utils::ColumnDisplayInfo;

#[cfg(feature = "ansi")]
use console::strip_ansi_codes;

pub fn delimiter(cell: &Cell, info: &ColumnDisplayInfo, table: &Table) -> char {
// Determine, which delimiter should be used
if let Some(delimiter) = cell.delimiter {
Expand Down Expand Up @@ -87,7 +92,7 @@ pub fn format_row(
// Iterate over each line and split it into multiple lines, if necessary.
// Newlines added by the user will be preserved.
for line in cell.content.iter() {
if line.width() > info.content_width.into() {
if measure_text_width(line) > info.content_width.into() {
let mut splitted = split_line(line, info, delimiter);
cell_lines.append(&mut splitted);
} else {
Expand All @@ -106,6 +111,13 @@ pub fn format_row(
.get_mut(lines - 1)
.expect("We know it's this long.");

// we are truncate the line, so we might cuttoff a ansi code
#[cfg(feature = "ansi")]
{
let stripped = strip_ansi_codes(last_line).to_string();
*last_line = stripped;
}

// Don't do anything if the collumn is smaller then 6 characters
let width: usize = info.content_width.into();
if width >= 6 {
Expand Down Expand Up @@ -177,7 +189,7 @@ pub fn format_row(
#[allow(unused_variables)]
fn align_line(table: &Table, info: &ColumnDisplayInfo, cell: &Cell, mut line: String) -> String {
let content_width = info.content_width;
let remaining: usize = usize::from(content_width).saturating_sub(line.width());
let remaining: usize = usize::from(content_width).saturating_sub(measure_text_width(&line));

// Apply the styling before aligning the line, if the user requests it.
// That way non-delimiter whitespaces won't have stuff like underlines.
Expand Down
Loading