aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2024-06-26 20:15:11 +0200
committerGitHub <noreply@github.com>2024-06-26 20:15:11 +0200
commit3726f0b73c980fa7e14f3ed668bdf5ca3441e57a (patch)
tree0a58cb2d5776942bfdfe7d74e447b4402663aa35
parent8d1827838fb902be4f16b3b028ac0d299a456857 (diff)
parentba354e0524ee6625ce13087b097fe96e5e8c9403 (diff)
Merge pull request #3812 from Feoramund/add-table-decorations
Add `write_decorated_table` to `text/table`
-rw-r--r--core/text/table/doc.odin51
-rw-r--r--core/text/table/table.odin79
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.