hnoss

hnoss

An immediate-mode terminal UI library for Odin. Pure Odin, no C, batteries included.

Get started Widget reference Source
hnoss system monitor

examples/monitor: a live system monitor reading /proc, theme Odlar Yurdu.

Why hnoss

Describe the whole UI every frame; hnoss works out what changed and writes only that.

◆ Pure Odin

Only core: and base:. Raw syscalls on Linux, no ncurses, no termbox, no libc bindings.

◆ Widgets are procedures

Calling one draws it, handles its own keys and mouse, and returns what happened. State is yours.

◆ Fast by default

Double-buffered diff, minimal cursor moves and SGR, synchronized output, one write per frame.

◆ Text done right

Unicode 16 widths and grapheme clusters: 世界, é, 👩‍💻, 🇦🇿 wrap and align correctly.

◆ Never a broken terminal

Raw mode, alt screen and cursor are restored on exit, panic, SIGINT, SIGTERM and crashes.

◆ Explicit memory

Allocators are parameters; per-frame scratch lives in context.temp_allocator. No hidden globals.

Thirty seconds of code

import hnoss "hnoss"

main :: proc() {
    term, _ := hnoss.init(hnoss.DEFAULT_OPTIONS + {.Mouse_Capture})
    defer hnoss.deinit(&term)

    cities := []string{"Bakı", "Gəncə", "Şəki", "Lənkəran"}
    list: hnoss.List_State
    events: []hnoss.Event
    for {
        f := hnoss.begin_frame(&term)
        ui := hnoss.ui(f, events)
        inner := hnoss.box(ui, hnoss.inset(f.area, 1), "🇦🇿 [b]Cities[/]")
        hnoss.focus(ui, &list)
        hnoss.list(ui, inner, cities, &list)        // ↑↓, click, wheel

        for ev in hnoss.unhandled(ui) {
            if hnoss.is_char(ev, 'q') { return }
        }
        hnoss.end_frame(&term)                      // diff, one write
        free_all(context.temp_allocator)
        events = hnoss.poll_events(&term, -1)
    }
}

Next: the guide walks through the frame loop, text, layout and widgets.