tabular

    A MoonBit library for pretty-printing tables in terminal. Ported from Rust tabled.

    table
    tui
    terminal
    cli
    format
    grid
    pretty-print
    Download zip
    Author
    Version
    0.6.0
    License
    Apache-2.0
    Last updated
    6 days ago
    Downloads
    228

    #Tabular

    A MoonBit library for pretty-printing tables in the terminal. Inspired by the Rust tabled project.

    #Features

    • 11 built-in style presets
    • Customizable borders and horizontal lines
    • Alignment, padding, width, height, and formatting controls
    • Row, column, cell, and segment based table editing
    • Column span and row span
    • Panel, merge, highlight, shadow, split, extract, remove, and border correction
    • Builder helpers with index and transpose support
    • Rotate, reverse, concatenate, and duplicate selected records
    • ANSI text colors, style parsing, and color-preserving width operations
    • Composable table and cell options with measurements and resizing priorities
    • Unicode 17 display width, colored padding, and margins

    See tabled parity status for the upstream test mapping and remaining work. The examples below use the 0.6 API. For the breaking changes from 0.5.2, including migration from Builder::extend to Builder::push_record, see the migration guide. The final names for APIs introduced during 0.6 development are listed in the API naming guide.

    #Installation

    moon add hustcer/tabular

    Add the package to the consuming directory's moon.pkg:

    import { "hustcer/tabular", }

    Examples that use @papergrid also need "hustcer/tabular/papergrid" in that import block. Use the documentation matching your installed package version; 0.6.0 is currently marked unreleased in the changelog. This source tree is validated with moon 0.1.20260827 and uses moon.mod and moon.pkg manifests.

    #Quick Start

    ///|
    test "README quick start" {
    let table = @tabular.Table::from_rows([
    ["Name", "Language", "Stars"],
    ["Deno", "Rust/TS", "101k"],
    ["Bun", "Zig/C++", "76k"],
    ["Node.js", "C++/JS", "110k"],
    ])

    table.apply(@tabular.Style::modern()) |> ignore
    table.with_(@tabular.Alignment::center()) |> ignore
    assert_eq(
    table.to_string(),
    (
    #|┌─────────┬──────────┬───────┐
    #|│ Name │ Language │ Stars │
    #|├─────────┼──────────┼───────┤
    #|│ Deno │ Rust/TS │ 101k │
    #|├─────────┼──────────┼───────┤
    #|│ Bun │ Zig/C++ │ 76k │
    #|├─────────┼──────────┼───────┤
    #|│ Node.js │ C++/JS │ 110k │
    #|└─────────┴──────────┴───────┘
    ),
    )
    }

    Output:

    ┌─────────┬──────────┬───────┐ │ Name │ Language │ Stars │ ├─────────┼──────────┼───────┤ │ Deno │ Rust/TS │ 101k │ ├─────────┼──────────┼───────┤ │ Bun │ Zig/C++ │ 76k │ ├─────────┼──────────┼───────┤ │ Node.js │ C++/JS │ 110k │ └─────────┴──────────┴───────┘

    #Style Presets

    table.apply(@tabular.Style::ascii()) |> ignore
    table.apply(@tabular.Style::modern()) |> ignore
    table.apply(@tabular.Style::rounded()) |> ignore
    table.apply(@tabular.Style::extended()) |> ignore
    table.apply(@tabular.Style::dots()) |> ignore
    table.apply(@tabular.Style::empty()) |> ignore
    table.apply(@tabular.Style::blank()) |> ignore
    table.apply(@tabular.Style::re_structured_text()) |> ignore
    table.apply(@tabular.Style::ascii_rounded()) |> ignore
    table.apply(@tabular.Style::markdown()) |> ignore
    table.apply(@tabular.Style::psql()) |> ignore

    These examples use Alignment::center(). Tables default to left alignment. Some presets still differ from Rust tabled; see the parity notes.

    ascii

    +----------+------+ | language | year | +----------+------+ | Rust | 2010 | +----------+------+ | MoonBit | 2022 | +----------+------+

    modern

    ┌──────────┬──────┐ │ language │ year │ ├──────────┼──────┤ │ Rust │ 2010 │ ├──────────┼──────┤ │ MoonBit │ 2022 │ └──────────┴──────┘

    rounded

    ╭──────────┬──────╮ │ language │ year │ ├──────────┼──────┤ │ Rust │ 2010 │ ├──────────┼──────┤ │ MoonBit │ 2022 │ ╰──────────┴──────╯

    markdown

    | language | year | |----------|------| | Rust | 2010 | | MoonBit | 2022 |

    psql

    language | year ----------+------ Rust | 2010 MoonBit | 2022

    dots

    :.................: : language : year : :..........:......: : Rust : 2010 : :..........:......: : MoonBit : 2022 : :.................:

    extended

    ╔══════════╦══════╗ ║ language ║ year ║ ╠══════════╬══════╣ ║ Rust ║ 2010 ║ ╠══════════╬══════╣ ║ MoonBit ║ 2022 ║ ╚══════════╩══════╝

    empty / blank

    language year Rust 2010 MoonBit 2022

    re_structured_text

    ========== ====== language year ========== ====== Rust 2010 MoonBit 2022 ========== ======

    ascii_rounded

    .-----------------. | language | year | | Rust | 2010 | | MoonBit | 2022 | '-----------------'

    #Custom Style

    let style = @tabular.Style::ascii()
    .top('─')
    .bottom('─')
    .left('│')
    .right('│')
    .horizontal('─')
    .vertical('│')
    .corner_top_left('┌')
    .corner_top_right('┐')
    .corner_bottom_left('└')
    .corner_bottom_right('┘')

    table.apply(style) |> ignore

    let style = @tabular.Style::ascii()
    .remove_horizontal()
    .horizontals([
    (1, @tabular.HorizontalLine::full('-', '+', '+', '+')),
    ])

    table.apply(style) |> ignore

    #Builder

    ///|
    test "README builder" {
    let builder = @tabular.Builder::default()
    builder.push_record(["Name", "Age", "City"])
    builder.push_record(["Alice", "30", "NYC"])
    builder.push_record(["Bob", "25", "LA"])
    let table = builder.build()
    assert_eq(table.shape(), (3, 3))
    assert_eq(table.rows[1], ["Alice", "30", "NYC"])
    }

    push_record(row) appends one record to the end of the builder. extend_(row) is a deprecated compatibility alias; use push_record(row) instead.

    ///|
    let builder = @tabular.Builder::from_rows([
    ["Name", "Age"],
    ["Alice", "30"],
    ["Bob", "25"],
    ])

    ///|
    let table1 = builder.index().build()

    ///|
    let table2 = builder.index().transpose().build()

    ///|
    let table3 = builder.index().hide().build()

    #Common Edits

    These setters and Setting helpers remain compatibility entry points. Width and height setters act during rendering and preserve the stored text. For measurements, priorities, word wrapping, and other advanced options, use with_ and modify.

    table.set_align(@tabular.Align::right()) |> ignore
    table.set_padding(@tabular.Padding::new(1, 1, 0, 0)) |> ignore
    table.set_width(@tabular.Width::wrap(10)) |> ignore
    table.set_height(@tabular.Height::increase(2)) |> ignore

    table.modify_rows(
    @tabular.Rows::first(),
    @tabular.Setting::align(@tabular.Align::center()),
    ) |> ignore

    table.modify_cols(
    @tabular.Cols::one(1),
    @tabular.Setting::width(@tabular.Width::wrap(8)),
    ) |> ignore

    table.modify_cell(
    @tabular.Cell::new(1, 2),
    @tabular.Setting::format(@tabular.Format::surround("[", "]")),
    ) |> ignore

    #Spans

    ///|
    test "README spans" {
    let table = @tabular.Table::from_rows([
    ["Team", "Q1", "Q2", "Q3"],
    ["A", "12", "18", "22"],
    ["B", "10", "16", "21"],
    ])

    table.apply(@tabular.Style::modern()) |> ignore
    table.with_(@tabular.Alignment::center()) |> ignore
    table.modify_cell(@tabular.Cell::new(0, 0), @tabular.Span::col(2)) |> ignore
    table.correct_borders() |> ignore
    assert_eq(
    table.to_string(),
    (
    #|┌────────┬────┬────┐
    #|│ Team │ Q2 │ Q3 │
    #|├───┬────┼────┼────┤
    #|│ A │ 12 │ 18 │ 22 │
    #|├───┼────┼────┼────┤
    #|│ B │ 10 │ 16 │ 21 │
    #|└───┴────┴────┴────┘
    ),
    )
    }

    Output:

    ┌────────┬────┬────┐ │ Team │ Q2 │ Q3 │ ├───┬────┼────┼────┤ │ A │ 12 │ 18 │ 22 │ ├───┼────┼────┼────┤ │ B │ 10 │ 16 │ 21 │ └───┴────┴────┴────┘

    #Panels And Merge

    let table = @tabular.Table::from_rows([
    ["0", "1", "2"],
    ["0", "1", "1"],
    ["1", "1", "2"],
    ["1", "1", "1"],
    ])

    table.panel(@tabular.Panel::header("Runtime Comparison")) |> ignore
    table.merge(@tabular.Merge::horizontal()) |> ignore
    println(table.to_string())

    #Highlight And Shadow

    table.highlight(
    @tabular.Highlight::outline_cell(@tabular.Cell::new(1, 1), '*'),
    ) |> ignore

    table.shadow(@tabular.Shadow::new(1)) |> ignore

    #Split, Extract, Remove

    table.extract_rows(@tabular.Rows::new(0, 2)) |> ignore
    table.remove_cols(@tabular.Cols::one(0)) |> ignore
    table.split(@tabular.Split::col(2).concat()) |> ignore

    #Data Transforms

    ///|
    test {
    let table = @tabular.Table::from_rows([["a", "b"], ["c", "d"]])
    table.rotate(@tabular.Rotate::Left) |> ignore
    assert_eq(table.rows, [["b", "d"], ["a", "c"]])

    table.reverse(@tabular.Reverse::rows(0)) |> ignore
    table.concat(
    @tabular.Concat::horizontal(@tabular.Table::from_rows([["e"], ["f"]])),
    )
    |> ignore
    table.duplicate(
    @tabular.Duplicate::new(
    source=@tabular.Rows::one(0),
    destination=@tabular.Rows::one(1),
    ),
    )
    |> ignore
    assert_eq(table.rows, [["a", "c", "e"], ["a", "c", "e"]])
    }

    #Composable Settings

    Table::with_ accepts any TableOption; Table::modify applies a CellOption to an object. Options can be reused and combined with Settings, tuples, or arrays. The trailing underscore avoids MoonBit's with keyword. Built-in resize priorities start an independent selection sequence for each application. Stateful custom ResizeSelector implementations should override fresh() to return an independent initial state while retaining their settings.

    ///|
    test {
    let settings = @tabular.Settings::default()
    .with_(@tabular.Style::psql())
    .with_(@tabular.Alignment::left())
    .modify(@tabular.Rows::first(), @tabular.Alignment::center())
    let table = @tabular.Table::from_rows([
    ["Name", "Status"],
    ["task", "pending"],
    ])
    .with_(settings)
    .modify(@tabular.Cell::new(1, 1), "done")
    assert_eq(table.shape(), (2, 2))
    assert_eq(table.rows[1], ["task", "done"])
    }

    #Text Formatting

    Tables default to left alignment. Multiline text is aligned as a block; AlignmentStrategy::PerLine aligns its lines independently. TrimStrategy trims displayed whitespace while preserving records and layout dimensions. TextCleanup changes records to remove control characters or expand tabs.

    ///|
    test {
    let table = @tabular.Table::from_rows([["hello"], ["a\nbc"]]).with_(
    (
    @tabular.Alignment::right(),
    @tabular.AlignmentStrategy::PerLine,
    @tabular.AlignmentFill::new('.'),
    ),
    )
    assert_eq(
    table.to_string(),
    "+-------+\n| hello |\n+-------+\n| ....a |\n| ...bc |\n+-------+",
    )
    }

    Color::fg_red() and other color constructors work as table or cell options. AlignmentFill::color colors only the alignment fill. ANSI sequences embedded in records are excluded from layout width. Wrapping preserves color styles and OSC8 hyperlinks; truncation closes styles before adding a suffix. A wide character that cannot fit is replaced by �; use Width::wrap_with for a custom placeholder. Text measurement follows Unicode 17.0.0, including emoji presentation and ZWJ sequences.

    ///|
    test {
    let red = @tabular.Color::parse_or_abort("\u001b[31mtext\u001b[39m")
    assert_eq(red.colorize("hello"), "\u001b[31mhello\u001b[39m")
    assert_true(@tabular.Color::try_parse("") is Err(_))
    let table = @tabular.Table::from_rows([[red.colorize("abcdef")]]).modify(
    (0, 0),
    @tabular.Width::wrap(3),
    )
    assert_eq(
    table.to_string(),
    "+-----+\n| \u001b[31mabc\u001b[39m |\n| \u001b[31mdef\u001b[39m |\n+-----+",
    )
    }

    #Width and Dimensions

    Width::wrap, Width::truncate, and Width::increase accept an integer, Max, Min, Percent, or a custom Measurement. Applied with modify, they change cell text. Applied with with_, they fit the total table width, including padding, borders, and margins. keep_words preserves words when they fit; priority chooses which columns to resize. Use Priority::round_robin(), Priority::first(), or Priority::last() for index-based selection. Priority::min(tie_break=TieBreak::First) and Priority::max(tie_break=TieBreak::Last) explicitly select how equal sizes are resolved; first/last refer to indexes and work for both columns and rows.

    ///|
    test {
    let table = @tabular.Table::from_rows([["abcdef", "x"]])
    .modify((0, 0), @tabular.Width::truncate(4).suffix("..."))
    .with_(@tabular.Width::increase(20))
    assert_eq(table.rows, [["a...", "x"]])
    assert_eq(table.total_width(), 20)
    }

    Truncation supports multiline, suffix_limit, and inherit_suffix_style. Width::uniform sets every cell's text width. Width::list directly sets column dimensions, including padding; it assumes the content already fits. Extra list entries remain cached, while table-level wrapping, truncation, and growth only measure and resize the actual columns. Later layout or content changes invalidate cached dimensions according to the option's hint. Rendering does not fill the public cache.

    Table::from_rows keeps the input arrays by reference. If you edit table.rows or table.config directly, clear cached dimensions with table.dimension_cache().clear() before running size-dependent operations. dimension_snapshot() returns an independent copy; dimension_cache() exposes the live cache.

    The earlier set_width and Setting::width methods retain their render-time wrap/truncate behavior. Use with_ or modify for the advanced options above. Dimension queries include these render-time width and height modes; explicit width and height lists take precedence over estimated dimensions.

    #Height

    Use modify to add or remove text lines in selected cells. Use with_ to adjust the total table height, including padding, horizontal borders and margins. Height options accept Max, Min, and Percent measurements; .priority(...) selects which rows grow or shrink. Height::list fixes individual row heights.

    ///|
    test {
    let table = @tabular.Table::from_rows([["first\nsecond"], ["last"]])
    table.modify((0, 0), @tabular.Height::limit(1)) |> ignore
    assert_eq(table.rows, [["first"], ["last"]])
    table.with_(@tabular.Height::increase(10)) |> ignore
    assert_eq(table.total_height(), 10)
    table.with_(@tabular.Height::list([0, 2])) |> ignore
    assert_eq(table.total_height(), 5)
    }

    #Padding and Margins

    Padding::fill chooses each cell's fill characters. PaddingColor and MarginColor accept Color, ANSIBuf, or ANSIStr values. Use PaddingExpand::Horizontal or PaddingExpand::Vertical to fill unused horizontal or vertical cell space according to its alignment.

    ///|
    test {
    let table = @tabular.Table::from_rows([["x"]])
    .with_(
    @tabular.Padding::new(1, 1, 1, 1).fill(
    left='>',
    right='<',
    top='^',
    bottom='v',
    ),
    )
    .with_(@tabular.PaddingColor::filled(@tabular.Color::bg_blue()))
    .with_(@tabular.Margin::new(left=1, right=1, top=0, bottom=0))
    assert_eq(
    @papergrid.strip_ansi(table.to_string()),
    " +---+ \n |^^^| \n |>x<| \n |vvv| \n +---+ ",
    )
    }

    #Validation

    Run the same checks as CI, including the executable examples in this README:

    moon fmt --check moon check --target all --deny-warn moon build --target all --deny-warn moon test --target all --deny-warn moon info git diff --exit-code -- '*.mbti'

    The targets are wasm, wasm-gc, JavaScript, and native. Passing these checks validates the covered behavior; it does not establish full Rust tabled parity. See the review and fixes since v0.5.2 for the release checks and regression coverage.

    #License

    Apache-2.0

    Adapted upstream code and tests retain their notices in THIRD_PARTY_NOTICES.md.

    Entity

    A table region used by configuration and selection APIs.

    Indent

    A character repeated to occupy an inner or outer indent.

    Offset

    An offset from the start or end of an axis.

    Sides

    Values associated with the left, right, top, and bottom of a box.

    CellOption

    pub(open) trait CellOption {
    fn change(Self, Table,
    Entity
    ) -> Unit
    fn hint_change(Self) ->
    Entity
    ? = _
    }

    A reusable option applied to a cell, row, column, or the entire table.
    impl CellOption for Array[T]
    impl CellOption for Tuple2[T0, T1]
    impl CellOption for Tuple3[T0, T1, T2]
    impl CellOption for Tuple4[T0, T1, T2, T3]
    impl CellOption for Tuple5[T0, T1, T2, T3, T4]
    impl CellOption for Tuple6[T0, T1, T2, T3, T4, T5]
    impl CellOption for Tuple7[T0, T1, T2, T3, T4, T5, T6]
    impl CellOption for Tuple8[T0, T1, T2, T3, T4, T5, T6, T7]
    impl CellOption for Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8]
    impl CellOption for Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]

    HeightOption

    pub(open) trait HeightOption {
    fn to_mode(Self) ->
    HeightMode

    }

    Compatibility conversion for the original render-time height setters.

    Measurement

    pub(open) trait Measurement {
    fn measure(Self, Table, Attribute) -> Int
    }

    Compute a width or height from the table's records and configuration. MoonBit traits do not accept type parameters, so Attribute selects the axis.

    test {
    let table = @tabular.Table::from_rows([["abcd", "x"]])
    assert_eq(
    @tabular.Measurement::measure(
    @tabular.Percent::new(50),
    table,
    @tabular.Attribute::Width,
    ),
    6,
    )
    assert_eq(
    @tabular.Measurement::measure(
    @tabular.Max::new(),
    table,
    @tabular.Attribute::Width,
    ),
    4,
    )
    }
    impl Measurement for Int

    Object

    pub(open) trait Object {
    fn cells(Self, Table) -> Array[Array[(Int, Int)]]
    fn entities(Self, Table) -> Array[
    Entity
    ] = _
    }

    Select ordered groups of cells from a table. Each group is an entity: a row, a column, a cell, or the whole table. Operations such as Duplicate restart the source sequence for each group.
    impl Object for Tuple2[Int, Int]

    ResizeSelector

    pub(open) trait ResizeSelector {
    fn select(Self, Array[Int], Array[Int]) -> Int?
    fn fresh(Self) -> &ResizeSelector = _
    }

    Select the next column or row to resize. Returning None stops resizing. Arguments after the selector are minimum sizes and current sizes, in index order. An empty minimum-size array means no explicit lower bounds were supplied. Zero sizes are skipped by default. A negative minimum makes a zero-sized entry eligible, allowing growth operations to expand an initially empty row. Table options call fresh once per resize operation. Stateful selectors should return an independent initial state; stateless selectors can use the default implementation, which returns the selector unchanged.

    test {
    let priority = @tabular.Priority::round_robin()
    let values = [5, 0, 2]
    assert_eq(
    @tabular.ResizeSelector::select(priority, [0, 0, 0], values),
    Some(0),
    )
    assert_eq(
    @tabular.ResizeSelector::select(priority, [0, 0, 0], values),
    Some(2),
    )
    assert_eq(
    @tabular.ResizeSelector::select(priority, [0, 0, 0], values),
    Some(0),
    )
    let independent = priority.fresh()
    assert_eq(independent.select([], values), Some(0))
    assert_eq(priority.select([], values), Some(2))
    }

    TableOption

    pub(open) trait TableOption {
    fn change(Self, Table) -> Unit
    fn hint_change(Self) ->
    Entity
    ? = _
    }

    A reusable option that changes table records, layout, or configuration.
    impl TableOption for Array[T]
    impl TableOption for Tuple2[T0, T1]
    impl TableOption for Tuple3[T0, T1, T2]
    impl TableOption for Tuple4[T0, T1, T2, T3]
    impl TableOption for Tuple5[T0, T1, T2, T3, T4]
    impl TableOption for Tuple6[T0, T1, T2, T3, T4, T5]
    impl TableOption for Tuple7[T0, T1, T2, T3, T4, T5, T6]
    impl TableOption for Tuple8[T0, T1, T2, T3, T4, T5, T6, T7]
    impl TableOption for Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8]
    impl TableOption for Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]

    WidthOption

    pub(open) trait WidthOption {
    fn to_mode(Self) ->
    WidthMode

    }

    Compatibility conversion for the original render-time width setters.

    Align

    pub enum Align {
    Left
    Right
    Center
    }

    impl CellOption for Align

    Align::center

    fn Align::center() -> Align

    Align::change

    fn Align::change(self : Align, table : Table) -> Unit

    Align::change_cell

    fn Align::change_cell(self : Align, table : Table, entity :
    Entity
    ) -> Unit

    Align::hint_change

    Align::hint_change_cell

    fn Align::hint_change_cell(_self : Align) ->
    Entity
    ?

    Align::left

    fn Align::left() -> Align

    Align::right

    fn Align::right() -> Align

    Alignment

    pub enum Alignment {
    Horizontal(Align)
    Vertical(VAlign)
    }

    Horizontal or vertical alignment, matching tabled's unified Alignment API.

    Alignment::as_horizontal

    fn Alignment::as_horizontal(self : Alignment) -> Align?

    Alignment::as_vertical

    fn Alignment::as_vertical(self : Alignment) -> VAlign?

    Alignment::bottom

    fn Alignment::bottom() -> Alignment

    Alignment::center

    fn Alignment::center() -> Alignment

    Alignment::center_vertical

    fn Alignment::center_vertical() -> Alignment

    Alignment::change

    fn Alignment::change(self : Alignment, table : Table) -> Unit

    Alignment::change_cell

    fn Alignment::change_cell(self : Alignment, table : Table, entity :
    Entity
    ) -> Unit

    Alignment::from_horizontal

    fn Alignment::from_horizontal(align : Align) -> Alignment

    Alignment::from_vertical

    fn Alignment::from_vertical(align : VAlign) -> Alignment

    Alignment::hint_change

    Alignment::hint_change_cell

    Alignment::left

    fn Alignment::left() -> Alignment

    Alignment::right

    fn Alignment::right() -> Alignment

    Alignment::top

    fn Alignment::top() -> Alignment

    AlignmentFill

    pub struct AlignmentFill {
    // private fields
    }

    Fill the space used to align text, independently from cell padding.

    AlignmentFill::change

    fn AlignmentFill::change(self : AlignmentFill, table : Table) -> Unit

    AlignmentFill::change_cell

    fn AlignmentFill::change_cell(self : AlignmentFill, table : Table, entity :
    Entity
    ) -> Unit

    AlignmentFill::color

    fn AlignmentFill::color(self : AlignmentFill, color : Color) -> AlignmentFill

    AlignmentFill::colored

    fn AlignmentFill::colored(fill : Char, color : Color) -> AlignmentFill

    AlignmentFill::default

    fn AlignmentFill::default() -> AlignmentFill

    AlignmentFill::hint_change

    AlignmentFill::hint_change_cell

    AlignmentFill::new

    fn AlignmentFill::new(fill : Char) -> AlignmentFill

    AlignmentStrategy

    pub(all) enum AlignmentStrategy {
    PerCell
    PerLine
    } derive(Eq,
    Debug
    )

    Align each cell as one block (the default), or align its lines separately.

    AlignmentStrategy::change

    fn AlignmentStrategy::change(self : AlignmentStrategy, table : Table) -> Unit

    AlignmentStrategy::change_cell

    fn AlignmentStrategy::change_cell(self : AlignmentStrategy, table : Table, entity :
    Entity
    ) -> Unit

    AlignmentStrategy::equal

    AlignmentStrategy::hint_change

    AlignmentStrategy::hint_change_cell

    AlignmentStrategy::not_equal

    fn AlignmentStrategy::not_equal(x : AlignmentStrategy, y : AlignmentStrategy) -> Bool

    Attribute

    pub(all) enum Attribute {
    Width
    Height
    } derive(Eq,
    Debug
    )

    The dimension being measured. This replaces Rust's trait type parameter.

    Attribute::equal

    fn Attribute::equal(Attribute, Attribute) -> Bool

    Attribute::not_equal

    fn Attribute::not_equal(x : Attribute, y : Attribute) -> Bool

    Builder

    pub struct Builder {
    rows : Array[Array[String]]
    empty_cell : String
    }

    Builder::build

    fn Builder::build(self : Builder) -> Table

    Builder::clean

    fn Builder::clean(self : Builder) -> Unit

    Builder::clear

    fn Builder::clear(self : Builder) -> Unit

    Builder::count_cols

    fn Builder::count_cols(self : Builder) -> Int

    Builder::count_records

    fn Builder::count_records(self : Builder) -> Int

    Builder::default

    fn Builder::default() -> Builder

    Builder::extend_

    #deprecated("Use Builder::push_record instead")
    fn Builder::extend_(self : Builder, row : Array[String]) -> Unit

    Appends one record. Use Builder::push_record instead.

    Builder::from_rows

    fn Builder::from_rows(rows : Array[Array[String]]) -> Builder

    Builder::index

    fn Builder::index(self : Builder) -> IndexBuilder

    Create an IndexBuilder from this Builder for index/transpose operations.

    Builder::insert_col

    fn Builder::insert_col(self : Builder, index : Int, col : Array[String]) -> Unit

    Builder::insert_record

    fn Builder::insert_record(self : Builder, index : Int, row : Array[String]) -> Unit

    Builder::push_col

    fn Builder::push_col(self : Builder, col : Array[String]) -> Unit

    Builder::push_record

    fn Builder::push_record(self : Builder, row : Array[String]) -> Unit

    Appends one record to the end of the builder.

    Builder::remove_col

    fn Builder::remove_col(self : Builder, index : Int) -> Unit

    Builder::remove_record

    fn Builder::remove_record(self : Builder, index : Int) -> Unit

    Builder::set_empty

    fn Builder::set_empty(self : Builder, value : String) -> Unit

    ByColName

    pub struct ByColName {
    name : String
    }

    impl Object for ByColName

    ByColName::cells

    fn ByColName::cells(self : ByColName, table : Table) -> Array[Array[(Int, Int)]]

    ByColName::entities

    ByColName::new

    fn ByColName::new(name : String) -> ByColName

    Cell

    pub struct Cell {
    row : Int
    col : Int
    }

    impl Object for Cell

    Cell::and_

    fn Cell::and_(self : Cell, other : Cell) -> Segment

    Cell::as_segment

    fn Cell::as_segment(self : Cell) -> Segment

    Cell::cells

    fn Cell::cells(self : Cell, table : Table) -> Array[Array[(Int, Int)]]

    Cell::entities

    fn Cell::entities(self : Cell, table : Table) -> Array[
    Entity
    ]

    Cell::inverse

    fn Cell::inverse(self : Cell) -> Segment

    Cell::new

    fn Cell::new(row : Int, col : Int) -> Cell

    Cell::not

    fn Cell::not(self : Cell, other : Cell) -> Segment

    CellHeightIncrease

    pub struct CellHeightIncrease[M] {
    height : M
    } derive(Eq,
    Debug
    )

    Increase cell text height with modify, or total table height with with_.

    test {
    let table = @tabular.Table::from_rows([["a"], ["b"]])
    table.modify((0, 0), @tabular.Height::increase(3)) |> ignore
    assert_eq(table.rows[0], ["a\n\n"])
    table.with_(@tabular.Height::increase(10)) |> ignore
    assert_eq(table.total_height(), 10)
    }

    CellHeightIncrease::change

    fn[M : Measurement] CellHeightIncrease::change(self : CellHeightIncrease[M], table : Table) -> Unit

    CellHeightIncrease::change_cell

    fn[M : Measurement] CellHeightIncrease::change_cell(self : CellHeightIncrease[M], table : Table, entity :
    Entity
    ) -> Unit

    CellHeightIncrease::equal

    CellHeightIncrease::hint_change

    CellHeightIncrease::hint_change_cell

    CellHeightIncrease::new

    fn[M] CellHeightIncrease::new(height : M) -> CellHeightIncrease[M]

    CellHeightIncrease::not_equal

    fn[M : Eq] CellHeightIncrease::not_equal(x : CellHeightIncrease[M], y : CellHeightIncrease[M]) -> Bool

    CellHeightIncrease::priority

    fn[M, P] CellHeightIncrease::priority(self : CellHeightIncrease[M], priority : P) -> TableHeightIncrease[M, P]

    CellHeightLimit

    pub struct CellHeightLimit[M] {
    height : M
    } derive(Eq,
    Debug
    )

    Limit the number of text lines. ANSI styles remain balanced on retained lines.

    CellHeightLimit::change

    fn[M : Measurement] CellHeightLimit::change(self : CellHeightLimit[M], table : Table) -> Unit

    CellHeightLimit::change_cell

    fn[M : Measurement] CellHeightLimit::change_cell(self : CellHeightLimit[M], table : Table, entity :
    Entity
    ) -> Unit

    CellHeightLimit::equal

    fn[M : Eq] CellHeightLimit::equal(CellHeightLimit[M], CellHeightLimit[M]) -> Bool

    CellHeightLimit::hint_change

    CellHeightLimit::hint_change_cell

    CellHeightLimit::new

    fn[M] CellHeightLimit::new(height : M) -> CellHeightLimit[M]

    CellHeightLimit::not_equal

    fn[M : Eq] CellHeightLimit::not_equal(x : CellHeightLimit[M], y : CellHeightLimit[M]) -> Bool

    CellHeightLimit::priority

    fn[M, P] CellHeightLimit::priority(self : CellHeightLimit[M], priority : P) -> TableHeightLimit[M, P]

    CellSettings

    pub struct CellSettings[O, M] {
    // private fields
    }

    Options are applied entity by entity, in the order they were appended.
    impl TableOption for CellSettings[O, M]

    CellSettings::change

    fn[O : Object, M : CellOption] CellSettings::change(self : CellSettings[O, M], table : Table) -> Unit

    CellSettings::hint_change

    CellSettings::with_

    fn[O, A, B] CellSettings::with_(self : CellSettings[O, A], option : B) -> CellSettings[O, Settings[A, B]]

    Color

    pub struct Color {
    // private fields
    } derive(Eq,
    Debug
    )

    A reusable ANSI text style. Predefined colors use lowercase constructors in place of Rust's associated constants.
    impl CellOption for Color
    impl ANSIFmt for Color
    impl BitOr for Color

    Color::as_static_ansi

    Return a style pair only for colors created from a static preset or ANSIStr. Dynamically parsed or constructed colors return None; use to_ansi_buf for those.

    Color::bg_black

    fn Color::bg_black() -> Color

    Color::bg_blue

    fn Color::bg_blue() -> Color

    Color::bg_bright_black

    fn Color::bg_bright_black() -> Color

    Color::bg_bright_blue

    fn Color::bg_bright_blue() -> Color

    Color::bg_bright_cyan

    fn Color::bg_bright_cyan() -> Color

    Color::bg_bright_green

    fn Color::bg_bright_green() -> Color

    Color::bg_bright_magenta

    fn Color::bg_bright_magenta() -> Color

    Color::bg_bright_red

    fn Color::bg_bright_red() -> Color

    Color::bg_bright_white

    fn Color::bg_bright_white() -> Color

    Color::bg_bright_yellow

    fn Color::bg_bright_yellow() -> Color

    Color::bg_cyan

    fn Color::bg_cyan() -> Color

    Color::bg_green

    fn Color::bg_green() -> Color

    Color::bg_magenta

    fn Color::bg_magenta() -> Color

    Color::bg_red

    fn Color::bg_red() -> Color

    Color::bg_rgb

    fn Color::bg_rgb(red : Byte, green : Byte, blue : Byte) -> Color

    Color::bg_white

    fn Color::bg_white() -> Color

    Color::bg_yellow

    fn Color::bg_yellow() -> Color

    fn Color::blink() -> Color

    Color::bold

    fn Color::bold() -> Color

    Color::change

    fn Color::change(self : Color, table : Table) -> Unit

    Color::change_cell

    fn Color::change_cell(self : Color, table : Table, entity :
    Entity
    ) -> Unit

    Color::colorize

    fn Color::colorize(self : Color, text : String) -> String

    Color each logical line separately; a trailing newline is omitted, as in tabled.

    Color::combine

    fn Color::combine(self : Color, other : Color) -> Color

    Combine styles in order, deduplicating identical prefixes or suffixes.

    Color::default

    fn Color::default() -> Color

    Color::dimmed

    fn Color::dimmed() -> Color

    Color::empty

    fn Color::empty() -> Color

    Color::equal

    fn Color::equal(Color, Color) -> Bool

    Color::fg_black

    fn Color::fg_black() -> Color

    Color::fg_blue

    fn Color::fg_blue() -> Color

    Color::fg_bright_black

    fn Color::fg_bright_black() -> Color

    Color::fg_bright_blue

    fn Color::fg_bright_blue() -> Color

    Color::fg_bright_cyan

    fn Color::fg_bright_cyan() -> Color

    Color::fg_bright_green

    fn Color::fg_bright_green() -> Color

    Color::fg_bright_magenta

    fn Color::fg_bright_magenta() -> Color

    Color::fg_bright_red

    fn Color::fg_bright_red() -> Color

    Color::fg_bright_white

    fn Color::fg_bright_white() -> Color

    Color::fg_bright_yellow

    fn Color::fg_bright_yellow() -> Color

    Color::fg_cyan

    fn Color::fg_cyan() -> Color

    Color::fg_green

    fn Color::fg_green() -> Color

    Color::fg_magenta

    fn Color::fg_magenta() -> Color

    Color::fg_red

    fn Color::fg_red() -> Color

    Color::fg_rgb

    fn Color::fg_rgb(red : Byte, green : Byte, blue : Byte) -> Color

    Color::fg_white

    fn Color::fg_white() -> Color

    Color::fg_yellow

    fn Color::fg_yellow() -> Color

    Color::fmt_ansi_prefix

    fn Color::fmt_ansi_prefix(self : Color, out : StringBuilder) -> Unit

    Color::fmt_ansi_suffix

    fn Color::fmt_ansi_suffix(self : Color, out : StringBuilder) -> Unit

    Color::from_ansi_buf

    Color::from_ansi_str

    Color::get_prefix

    fn Color::get_prefix(self : Color) -> String

    Color::get_suffix

    fn Color::get_suffix(self : Color) -> String

    Color::hidden

    fn Color::hidden() -> Color

    Color::hint_change

    Color::hint_change_cell

    fn Color::hint_change_cell(_self : Color) ->
    Entity
    ?

    Color::invert

    fn Color::invert() -> Color

    Color::is_empty

    fn Color::is_empty(self : Color) -> Bool

    Color::italic

    fn Color::italic() -> Color

    Color::lor

    fn Color::lor(self : Color, other : Color) -> Color

    Color::new

    fn Color::new(prefix : String, suffix : String) -> Color

    Color::not_equal

    fn Color::not_equal(x : Color, y : Color) -> Bool

    Color::parse_or_abort

    fn Color::parse_or_abort(text : String) -> Color

    Parse a style, aborting on input without a text block. Use try_parse when a missing text block must be handled explicitly.

    Color::reset

    fn Color::reset() -> Color

    Color::strikethrough

    fn Color::strikethrough() -> Color

    Color::to_ansi_buf

    Color::to_repr

    Color::try_parse

    fn Color::try_parse(text : String) -> Result[Color, Unit]

    Extract the style of the first text block; no text block produces Err.

    Color::underline

    fn Color::underline() -> Color

    Cols

    pub struct Cols {
    start : Int
    end_ : Int
    skip_n : Int
    step_n : Int
    exclude : Cols?
    predicate : (
    Entity
    ) -> Bool?
    }

    impl Object for Cols

    Cols::all

    fn Cols::all() -> Cols

    Cols::and_

    fn Cols::and_(self : Cols, other : Cols) -> Segment

    Cols::and_cell

    fn Cols::and_cell(self : Cols, cell : Cell) -> Segment

    Cols::and_rows

    fn Cols::and_rows(self : Cols, rows : Rows) -> Segment

    Cols::as_segment

    fn Cols::as_segment(self : Cols) -> Segment

    Cols::cells

    fn Cols::cells(self : Cols, table : Table) -> Array[Array[(Int, Int)]]

    Cols::entities

    fn Cols::entities(self : Cols, table : Table) -> Array[
    Entity
    ]

    Cols::filter

    fn Cols::filter(self : Cols, predicate : (
    Entity
    ) -> Bool) -> Cols

    Cols::first

    fn Cols::first() -> Cols

    Cols::first_offset

    fn Cols::first_offset(offset : Int) -> Cols

    Cols::intersect

    fn Cols::intersect(self : Cols, rows : Rows) -> Segment

    Cols::inverse

    fn Cols::inverse(self : Cols) -> Segment

    Cols::last

    fn Cols::last() -> Cols

    Cols::last_offset

    fn Cols::last_offset(offset : Int) -> Cols

    Cols::new

    fn Cols::new(start : Int, end_ : Int) -> Cols

    Cols::not

    fn Cols::not(self : Cols, other : Cols) -> Cols

    Cols::not_cell

    fn Cols::not_cell(self : Cols, cell : Cell) -> Segment

    Cols::not_rows

    fn Cols::not_rows(self : Cols, rows : Rows) -> Segment

    Cols::one

    fn Cols::one(index : Int) -> Cols

    Cols::skip

    fn Cols::skip(self : Cols, count : Int) -> Cols

    Cols::step_by

    fn Cols::step_by(self : Cols, step : Int) -> Cols

    CompleteDimension

    pub struct CompleteDimension {
    widths : Array[Int]?
    heights : Array[Int]?
    } derive(Eq,
    Debug
    )

    Cached column widths and row heights. Options invalidate only affected axes.

    CompleteDimension::clear

    fn CompleteDimension::clear(self : CompleteDimension) -> Unit

    CompleteDimension::clear_height

    fn CompleteDimension::clear_height(self : CompleteDimension) -> Unit

    CompleteDimension::clear_width

    fn CompleteDimension::clear_width(self : CompleteDimension) -> Unit

    CompleteDimension::default

    CompleteDimension::equal

    CompleteDimension::estimate

    fn CompleteDimension::estimate(self : CompleteDimension, table : Table) -> Unit

    Recompute missing axes or arrays too short for the current records. Longer arrays remain valid, matching explicit width and height lists.

    CompleteDimension::get_height

    fn CompleteDimension::get_height(self : CompleteDimension, row : Int) -> Int

    CompleteDimension::get_heights

    fn CompleteDimension::get_heights(self : CompleteDimension) -> Array[Int]?

    CompleteDimension::get_width

    fn CompleteDimension::get_width(self : CompleteDimension, col : Int) -> Int

    CompleteDimension::get_widths

    fn CompleteDimension::get_widths(self : CompleteDimension) -> Array[Int]?

    CompleteDimension::invalidate

    Invalidate the cached axes affected by an option's change hint. None keeps the cache; row hints clear heights, column hints clear widths, and cell/global hints clear both. Measurement is deferred until estimate.

    CompleteDimension::is_complete

    fn CompleteDimension::is_complete(self : CompleteDimension) -> Bool

    CompleteDimension::is_empty

    fn CompleteDimension::is_empty(self : CompleteDimension) -> Bool

    CompleteDimension::not_equal

    fn CompleteDimension::not_equal(x : CompleteDimension, y : CompleteDimension) -> Bool

    CompleteDimension::set_heights

    fn CompleteDimension::set_heights(self : CompleteDimension, heights : Array[Int]) -> Unit

    CompleteDimension::set_widths

    fn CompleteDimension::set_widths(self : CompleteDimension, widths : Array[Int]) -> Unit

    Concat

    pub struct Concat {
    // private fields
    }

    Append another table's records, using the first table's configuration.

    Concat::change

    fn Concat::change(self : Concat, table : Table) -> Unit

    Concat::default_cell

    fn Concat::default_cell(self : Concat, text : String) -> Concat

    Fill the first table's newly introduced rows (horizontal concatenation) or columns (vertical concatenation). Other missing cells remain empty.

    Concat::hint_change

    Concat::horizontal

    fn Concat::horizontal(table : Table) -> Concat

    Append columns from another table.

    Concat::vertical

    fn Concat::vertical(table : Table) -> Concat

    Append rows from another table.

    Duplicate

    pub struct Duplicate {
    // private fields
    }

    Duplicate an ordered source selection into a destination selection.

    Duplicate::change

    fn Duplicate::change(self : Duplicate, table : Table) -> Unit

    Duplicate::hint_change

    Duplicate::new

    fn Duplicate::new(source~ : &Object, destination~ : &Object) -> Duplicate

    Source values are collected before any destination is changed. The source cycles independently for each destination entity.

    EmptySettings

    pub struct EmptySettings {
    }

    An option that leaves records and configuration unchanged.

    EmptySettings::change

    fn EmptySettings::change(_self : EmptySettings, _table : Table) -> Unit

    EmptySettings::change_cell

    fn EmptySettings::change_cell(_self : EmptySettings, _table : Table, _entity :
    Entity
    ) -> Unit

    EmptySettings::default

    fn EmptySettings::default() -> EmptySettings

    EmptySettings::hint_change

    EmptySettings::hint_change_cell

    Format

    pub enum Format {
    Surround(String, String, Bool)
    Value(String, Bool)
    Content((String) -> String, Bool)
    Positioned((String, Int, Int) -> String, Bool)
    }

    Format::change

    fn Format::change(self : Format, table : Table) -> Unit

    Format::change_cell

    fn Format::change_cell(self : Format, table : Table, entity :
    Entity
    ) -> Unit

    Format::content

    fn Format::content(transform : (String) -> String) -> Format

    Format::hint_change

    Format::hint_change_cell

    fn Format::hint_change_cell(_self : Format) ->
    Entity
    ?

    Format::multiline

    fn Format::multiline(self : Format) -> Format

    Format::positioned

    fn Format::positioned(transform : (String, Int, Int) -> String) -> Format

    Format::surround

    fn Format::surround(prefix : String, suffix : String) -> Format

    Format::value

    fn Format::value(text : String) -> Format

    Height

    pub enum Height {
    }

    Height::increase

    fn[M] Height::increase(height : M) -> CellHeightIncrease[M]

    Height::limit

    fn[M] Height::limit(height : M) -> CellHeightLimit[M]

    Height::list

    fn Height::list(heights : Array[Int]) -> HeightList

    Fix row heights, including cell padding. A shorter list has no effect.

    test {
    let table = @tabular.Table::from_rows([["one"], ["two"]]).with_(
    @tabular.Height::list([0, 2]),
    )
    assert_eq(table.to_string(), "+-----+\n+-----+\n| two |\n| |\n+-----+")
    }

    HeightList

    pub struct HeightList {
    heights : Array[Int]
    } derive(
    Debug
    )

    HeightList::change

    fn HeightList::change(self : HeightList, table : Table) -> Unit

    HeightList::from_array

    fn HeightList::from_array(heights : Array[Int]) -> HeightList

    HeightList::from_iter

    fn HeightList::from_iter(heights : Iter[Int]) -> HeightList

    HeightList::hint_change

    HeightList::new

    fn HeightList::new(heights : Array[Int]) -> HeightList

    Highlight

    pub struct Highlight {
    target : HighlightTarget
    border :
    CellBorder

    }

    Highlight::change

    fn Highlight::change(self : Highlight, table : Table) -> Unit

    Highlight::hint_change

    Highlight::new_cell

    fn Highlight::new_cell(cell : Cell) -> Highlight

    Highlight::new_cols

    fn Highlight::new_cols(cols : Cols) -> Highlight

    Highlight::new_rows

    fn Highlight::new_rows(rows : Rows) -> Highlight

    Highlight::new_segment

    fn Highlight::new_segment(segment : Segment) -> Highlight

    Highlight::outline_cell

    fn Highlight::outline_cell(cell : Cell, ch : Char) -> Highlight

    Highlight::outline_cols

    fn Highlight::outline_cols(cols : Cols, ch : Char) -> Highlight

    Highlight::outline_rows

    fn Highlight::outline_rows(rows : Rows, ch : Char) -> Highlight

    Highlight::outline_segment

    fn Highlight::outline_segment(segment : Segment, ch : Char) -> Highlight

    Highlight::with_border

    HighlightTarget

    pub enum HighlightTarget {
    HCell(Cell)
    HRows(Rows)
    HCols(Cols)
    HSegment(Segment)
    }

    HorizontalLine

    HorizontalLine::filled

    fn HorizontalLine::filled(ch : Char) -> HorizontalLine

    HorizontalLine::from_style

    fn HorizontalLine::from_style(style : Style) -> HorizontalLine

    HorizontalLine::full

    fn HorizontalLine::full(main : Char, left? : Char, intersection? : Char, right? : Char) -> HorizontalLine

    HorizontalLine::intersection

    fn HorizontalLine::intersection(self : HorizontalLine, ch : Char) -> HorizontalLine

    HorizontalLine::left

    fn HorizontalLine::left(self : HorizontalLine, ch : Char) -> HorizontalLine

    HorizontalLine::new

    fn HorizontalLine::new(ch : Char) -> HorizontalLine

    HorizontalLine::right

    fn HorizontalLine::right(self : HorizontalLine, ch : Char) -> HorizontalLine

    IndexBuilder

    pub struct IndexBuilder {
    rows : Array[Array[String]]
    empty_cell : String
    index_col : Int?
    index_name : String?
    show_index : Bool
    }

    IndexBuilder::build

    fn IndexBuilder::build(self : IndexBuilder) -> Table

    Build the final Table from the IndexBuilder.

    IndexBuilder::col

    fn IndexBuilder::col(self : IndexBuilder, col : Int) -> IndexBuilder

    Use the specified col as the index col (0-based).

    IndexBuilder::hide

    Hide the index col.

    IndexBuilder::name

    fn IndexBuilder::name(self : IndexBuilder, name : String?) -> IndexBuilder

    Set the name for the index col. None removes the name row.

    IndexBuilder::transpose

    fn IndexBuilder::transpose(self : IndexBuilder) -> IndexBuilder

    Transpose the table (swap rows and cols).

    Margin

    pub struct Margin {
    left : Int
    right : Int
    top : Int
    bottom : Int
    fill_left : Char
    fill_right : Char
    fill_top : Char
    fill_bottom : Char
    } derive(
    Debug
    )

    Outer table spacing. Fill characters are configurable for each side.

    Margin::change

    fn Margin::change(self : Margin, table : Table) -> Unit

    Margin::fill

    fn Margin::fill(self : Margin, left~ : Char, right~ : Char, top~ : Char, bottom~ : Char) -> Margin

    Margin::hint_change

    Margin::new

    fn Margin::new(left~ : Int, right~ : Int, top~ : Int, bottom~ : Int) -> Margin

    Margin::to_repr

    MarginColor

    pub struct MarginColor[C] {
    colors :
    Sides
    [C]
    } derive(
    Debug
    )

    MarginColor::change

    fn[C :
    ANSIFmt
    ] MarginColor::change(self : MarginColor[C], table : Table) -> Unit

    MarginColor::filled

    fn[C] MarginColor::filled(color : C) -> MarginColor[C]

    MarginColor::new

    fn[C] MarginColor::new(left~ : C, right~ : C, top~ : C, bottom~ : C) -> MarginColor[C]

    Max

    pub(all) struct Max {
    } derive(Eq,
    Debug
    )

    impl Measurement for Max

    Max::default

    fn Max::default() -> Max

    Max::equal

    fn Max::equal(Max, Max) -> Bool

    Max::measure

    fn Max::measure(_self : Max, table : Table, attribute : Attribute) -> Int

    Max::new

    fn Max::new() -> Max

    Max::not_equal

    fn Max::not_equal(x : Max, y : Max) -> Bool

    Max::to_repr

    Merge

    pub enum Merge {
    Horizontal
    Vertical
    }

    Merge::change

    fn Merge::change(self : Merge, table : Table) -> Unit

    Merge::hint_change

    Merge::horizontal

    fn Merge::horizontal() -> Merge

    Merge::vertical

    fn Merge::vertical() -> Merge

    Min

    pub(all) struct Min {
    } derive(Eq,
    Debug
    )

    impl Measurement for Min

    Min::default

    fn Min::default() -> Min

    Min::equal

    fn Min::equal(Min, Min) -> Bool

    Min::measure

    fn Min::measure(_self : Min, table : Table, attribute : Attribute) -> Int

    Min::new

    fn Min::new() -> Min

    Min::not_equal

    fn Min::not_equal(x : Min, y : Min) -> Bool

    Min::to_repr

    MinWidth

    pub struct MinWidth[M, P] {
    width : M
    fill : Char
    priority : P
    }

    impl CellOption for MinWidth[M, P]
    impl TableOption for MinWidth[M, P]

    MinWidth::change

    fn[M : Measurement, P : ResizeSelector] MinWidth::change(self : MinWidth[M, P], table : Table) -> Unit

    MinWidth::change_cell

    fn[M : Measurement, P] MinWidth::change_cell(self : MinWidth[M, P], table : Table, entity :
    Entity
    ) -> Unit

    MinWidth::fill_with

    fn[M, P] MinWidth::fill_with(self : MinWidth[M, P], fill : Char) -> MinWidth[M, P]

    MinWidth::hint_change

    MinWidth::hint_change_cell

    fn[M : Measurement, P] MinWidth::hint_change_cell(_self : MinWidth[M, P]) ->
    Entity
    ?

    MinWidth::new

    fn[M] MinWidth::new(width : M) -> MinWidth[M, PriorityRoundRobin]

    MinWidth::priority

    fn[M, P, Q] MinWidth::priority(self : MinWidth[M, P], priority : Q) -> MinWidth[M, Q]

    Modify

    pub struct Modify[O] {
    // private fields
    }

    Select an object for deferred cell configuration.

    Modify::new

    fn[O] Modify::new(object : O) -> Modify[O]

    Modify::with_

    fn[O, M] Modify::with_(self : Modify[O], option : M) -> CellSettings[O, M]

    Padding

    pub struct Padding {
    left : Int
    right : Int
    top : Int
    bottom : Int
    fills :
    Sides
    [Char]
    } derive(Compare, Eq,
    Debug
    )

    Padding::change

    fn Padding::change(self : Padding, table : Table) -> Unit

    Padding::change_cell

    fn Padding::change_cell(self : Padding, table : Table, entity :
    Entity
    ) -> Unit

    Padding::compare

    fn Padding::compare(Padding, Padding) -> Int

    Padding::equal

    fn Padding::equal(Padding, Padding) -> Bool

    Padding::fill

    fn Padding::fill(self : Padding, left~ : Char, right~ : Char, top~ : Char, bottom~ : Char) -> Padding

    Choose the fill character independently for each side of a cell.

    test {
    let table = @tabular.Table::from_rows([["x"]]).with_(
    @tabular.Padding::new(1, 1, 1, 1).fill(
    left='>',
    right='<',
    top='^',
    bottom='v',
    ),
    )
    assert_eq(table.to_string(), "+---+\n|^^^|\n|>x<|\n|vvv|\n+---+")
    }

    Padding::hint_change

    Padding::hint_change_cell

    fn Padding::hint_change_cell(_self : Padding) ->
    Entity
    ?

    Padding::new

    fn Padding::new(left : Int, right : Int, top : Int, bottom : Int) -> Padding

    Padding::not_equal

    fn Padding::not_equal(x : Padding, y : Padding) -> Bool

    Padding::op_ge

    fn Padding::op_ge(x : Padding, y : Padding) -> Bool

    Padding::op_gt

    fn Padding::op_gt(x : Padding, y : Padding) -> Bool

    Padding::op_le

    fn Padding::op_le(x : Padding, y : Padding) -> Bool

    Padding::op_lt

    fn Padding::op_lt(x : Padding, y : Padding) -> Bool

    Padding::to_repr

    Padding::zero

    fn Padding::zero() -> Padding

    PaddingColor

    pub struct PaddingColor[C] {
    colors :
    Sides
    [C]
    } derive(Eq,
    Debug
    )

    Independent colors for the four padding sides.

    PaddingColor::change

    fn[C :
    ANSIFmt
    ] PaddingColor::change(self : PaddingColor[C], table : Table) -> Unit

    PaddingColor::change_cell

    PaddingColor::equal

    fn[C : Eq] PaddingColor::equal(PaddingColor[C], PaddingColor[C]) -> Bool

    PaddingColor::filled

    fn[C] PaddingColor::filled(color : C) -> PaddingColor[C]

    PaddingColor::from_sides

    PaddingColor::hint_change_cell

    PaddingColor::new

    fn[C] PaddingColor::new(left~ : C, right~ : C, top~ : C, bottom~ : C) -> PaddingColor[C]

    PaddingColor::not_equal

    fn[C : Eq] PaddingColor::not_equal(x : PaddingColor[C], y : PaddingColor[C]) -> Bool

    PaddingColor::to_sides

    PaddingExpand

    pub(all) enum PaddingExpand {
    Horizontal
    Vertical
    } derive(Compare, Eq,
    Debug
    )

    PaddingExpand::change

    fn PaddingExpand::change(self : PaddingExpand, table : Table) -> Unit

    PaddingExpand::change_cell

    fn PaddingExpand::change_cell(self : PaddingExpand, table : Table, entity :
    Entity
    ) -> Unit

    PaddingExpand::compare

    PaddingExpand::equal

    PaddingExpand::hint_change

    PaddingExpand::hint_change_cell

    PaddingExpand::not_equal

    fn PaddingExpand::not_equal(x : PaddingExpand, y : PaddingExpand) -> Bool

    PaddingExpand::op_ge

    fn PaddingExpand::op_ge(x : PaddingExpand, y : PaddingExpand) -> Bool

    PaddingExpand::op_gt

    fn PaddingExpand::op_gt(x : PaddingExpand, y : PaddingExpand) -> Bool

    PaddingExpand::op_le

    fn PaddingExpand::op_le(x : PaddingExpand, y : PaddingExpand) -> Bool

    PaddingExpand::op_lt

    fn PaddingExpand::op_lt(x : PaddingExpand, y : PaddingExpand) -> Bool

    Panel

    pub enum Panel {
    }

    Panel::footer

    fn Panel::footer(text : String) -> PanelConfig

    Insert a footer panel after the last row.

    Panel::header

    fn Panel::header(text : String) -> PanelConfig

    Insert a header panel at row 0.

    Panel::horizontal

    fn Panel::horizontal(row : Int, text : String) -> PanelConfig

    Insert a horizontal panel at the given row index. The panel text spans all cols.

    Panel::vertical

    fn Panel::vertical(col : Int, text : String) -> PanelConfig

    Insert a vertical panel at the given col index. The panel text spans all rows.

    Panel::vertical_with_width

    fn Panel::vertical_with_width(col : Int, text : String, width : Int) -> PanelConfig

    Insert a vertical panel with text split to fit a certain width.

    PanelConfig

    type PanelConfig

    PanelConfig::change

    fn PanelConfig::change(self : PanelConfig, table : Table) -> Unit

    PanelConfig::hint_change

    Percent

    pub(all) struct Percent(Int) derive(Eq,
    Debug
    )

    Percent::equal

    fn Percent::equal(Percent, Percent) -> Bool

    Percent::measure

    fn Percent::measure(self : Percent, table : Table, attribute : Attribute) -> Int

    Percent::new

    fn Percent::new(value : Int) -> Percent

    Percent::not_equal

    fn Percent::not_equal(x : Percent, y : Percent) -> Bool

    Percent::to_repr

    Priority

    pub enum Priority {
    }

    Factories for the upstream dimension-resizing priorities.

    Priority::first

    fn Priority::first() -> PriorityFirst

    Priority::last

    fn Priority::last() -> PriorityLast

    Priority::max

    fn Priority::max(tie_break~ : TieBreak) -> PriorityMax

    Priority::min

    fn Priority::min(tie_break~ : TieBreak) -> PriorityMin

    Priority::round_robin

    fn Priority::round_robin() -> PriorityRoundRobin

    PriorityFirst

    pub struct PriorityFirst {
    } derive(Eq,
    Debug
    )

    Select the lowest eligible index (leftmost column or topmost row).

    PriorityFirst::default

    fn PriorityFirst::default() -> PriorityFirst

    PriorityFirst::equal

    PriorityFirst::fresh

    PriorityFirst::new

    PriorityFirst::not_equal

    fn PriorityFirst::not_equal(x : PriorityFirst, y : PriorityFirst) -> Bool

    PriorityFirst::select

    fn PriorityFirst::select(_self : PriorityFirst, minimums : Array[Int], sizes : Array[Int]) -> Int?

    PriorityLast

    pub struct PriorityLast {
    } derive(Eq,
    Debug
    )

    Select from the highest eligible index (rightmost column or bottommost row).

    PriorityLast::default

    fn PriorityLast::default() -> PriorityLast

    PriorityLast::equal

    PriorityLast::fresh

    PriorityLast::new

    PriorityLast::not_equal

    fn PriorityLast::not_equal(x : PriorityLast, y : PriorityLast) -> Bool

    PriorityLast::select

    fn PriorityLast::select(_self : PriorityLast, minimums : Array[Int], sizes : Array[Int]) -> Int?

    PriorityMax

    pub struct PriorityMax {
    // private fields
    } derive(Eq,
    Debug
    )

    Select a maximum size; equal values use the explicitly chosen tie break.

    PriorityMax::default

    fn PriorityMax::default() -> PriorityMax

    Preserve the upstream default: equal maximum sizes prefer the first index.

    PriorityMax::equal

    fn PriorityMax::equal(PriorityMax, PriorityMax) -> Bool

    PriorityMax::fresh

    fn PriorityMax::fresh(self : PriorityMax) -> &ResizeSelector

    PriorityMax::new

    fn PriorityMax::new(tie_break~ : TieBreak) -> PriorityMax

    PriorityMax::not_equal

    fn PriorityMax::not_equal(x : PriorityMax, y : PriorityMax) -> Bool

    PriorityMax::prefer_first

    fn PriorityMax::prefer_first() -> PriorityMax

    PriorityMax::prefer_last

    fn PriorityMax::prefer_last() -> PriorityMax

    PriorityMax::select

    fn PriorityMax::select(self : PriorityMax, minimums : Array[Int], sizes : Array[Int]) -> Int?

    PriorityMin

    pub struct PriorityMin {
    // private fields
    } derive(Eq,
    Debug
    )

    Select a minimum size; equal values use the explicitly chosen tie break.

    PriorityMin::default

    fn PriorityMin::default() -> PriorityMin

    Preserve the upstream default: equal minimum sizes prefer the last index.

    PriorityMin::equal

    fn PriorityMin::equal(PriorityMin, PriorityMin) -> Bool

    PriorityMin::fresh

    fn PriorityMin::fresh(self : PriorityMin) -> &ResizeSelector

    PriorityMin::new

    fn PriorityMin::new(tie_break~ : TieBreak) -> PriorityMin

    PriorityMin::not_equal

    fn PriorityMin::not_equal(x : PriorityMin, y : PriorityMin) -> Bool

    PriorityMin::prefer_first

    fn PriorityMin::prefer_first() -> PriorityMin

    PriorityMin::prefer_last

    fn PriorityMin::prefer_last() -> PriorityMin

    PriorityMin::select

    fn PriorityMin::select(self : PriorityMin, minimums : Array[Int], sizes : Array[Int]) -> Int?

    PriorityRoundRobin

    pub struct PriorityRoundRobin {
    // private fields
    } derive(Eq,
    Debug
    )

    Round-robin selection retains its next index. Zero sizes are skipped unless a negative minimum explicitly makes them eligible for growth.

    PriorityRoundRobin::default

    PriorityRoundRobin::equal

    PriorityRoundRobin::fresh

    PriorityRoundRobin::new

    PriorityRoundRobin::not_equal

    PriorityRoundRobin::select

    fn PriorityRoundRobin::select(self : PriorityRoundRobin, minimums : Array[Int], sizes : Array[Int]) -> Int?

    Reverse

    pub struct Reverse {
    // private fields
    }

    Reverse a contiguous range of rows or columns.

    Reverse::change

    fn Reverse::change(self : Reverse, table : Table) -> Unit

    Reverse::cols

    fn Reverse::cols(start : Int) -> Reverse

    Reverse all columns from start, including start.

    Reverse::exclude_last

    fn Reverse::exclude_last(self : Reverse, count : Int) -> Reverse

    Exclude count trailing rows or columns from the reversed range. Replaces any previous take or exclude_last bound.

    test {
    let table = @tabular.Table::from_rows([["a"], ["b"], ["c"], ["d"], ["e"]])
    table.reverse(@tabular.Reverse::rows(1).exclude_last(1)) |> ignore
    assert_eq(table.rows, [["a"], ["d"], ["c"], ["b"], ["e"]])
    }

    Reverse::hint_change

    Reverse::rows

    fn Reverse::rows(start : Int) -> Reverse

    Reverse all rows from start, including start.

    Reverse::take

    fn Reverse::take(self : Reverse, count : Int) -> Reverse

    Reverse exactly count items, starting at the configured index. A negative count or a range extending past the table leaves it unchanged. Replaces any previous take or exclude_last bound.

    Rotate

    pub(all) enum Rotate {
    Left
    Right
    } derive(Eq,
    Debug
    )

    Rotate the records while keeping formatting attached to table coordinates. Use Reverse::rows(0) to reverse row order without rotating columns.

    Rotate::change

    fn Rotate::change(self : Rotate, table : Table) -> Unit

    Rotate::equal

    fn Rotate::equal(Rotate, Rotate) -> Bool

    Rotate::hint_change

    Rotate::not_equal

    fn Rotate::not_equal(x : Rotate, y : Rotate) -> Bool

    Rotate::to_repr

    Rows

    pub struct Rows {
    start : Int
    end_ : Int
    skip_n : Int
    step_n : Int
    exclude : Rows?
    predicate : (
    Entity
    ) -> Bool?
    }

    impl Object for Rows

    Rows::all

    fn Rows::all() -> Rows

    Rows::and_

    fn Rows::and_(self : Rows, other : Rows) -> Segment

    Rows::and_cell

    fn Rows::and_cell(self : Rows, cell : Cell) -> Segment

    Rows::and_cols

    fn Rows::and_cols(self : Rows, cols : Cols) -> Segment

    Rows::as_segment

    fn Rows::as_segment(self : Rows) -> Segment

    Rows::cells

    fn Rows::cells(self : Rows, table : Table) -> Array[Array[(Int, Int)]]

    Rows::entities

    fn Rows::entities(self : Rows, table : Table) -> Array[
    Entity
    ]

    Rows::filter

    fn Rows::filter(self : Rows, predicate : (
    Entity
    ) -> Bool) -> Rows

    Rows::first

    fn Rows::first() -> Rows

    Rows::first_offset

    fn Rows::first_offset(offset : Int) -> Rows

    Rows::intersect

    fn Rows::intersect(self : Rows, cols : Cols) -> Segment

    Rows::inverse

    fn Rows::inverse(self : Rows) -> Segment

    Rows::last

    fn Rows::last() -> Rows

    Rows::last_offset

    fn Rows::last_offset(offset : Int) -> Rows

    Rows::new

    fn Rows::new(start : Int, end_ : Int) -> Rows

    Rows::not

    fn Rows::not(self : Rows, other : Rows) -> Rows

    Rows::not_cell

    fn Rows::not_cell(self : Rows, cell : Cell) -> Segment

    Rows::not_cols

    fn Rows::not_cols(self : Rows, cols : Cols) -> Segment

    Rows::one

    fn Rows::one(index : Int) -> Rows

    Rows::skip

    fn Rows::skip(self : Rows, count : Int) -> Rows

    Rows::step_by

    fn Rows::step_by(self : Rows, step : Int) -> Rows

    Segment

    pub struct Segment {
    kind : SegmentKind
    skip_n : Int
    step_n : Int
    }

    impl Object for Segment

    Segment::all

    fn Segment::all() -> Segment

    Segment::and_

    fn Segment::and_(self : Segment, other : Segment) -> Segment

    Segment::and_cell

    fn Segment::and_cell(self : Segment, cell : Cell) -> Segment

    Segment::and_cols

    fn Segment::and_cols(self : Segment, cols : Cols) -> Segment

    Segment::and_rows

    fn Segment::and_rows(self : Segment, rows : Rows) -> Segment

    Segment::cells

    fn Segment::cells(self : Segment, table : Table) -> Array[Array[(Int, Int)]]

    Segment::entities

    Segment::new

    fn Segment::new(row_start : Int, row_end : Int, col_start : Int, col_end : Int) -> Segment

    Segment::not

    fn Segment::not(self : Segment, other : Segment) -> Segment

    Segment::not_

    fn Segment::not_(self : Segment, other : Segment) -> Segment

    Segment::not_cell

    fn Segment::not_cell(self : Segment, cell : Cell) -> Segment

    Segment::skip

    fn Segment::skip(self : Segment, count : Int) -> Segment

    Segment::step_by

    fn Segment::step_by(self : Segment, step : Int) -> Segment

    SegmentKind

    pub enum SegmentKind {
    All
    Range(Int, Int, Int, Int)
    RowsOnly(Rows)
    ColsOnly(Cols)
    CellOnly(Cell)
    Cross(Rows, Cols)
    InverseRows(Rows)
    InverseCols(Cols)
    InverseCell(Cell)
    Union2(Segment, Segment)
    Diff2(Segment, Segment)
    }

    Setting

    pub enum Setting {
    Align(Align)
    VAlign(VAlign)
    Pad(Padding)
    W(
    WidthMode
    )
    H(
    HeightMode
    )
    Fmt(Format)
    SpanCol(Int)
    SpanRow(Int)
    }

    Setting::align

    fn Setting::align(align : Align) -> Setting

    Setting::change

    fn Setting::change(self : Setting, table : Table) -> Unit

    Setting::change_cell

    fn Setting::change_cell(self : Setting, table : Table, entity :
    Entity
    ) -> Unit

    Setting::format

    fn Setting::format(format : Format) -> Setting

    Setting::height

    fn[H : HeightOption] Setting::height(height : H) -> Setting

    Setting::hint_change

    Setting::hint_change_cell

    fn Setting::hint_change_cell(_self : Setting) ->
    Entity
    ?

    Setting::padding

    fn Setting::padding(padding : Padding) -> Setting

    Setting::valign

    fn Setting::valign(align : VAlign) -> Setting

    Setting::width

    fn[W : WidthOption] Setting::width(width : W) -> Setting

    Settings

    pub struct Settings[A, B] {
    // private fields
    }

    Compose options while preserving their application order.
    impl CellOption for Settings[A, B]
    impl TableOption for Settings[A, B]

    Settings::change

    fn[A : TableOption, B : TableOption] Settings::change(self : Settings[A, B], table : Table) -> Unit

    Settings::change_cell

    fn[A : CellOption, B : CellOption] Settings::change_cell(self : Settings[A, B], table : Table, entity :
    Entity
    ) -> Unit

    Settings::default

    Settings::empty

    Settings::hint_change

    Settings::hint_change_cell

    fn[A : CellOption, B : CellOption] Settings::hint_change_cell(self : Settings[A, B]) ->
    Entity
    ?

    Settings::modify

    fn[A, B, O, M] Settings::modify(self : Settings[A, B], object : O, option : M) -> Settings[Settings[A, B], CellSettings[O, M]]

    Append a modification of a selected object to this configuration chain.

    Settings::new

    fn[A, B] Settings::new(first : A, second : B) -> Settings[A, B]

    Settings::with_

    fn[A, B, C] Settings::with_(self : Settings[A, B], option : C) -> Settings[Settings[A, B], C]

    Shadow

    pub struct Shadow {
    size : Int
    offset : Int
    fill : Char
    top : Bool
    bottom : Bool
    left : Bool
    right : Bool
    }

    Shadow::change

    fn Shadow::change(self : Shadow, table : Table) -> Unit

    Shadow::hint_change

    Shadow::new

    fn Shadow::new(size : Int) -> Shadow

    Create a shadow with default direction (bottom-right) and default fill '▒'.

    Shadow::set_bottom

    fn Shadow::set_bottom(self : Shadow) -> Shadow

    Shadow::set_fill

    fn Shadow::set_fill(self : Shadow, c : Char) -> Shadow

    Shadow::set_left

    fn Shadow::set_left(self : Shadow) -> Shadow

    Shadow::set_offset

    fn Shadow::set_offset(self : Shadow, offset : Int) -> Shadow

    Shadow::set_right

    fn Shadow::set_right(self : Shadow) -> Shadow

    Shadow::set_top

    fn Shadow::set_top(self : Shadow) -> Shadow

    Span

    pub enum Span {
    }

    Span::col

    fn Span::col(size : Int) -> Setting

    Span::row

    fn Span::row(size : Int) -> Setting

    Split

    pub struct Split {
    // private fields
    }

    Split::change

    fn Split::change(self : Split, table : Table) -> Unit

    Split::clean

    fn Split::clean(self : Split) -> Split

    Split::col

    fn Split::col(index : Int) -> Split

    Split::concat

    fn Split::concat(self : Split) -> Split

    Split::hint_change

    Split::retain

    fn Split::retain(self : Split) -> Split

    Split::row

    fn Split::row(index : Int) -> Split

    Split::zip

    fn Split::zip(self : Split) -> Split

    Style

    Style::ascii

    fn Style::ascii() -> Style

    Style::ascii_rounded

    fn Style::ascii_rounded() -> Style

    Style::blank

    fn Style::blank() -> Style

    Style::borders

    Style::bottom

    fn Style::bottom(self : Style, ch : Char) -> Style

    Style::change

    fn Style::change(self : Style, table : Table) -> Unit

    Style::corner_bottom_left

    fn Style::corner_bottom_left(self : Style, ch : Char) -> Style

    Style::corner_bottom_right

    fn Style::corner_bottom_right(self : Style, ch : Char) -> Style

    Style::corner_top_left

    fn Style::corner_top_left(self : Style, ch : Char) -> Style

    Style::corner_top_right

    fn Style::corner_top_right(self : Style, ch : Char) -> Style

    Style::custom_horizontal_lines

    fn Style::custom_horizontal_lines(self : Style) -> Array[(Int,
    HorizontalLine
    )]

    Style::dots

    fn Style::dots() -> Style

    Style::empty

    fn Style::empty() -> Style

    Style::extended

    fn Style::extended() -> Style

    Style::hint_change

    Style::horizontal

    fn Style::horizontal(self : Style, ch : Char) -> Style

    Style::horizontal_lines

    Style::horizontals

    fn Style::horizontals(self : Style, lines : Array[(Int, HorizontalLine)]) -> Style

    Style::intersection

    fn Style::intersection(self : Style, ch : Char) -> Style

    Style::intersection_bottom

    fn Style::intersection_bottom(self : Style, ch : Char) -> Style

    Style::intersection_left

    fn Style::intersection_left(self : Style, ch : Char) -> Style

    Style::intersection_right

    fn Style::intersection_right(self : Style, ch : Char) -> Style

    Style::intersection_top

    fn Style::intersection_top(self : Style, ch : Char) -> Style

    Style::left

    fn Style::left(self : Style, ch : Char) -> Style

    Style::markdown

    fn Style::markdown() -> Style

    Style::modern

    fn Style::modern() -> Style

    Style::psql

    fn Style::psql() -> Style

    Style::re_structured_text

    fn Style::re_structured_text() -> Style

    Style::remove_bottom

    fn Style::remove_bottom(self : Style) -> Style

    Style::remove_horizontal

    fn Style::remove_horizontal(self : Style) -> Style

    Style::remove_horizontals

    fn Style::remove_horizontals(self : Style) -> Style

    Style::remove_left

    fn Style::remove_left(self : Style) -> Style

    Style::remove_right

    fn Style::remove_right(self : Style) -> Style

    Style::remove_top

    fn Style::remove_top(self : Style) -> Style

    Style::remove_vertical

    fn Style::remove_vertical(self : Style) -> Style

    Style::right

    fn Style::right(self : Style, ch : Char) -> Style

    Style::rounded

    fn Style::rounded() -> Style

    Style::top

    fn Style::top(self : Style, ch : Char) -> Style

    Style::vertical

    fn Style::vertical(self : Style, ch : Char) -> Style

    SuffixLimit

    pub(all) enum SuffixLimit {
    Cut
    Ignore
    Replace(Char)
    } derive(Eq,
    Debug
    )

    SuffixLimit::equal

    fn SuffixLimit::equal(SuffixLimit, SuffixLimit) -> Bool

    SuffixLimit::not_equal

    fn SuffixLimit::not_equal(x : SuffixLimit, y : SuffixLimit) -> Bool

    Table

    pub struct Table {
    rows : Array[Array[String]]
    config :
    SpannedConfig

    dimension : CompleteDimension
    // private fields
    }

    Table::apply

    fn Table::apply(self : Table, style : Style) -> Table

    Table::concat

    fn Table::concat(self : Table, concat : Concat) -> Table

    Concatenate records, keeping the receiving table's style and cell settings.

    test {
    let table = @tabular.Table::from_rows([["a"]])
    let other = @tabular.Table::from_rows([["b"], ["c"]])
    table.concat(@tabular.Concat::horizontal(other).default_cell("?")) |> ignore
    assert_eq(table.rows, [["a", "b"], ["?", "c"]])
    }

    Table::correct_borders

    fn Table::correct_borders(self : Table) -> Table

    Correct border junctions at span boundaries so merged cells display proper corners.

    Table::count_cols

    fn Table::count_cols(self : Table) -> Int

    Table::count_rows

    fn Table::count_rows(self : Table) -> Int

    Table::dimension_cache

    fn Table::dimension_cache(self : Table) -> CompleteDimension

    Return the shared dimension cache. Changes affect this table directly. Clear it after changing records or configuration through raw mutable access.

    Table::dimension_snapshot

    fn Table::dimension_snapshot(self : Table) -> CompleteDimension

    Return an independent snapshot of the dimension cache without measuring.

    Table::duplicate

    fn Table::duplicate(self : Table, duplication : Duplicate) -> Table

    Copy source contents to selected cells without changing formatting.

    test {
    let table = @tabular.Table::from_rows([["a", "b"], ["c", "d"]])
    table.duplicate(
    @tabular.Duplicate::new(
    source=@tabular.Rows::one(0),
    destination=@tabular.Rows::one(1),
    ),
    )
    |> ignore
    assert_eq(table.rows, [["a", "b"], ["a", "b"]])
    }

    Table::extract_cols

    fn Table::extract_cols(self : Table, cols : Cols) -> Table

    Table::extract_rows

    fn Table::extract_rows(self : Table, rows : Rows) -> Table

    Table::extract_segment

    fn Table::extract_segment(self : Table, rows : Rows, cols : Cols) -> Table

    Table::from_rows

    fn Table::from_rows(rows : Array[Array[String]]) -> Table

    Table::highlight

    fn Table::highlight(self : Table, highlight : Highlight) -> Table

    Table::is_empty

    fn Table::is_empty(self : Table) -> Bool

    Table::merge

    fn Table::merge(self : Table, merge : Merge) -> Table

    Apply merge to the table, combining adjacent duplicate cells using spans.

    Table::modify

    fn[O : Object, M : CellOption] Table::modify(self : Table, object : O, option : M) -> Table

    Apply a cell option to each entity selected by an object.

    Table::modify_by_col_name

    fn Table::modify_by_col_name(self : Table, by_name : ByColName, setting : Setting) -> Table

    Table::modify_cell

    fn Table::modify_cell(self : Table, cell : Cell, setting : Setting) -> Table

    Table::modify_cols

    fn Table::modify_cols(self : Table, cols : Cols, setting : Setting) -> Table

    Table::modify_rows

    fn Table::modify_rows(self : Table, rows : Rows, setting : Setting) -> Table

    Table::modify_segment

    fn Table::modify_segment(self : Table, segment : Segment, setting : Setting) -> Table

    Table::panel

    fn Table::panel(self : Table, panel : PanelConfig) -> Table

    Apply a horizontal or vertical panel to the table.

    Table::remove_by_col_name

    fn Table::remove_by_col_name(self : Table, by_name : ByColName) -> Table

    Table::remove_cols

    fn Table::remove_cols(self : Table, cols : Cols) -> Table

    Table::remove_rows

    fn Table::remove_rows(self : Table, rows : Rows) -> Table

    Table::reverse

    fn Table::reverse(self : Table, reverse : Reverse) -> Table

    Reverse records without moving coordinate-based formatting. Invalid ranges leave the table unchanged.

    test {
    let table = @tabular.Table::from_rows([["a"], ["b"], ["c"], ["d"]])
    table.reverse(@tabular.Reverse::rows(1).take(2)) |> ignore
    assert_eq(table.rows, [["a"], ["c"], ["b"], ["d"]])
    }

    Table::rotate

    fn Table::rotate(self : Table, rotation : Rotate) -> Table

    Rotate table contents by a quarter turn.

    test {
    let table = @tabular.Table::from_rows([["a", "b"], ["c", "d"]])
    table.rotate(@tabular.Rotate::Left) |> ignore
    assert_eq(table.rows, [["b", "d"], ["a", "c"]])
    }

    Table::set_align

    fn Table::set_align(self : Table, align : Align) -> Table

    Table::set_height

    fn[H : HeightOption] Table::set_height(self : Table, height : H) -> Table

    Table::set_padding

    fn Table::set_padding(self : Table, padding : Padding) -> Table

    Table::set_valign

    fn Table::set_valign(self : Table, align : VAlign) -> Table

    Table::set_width

    fn[W : WidthOption] Table::set_width(self : Table, width : W) -> Table

    Table::shadow

    fn Table::shadow(self : Table, shadow : Shadow) -> Table

    Table::shape

    fn Table::shape(self : Table) -> (Int, Int)

    Table::split

    fn Table::split(self : Table, split : Split) -> Table

    Apply a Split setting to reshape the table. This resets config (spans, borders) since Split fundamentally changes the table shape.

    Table::to_string

    fn Table::to_string(self : Table) -> String

    Table::total_height

    fn Table::total_height(self : Table) -> Int

    Table::total_width

    fn Table::total_width(self : Table) -> Int

    Table::with_

    fn[T : TableOption] Table::with_(self : Table, option : T) -> Table

    Apply any table option. The suffix avoids MoonBit's with keyword.

    test {
    let table = @tabular.Table::from_rows([["a", "b"]])
    table.with_(@tabular.Rotate::Left) |> ignore
    assert_eq(table.rows, [["b"], ["a"]])
    }

    TableHeightIncrease

    pub struct TableHeightIncrease[M, P] {
    height : M
    priority : P
    } derive(
    Debug
    )

    TableHeightIncrease::change

    fn[M : Measurement, P : ResizeSelector] TableHeightIncrease::change(self : TableHeightIncrease[M, P], table : Table) -> Unit

    TableHeightIncrease::hint_change

    TableHeightIncrease::new

    TableHeightIncrease::priority

    fn[M, P, Q] TableHeightIncrease::priority(self : TableHeightIncrease[M, P], priority : Q) -> TableHeightIncrease[M, Q]

    TableHeightLimit

    pub struct TableHeightLimit[M, P] {
    height : M
    priority : P
    } derive(
    Debug
    )

    TableHeightLimit::change

    fn[M : Measurement, P : ResizeSelector] TableHeightLimit::change(self : TableHeightLimit[M, P], table : Table) -> Unit

    TableHeightLimit::hint_change

    TableHeightLimit::new

    TableHeightLimit::priority

    fn[M, P, Q] TableHeightLimit::priority(self : TableHeightLimit[M, P], priority : Q) -> TableHeightLimit[M, Q]

    TextCleanup

    pub struct TextCleanup {
    // private fields
    }

    Clean layout-disrupting control characters and expand tabs in records.

    TextCleanup::change

    fn TextCleanup::change(self : TextCleanup, table : Table) -> Unit

    TextCleanup::change_cell

    fn TextCleanup::change_cell(self : TextCleanup, table : Table, entity :
    Entity
    ) -> Unit

    TextCleanup::clean_text

    fn TextCleanup::clean_text(text : String) -> String

    Remove C0 controls except newlines and expand tabs to four spaces.

    test {
    assert_eq(@tabular.TextCleanup::clean_text("a\tb\r\nc"), "a b\nc")
    }

    TextCleanup::default

    fn TextCleanup::default() -> TextCleanup

    TextCleanup::expand_tabs

    fn TextCleanup::expand_tabs(self : TextCleanup, tab_width : Int) -> TextCleanup

    Replace each tab with tab_width spaces, independently of its column.

    TextCleanup::hint_change

    TextCleanup::hint_change_cell

    TextCleanup::new

    TextCleanup::remove_control_chars

    fn TextCleanup::remove_control_chars(self : TextCleanup) -> TextCleanup

    Remove C0 controls (U+0000..U+001F), preserving newlines. Tabs are removed unless expand_tabs supplies their replacement width.

    TieBreak

    pub(all) enum TieBreak {
    First
    Last
    } derive(Eq,
    Debug
    )

    Choose the lowest or highest index when eligible sizes are equal. This applies to both columns (left/right) and rows (top/bottom).

    TieBreak::equal

    fn TieBreak::equal(TieBreak, TieBreak) -> Bool

    TieBreak::not_equal

    fn TieBreak::not_equal(x : TieBreak, y : TieBreak) -> Bool

    TieBreak::to_repr

    TrimStrategy

    pub(all) enum TrimStrategy {
    Vertical
    Horizontal
    Both
    None
    } derive(Eq,
    Debug
    )

    Trim whitespace when rendering, without changing records or dimensions.

    TrimStrategy::change

    fn TrimStrategy::change(self : TrimStrategy, table : Table) -> Unit

    TrimStrategy::change_cell

    fn TrimStrategy::change_cell(self : TrimStrategy, table : Table, entity :
    Entity
    ) -> Unit

    TrimStrategy::equal

    TrimStrategy::hint_change

    TrimStrategy::hint_change_cell

    TrimStrategy::not_equal

    fn TrimStrategy::not_equal(x : TrimStrategy, y : TrimStrategy) -> Bool

    Truncate

    pub struct Truncate[M, P] {
    width : M
    suffix : String
    suffix_limit : SuffixLimit
    multiline : Bool
    inherit_suffix_style : Bool
    priority : P
    }

    impl CellOption for Truncate[M, P]
    impl TableOption for Truncate[M, P]

    Truncate::change

    fn[M : Measurement, P : ResizeSelector] Truncate::change(self : Truncate[M, P], table : Table) -> Unit

    Truncate::change_cell

    fn[M : Measurement, P] Truncate::change_cell(self : Truncate[M, P], table : Table, entity :
    Entity
    ) -> Unit

    Truncate::hint_change

    Truncate::hint_change_cell

    fn[M : Measurement, P] Truncate::hint_change_cell(_self : Truncate[M, P]) ->
    Entity
    ?

    Truncate::inherit_suffix_style

    fn[M, P] Truncate::inherit_suffix_style(self : Truncate[M, P], enabled : Bool) -> Truncate[M, P]

    Let the suffix inherit the last text block's ANSI style when enabled.

    Truncate::multiline

    fn[M, P] Truncate::multiline(self : Truncate[M, P], enabled : Bool) -> Truncate[M, P]

    Truncate::new

    fn[M] Truncate::new(width : M) -> Truncate[M, PriorityRoundRobin]

    Truncate::priority

    fn[M, P, Q] Truncate::priority(self : Truncate[M, P], priority : Q) -> Truncate[M, Q]

    Truncate::suffix

    fn[M, P] Truncate::suffix(self : Truncate[M, P], suffix : String) -> Truncate[M, P]

    Truncate::suffix_limit

    fn[M, P] Truncate::suffix_limit(self : Truncate[M, P], limit : SuffixLimit) -> Truncate[M, P]

    Truncate::to_mode

    Truncate::truncate

    fn Truncate::truncate(text : String, width : Int) -> String

    UniformWidth

    pub struct UniformWidth[M] {
    width : M
    }

    UniformWidth::change

    fn[M : Measurement] UniformWidth::change(self : UniformWidth[M], table : Table) -> Unit

    UniformWidth::hint_change

    UniformWidth::max

    UniformWidth::min

    UniformWidth::new

    fn[M] UniformWidth::new(width : M) -> UniformWidth[M]

    VAlign

    pub enum VAlign {
    Top
    Bottom
    Center
    }

    VAlign::bottom

    fn VAlign::bottom() -> VAlign

    VAlign::center

    fn VAlign::center() -> VAlign

    VAlign::change

    fn VAlign::change(self : VAlign, table : Table) -> Unit

    VAlign::change_cell

    fn VAlign::change_cell(self : VAlign, table : Table, entity :
    Entity
    ) -> Unit

    VAlign::hint_change

    VAlign::hint_change_cell

    fn VAlign::hint_change_cell(_self : VAlign) ->
    Entity
    ?

    VAlign::top

    fn VAlign::top() -> VAlign

    Width

    pub enum Width {
    }

    Width::increase

    fn[M] Width::increase(width : M) -> MinWidth[M, PriorityRoundRobin]

    Increase the total table width, including padding, borders, and margins. Cell application pads the text itself and does not include cell padding.

    test {
    let table = @tabular.Table::from_rows([["a", "bb"]]).with_(
    @tabular.Width::increase(20),
    )
    assert_eq(table.total_width(), 20)
    assert_eq(table.rows, [["a", "bb"]])
    }

    Width::list

    fn Width::list(widths : Array[Int]) -> WidthList

    Width::truncate

    fn[M] Width::truncate(width : M, suffix? : String) -> Truncate[M, PriorityRoundRobin]

    Width::uniform

    fn[M] Width::uniform(width : M) -> UniformWidth[M]

    Width::wrap

    fn[M] Width::wrap(width : M) -> Wrap[M, PriorityRoundRobin]

    Wrap records at a cell width with modify, or fit the total table with with_.

    test {
    let table = @tabular.Table::from_rows([["hello world"]])
    table.modify((0, 0), @tabular.Width::wrap(7).keep_words(true)) |> ignore
    assert_eq(table.rows, [["hello \nworld"]])
    }

    Width::wrap_with

    fn Width::wrap_with(width : Int, placeholder : String) -> Wrap[Int, PriorityRoundRobin]

    WidthList

    pub struct WidthList {
    widths : Array[Int]
    }

    WidthList::change

    fn WidthList::change(self : WidthList, table : Table) -> Unit

    WidthList::from_array

    fn WidthList::from_array(widths : Array[Int]) -> WidthList

    WidthList::from_iter

    fn WidthList::from_iter(widths : Iter[Int]) -> WidthList

    WidthList::hint_change

    WidthList::new

    fn WidthList::new(widths : Array[Int]) -> WidthList

    Wrap

    pub struct Wrap[M, P] {
    width : M
    keep_words : Bool
    priority : P
    placeholder : String
    }

    impl CellOption for Wrap[M, P]
    impl TableOption for Wrap[M, P]
    impl WidthOption for Wrap[Int, P]

    Wrap::change

    fn[M : Measurement, P : ResizeSelector] Wrap::change(self : Wrap[M, P], table : Table) -> Unit

    Wrap::change_cell

    fn[M : Measurement, P] Wrap::change_cell(self : Wrap[M, P], table : Table, entity :
    Entity
    ) -> Unit

    Wrap::hint_change

    fn[M : Measurement, P : ResizeSelector] Wrap::hint_change(_self : Wrap[M, P]) ->
    Entity
    ?

    Wrap::hint_change_cell

    fn[M : Measurement, P] Wrap::hint_change_cell(_self : Wrap[M, P]) ->
    Entity
    ?

    Wrap::keep_words

    fn[M, P] Wrap::keep_words(self : Wrap[M, P], enabled : Bool) -> Wrap[M, P]

    Wrap::new

    fn[M] Wrap::new(width : M) -> Wrap[M, PriorityRoundRobin]

    Wrap::priority

    fn[M, P, Q] Wrap::priority(self : Wrap[M, P], priority : Q) -> Wrap[M, Q]

    Wrap::to_mode

    fn[P] Wrap::to_mode(self : Wrap[Int, P]) ->
    WidthMode

    Wrap::wrap

    fn Wrap::wrap(text : String, width : Int, keep_words~ : Bool) -> String