Repository: Nukesor/comfy-table
Pull request #163 (2024-12-14 22:38:05)

feat: added truncation_indicator


Patch:
diff --git a/src/table.rs b/src/table.rs
index aa4dfba..3410ec1 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -29,6 +29,7 @@ pub struct Table {
     pub(crate) rows: Vec<Row>,
     pub(crate) arrangement: ContentArrangement,
     pub(crate) delimiter: Option<char>,
+    pub(crate) truncation_indicator: String,
     #[cfg(feature = "tty")]
     no_tty: bool,
     #[cfg(feature = "tty")]
@@ -63,6 +64,7 @@ impl Table {
             rows: Vec::new(),
             arrangement: ContentArrangement::Disabled,
             delimiter: None,
+            truncation_indicator: "...".to_string(),
             #[cfg(feature = "tty")]
             no_tty: false,
             #[cfg(feature = "tty")]
@@ -316,6 +318,15 @@ impl Table {
         self
     }
 
+    /// Set the truncation indicator for cells that are too long to be displayed.
+    ///
+    /// Set it to "…" for example to use an ellipsis that only takes up one character.
+    pub fn set_truncation_indicator(&mut self, indicator: &str) -> &mut Self {
+        self.truncation_indicator = indicator.to_string();
+
+        self
+    }
+
     /// In case you are sure you don't want export tables to a tty or you experience
     /// problems with tty specific code, you can enforce a non_tty mode.
     ///
diff --git a/src/utils/formatting/content_format.rs b/src/utils/formatting/content_format.rs
index 552b95b..5aea699 100644
--- a/src/utils/formatting/content_format.rs
+++ b/src/utils/formatting/content_format.rs
@@ -120,12 +120,13 @@ pub fn format_row(
                 // Don't do anything if the column is smaller then 6 characters
                 let width: usize = info.content_width.into();
                 if width >= 6 {
-                    // Truncate the line if '...' doesn't fit
-                    if last_line.width() >= width - 3 {
-                        let surplus = (last_line.width() + 3) - width;
+                    let indicator_width = table.truncation_indicator.width();
+                    // Truncate the line if indicator doesn't fit
+                    if last_line.width() >= width - indicator_width {
+                        let surplus = (last_line.width() + indicator_width) - width;
                         last_line.truncate(last_line.width() - surplus);
                     }
-                    last_line.push_str("...");
+                    last_line.push_str(&table.truncation_indicator);
                 }
             }
         }


Test patch:
diff --git a/tests/all/content_arrangement_test.rs b/tests/all/content_arrangement_test.rs
index a30d750..2f1d625 100644
--- a/tests/all/content_arrangement_test.rs
+++ b/tests/all/content_arrangement_test.rs
@@ -124,6 +124,61 @@ fn table_with_truncate() {
     assert_eq!(expected, "\n".to_string() + &table.to_string());
 }
 
+#[test]
+fn table_with_truncate_indicator() {
+    let mut table = Table::new();
+    let mut first_row: Row = Row::from(vec![
+        "This is a very long line with a lot of text",
+        "This is anotherverylongtextwithlongwords text",
+        "smol",
+    ]);
+    first_row.max_height(4);
+
+    let mut second_row = Row::from(vec![
+        "Now let's\nadd a really long line in the middle of the cell \n and add more multi line stuff",
+        "This is another text",
+        "smol",
+    ]);
+    second_row.max_height(4);
+
+    table
+        .set_header(vec!["Header1", "Header2", "Head"])
+        .set_content_arrangement(ContentArrangement::Dynamic)
+        .set_truncation_indicator("…")
+        .set_width(35)
+        .add_row(first_row)
+        .add_row(second_row);
+
+    // The first column will be wider than 6 chars.
+    // The second column's content is wider than 6 chars. There should be a '…'.
+    let second_column = table.column_mut(1).unwrap();
+    second_column.set_constraint(Absolute(Fixed(8)));
+
+    // The third column's content is less than 6 chars width. There shouldn't be a '…'.
+    let third_column = table.column_mut(2).unwrap();
+    third_column.set_constraint(Absolute(Fixed(7)));
+
+    println!("{table}");
+    let expected = "
++----------------+--------+-------+
+| Header1        | Header | Head  |
+|                | 2      |       |
++=================================+
+| This is a very | This   | smol  |
+| long line with | is ano |       |
+| a lot of text  | therve |       |
+|                | rylon… |       |
+|----------------+--------+-------|
+| Now let's      | This   | smol  |
+| add a really   | is ano |       |
+| long line in   | ther   |       |
+| the middle of… | text   |       |
++----------------+--------+-------+";
+    println!("{expected}");
+    assert_table_line_width(&table, 35);
+    assert_eq!(expected, "\n".to_string() + &table.to_string());
+}
+
 /// This table checks the scenario, where a column has a big max_width, but a lot of the assigned
 /// space doesn't get used after splitting the lines. This happens mostly when there are
 /// many long words in a single column.