:large_orange_diamond: Build beautiful terminal tables with automatic content wrapping

Overview

Comfy-table

GitHub Actions Workflow docs license Crates.io codecov

comfy-table

Comfy-table tries to provide utility for building beautiful tables, while being easy to use.

Features:

  • Dynamic arrangement of content to a specific width.
  • Content styling for terminals (Colors, Bold, Blinking, etc.).
  • Presets and preset modifiers to get you started.
  • Pretty much every part of the table is customizable (borders, lines, padding, alignment).
  • Constraints on columns that allow some additional control over how to arrange content.
  • Cross plattform (Linux, macOS, Windows).

Comfy-table is written for the current stable Rust version. Older Rust versions may work, but aren't officially supported.

Examples

use comfy_table::Table;

fn main() {
    let mut table = Table::new();
    table
        .set_header(vec!["Header1", "Header2", "Header3"])
        .add_row(vec![
                 "This is a text",
                 "This is another text",
                 "This is the third text",
        ])
        .add_row(vec![
                 "This is another text",
                 "Now\nadd some\nmulti line stuff",
                 "This is awesome",
        ]);

    println!("{}", table);
}

Create a very basic table.
This table will become as wide as your content, nothing fancy happening here.

+----------------------+----------------------+------------------------+
| Header1              | Header2              | Header3                |
+======================================================================+
| This is a text       | This is another text | This is the third text |
|----------------------+----------------------+------------------------|
| This is another text | Now                  | This is awesome        |
|                      | add some             |                        |
|                      | multi line stuff     |                        |
+----------------------+----------------------+------------------------+

More Features

use comfy_table::*;
use comfy_table::presets::UTF8_FULL;
use comfy_table::modifiers::UTF8_ROUND_CORNERS;

fn main() {
    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .apply_modifier(UTF8_ROUND_CORNERS)
        .set_content_arrangement(ContentArrangement::Dynamic)
        .set_table_width(40)
        .set_header(vec!["Header1", "Header2", "Header3"])
        .add_row(vec![
                 Cell::new("Center aligned").set_alignment(CellAlignment::Center),
                 Cell::new("This is another text"),
                 Cell::new("This is the third text"),
        ])
        .add_row(vec![
                 "This is another text",
                 "Now\nadd some\nmulti line stuff",
                 "This is awesome",
        ]);

    // Set the default alignment for the third column to right
    let column = table.get_column_mut(2).expect("Our table has three columns");
    column.set_cell_alignment(CellAlignment::Right);

    println!("{}", table);
}

Create a table with UTF8 styling, and apply a modifier, which gives the table round corners.
Additionall the content will dynamically wrap to maintain a given table width.
If the table width isn't explicitely set, the terminal size will be used, if this is executed in a terminal.

On top of this, we set the default alignment for the right column to Right and the Alignment of the left top cell to Center.

╭────────────┬────────────┬────────────╮
│ Header1    ┆ Header2    ┆    Header3 │
╞════════════╪════════════╪════════════╡
│  This is a ┆ This is    ┆    This is │
│    text    ┆ another    ┆  the third │
│            ┆ text       ┆       text │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ This is    ┆ Now        ┆    This is │
│ another    ┆ add some   ┆    awesome │
│ text       ┆ multi line ┆            │
│            ┆ stuff      ┆            │
╰────────────┴────────────┴────────────╯

Styling

use comfy_table::*;
use comfy_table::presets::UTF8_FULL;

fn main() {
    let mut table = Table::new();
    table.load_preset(UTF8_FULL)
        .set_content_arrangement(ContentArrangement::Dynamic)
        .set_table_width(80)
        .set_header(vec![
                    Cell::new("Header1").add_attribute(Attribute::Bold),
                    Cell::new("Header2").fg(Color::Green),
                    Cell::new("Header3"),
        ])
        .add_row(vec![
                 Cell::new("This is a bold text").add_attribute(Attribute::Bold),
                 Cell::new("This is a green text").fg(Color::Green),
                 Cell::new("This one has black background").bg(Color::Black),
        ])
        .add_row(vec![
                 Cell::new("Blinky boi").add_attribute(Attribute::SlowBlink),
                 Cell::new("This table's content is dynamically arranged. The table is exactly 80 characters wide.\nHere comes a reallylongwordthatshoulddynamicallywrap"),
                 Cell::new("COMBINE ALL THE THINGS")
                 .fg(Color::Green)
                 .bg(Color::Black)
                 .add_attributes(vec![
                                 Attribute::Bold,
                                 Attribute::SlowBlink,
                 ])
        ]);

    println!("{}", table);
}

This code generates the table that can be seen at the top of this Readme.

Code Examples

There is an example folder containing a few examples. To run an example, run it with run --example. E.g.:

cargo run --example readme_table

If you're looking for more information, take a look at the tests folder.
There is a test for almost every feature including a visual view for each resulting table.

Contribution Guidelines

Comfy-table is supposed to be minimalistic. A fixed set of features that just work, for a simple use-case:

  • Normal tables (columns, rows, one cell per column/row).
  • Dynamic arrangement of content to a given width.
  • Some kind of manual intervention in the arrangement process.

If you come up with an idea or an improvement, that fits into the current scope of the project, feel free to create an issue :)!

Some things however will most likely not be added to the project, since they drastically increase the complexity of the library or cover very specific edge-cases.

Such features are:

  • Nested tables
  • Cells that span over multiple columns/rows
  • CSV to table conversion and vice versa
Comments
  • How to get formatting of 0.5.1

    How to get formatting of 0.5.1

    We've tried updating comfytable in polars from 0.5.1 to 0.6.1 and only had to adapt a few method names, so that was great.

    However the table formatting changed. This made all our doctests fail. Given that it is a huge undertaking to update all of them, I wonder if we can get the old formatting behavior.

    An example of what we had:

        shape: (3, 3)
        ┌─────┬─────┬───────────┐
        │ a   ┆ b   ┆ b_squared │
        │ --- ┆ --- ┆ ---       │
        │ i64 ┆ i64 ┆ f64       │
        ╞═════╪═════╪═══════════╡
        │ 1   ┆ 2   ┆ 4.0       │
        ├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
        │ 3   ┆ 4   ┆ 16.0      │
        ├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
        │ 5   ┆ 6   ┆ 36.0      │
        └─────┴─────┴───────────┘
    
    -----------------------------
    

    And what we got after updating:

        shape: (3, 3)
        ┌─────┬─────┬─────────┐
        │ a   ┆ b   ┆ b_squar │
        │ --- ┆ --- ┆ ed      │
        │ i64 ┆ i64 ┆ ---     │
        │     ┆     ┆ f64     │
        ╞═════╪═════╪═════════╡
        │ 1   ┆ 2   ┆ 4.0     │
        ├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
        │ 3   ┆ 4   ┆ 16.0    │
        ├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
        │ 5   ┆ 6   ┆ 36.0    │
        └─────┴─────┴─────────┘
    

    Any ideas?

    t: bug 
    opened by ritchie46 18
  • Add support for cells with ansi codes.

    Add support for cells with ansi codes.

    I wanted to use comfy-table with cells that contain ANSI escape characters, generated with the colored crate. However, when calculating the width of a cell, the ANSI escape characters were counted as well, resulting in funny looking tables.

    By using textwrap's function to calculate the display width of a String, the tables have the correct cells and display correctly.

    opened by thvdveld 14
  • Efficient way to produce table from vector of structs?

    Efficient way to produce table from vector of structs?

    Hi, I'm experimenting with this library and I have a question. I have a vector containing custom structs, where each struct field should be a table column. I'm trying to figure out how to produce this table efficiently. Right now I'm basically doing this:

        let mut table = Table::new();
        table.load_preset(UTF8_FULL)
            .set_content_arrangement(ContentArrangement::Dynamic)
            .set_header(vec![
                Cell::new("a"),
                Cell::new("b"),
                Cell::new("c"),
                Cell::new("d"),
                Cell::new("e"),
                Cell::new("f"),
                Cell::new("g"),
            ]);
    
        // let things: Vec<Thing> = get_things(...);
        for d in things.iter() {
            table.add_row(vec![
                Cell::new(&d.a),
                Cell::new(&d.b),
                Cell::new(&d.c),
                Cell::new(&d.d),
                Cell::new(&d.e),
                Cell::new(&d.f),
                Cell::new(&d.g),
            ]);
        }
    

    This works, and produces the correct output, but it seems a little slow with ~670 structs in the vector. It gets a bit faster if I turn off dynamic layout, but without that feature the table is sized incorrectly so I think I need it to be enabled.

    1. Is there a more efficient way to load a vector of structs instead of iter + add_row? For example, I think the tabled crate can accept that data structure directly (maybe it's doing iter + add_row internally though I don't know)
    2. Is there a way to size the table to the terminal width without dynamic content arrangement (if that's actually the right choice regardless?)
    3. Do you have any other recommendations for this situation?
    opened by aharpervc 12
  • How to format special characters correctly?

    How to format special characters correctly?

    https://github.com/datafuselabs/datafuse/pull/1323

    preset: table.load_preset("||--+-++| ++++++");

    Cell::new(format!("{}", "✅ ".blue())); // error, missing spaces for padding. `.blue()` comes from `colored`
    

    error-pretty-table

    Cell::new(format!("{}", "✅ "));  // error, it looks like there is an extra blank character 
    

    wrong-pretty-table

    Cell::new(format!("{}", "☑")); or Cell::new("☑").fg(Color::Green); // ok, `CellAlignment::Center`, but i want ✅
    

    pretty-table

    opened by PsiACE 11
  • Comparison with other 'table' libraries

    Comparison with other 'table' libraries

    There are now a few libraries for pretty-printing tables to the console. It would be really helpful to have a bit of a comparison to allow users (including myself!) to determine which one to go for.

    opened by danieleades 9
  • Get the width of a column

    Get the width of a column

    I am wondering if it is possible to get the width of a column? I have a table like this:

    table
        .load_preset(UTF8_FULL)
        .apply_modifier(UTF8_ROUND_CORNERS)
        .set_content_arrangement(ContentArrangement::Dynamic);
    table.add_row(vec![Cell::new("Hello"), Cell::new("How do you do")]);
    

    And i would like to get the width of the second column of this table.

    opened by Mohammadreza99A 8
  • table.is_tty assumes stdout and doesn't work when stderr is tty

    table.is_tty assumes stdout and doesn't work when stderr is tty

    I dont know if my particular usecase is weird or not:

    • A shell function wraps the invocation of a rust program, like so
      foo() {
            eval "$(bar "$@")"
      }
      
    • but the rust program bar, outputs tables produced by this library to stderr. So I'd like to be able to still make use of the auto-detection of the terminal width / table width.

    Looking at the implementation, you pivot is_tty purely based off the stdout's tty. But I can, in fact use crossterm::terminal::size() directly, and send the width of that into table.set_table_width, and all appears to work just fine from there, because the output is all going to stderr.

    (Although i'm not a unix expert, but I almost think stderr would be a better default anyways to output these kinds of tables that are intended for human consumption)

    It's not obvious to me what the least disruptive way to enable this would be, but it'd be handy if either the default behavior could

    • only take heed of the not_tty's value before calling size() and don't bother checking is_tty (assuming size() returns Err when it couldn't i.e. neither were tty)
    • either fall back to stderr tty when stdout is false
    • allow me to call a method to set when tty ought to be true (the current api only lets one force disable it, not force enable it).

    Obviously, feel free to correct me if any of this is blatantly wrong!

    f: help wanted t: feature 
    opened by DanCardin 7
  • Tables print with middle lines

    Tables print with middle lines

    Using presets::ASCII_BORDERS_ONLY, whose sample table is:

    +---------------+
    | Hello   there |
    +===============+
    | a       b     |
    | c       d     |
    +---------------+
    

    I'm instead getting an empty middle row between each actual row:

    +-------------------------------+
    | timestamp   one   two   three |
    +===============================+
    | 2001000     12    15    19    |
    |                               |
    | 2001001     22    25    29    |
    |                               |
    | 2001002     32    35    39    |
    +-------------------------------+
    

    This is with v4.0.1. Is this a bug? Or some row padding section I'm not seeing?

    Thanks!

    opened by abreis 6
  • Avoiding wrapping contents

    Avoiding wrapping contents

    I think I must be missing something, but I can't figure out how to prevent the contents of cells from wrapping.

    Here's my code:

        let mut table = comfy_table::Table::new();
        table.set_table_width(100);
    
        table.set_header(&["", "redb", "lmdb", "sled"]);
    
        for (benchmark, _duration) in &redb_results {
            table.add_row(&[benchmark]);
        }
    
        for results in [redb_results, lmdb_results, sled_results] {
            for (i, (_benchmark, duration)) in results.iter().enumerate() {
                table
                    .get_row_mut(i)
                    .unwrap()
                    .add_cell(comfy_table::Cell::new(format!(
                        "{}ms",
                        duration.as_millis()
                    )));
            }
        }
    
        println!("{table}");
    

    And here's the table it prints:

    +--------------------+------+------+------+
    |                    | redb | lmdb | sled |
    +=========================================+
    | bulk load          | 4136 | 1235 | 1428 |
    |                    | ms   | ms   | 2ms  |
    |--------------------+------+------+------|
    | individual writes  | 50ms | 10ms | 3547 |
    |                    |      |      | ms   |
    |--------------------+------+------+------|
    | batch writes       | 5495 | 3010 | 1126 |
    |                    | ms   | ms   | 8ms  |
    |--------------------+------+------+------|
    | random reads       | 1106 | 1108 | 1703 |
    |                    | ms   | ms   | ms   |
    |--------------------+------+------+------|
    | random reads       | 926m | 1104 | 1518 |
    |                    | s    | ms   | ms   |
    |--------------------+------+------+------|
    | random reads       | 993m | 1219 | 1495 |
    |                    | s    | ms   | ms   |
    |--------------------+------+------+------|
    | random range reads | 1137 | 1481 | 2264 |
    |                    | ms   | ms   | ms   |
    |--------------------+------+------+------|
    | random range reads | 1144 | 1461 | 2317 |
    |                    | ms   | ms   | ms   |
    |--------------------+------+------+------|
    | random range reads | 1154 | 1422 | 2169 |
    |                    | ms   | ms   | ms   |
    |--------------------+------+------+------|
    | removals           | 2677 | 1004 | 2824 |
    |                    | ms   | ms   | ms   |
    +--------------------+------+------+------+
    

    I'd like the table to be wider to avoid wrapping the content of any of the cells. Is there a way to do this?

    opened by casey 5
  • Applying an underline only to the table heading, not the entire cell

    Applying an underline only to the table heading, not the entire cell

    The following code:

    let mut table = Table::new();
    table.load_preset(comfy_table::presets::NOTHING);
    table.set_header(vec![
        "A heading".bold(),
        "Column 1".bold(),
        "A slightly longer heading".bold(),
    ]);
    for i in 0..5 {
        let row: Vec<_> = (0..3).map(|j| format!("Row {} col {}", i, j)).collect();
        table.add_row(row);
    }
    

    produces a table with misaligned headings.

    screenshot-211107-202200

    If I coerce each row into a Vec<StyledContent<String>> by calling .reset() on the Strings:

    let mut table = Table::new();
    table.load_preset(comfy_table::presets::NOTHING);
    table.set_header(vec![
        "A heading".bold(),
        "Column 1".bold(),
        "A slightly longer heading".bold(),
    ]);
    for i in 0..5 {
        let row: Vec<_> = (0..3)
            .map(|j| format!("Row {} col {}", i, j).reset()) // Change.
            .collect();
        table.add_row(row);
    }
    

    the problem goes away.

    screenshot-211107-202527

    opened by david-perez 5
  • Syntax highlighting for in-table code snippets

    Syntax highlighting for in-table code snippets

    Is there any easy way that I can use bat (library) to render output of the table? This would greatly improve the aesthetic of the output and may even make the library way more ergonomic.

    t: enhancement 
    opened by Rudo2204 5
  • [Feature] Handle ANSI escape codes from external libraries

    [Feature] Handle ANSI escape codes from external libraries

    Describe the bug

    Column alignment breaks if printed text has formatting control codes.

    Expected behavior

    Text in a column contains parts formated with color/style using console crate. Alignment of later columns should be correct.

    Code

    use comfy_table::{Table, Row, Cell};
    use console::Style;
    
    fn main() {
        let mut table = Table::new();
        table.load_preset(comfy_table::presets::NOTHING);
        
        let mut row = Row::new();
        row.add_cell(Cell::new(
            "cell1"
        ));
        row.add_cell(Cell::new(
            "cell2"
        ));
    
        table.add_row(row);
    
        let mut row = Row::new();
        row.add_cell(Cell::new(
            format!("cell{}", console::style("3").bold().red())
        ));
        row.add_cell(Cell::new(
            "cell4"
        ));
        table.add_row(row);
    
        println!("{}", table);   
    }
    

    image

    Additional context

    • Operating System: nixos linux
    • comfy-table version: 6.1.0
    t: feature 
    opened by blueforesticarus 3
  • [Feature] Vertical alignment

    [Feature] Vertical alignment

    I'm honestly impressed by comfy-table, and it handled a multiline string like a champ. What I would like to ask is for the ability to set vertical alignment (perhaps through a new enum and method, perhaps through adding new values to CellAlignment).

    For example, in the table from this screenshot below, I would like the single line text in the header to be in the lower line, so that unit, status and state transition are all in the same line.

    image

    f: help wanted t: feature 
    opened by jaskij 4
  • [BUG] Handle minimum table width for multi-column utf-8 characters

    [BUG] Handle minimum table width for multi-column utf-8 characters

    This is a follow-up issue to #44.

    By default, if there's not enough space and dynamic mode is active, comfy-table falls back to a column with minimum-width of 1. However, if there are multi-column characters in the text, the format will break as the character doesn't fit into the line.

    Example:

    ╭───╮
    │   │
    ├╌╌╌┤
    │ ⺀ │
    ╰───╯
    

    This is a super rare edge-case and this will need quite a bit of special logic to be properly handled. This includes iterating through all characters of a column.

    I'm not sure if it's worth doing it. However, it's probably better to do so, even if it's just for the sake of consistency and correctness.

    This behavior will also show up if the user enforces a width of 1 for a column, but this is something we won't handle!

    t: bug f: help wanted 
    opened by Nukesor 0
Releases(v6.1.4)
  • v6.1.4(Dec 31, 2022)

  • v6.1.3(Nov 21, 2022)

  • v6.1.1(Oct 18, 2022)

    Fixed

    • Fixed an issue where dynamic arrangement failed when setting the table to the exact width of the content #90.
    • The header size is now properly respected in the final optimization step #90. Previously, this wasn't the case and lead to weird formatting behavior when both of the following were true
      • Dynamic content adjustment was active.
      • The table didn't fit into the the available space.
      • The header of a row was longer than its content.
    • Fix wrong LowerBoundary calculation. This was introduced in commit bee764d, when this logic was refactored. #90.
    • Table::column_iter no longer requires a &mut self, but only &self.
    Source code(tar.gz)
    Source code(zip)
  • v6.1.0(Sep 26, 2022)

  • v6.0.0(Sep 26, 2022)

    Added

    • Add Table::style_text_only(), which prevents non-delimiter whitespaces in cells to be styled.
    • Add the Table::discover_columns function and add info on when to use it to Row::add_cell.

    Breaking Changes

    • Renaming of several functions to be Rust idiomatic:
      • Cell::get_content -> Cell::content
      • Column::get_padding_width -> Column::padding_width
      • Column::get_constraint -> Column::constraint
      • Table::get_header -> Table::header
      • Table::get_table_width -> Table::width
      • Table::set_table_width -> Table::set_width
      • Table::set_style -> Table::style
      • Table::get_column -> Table::column
      • Table::get_column_mut -> Table::column_mut
      • Table::get_row -> Table::row
      • Table::get_row_mut -> Table::row_mut
    • Column::get_max_width and Column::get_max_content_width have been removed as we cannot guarantee that these numbers are always correct. Use Table::column_max_content_widths instead

    Changed

    • Table::column_max_content_widths now performs a full scan of the table's content when called.
    • Don't include Table::is_tty, Table::force_no_tty and Table::should_style if tty feature isn't enabled.
    Source code(tar.gz)
    Source code(zip)
  • v6.0.0-rc.1(Mar 11, 2022)

  • v5.0.0(Nov 7, 2021)

    [5.0.0] - 2021-11-07

    Updates

    • All dependencies have been bumped.

    Added

    • Add option to use stderr for is_tty check #25.

    Breaking

    • Remove ASCII_HORIZONTAL_BORDERS_ONLY in favor of ASCII_HORIZONTAL_ONLY.
    • Remove UTF8_HORIZONTAL_BORDERS_ONLY in favor of UTF8_HORIZONTAL_ONLY.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.1(Aug 11, 2021)

    [4.1.1] - 2021-08-11

    Added

    • tty feature flag, which enables tty related functionality. This includes styling and terminal-width detection. The tty feature flag is enabled by default. Implemented by roee88 in #47.
    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Aug 9, 2021)

    [4.1.0] - 2021-08-09

    Added

    • Add modifiers::UTF8_SOLID_INNER_BORDERS, which makes the inner borders solid lines: │─ by ModProg for #39.
    • Add presets::ASCII_BORDERS_ONLY_CONDENSED, which is ASCII_BORDERS_ONLY but without spacing between rows #43.

    Fixed

    • Several preset examples weren't correct.
    • Multi-character UTF8 symbols are now handled correctly in most situations. Table-layout might still break for 1-character columns.
    • Mid-word splitting now takes multi-character utf8 characters into account.

    Changed

    • Rename ASCII_HORIZONTAL_BORDERS_ONLY to ASCII_HORIZONTAL_ONLY. Old imports will still work until v5.0.
    • Rename UTF8_HORIZONTAL_BORDERS_ONLY to UTF8_HORIZONTAL_ONLY. Old imports will still work until v5.0.
    Source code(tar.gz)
    Source code(zip)
  • v4.0.1(Jul 8, 2021)

  • v4.0.0(Jul 3, 2021)

    [4.0.0] - 2021-07-03

    Added

    • Add Table::lines, which returns an iterator over all lines of the final table output by dmaahs2017 for #35.
    • Add ColumnConstraints::Boundaries{lower: Width, upper: Width} to specify both an upper and a lower boundary.

    Fixed

    • Fixed percentages sometimes weren't correctly calculated, due to not taking border columns into account.
    • Return None for Table::get_table_width, if getting the terminal size somehow failed.
    • Fixed a lot of possible, but highly unlikely number conversion overflow issues.
    • Run space optimization under all circumstances.
    • Percentage constraints with values of >100 will now be capped to 100.
    • The MinConstraint would be ignored when:
      • The content was larger than the min constraint
      • There was less space available than specified in the constraint.

    Changed

    • The way ColumnConstraints are initialized has been changed. There is now
    enum ColumnConstraints {
        ...,
        /// Enforce a absolute width for a column.
        Absolute(Width),
        /// Specify a lower boundary, either fixed or as percentage of the total width.
        LowerBoundary(Width),
        /// Specify a upper boundary, either fixed or as percentage of the total width.
        UpperBoundary(Width),
    }
    
    pub enum Width {
        /// Specify a min amount of characters per line for a column.
        Fixed(u16),
        /// Set a a minimum percentage in respect to table_width for this column.
        /// Values above 100 will be automatically reduced to 100.
        /// **Warning:** This option will be ignored, if the width cannot be determined!
        Percentage(u16),
    }
    

    Instead of the old

    enum ColumnConstraints {
        ...,
        Width(u16),
        MinWidth(u16),
        MaxWidth(u16),
        Percentage(u16),
        MinPercentage(u16),
        MaxPercentage(u16),
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(Jun 13, 2021)

    [3.0.0] - 2021-06-13

    Breaking changes

    • Remove most custom traits and replace them with std's generic From trait.
      Check the docs on the trait implementations for Cell, Row and Cells
    • Add the Cells type, to allow super generic Iterator -> Row conversions.
    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Jan 26, 2021)

    [2.1.0] - 2021-01-26

    Added

    • DynamicFullWidth arrangement. This mode is basically the same as the Dynamic arrangement mode, but it will always use the full available width, even if there isn't enough content to fill the space.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jan 26, 2021)

    [2.0.0] - 2021-01-16

    Added

    Dynamic arrangement

    A new logic to optimize space usage after splitting content has been added.
    If there is a lot of unused space after the content has been arranged, this space will now be redistributed ot the remaining columns. Or it will be removed if there are no other columns.

    This is considered a breaking change, since this can result in different table layouts!!

    This process is far from perfect, but the behavior is better than before.

    Old behavior:

    +-----------------------------------+-----------------------------------+------+
    | Header1                           | Header2                           | Head |
    +==============================================================================+
    | This is a very long line with a   | This is text with a               | smol |
    | lot of text                       | anotherverylongtexttesttest       |      |
    +-----------------------------------+-----------------------------------+------+
    

    New behavior:

    +-----------------------------------------+-----------------------------+------+
    | Header1                                 | Header2                     | Head |
    +==============================================================================+
    | This is a very long line with a lot of  | This is text with a         | smol |
    | text                                    | anotherverylongtexttesttest |      |
    +-----------------------------------------+-----------------------------+------+
    

    Old behavior:

    +------------------------------------------------+
    | Header1                                        |
    +================================================+
    | This is text with a                            |
    | anotherverylongtexttesttestaa                  |
    +------------------------------------------------+
    

    New behavior:

    +-------------------------------+
    | Header1                       |
    +===============================+
    | This is text with a           |
    | anotherverylongtexttesttestaa |
    +-------------------------------+
    
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(Jan 26, 2021)

  • v1.5.0(Dec 29, 2020)

  • v1.4.0(Dec 6, 2020)

    [1.4.0] - 2020-12-06

    Added

    • Allow to set custom delimiters on tables, columns and cells.

    Changed

    • Expose all important traits. I.e. ToRow, ToCell and ToCells.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Nov 8, 2020)

  • v1.2.0(Nov 3, 2020)

  • v1.1.1(Oct 2, 2020)

  • v1.1.0(Oct 2, 2020)

    [1.1.0] - 2020-08-23

    Changed

    • Move is_tty logic from atty to crossterm.
    • Remove skeptic, since it fails in CI and bloats compile time. Compile time is reduced by ca. 40%.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jul 11, 2020)

    [1.0.0] - 2020-07-07

    Changed

    • The project has been in use for quite some time and seems to be quite stable!
    • Use cargo's example functionality for examples.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Jul 11, 2020)

    [0.1.1] - 2020-05-24

    Added

    • Column::get_max_width(), which returns the character count of the widest line in this column including padding.
    • current_style_as_preset method for convenient conversion of a style into a preset
    • New Markdown like table style prefix. Thanks to joeydumont.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jul 11, 2020)

  • v0.0.7(Jul 11, 2020)

    [0.0.7] - 2020-02-09

    Added

    • Introduce proptest

    Fixed

    • Fix wrong calculation due to bytes count instead of char count
    • Fix panics caused by wrong string splits
    Source code(tar.gz)
    Source code(zip)
  • v0.0.6(Jul 11, 2020)

  • v0.0.5(Jul 11, 2020)

  • v0.0.4(Jul 11, 2020)

Owner
Arne Beer
Dev and Ops guy. Open-source, commandline and automation enthusiast
Arne Beer
A fast python geohash library created by wrapping rust.

Pygeohash-Fast A Fast geohasher for python. Created by wrapping the rust geohash crate with pyo3. Huge shout out to the georust community :) Currently

Zach Paden 3 Aug 18, 2022
Rust crate for Ok-wrapping and try blocks

tryvial A small crate for Ok-wrapping and try blocks. This is compatible with Result, Option, and any type implementing the unstable std::ops::Try tra

null 11 Jan 25, 2023
An easy to use library for pretty print tables of Rust structs and enums.

tabled An easy to use library for pretty printing tables of Rust structs and enums. Table of Contents Usage Settings Style Themes ASCII Psql Github Ma

Maxim Zhiburt 1.3k Jan 9, 2023
More beautiful HTML reports for llvm-cov/cargo-llvm-cov

?? llvm-cov-pretty More beautiful HTML reports for llvm-cov (cargo-llvm-cov specifically). Dark theme support (switches automatically based on your br

Dominik Nakamura 13 Jun 26, 2023
Beautiful, minimal, opinionated CLI prompts inspired by the Clack NPM package

Effortlessly build beautiful command-line apps with Rust ?? ✨ Beautiful, minimal, opinionated CLI prompts inspired by the @clack/prompts npm package.

Alexander Fadeev 7 Jul 23, 2023
A beautiful and feature-packed Apple Music CLI

am A beautiful and feature-packed Apple Music CLI! Written in Rust. Installation Nix (recommended) This GitHub repository contains a flake. Add github

Ryan Cao 5 Sep 21, 2023
A Rust command that prettifies the ugly `cargo test` output into a beautiful one.

Cargo Pretty Test ✨ A Rust command-line tool that prettifies the ugly cargo test output into a beautiful output. This crate can be also used as a libr

Jose Celano 105 Oct 10, 2023
Make beautiful colored code listings in LaTeX with the power of TreeSitter.

What is this? This is a CLI tool that consumes TreeSitter's output and transforms it into LaTeX code that will produce syntax-colored code listing. If

Tomáš Lebeda 11 Sep 4, 2023
A beautiful, tiny traceback and logging library supporting #![no_std] rust.

breadcrumbs Breadcrumbs is a beautiful, tiny traceback and logging library for Rust that offers seamless integration with #![no_std], multi-threading

Michael 18 Nov 21, 2023
Pure-Rust implementation of Fast Static Symbol Tables string compression

fsst-rs A pure-Rust, zero-dependency implementation of the FSST string compression algorithm. FSST is a string compression algorithm meant for use in

Spiral 78 Sep 29, 2024
Build Java applications without fighting your build tool. Drink some espresso.

Espresso Build Java applications without fighting your build tool. Drink some espresso. Features Modern Look & Feel Command line interface inspired by

Hunter LaFaille 5 Apr 2, 2024
A simple CLI tool for converting CSV file content to JSON.

fast-csv-to-json A simple CLI tool for converting CSV file content to JSON. 我花了一個小時搓出來,接著優化了兩天的快速 CSV 轉 JSON CLI 小工具 Installation Install Rust with ru

Ming Chang 3 Apr 5, 2023
Ideas => Creations, a multi-language CMS(Content Management System) based on Rust Web stacks, with long-term upgrade and maintenance.

Ideas => Creations 中文 RustHub: Rust ideas yesterday, shining creations today! This repository holds source code used to run https://rusthub.org, it's

rusthub.org 4 May 9, 2023
This is an example Nostr rust project to enable '402 Payment Required' responses for requests to paid content.

Nostr Paywall Example This is an example Nostr rust project to enable 402 Payment Required responses for requests to paid content. To prove payment, a

Blake Jakopovic 6 May 6, 2023
Shared k-mer content between two genomes

skc skc is a simple tool for finding shared k-mer content between two genomes. Installation Prebuilt binary curl -sSL skc.mbh.sh | sh # or with wget w

Michael Hall 16 Jun 26, 2023
Rust SDK for the core C2PA (Coalition for Content Provenance and Authenticity) specification

C2PA Rust SDK The Coalition for Content Provenance and Authenticity (C2PA) addresses the prevalence of misleading information online through the devel

Content Authenticity Initiative 46 Jun 30, 2023
A Content Discovery Tool insipired from Feroxbuster. Work In Progress

monologue A Content Discovery Tool written in Rust, insipired from Feroxbuster. Installation Dependencies OpenSSL (If You are on linux). Rust programm

Voyage 3 Jul 20, 2023
Show HTML content "inside" your egui rendered application

hframe Show HTML content "inside" your egui rendered application. "hframe" stands for "HTML Frame". Note: hframe only works when the application is co

Franco Profeti 3 Feb 26, 2024
Fast, deduplicated content and database seeding for WordPress

Sprout Fast, deduplicated content and database seeding for WordPress. Documentation | Install | Releases Store your uploads and database in a secure,

Tom Lawton 14 Feb 22, 2024