A port of Rich (rich text and beautiful formatting in the terminal) to MoonBit
///|
test "print markup and a table" {
let file = @rich.StringIO::new()
let console = @rich.Console::new(file~, width=30, color_system=None)
console.print("Hello, [bold magenta]World[/]!")
let table = @rich.Table::new(headers=["Name", "Value"])
table.add_row(["foo", "1"])
table.add_row(["bar", "2"])
console.print(table)
inspect(
file.getvalue(),
content=(
#|Hello, World!
#|┏━━━━━━┳━━━━━━━┓
#|┃ Name ┃ Value ┃
#|┡━━━━━━╇━━━━━━━┩
#|│ foo │ 1 │
#|│ bar │ 2 │
#|└──────┴───────┘
#|
),
)
}///|
fn main {
@rich.print("[bold red]alert![/] Something happened") catch {
_ => ()
}
}///|
fn main raise {
let console = @rich.Console::new()
console.print(@panel.Panel::new("Hello, [red]World!", title="Greeting"))
let tree = @tree.Tree::new("Rich Tree")
tree.add("foo").add("bar") |> ignore
console.print(tree)
console.print(
@syntax.Syntax::new(
"def f(x):\n return x + 1",
"python",
line_numbers=true,
),
)
console.print(@markdown.Markdown::new("# Title\n\n* one\n* **two**"))
let data : Json = { "numbers": [1, 2, 3], "ok": true }
console.print(@pretty.Pretty::new(data))
let progress = @progress.Progress::new()
progress.start()
let task = progress.add_task("Working...", total=Some(10.0))
for _ in 0..<10 {
progress.advance(task) // refreshes when the refresh interval has passed
}
progress.stop()
}///|
async fn main {
let progress = @progress.Progress::new()
@aio.run_progress(progress, () => {
let task = progress.add_task("Downloading", total=Some(3.0))
for _ in 0..<3 {
@async.sleep(500) // network IO, subprocesses, ...
progress.advance(task)
}
})
}moon run cmd/demomoonx bobzhang/rich/cmd/rich README.md # Markdown
moonx bobzhang/rich/cmd/rich main.py -n -g # line numbers, indent guides
moonx bobzhang/rich/cmd/rich data.csv --head 10 # CSV as a table
moonx bobzhang/rich/cmd/rich "Hello [b]World[/b]!" -p -a rounded -c
moonx bobzhang/rich/cmd/rich "Section" --rule --rule-style red
cat data.json | moonx bobzhang/rich/cmd/rich - --json --force-terminal
moonx bobzhang/rich/cmd/rich --help| Package | Upstream module(s) |
|---|---|
| bobzhang/rich | console, text, style, segment, markup, table, rule, padding, align, constrain, styled, box, measure, containers, control, json, ansi, highlighter, theme, emoji, filesize, _log_render, _ratio, _wrap, export (text/HTML/SVG) |
| bobzhang/rich/cells | cells, _unicode_data (all Unicode versions) |
| bobzhang/rich/color | color, color_triplet, palette, terminal_theme |
| bobzhang/rich/emoji | _emoji_codes, _emoji_replace |
| bobzhang/rich/panel | panel |
| bobzhang/rich/columns | columns |
| bobzhang/rich/tree | tree |
| bobzhang/rich/bar | bar |
| bobzhang/rich/layout | layout |
| bobzhang/rich/spinner | spinner, _spinners |
| bobzhang/rich/progress_bar | progress_bar |
| bobzhang/rich/live | live, live_render |
| bobzhang/rich/status | status |
| bobzhang/rich/progress | progress |
| bobzhang/rich/aio | the refresh thread: timer-driven Live/Progress/Status on moonbitlang/async (native) |
| bobzhang/rich/pretty | pretty, repr |
| bobzhang/rich/scope | scope |
| bobzhang/rich/syntax | syntax (via pygments.mbt) |
| bobzhang/rich/traceback | traceback (renders caller-built traces) |
| bobzhang/rich/markdown | markdown (via moonbit-community/cmark) |
| bobzhang/rich/prompt | prompt |
| bobzhang/rich/logging | logging (RichHandler over a LogRecord) |
| bobzhang/rich/demo, cmd/demo | __main__ (the feature card) |
| bobzhang/rich/cli, cmd/rich | rich-cli (the rich command) |
moon run --target native --release cmd/bench # or: -- table syntax
moon build --target wasm-gc --release cmd/bench
moonrun _build/wasm-gc/release/build/cmd/bench/bench.wasm
.venv/bin/python scripts/bench.py| Workload | Python | native | wasm-gc | wasm |
|---|---|---|---|---|
| feature card (python -m rich) | 10.8 | 0.87 | 0.92 | 2.35 |
| table, 1,000 rows × 6 columns with markup | 361 | 20.0 | 19.1 | 56.5 |
| 200 KB text, styled spans, justify="full" | 235 | 19.7 | 20.9 | 50.0 |
| 2,000 lines of markup (repr highlighting) | 540 | 49.1 | 61.8 | 124 |
| Pretty of a 300-item document | 116 | 10.4 | 12.3 | 27.5 |
| Syntax, 2,000 lines of Python, line numbers | 112 | 8.84 | 13.4 | 23.2 |
| Markdown of Rich's README | 23.2 | 2.38 | 2.60 | 6.18 |
| Progress with 100 tasks | 13.4 | 1.04 | 0.88 | 2.84 |
| JSON of a 300-item document | 91.8 | 7.86 | 8.91 | 20.7 |
pub(open) trait ConsoleFile {
fn write(Self, String) -> Unit raise
fn flush(Self) -> Unit raise = _
fn isatty(Self) -> Bool = _
fn encoding(Self) -> String = _
}pub(open) trait RenderHook {
fn process_renderables(Self, Array[&Renderable]) -> Array[&Renderable] raise
}pub(open) trait Renderable {
fn rich_console(Self, Console, ConsoleOptions) -> Array[RenderItem] raise
fn rich_measure(Self, Console, ConsoleOptions) -> Measurement? raise = _
fn text_kind(Self) -> TextKind = _
fn vertical_align(Self) -> VerticalAlignMethod? = _
}impl Renderable for Stringfn rich_console(self : String, console : Console, options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Colorfn rich_console(self : Color, console : Console, options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Palettefn rich_console(self : Palette, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisepub(all) suberror RichError {
StyleSyntaxError(String)
MissingStyle(String)
StyleStackError(String)
NotRenderableError(String)
MarkupError(String)
LiveError(String)
NoAltScreen(String)
WriteError(String)
NoEmoji(String)
ValueError(String)
} derive(Debug)pub struct Align {
renderable : &Renderable
align : AlignMethod
style : StyleType?
vertical : VerticalAlignMethod?
pad : Bool
width : Int?
height : Int?
}impl Renderable for Alignfn rich_console(self : Align, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn Align::center(renderable : &Renderable, style? : &IntoStyle, vertical? : VerticalAlignMethod, pad? : Bool, width? : Int, height? : Int) -> Alignfn Align::left(renderable : &Renderable, style? : &IntoStyle, vertical? : VerticalAlignMethod, pad? : Bool, width? : Int, height? : Int) -> Alignfn Align::new(renderable : &Renderable, align : AlignMethod, style? : &IntoStyle, vertical? : VerticalAlignMethod, pad? : Bool, width? : Int, height? : Int) -> Alignfn Align::right(renderable : &Renderable, style? : &IntoStyle, vertical? : VerticalAlignMethod, pad? : Bool, width? : Int, height? : Int) -> Alignpub struct AnsiDecoder {
// private fields
}pub struct Box {
name : String
box_ : String
ascii : Bool
top_left : String
top : String
top_divider : String
top_right : String
head_left : String
head_vertical : String
head_right : String
head_row_left : String
head_row_horizontal : String
head_row_cross : String
head_row_right : String
mid_left : String
mid_vertical : String
mid_right : String
row_left : String
row_horizontal : String
row_cross : String
row_right : String
foot_row_left : String
foot_row_horizontal : String
foot_row_cross : String
foot_row_right : String
foot_left : String
foot_vertical : String
foot_right : String
bottom_left : String
bottom : String
bottom_divider : String
bottom_right : String
} derive(Eq, Debug) ┌─┬┐ top
│ ││ head
├─┼┤ head_row
│ ││ mid
├─┼┤ row
├─┼┤ foot_row
│ ││ foot
└─┴┘ bottompub(all) struct Column {
header : &Renderable
footer : &Renderable
header_style : StyleType
footer_style : StyleType
style : StyleType
justify : JustifyMethod
vertical : VerticalAlignMethod
overflow : OverflowMethod
width : Int?
min_width : Int?
max_width : Int?
ratio : Int?
no_wrap : Bool
highlight : Bool
// private fields
}impl IntoColumn for Columnfn Column::new(header? : &Renderable, footer? : &Renderable, header_style? : &IntoStyle, footer_style? : &IntoStyle, style? : &IntoStyle, justify? : JustifyMethod, vertical? : VerticalAlignMethod, overflow? : OverflowMethod, width? : Int, min_width? : Int, max_width? : Int, ratio? : Int, no_wrap? : Bool, highlight? : Bool) -> Columnpub(all) struct Console {
stderr : Bool
quiet : Bool
tab_size : Int
record : Bool
soft_wrap : Bool
legacy_windows : Bool
safe_box : Bool
no_color : Bool
is_interactive : Bool
is_jupyter : Bool
style : StyleType?
highlighter : &Highlighter
get_datetime : () -> Double
get_time : () -> Double
// private fields
}fn Console::export_html(self : Console, theme? : TerminalTheme, clear? : Bool, code_format? : String, inline_styles? : Bool) -> Stringfn Console::export_svg(self : Console, title? : String, theme? : TerminalTheme, clear? : Bool, code_format? : String, font_aspect_ratio? : Double, unique_id? : String) -> String#callsite(autofill(loc))
fn Console::log(self : Console, object : &Renderable, sep? : String, end? : String, style? : &IntoStyle, justify? : JustifyMethod, emoji? : Bool, markup? : Bool, highlight? : Bool, loc~ : SourceLoc) -> Unit raise#callsite(autofill(loc))
fn Console::log_many(self : Console, objects : ArrayView[&Renderable], sep? : String, end? : String, style? : &IntoStyle, justify? : JustifyMethod, emoji? : Bool, markup? : Bool, highlight? : Bool, loc~ : SourceLoc) -> Unit raisefn Console::measure(self : Console, renderable : &Renderable, options? : ConsoleOptions) -> Measurement raisefn Console::new(color_system? : String?, force_terminal? : Bool, force_jupyter? : Bool, force_interactive? : Bool, soft_wrap? : Bool, theme? : Theme, stderr? : Bool, file? : &ConsoleFile, quiet? : Bool, width? : Int, height? : Int, style? : &IntoStyle, no_color? : Bool, tab_size? : Int, record? : Bool, markup? : Bool, emoji? : Bool, emoji_variant? : EmojiVariant, highlight? : Bool, log_time? : Bool, log_path? : Bool, log_time_format? : String, log_time_formatter? : (Double) -> Text, highlighter? : &Highlighter, legacy_windows? : Bool, safe_box? : Bool, get_datetime? : () -> Double, get_time? : () -> Double, environ? : Map[String, String]) -> Console raise RichErrorfn Console::print(self : Console, object : &Renderable, sep? : String, end? : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, no_wrap? : Bool, emoji? : Bool, markup? : Bool, highlight? : Bool, width? : Int, height? : Int, crop? : Bool, soft_wrap? : Bool, new_line_start? : Bool) -> Unit raisefn Console::print_many(self : Console, objects : ArrayView[&Renderable], sep? : String, end? : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, no_wrap? : Bool, emoji? : Bool, markup? : Bool, highlight? : Bool, width? : Int, height? : Int, crop? : Bool, soft_wrap? : Bool, new_line_start? : Bool) -> Unit raisefn Console::render(self : Console, renderable : &Renderable, options? : ConsoleOptions) -> Array[Segment] raisefn Console::render_lines(self : Console, renderable : &Renderable, options? : ConsoleOptions, style? : Style, pad? : Bool, new_lines? : Bool) -> Array[Array[Segment]] raisefn Console::render_str(self : Console, text : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, emoji? : Bool?, markup? : Bool?, highlight? : Bool?, highlighter? : &Highlighter) -> Text raisefn Console::rule(self : Console, title? : &IntoText, characters? : String, style? : &IntoStyle, align? : AlignMethod) -> Unit raisefn Console::save_html(self : Console, path : String, theme? : TerminalTheme, clear? : Bool, code_format? : String, inline_styles? : Bool) -> Unit raisefn Console::save_svg(self : Console, path : String, title? : String, theme? : TerminalTheme, clear? : Bool, code_format? : String, font_aspect_ratio? : Double, unique_id? : String) -> Unit raisefn Console::screen(self : Console, f : (ScreenContext) -> Unit raise, hide_cursor? : Bool, style? : &IntoStyle) -> Unit raisefn Console::screen_context(self : Console, hide_cursor? : Bool, style? : &IntoStyle) -> ScreenContextfn Console::update_screen(self : Console, renderable : &Renderable, region? : Region, options? : ConsoleOptions) -> Unit raisepub(all) struct ConsoleOptions {
size : ConsoleDimensions
legacy_windows : Bool
min_width : Int
max_width : Int
is_terminal : Bool
encoding : String
max_height : Int
justify : JustifyMethod?
overflow : OverflowMethod?
no_wrap : Bool?
highlight : Bool?
markup : Bool?
height : Int?
}fn ConsoleOptions::update(self : ConsoleOptions, width? : Int, min_width? : Int, max_width? : Int, justify? : JustifyMethod?, overflow? : OverflowMethod?, no_wrap? : Bool?, highlight? : Bool?, markup? : Bool?, height? : Int?) -> ConsoleOptionsfn ConsoleOptions::update_dimensions(self : ConsoleOptions, width : Int, height : Int) -> ConsoleOptionsimpl Renderable for Constrainfn rich_console(self : Constrain, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn rich_measure(self : Constrain, console : Console, options : ConsoleOptions) -> Measurement? raiseimpl Renderable for Controlfn rich_console(self : Control, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisepub(all) enum ControlCode {
Code(ControlType)
CodeInt(ControlType, Int)
CodeStr(ControlType, String)
CodeXY(ControlType, Int, Int)
} derive(Eq, Hash, Debug)impl Renderable for Emojifn rich_console(self : Emoji, console : Console, _options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Groupfn rich_console(self : Group, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisepub struct ISO8601Highlighter {
// private fields
}impl Highlighter for ISO8601Highlighterimpl Renderable for JSONfn rich_console(self : JSON, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Linesfn rich_console(self : Lines, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisefn Lines::justify(self : Lines, console : Console, width : Int, justify? : JustifyMethod, overflow? : OverflowMethod) -> Unit raisepub struct LogRender {
show_time : Bool
show_level : Bool
show_path : Bool
time_format : String
time_formatter : (Double) -> Text?
omit_repeated_times : Bool
level_width : Int?
// private fields
}impl Show for Measurementfn Measurement::get(console : Console, options : ConsoleOptions, renderable : &Renderable) -> Measurement raisepub struct NewLine {
count : Int
}impl Renderable for NewLinefn rich_console(self : NewLine, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisepub struct NullFile {
}pub struct NullHighlighter {
}impl Highlighter for NullHighlighterpub struct Padding {
renderable : &Renderable
top : Int
right : Int
bottom : Int
left : Int
style : StyleType
expand : Bool
}impl Renderable for Paddingfn rich_console(self : Padding, console : Console, options : ConsoleOptions) -> Array[RenderItem] raiseimpl Highlighter for RegexHighlighterfn RegexHighlighter::new(highlights : Array[String], base_style? : String) -> RegexHighlighter raise RegexErrorimpl Renderable for Renderablesfn rich_console(self : Renderables, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisefn rich_measure(self : Renderables, console : Console, options : ConsoleOptions) -> Measurement? raisepub struct ReprHighlighter {
// private fields
}impl Highlighter for ReprHighlighterpub struct Rule {
title : TextType
characters : String
style : StyleType
end : String
align : AlignMethod
}impl Renderable for Rulefn rich_console(self : Rule, console : Console, options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Screenfn rich_console(self : Screen, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn ScreenContext::update(self : ScreenContext, renderables? : Array[&Renderable], style? : &IntoStyle) -> Unit raiseimpl Renderable for ScreenUpdatefn rich_console(self : ScreenUpdate, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for SegmentLinesfn rich_console(self : SegmentLines, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raiseimpl Renderable for Segmentsfn rich_console(self : Segments, _console : Console, _options : ConsoleOptions) -> Array[RenderItem] raisepub struct StdStream {
fd : Int
}impl ConsoleFile for StdStreampub struct StringIO {
// private fields
}impl ConsoleFile for StringIOpub struct Style {
// private fields
}fn Style::new(color? : Color, bgcolor? : Color, bold? : Bool, dim? : Bool, italic? : Bool, underline? : Bool, blink? : Bool, blink2? : Bool, reverse? : Bool, conceal? : Bool, strike? : Bool, underline2? : Bool, frame? : Bool, encircle? : Bool, overline? : Bool, link? : String, meta? : Map[String, Json]) -> Stylefn Style::render(self : Style, text? : String, color_system? : ColorSystem?, legacy_windows? : Bool) -> Stringpub struct StyleStack {
// private fields
}impl Renderable for Styledfn rich_console(self : Styled, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisepub struct SystemPager {
command : String?
}impl Pager for SystemPagerpub(all) struct Table {
columns : Array[Column]
rows : Array[Row]
title : TextType?
caption : TextType?
width : Int?
min_width : Int?
box_ : Box?
safe_box : Bool?
pad_edge : Bool
show_header : Bool
show_footer : Bool
show_edge : Bool
show_lines : Bool
leading : Int
collapse_padding : Bool
style : StyleType
header_style : StyleType
footer_style : StyleType
border_style : StyleType?
title_style : StyleType?
caption_style : StyleType?
title_justify : JustifyMethod
caption_justify : JustifyMethod
highlight : Bool
row_styles : Array[StyleType]
// private fields
}impl Renderable for Tablefn rich_console(self : Table, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn Table::add_column(self : Table, header? : &Renderable, footer? : &Renderable, header_style? : &IntoStyle, highlight? : Bool, footer_style? : &IntoStyle, style? : &IntoStyle, justify? : JustifyMethod, vertical? : VerticalAlignMethod, overflow? : OverflowMethod, width? : Int, min_width? : Int, max_width? : Int, ratio? : Int, no_wrap? : Bool) -> Unitfn Table::add_row(self : Table, renderables : ArrayView[&Renderable], style? : &IntoStyle, end_section? : Bool) -> Unitfn Table::new(headers? : Array[&IntoColumn], title? : &IntoText, caption? : &IntoText, width? : Int, min_width? : Int, box_? : Box, no_box? : Bool, safe_box? : Bool, padding? : ArrayView[Int], collapse_padding? : Bool, pad_edge? : Bool, expand? : Bool, show_header? : Bool, show_footer? : Bool, show_edge? : Bool, show_lines? : Bool, leading? : Int, style? : &IntoStyle, row_styles? : Array[&IntoStyle], header_style? : &IntoStyle, footer_style? : &IntoStyle, border_style? : &IntoStyle, title_style? : &IntoStyle, caption_style? : &IntoStyle, title_justify? : JustifyMethod, caption_justify? : JustifyMethod, highlight? : Bool) -> Table raise RichErrorpub(all) struct Text {
style : StyleType
justify : JustifyMethod?
overflow : OverflowMethod?
no_wrap : Bool?
end : String
tab_size : Int?
// private fields
}impl Renderable for Textfn rich_console(self : Text, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn Text::assemble(parts : ArrayView[&TextPart], style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, no_wrap? : Bool, end? : String, tab_size? : Int, meta? : Map[String, Json]) -> Textfn Text::from_ansi(text : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, no_wrap? : Bool, end? : String, tab_size? : Int) -> Textfn Text::from_markup(text : String, style? : &IntoStyle, emoji? : Bool, emoji_variant? : EmojiVariant, justify? : JustifyMethod, overflow? : OverflowMethod, end? : String) -> Text raise RichErrorfn Text::highlight_pattern(self : Text, pattern : String, style? : &IntoStyle, style_prefix? : String) -> Int raise RegexErrorfn Text::highlight_words(self : Text, words : ArrayView[String], style : &IntoStyle, case_sensitive? : Bool) -> Int raise RegexErrorfn Text::new(text? : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod, no_wrap? : Bool, end? : String, tab_size? : Int, spans? : Array[Span]) -> Textfn Text::styled(text : String, style? : &IntoStyle, justify? : JustifyMethod, overflow? : OverflowMethod) -> Textfn Text::wrap(self : Text, console : Console, width : Int, justify? : JustifyMethod, overflow? : OverflowMethod, tab_size? : Int, no_wrap? : Bool) -> Lines raiseimpl Renderable for TextTypefn rich_console(self : TextType, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisepub struct ThemeStack {
// private fields
}impl Renderable for VerticalCenterfn rich_console(self : VerticalCenter, console : Console, options : ConsoleOptions) -> Array[RenderItem] raisefn rich_measure(self : VerticalCenter, console : Console, options : ConsoleOptions) -> Measurement? raisefn escape(markup : String) -> Stringfn escape_control_codes(text : String) -> Stringfn filesize_decimal(size : Int64, precision? : Int, separator? : String) -> Stringfn measure_renderables(console : Console, options : ConsoleOptions, renderables : ArrayView[&Renderable]) -> Measurement raisefn print_json(json? : String, data? : Json, indent? : Int?, highlight? : Bool, ensure_ascii? : Bool, sort_keys? : Bool) -> Unit raisefn print_many(objects : ArrayView[&Renderable], sep? : String, end? : String, file? : &ConsoleFile) -> Unit raisefn py_format_exp(d : Double, precision : Int, upper? : Bool) -> Stringfn py_format_fixed(d : Double, precision : Int) -> Stringfn py_format_g(d : Double) -> Stringfn py_format_general(d : Double, precision? : Int, upper? : Bool, alternate? : Bool) -> Stringfn py_group_thousands(s : String) -> Stringfn render_markup(markup : String, style? : StyleType, emoji? : Bool, emoji_variant? : EmojiVariant) -> Text raise RichErrorfn strip_control_codes(text : String) -> StringInstall
Download zipA port of Rich (rich text and beautiful formatting in the terminal) to MoonBit