feat(tui): rich display mode with type glyphs (#15)#17
Merged
Conversation
Add a TUI-only rich display mode that renders structured messages
instead of the flat line view: each DataRow becomes a per-message
key/value table (column = value, with its type) and a RowDescription
becomes a typed column list. Toggle with `r`, or start with --tui-rich.
The default line view is unchanged.
The decoder now carries structured detail alongside the line text so the
TUI can draw these messages:
- New Output::Rich { text, detail }; EventDetail captures RowDescription
fields and DataRow columns (name, type_oid, value). stdout/capture
consumers print `text` and ignore `detail`.
- DataRow parsing is refactored into data_row_columns(), shared by both
the line formatter and the structured detail. Line-view text is
byte-for-byte identical (replay tests unchanged).
- RowDescription stays cached per connection (Direction::row_desc) and
the rich DataRow detail is emitted only while one is cached. The cache
is intentionally NOT cleared at ReadyForQuery: in the extended
protocol a statement/portal is described once but executed across many
ReadyForQuery cycles, so columns must outlive a single command cycle.
The TUI message windowing is generalized to count display rows per event
(wrap and rich mode both let one event span many rows), so a key/value
table is never clipped mid-item. Type names use a safe textual fallback
keyed on OID (no glyph/font assumptions), per #15's guidance ahead of an
optional glyph layer.
Refs #15.
The rich header used to repeat the line-view content (`{ id=1, ... }`)
above the key/value table that already showed it. Now the header carries
only the timestamp/direction/kind, so each value appears once.
Field names move from cyan (which collides with the F→B direction
colour) to bold yellow, so the key column reads as a header and stays
distinct from the cyan/magenta direction colours.
build_line is factored to share a parser (parse_line) with a new
build_header_line that drops the trailing content.
In rich mode each column type now shows an icon-font glyph plus its
textual name, keyed on the PostgreSQL OID:
# int4 A text ✓ bool { json ⏾ uuid …
Glyphs use Nerd Font / Font Awesome solid codepoints (bool->check,
int->hashtag, float/numeric->calculator, text->font, json->code,
uuid->fingerprint, bytea->database, date->calendar, time->clock).
They are coloured by category and the textual type name is always shown
alongside, so a terminal without a Nerd Font never loses the type -- it
just sees tofu where the glyph would be.
Disable glyphs with `i` at runtime, `--no-glyphs` at startup, or the
TAPGRES_NO_GLYPHS env var.
Plumbing: rendering options are bundled into a `View { rich, wrap,
glyphs }` struct so the draw/window functions take one argument instead
of three bools. Field names move to blue (distinct from the
cyan/magenta direction colours).
Refs #15.
Glyphs were behind a mode (i key, --no-glyphs, TAPGRES_NO_GLYPHS). Per #15 the Nerd Font is an assumed prerequisite for rich mode, so drop the toggle entirely: type icons now always render alongside the type name. Removed: the glyphs field and App/run plumbing, the --no-glyphs flag and TAPGRES_NO_GLYPHS env, the i keybinding, the footer indicator, and the glyphs flag on View/type_spans. type_spans(oid) and render_rich(text, detail) no longer take an options argument.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First slice of #15: a TUI-only rich display mode that renders structured messages instead of the flat line view. Toggle with `r`, or start with `--tui-rich`. The default line view and stdout output are unchanged.
What it does
`DataRow` → a per-message key/value table: one `column = value` row per field (field names in blue, value default, type dimmed on the right).
`RowDescription` → a typed column list (`name typename`).
Type glyphs — each type shows an icon-font (Nerd Font) glyph plus its name, keyed on the PostgreSQL OID, coloured by category:
Glyphs are always on in rich mode (Nerd Font assumed); the textual type name is always shown alongside, so nothing is hidden on a non-Nerd-Font terminal.
How it's wired
The decoder now emits structured detail alongside the line text:
RowDescription caching
The cached `RowDescription` (`Direction::row_desc`) is not cleared at `ReadyForQuery`. In the extended protocol a statement/portal is described once but executed across many `ReadyForQuery` cycles, so the columns must outlive a single command cycle — otherwise later-cycle `DataRow`s would lose their field names. It is only cleared by `NoData`. The rich `DataRow` detail is emitted only while a description is cached.
The TUI message windowing is generalized to count display rows per event (wrap and rich mode both let one event span many rows), so a key/value table is never clipped mid-item.
Out of scope for this slice (future #15 work)
Tests
Refs #15.