From bd39e93785ae465251fdf08b90cdcb1c4123515c Mon Sep 17 00:00:00 2001 From: Spencer Brower Date: Wed, 24 Jun 2026 16:21:35 -0400 Subject: [PATCH] refactor(cli): `write_usage` and `write_command_help` now use `text/table`. --- TODOS.md | 2 +- cli.odin | 62 ++++++++++++++++++++++++------------------------------ table.odin | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/TODOS.md b/TODOS.md index cca41e1..1fa4581 100644 --- a/TODOS.md +++ b/TODOS.md @@ -6,7 +6,7 @@ 3. Add color flag and support non colored output. -4. Use text/tables for command output +4. Rewrite `write_command_help` to use text/tables 5. Generate md and man pages again. diff --git a/cli.odin b/cli.odin index 419b4bc..e39462f 100644 --- a/cli.odin +++ b/cli.odin @@ -5,6 +5,7 @@ import "core:fmt" import "core:io" import "core:os" import "core:strings" +import "core:text/table" Command :: struct { name: string, @@ -253,56 +254,47 @@ at before, restore your backup with: %senvr%s [command] -%sAvailable Commands:%s `, COLOR_HEADINGS, ANSI_RESET, COLOR_FLAGS, ANSI_RESET, - COLOR_HEADINGS, - ANSI_RESET, flush = false, ) + tbl: table.Table + table.init(&tbl, context.temp_allocator, context.temp_allocator) + table.padding(&tbl, 2, 0) + + table.caption(&tbl, "Available Commands:") + for c in COMMANDS { - name_start := len(c.name) - fmt.wprintf(w, " %s%s", COLOR_COMMANDS, c.name, flush = false) + name := c.name + // TODO: Can we do better? for a in c.aliases { - fmt.wprintf(w, ", %s", a, flush = false) - name_start += len(a) + 2 + name = strings.join([]string{name, a}, ", ", tbl.format_allocator) } - fmt.wprint(w, ANSI_RESET) - padding := 20 - name_start - if padding > 0 { - for _ in 0 ..< padding { - io.write_byte(w, ' ') - } - } - fmt.wprintf(w, " %s\n", c.short, flush = false) + table.row(&tbl, table.format(&tbl, "%s%s%s", COLOR_COMMANDS, name, ANSI_RESET), c.short) } + write_borderless_table(w, &tbl) + table_reset(&tbl) + + table.caption(&tbl, "Flags:") + + table.row(&tbl, COLOR_FLAGS + "-h, --help" + ANSI_RESET, `show this documentation`) + table.row( + &tbl, + COLOR_FLAGS + "-c, --config-file" + ANSI_RESET + " ", + `config file (default "~/.envr/config.json")`, + ) + write_borderless_table(w, &tbl) + fmt.wprintf( w, - "\n" + - COLOR_HEADINGS + - "Flags:" + - ANSI_RESET + - "\n\n " + - COLOR_FLAGS + - "-h, --help" + - ANSI_RESET + - " help for envr\n" + - COLOR_FLAGS + - ` -c, --config-file` + - ANSI_RESET + - ` config file (default "~/.envr/config.json") - -Use "` + - COLOR_FLAGS + - "envr" + - ANSI_RESET + - ` [command] --help" for more information about a command. -`, + `Use "%senvr%s [command] --help" for more information about a command.`, + COLOR_FLAGS, + ANSI_RESET, flush = false, ) } diff --git a/table.odin b/table.odin index 7f33b26..99959ff 100644 --- a/table.odin +++ b/table.odin @@ -1,5 +1,7 @@ package main +import "core:fmt" +import "core:io" import "core:text/table" import "core:unicode/utf8" @@ -34,3 +36,44 @@ ansi_aware_width :: proc(str: string) -> int { return width } +write_borderless_table :: proc(w: io.Writer, t: ^table.Table) { + table.build(t, ansi_aware_width) + + write_table_separator :: proc(w: io.Writer, tbl: ^table.Table) { + io.write_byte(w, '\n') + } + + if t.caption != "" { + table.write_text_align( + w, + fmt.tprintf("%s%s%s", COLOR_HEADINGS, t.caption, ANSI_RESET), + .Left, + 0, //t.lpad, + 0, //t.rpad, + t.tblw + t.nr_cols - 1 - ansi_aware_width(t.caption) - t.lpad - t.rpad, + ) + io.write_byte(w, '\n') + } + + write_table_separator(w, t) + for row in 0 ..< t.nr_rows { + for col in 0 ..< t.nr_cols { + table.write_table_cell(w, t, row, col) + } + io.write_byte(w, '\n') + if t.has_header_row && row == table.header_row(t) { + write_table_separator(w, t) + } + } + write_table_separator(w, t) +} + +table_reset :: proc(t: ^table.Table) { + clear(&t.cells) + clear(&t.colw) + t.caption = "" + t.tblw = 0 + t.nr_cols = 0 + t.nr_rows = 0 +} +