A MoonBit library for pretty-printing tables in terminal. Ported from Rust tabled.
moon add hustcer/tabularimport {
"hustcer/tabular",
}///|
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 │
#|└─────────┴──────────┴───────┘
),
)
}┌─────────┬──────────┬───────┐
│ Name │ Language │ Stars │
├─────────┼──────────┼───────┤
│ Deno │ Rust/TS │ 101k │
├─────────┼──────────┼───────┤
│ Bun │ Zig/C++ │ 76k │
├─────────┼──────────┼───────┤
│ Node.js │ C++/JS │ 110k │
└─────────┴──────────┴───────┘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+----------+------+
| language | year |
+----------+------+
| Rust | 2010 |
+----------+------+
| MoonBit | 2022 |
+----------+------+┌──────────┬──────┐
│ language │ year │
├──────────┼──────┤
│ Rust │ 2010 │
├──────────┼──────┤
│ MoonBit │ 2022 │
└──────────┴──────┘╭──────────┬──────╮
│ language │ year │
├──────────┼──────┤
│ Rust │ 2010 │
├──────────┼──────┤
│ MoonBit │ 2022 │
╰──────────┴──────╯| language | year |
|----------|------|
| Rust | 2010 |
| MoonBit | 2022 | language | year
----------+------
Rust | 2010
MoonBit | 2022:.................:
: language : year :
:..........:......:
: Rust : 2010 :
:..........:......:
: MoonBit : 2022 :
:.................:╔══════════╦══════╗
║ language ║ year ║
╠══════════╬══════╣
║ Rust ║ 2010 ║
╠══════════╬══════╣
║ MoonBit ║ 2022 ║
╚══════════╩══════╝ language year
Rust 2010
MoonBit 2022========== ======
language year
========== ======
Rust 2010
MoonBit 2022
========== ======.-----------------.
| language | year |
| Rust | 2010 |
| MoonBit | 2022 |
'-----------------'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) |> ignorelet style = @tabular.Style::ascii()
.remove_horizontal()
.horizontals([
(1, @tabular.HorizontalLine::full('-', '+', '+', '+')),
])
table.apply(style) |> ignore///|
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"])
}///|
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()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)) |> ignoretable.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///|
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 │
#|└───┴────┴────┴────┘
),
)
}┌────────┬────┬────┐
│ Team │ Q2 │ Q3 │
├───┬────┼────┼────┤
│ A │ 12 │ 18 │ 22 │
├───┼────┼────┼────┤
│ B │ 10 │ 16 │ 21 │
└───┴────┴────┴────┘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())table.highlight(
@tabular.Highlight::outline_cell(@tabular.Cell::new(1, 1), '*'),
) |> ignore
table.shadow(@tabular.Shadow::new(1)) |> ignoretable.extract_rows(@tabular.Rows::new(0, 2)) |> ignore
table.remove_cols(@tabular.Cols::one(0)) |> ignore
table.split(@tabular.Split::col(2).concat()) |> ignore///|
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"]])
}///|
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"])
}///|
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+-------+",
)
}///|
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+-----+",
)
}///|
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)
}///|
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)
}///|
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 +---+ ",
)
}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'impl CellOption for Stringimpl CellOption for Array[T]impl CellOption for Tuple2[T0, T1]fn[T0 : CellOption, T1 : CellOption] change(self : (T0, T1), table : Table, entity : Entity) -> Unitimpl CellOption for Tuple3[T0, T1, T2]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption] change(self : (T0, T1, T2), table : Table, entity : Entity) -> Unitimpl CellOption for Tuple4[T0, T1, T2, T3]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption] change(self : (T0, T1, T2, T3), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption] hint_change(self : (T0, T1, T2, T3)) -> Entity?impl CellOption for Tuple5[T0, T1, T2, T3, T4]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption] change(self : (T0, T1, T2, T3, T4), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption] hint_change(self : (T0, T1, T2, T3, T4)) -> Entity?impl CellOption for Tuple6[T0, T1, T2, T3, T4, T5]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption] change(self : (T0, T1, T2, T3, T4, T5), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption] hint_change(self : (T0, T1, T2, T3, T4, T5)) -> Entity?impl CellOption for Tuple7[T0, T1, T2, T3, T4, T5, T6]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption] change(self : (T0, T1, T2, T3, T4, T5, T6), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6)) -> Entity?impl CellOption for Tuple8[T0, T1, T2, T3, T4, T5, T6, T7]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7)) -> Entity?impl CellOption for Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption, T8 : CellOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption, T8 : CellOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8)) -> Entity?impl CellOption for Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]fn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption, T8 : CellOption, T9 : CellOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), table : Table, entity : Entity) -> Unitfn[T0 : CellOption, T1 : CellOption, T2 : CellOption, T3 : CellOption, T4 : CellOption, T5 : CellOption, T6 : CellOption, T7 : CellOption, T8 : CellOption, T9 : CellOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)) -> Entity?impl HeightOption for HeightModetest {
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 Intpub(open) trait ResizeSelector {
fn select(Self, Array[Int], Array[Int]) -> Int?
fn fresh(Self) -> &ResizeSelector = _
}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))
}impl TableOption for Array[T]impl TableOption for Tuple2[T0, T1]impl TableOption for Tuple3[T0, T1, T2]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption] change(self : (T0, T1, T2), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption] hint_change(self : (T0, T1, T2)) -> Entity?impl TableOption for Tuple4[T0, T1, T2, T3]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption] change(self : (T0, T1, T2, T3), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption] hint_change(self : (T0, T1, T2, T3)) -> Entity?impl TableOption for Tuple5[T0, T1, T2, T3, T4]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption] change(self : (T0, T1, T2, T3, T4), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption] hint_change(self : (T0, T1, T2, T3, T4)) -> Entity?impl TableOption for Tuple6[T0, T1, T2, T3, T4, T5]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption] change(self : (T0, T1, T2, T3, T4, T5), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption] hint_change(self : (T0, T1, T2, T3, T4, T5)) -> Entity?impl TableOption for Tuple7[T0, T1, T2, T3, T4, T5, T6]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption] change(self : (T0, T1, T2, T3, T4, T5, T6), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6)) -> Entity?impl TableOption for Tuple8[T0, T1, T2, T3, T4, T5, T6, T7]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7)) -> Entity?impl TableOption for Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption, T8 : TableOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption, T8 : TableOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8)) -> Entity?impl TableOption for Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]fn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption, T8 : TableOption, T9 : TableOption] change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), table : Table) -> Unitfn[T0 : TableOption, T1 : TableOption, T2 : TableOption, T3 : TableOption, T4 : TableOption, T5 : TableOption, T6 : TableOption, T7 : TableOption, T8 : TableOption, T9 : TableOption] hint_change(self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)) -> Entity?impl WidthOption for WidthModeimpl CellOption for Alignmentimpl TableOption for Alignmentpub struct AlignmentFill {
// private fields
}impl CellOption for AlignmentFillimpl TableOption for AlignmentFillimpl CellOption for AlignmentStrategyimpl TableOption for AlignmentStrategypub struct ByColName {
name : String
}pub struct Cell {
row : Int
col : Int
}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)
}impl CellOption for CellHeightIncrease[M]impl HeightOption for CellHeightIncrease[Int]impl TableOption for CellHeightIncrease[M]fn[M : Measurement] CellHeightIncrease::change_cell(self : CellHeightIncrease[M], table : Table, entity : Entity) -> Unitfn[M : Eq] CellHeightIncrease::not_equal(x : CellHeightIncrease[M], y : CellHeightIncrease[M]) -> Boolfn[M, P] CellHeightIncrease::priority(self : CellHeightIncrease[M], priority : P) -> TableHeightIncrease[M, P]impl CellOption for CellHeightLimit[M]impl HeightOption for CellHeightLimit[Int]impl TableOption for CellHeightLimit[M]fn[M : Measurement] CellHeightLimit::change_cell(self : CellHeightLimit[M], table : Table, entity : Entity) -> Unitfn[M, P] CellHeightLimit::priority(self : CellHeightLimit[M], priority : P) -> TableHeightLimit[M, P]pub struct CellSettings[O, M] {
// private fields
}impl TableOption for CellSettings[O, M]fn[O : Object, M : CellOption] CellSettings::change(self : CellSettings[O, M], table : Table) -> Unitfn[O, A, B] CellSettings::with_(self : CellSettings[O, A], option : B) -> CellSettings[O, Settings[A, B]]impl CellOption for Colorimpl TableOption for Colorpub struct Concat {
// private fields
}impl TableOption for Concatpub struct Duplicate {
// private fields
}impl TableOption for Duplicatepub struct EmptySettings {
}impl CellOption for EmptySettingsimpl TableOption for EmptySettingspub enum Format {
Surround(String, String, Bool)
Value(String, Bool)
Content((String) -> String, Bool)
Positioned((String, Int, Int) -> String, Bool)
}pub enum Height {
}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+-----+")
}impl TableOption for HeightListfn HorizontalLine::full(main : Char, left? : Char, intersection? : Char, right? : Char) -> HorizontalLinepub struct Margin {
left : Int
right : Int
top : Int
bottom : Int
fill_left : Char
fill_right : Char
fill_top : Char
fill_bottom : Char
} derive(Debug)impl TableOption for Marginpub struct MinWidth[M, P] {
width : M
fill : Char
priority : P
}impl CellOption for MinWidth[M, P]impl TableOption for MinWidth[M, P]fn[M : Measurement, P : ResizeSelector] MinWidth::change(self : MinWidth[M, P], table : Table) -> Unitfn[M : Measurement, P] MinWidth::change_cell(self : MinWidth[M, P], table : Table, entity : Entity) -> Unitpub struct Modify[O] {
// private fields
}impl TableOption for Paddingtest {
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+---+")
}impl CellOption for PaddingColor[C]impl TableOption for PaddingColor[C]fn[C : ANSIFmt] PaddingColor::change_cell(self : PaddingColor[C], table : Table, entity : Entity) -> Unitimpl CellOption for PaddingExpandimpl TableOption for PaddingExpandpub enum Panel {
}pub enum Priority {
}impl ResizeSelector for PriorityFirstimpl ResizeSelector for PriorityLastimpl ResizeSelector for PriorityMaximpl ResizeSelector for PriorityMinimpl ResizeSelector for PriorityRoundRobinfn PriorityRoundRobin::select(self : PriorityRoundRobin, minimums : Array[Int], sizes : Array[Int]) -> Int?pub struct Reverse {
// private fields
}impl TableOption for Reversetest {
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"]])
}impl TableOption for Rotatepub struct Settings[A, B] {
// private fields
}impl CellOption for Settings[A, B]fn[A : CellOption, B : CellOption] change(self : Settings[A, B], table : Table, entity : Entity) -> Unitimpl TableOption for Settings[A, B]fn[A : CellOption, B : CellOption] Settings::change_cell(self : Settings[A, B], table : Table, entity : Entity) -> Unitfn[A, B, O, M] Settings::modify(self : Settings[A, B], object : O, option : M) -> Settings[Settings[A, B], CellSettings[O, M]]pub struct Shadow {
size : Int
offset : Int
fill : Char
top : Bool
bottom : Bool
left : Bool
right : Bool
}impl TableOption for Shadowpub enum Span {
}pub struct Style {
borders : Borders
horizontal_lines : HorizontalLines
custom_horizontal_lines : Array[(Int, HorizontalLine)]
}pub struct Table {
rows : Array[Array[String]]
config : SpannedConfig
dimension : CompleteDimension
// private fields
}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"]])
}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"]])
}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"]])
}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"]])
}test {
let table = @tabular.Table::from_rows([["a", "b"]])
table.with_(@tabular.Rotate::Left) |> ignore
assert_eq(table.rows, [["b"], ["a"]])
}impl TableOption for TableHeightIncrease[M, P]fn[M : Measurement, P : ResizeSelector] change(self : TableHeightIncrease[M, P], table : Table) -> Unitfn[M : Measurement, P : ResizeSelector] TableHeightIncrease::change(self : TableHeightIncrease[M, P], table : Table) -> Unitfn[M : Measurement, P : ResizeSelector] TableHeightIncrease::hint_change(_self : TableHeightIncrease[M, P]) -> Entity?fn[M, P, Q] TableHeightIncrease::priority(self : TableHeightIncrease[M, P], priority : Q) -> TableHeightIncrease[M, Q]impl TableOption for TableHeightLimit[M, P]fn[M : Measurement, P : ResizeSelector] change(self : TableHeightLimit[M, P], table : Table) -> Unitfn[M : Measurement, P : ResizeSelector] TableHeightLimit::change(self : TableHeightLimit[M, P], table : Table) -> Unitfn[M : Measurement, P : ResizeSelector] TableHeightLimit::hint_change(_self : TableHeightLimit[M, P]) -> Entity?fn[M, P, Q] TableHeightLimit::priority(self : TableHeightLimit[M, P], priority : Q) -> TableHeightLimit[M, Q]pub struct TextCleanup {
// private fields
}impl CellOption for TextCleanupimpl TableOption for TextCleanuptest {
assert_eq(@tabular.TextCleanup::clean_text("a\tb\r\nc"), "a b\nc")
}impl CellOption for TrimStrategyimpl TableOption for TrimStrategypub 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]fn[M : Measurement, P : ResizeSelector] Truncate::change(self : Truncate[M, P], table : Table) -> Unitfn[M : Measurement, P] Truncate::change_cell(self : Truncate[M, P], table : Table, entity : Entity) -> Unitpub struct UniformWidth[M] {
width : M
}pub enum Width {
}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"]])
}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"]])
}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]Install
Download zipA MoonBit library for pretty-printing tables in terminal. Ported from Rust tabled.