diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-06-26 20:15:11 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-26 20:15:11 +0200 |
| commit | 3726f0b73c980fa7e14f3ed668bdf5ca3441e57a (patch) | |
| tree | 0a58cb2d5776942bfdfe7d74e447b4402663aa35 | |
| parent | 8d1827838fb902be4f16b3b028ac0d299a456857 (diff) | |
| parent | ba354e0524ee6625ce13087b097fe96e5e8c9403 (diff) | |
Merge pull request #3812 from Feoramund/add-table-decorations
Add `write_decorated_table` to `text/table`
| -rw-r--r-- | core/text/table/doc.odin | 51 | ||||
| -rw-r--r-- | core/text/table/table.odin | 79 |
2 files changed, 130 insertions, 0 deletions
diff --git a/core/text/table/doc.odin b/core/text/table/doc.odin index 30358f31e..955ab8d21 100644 --- a/core/text/table/doc.odin +++ b/core/text/table/doc.odin @@ -265,5 +265,56 @@ This will print out: | Excessive Diacritics | H̷e̶l̵l̸o̴p̵e̷ ̸w̶o̸r̵l̶d̵!̴ | +-----------------------------+----------------------------------------------------------------------------------------------+ +**Decorated Tables:** + +If you'd prefer to change the borders used by the plain-text table printing, +there is the `write_decorated_table` procedure that allows you to change the +corners and dividers. + +Here is a complete example: + + package main + + import "core:fmt" + import "core:io" + import "core:os" + import "core:text/table" + + box_drawing :: proc(w: io.Writer) { + t: table.Table + table.init(&t) + table.caption(&t, "Box Drawing Example") + table.padding(&t, 2, 2) + table.header_of_aligned_values(&t, {{.Left, "Operating System"}, {.Center, "Year Introduced"}}) + + table.row(&t, "UNIX", "1973") + table.row(&t, "MS-DOS", "1981") + table.row(&t, "Commodore 64 KERNAL", "1982") + table.row(&t, "Mac OS", "1984") + table.row(&t, "Amiga", "1985") + table.row(&t, "Windows 1.0", "1985") + table.row(&t, "Linux", "1991") + table.row(&t, "Windows 3.1", "1992") + + decorations := table.Decorations { + "┌", "┬", "┐", + "├", "┼", "┤", + "└", "┴", "┘", + "│", "─", + } + + table.write_decorated_table(w, &t, decorations) + fmt.println() + } + + main :: proc() { + stdout := os.stream_from_handle(os.stdout) + + box_drawing(stdout) + } + +While the decorations support multi-codepoint Unicode graphemes, do note that +each border character should not be larger than one monospace cell. + */ package text_table diff --git a/core/text/table/table.odin b/core/text/table/table.odin index 7b4942478..27c99b1f1 100644 --- a/core/text/table/table.odin +++ b/core/text/table/table.odin @@ -51,6 +51,19 @@ Table :: struct { tblw: int, // Width of entire table (including padding, excluding borders) } +Decorations :: struct { + // These are strings, because of multi-codepoint Unicode graphemes. + + // Connecting decorations: + nw, n, ne, + w, x, e, + sw, s, se: string, + + // Straight lines: + vert: string, + horz: string, +} + ascii_width_proc :: proc(str: string) -> int { return len(str) } @@ -397,6 +410,72 @@ write_plain_table :: proc(w: io.Writer, tbl: ^Table, width_proc: Width_Proc = un write_table_separator(w, tbl) } +write_decorated_table :: proc(w: io.Writer, tbl: ^Table, decorations: Decorations, width_proc: Width_Proc = unicode_width_proc) { + draw_dividing_row :: proc(w: io.Writer, tbl: ^Table, left, horz, divider, right: string) { + io.write_string(w, left) + for col in 0..<tbl.nr_cols { + for _ in 0..<tbl.colw[col] + tbl.lpad + tbl.rpad { + io.write_string(w, horz) + } + if col < tbl.nr_cols-1 { + io.write_string(w, divider) + } + } + io.write_string(w, right) + io.write_byte(w, '\n') + } + + build(tbl, width_proc) + + // This determines whether or not to divide the top border. + top_divider := decorations.n if len(tbl.caption) == 0 else decorations.horz + + // Draw the north border. + draw_dividing_row(w, tbl, decorations.nw, decorations.horz, top_divider, decorations.ne) + + if len(tbl.caption) != 0 { + // Draw the caption. + io.write_string(w, decorations.vert) + write_text_align(w, tbl.caption, .Center, + tbl.lpad, tbl.rpad, tbl.tblw + tbl.nr_cols - 1 - width_proc(tbl.caption) - tbl.lpad - tbl.rpad) + io.write_string(w, decorations.vert) + io.write_byte(w, '\n') + + // Draw the divider between the caption and the table rows. + draw_dividing_row(w, tbl, decorations.w, decorations.horz, decorations.n, decorations.e) + } + + // Draw the header. + start := 0 + if tbl.has_header_row { + io.write_string(w, decorations.vert) + row := header_row(tbl) + for col in 0..<tbl.nr_cols { + write_table_cell(w, tbl, row, col) + io.write_string(w, decorations.vert) + } + io.write_byte(w, '\n') + start += row + 1 + + draw_dividing_row(w, tbl, decorations.w, decorations.horz, decorations.x, decorations.e) + } + + // Draw the cells. + for row in start..<tbl.nr_rows { + for col in 0..<tbl.nr_cols { + if col == 0 { + io.write_string(w, decorations.vert) + } + write_table_cell(w, tbl, row, col) + io.write_string(w, decorations.vert) + } + io.write_byte(w, '\n') + } + + // Draw the south border. + draw_dividing_row(w, tbl, decorations.sw, decorations.horz, decorations.s, decorations.se) +} + // Renders table according to GitHub Flavored Markdown (GFM) specification write_markdown_table :: proc(w: io.Writer, tbl: ^Table, width_proc: Width_Proc = unicode_width_proc) { // NOTE(oskar): Captions or colspans are not supported by GFM as far as I can tell. |