3.8 KiB
3.8 KiB
TUI Style Guide — Nostr Terminal
Library
The TUI is built on tui_ncurses (vendored at resources/tui_ncurses/), which provides:
- Pinned header/footer panes with a scrollable body window
- Library-owned menu loops (
tuin_menu_run) - Library-owned table loops (
tuin_table_run) - Library-owned pager (
tuin_pager_run) - Modal dialogs (
tuin_prompt,tuin_confirm,tuin_notice) - Automatic
KEY_RESIZEhandling
Adapter Layer (src/nt_tui_adapter.c)
App-specific helpers wrapping the library:
| Function | Purpose |
|---|---|
nt_frame(breadcrumb) |
Build a TuiFrame with current app title + user |
nt_status() |
Build a TuiStatus with latest log line |
nt_set_app_info(name, version) |
Set app name/version for header |
nt_set_user(user) |
Set user label for header (empty hides it) |
nt_set_window_title(title) |
OSC 2 terminal title |
nt_print(fmt, ...) |
Write to body window (in-screen composition) |
nt_print_reset() |
Clear body window + reset cursor |
nt_run_external_editor(spawn, user) |
Bracket editor with cleanup/init |
nt_log(fmt, ...) |
Append to footer-log (informational stream) |
nt_log_show() |
Open full log in scrollable pager |
nt_log_clear() |
Clear log buffer |
nt_pager_show_text(breadcrumb, text) |
Show text in full-screen pager |
Three-Tier Output Model
Every "show something to the user" call fits one of three tiers:
Tier 1: Footer-Log (nt_log)
- When: Passive informational stream — publishes, network events, action completions.
- Behavior: Latest line shown in footer status area. Full history via "View log" main menu entry.
- Example:
nt_log("Tweet published to 3/5 relays.");
Tier 2: Modal Dialog (tuin_notice / tuin_confirm)
- When: Must-acknowledge errors or destructive confirmations.
- Behavior: Centered popup, blocks until user responds.
- Example:
tuin_notice("Failed to connect to relay."); - Example:
if (tuin_confirm("Delete this relay?") == 1) { ... }
Tier 3: Full-Screen Pager (nt_pager_show_text)
- When: Intentional content viewing — DM threads, event JSON, AI responses, blog posts, NIP-11 info.
- Behavior: Full-screen scrollable view with Up/Down/PgUp/PgDn/Home/End. Esc returns.
- Example:
nt_pager_show_text("> Relays > NIP-11", nip11_text);
In-Screen Composition (nt_print)
- When: Building custom body content inside streaming/live loops.
- Not for: Post-action results (use
nt_log) or content viewing (use pager).
Header Format
================ NOSTR TERMINAL - v0.0.13 - alice ================
> Main Menu > Relays
- Pre-login:
NOSTR TERMINAL - v0.0.13 - Logged in:
NOSTR TERMINAL - v0.0.13 - <username>
Menu Pattern
static const TuiMenuItem ITEMS[] = {
{NT_HK("A","dd relay"), 'a'},
{NT_HK("D","elete relay"), 'd'},
{"E" NT_HK("x","it"), 'x'},
};
TuiMenuState state = {0};
TuiFrame frame = nt_frame("> Main Menu > Relays");
TuiMenu menu = {ITEMS, 3};
TuiStatus status = nt_status();
int idx = tuin_menu_run(&frame, &menu, &status, &state);
Hotkey Convention
Use NT_HK("X", "rest") macro which expands to "\033[4mX\033[0mrest" (underlined first letter).
Breadcrumb Convention
Format: "> Main Menu > SubMenu > Action"
- Root:
"> Main Menu" - Sub:
"> Main Menu > Relays" - Deep:
"> Main Menu > Relays > NIP-11"
Main Menu Entries
Write, Tweet, Profile, Relays, Follows, Kind/event dump, Notifications, Blogs/posts, Live feeds, Message, Todo, Journal, Ai, Ecash, View log, Quit.
Key Bindings (library-provided)
- Menus: Up/Down + Enter, or shortcut key. Esc/q/x to cancel.
- Tables: Up/Down/PgUp/PgDn/Home/End + Enter to select. Esc/q/x to cancel.
- Pager: Up/Down/j/k, PgUp/PgDn, Home/End/g/G. Esc/q/x/Enter to return.
- Prompts: Type + Enter to submit. Esc to cancel.
- Confirm: y/n keys.