Een Terminal UI bouwen met Ito

Snelstart

  • Dezelfde Lua: Begin met require("ito") en return een functie die een view bouwt. Gebruik ito.state(value) voor waarden die veranderen.
  • Compositie: Combineer elementen met VStack, HStack, Text en de controls die beschreven zijn in de documentatie.
  • Views en modifiers: Gebruik :spacing(1), :padding(2), :grow(), :bold() en :dim() om views te rangschikken en te stylen.
  • Preview: De preview wordt bijgewerkt tijdens het bewerken. Bij een fout blijft de laatste werkende preview zichtbaar.

Een volledig voorbeeld

local ito = require("ito")
local phase = ito.state("edit")
local name = ito.state("")
local saved = ito.state("")

return function()
    if phase.value == "edit" then
        return ito.VStack({
            ito.Text("NAME YOUR PROJECT"):bold(),
            ito.TextField(name):label("Project name"):focused()
                :on_submit(function(value)
                    if value:match("%S") then
                        saved.value = value
                        phase.value = "done"
                    end
                end)
                :on_cancel(function() name.value = "" end),
            ito.Text("Enter to save · Esc to clear"):dim():wrap(),
        }):spacing(1):padding(1)
    end

    return ito.VStack({
        ito.Text("Saved: " .. saved.value):bold():wrap(),
        ito.Button("Edit again", function() phase.value = "edit" end):focused(),
    }):spacing(1):padding(1)
end

De playground beheert ito.open(), het venster, het thema en de event loop. Er moet een functie worden geretourneerd die één view bouwt. Een lokale host gebruikt diezelfde view-functie met ito.Window, roept window:event(event) aan voor terminal-events en rendert opnieuw na input. Gebruik de huidige Ito-build van deze branch voor de gedeelde control-toevoegingen. Open geen andere terminal en implementeer geen blokkerende loop in de playground-code.

Input en status

  • Actieve controls: De actieve control ontvangt input. TextField(state) bewerkt een Lua-buffer en tekent een inline caret. Het is geen onafhankelijke HTML-tekstbox.
  • Focus:
  • :focused() vraagt focus aan wanneer een control verschijnt.
  • :focused(condition) vraagt focus aan wanneer de conditie waar wordt.
  • Stabiele focus blijft behouden tijdens redraws.
  • Kliks met de pointer geven focus aan een control.
  • Tab en Shift-Tab navigeren tussen controls wanneer de actieve control deze niet consumeert. Op de grens kan de browser de preview verlaten. Alleen het actieve tekstveld toont een caret.
  • TextField Events:
  • TextField:on_submit(fn) handelt Enter af.
  • :on_cancel(fn) handelt Escape af.
  • Beiden ontvangen de huidige string.
  • :on_change(fn) ontvangt feitelijke tekstwijzigingen.
  • Cancel draait een waarde niet automatisch terug. Houd een concept apart van de opgeslagen waarde wanneer bewerkingen bij annuleren moeten worden weggegooid.
  • Statusbeheer: Gebruik een status zoals phase = ito.state("choose") en conditionele views voor flows zoals choose → edit → review → done. Voeg :id(phase.value) toe als elke fase een nieuwe interne view-status moet krijgen. Houd de applicatiestatus boven de geretourneerde functie.
  • Toetsenbord: :on_key(function(event) ... end) handelt toetsen af die door de gefocuste control onbehandeld blijven. Return true bij consumptie, anders false. event.key gebruikt: enter, esc, tab, backtab, up, down, left, right, home, end, backspace, of een karakter. Modifiers zijn ctrl, alt, shift en meta.
  • Plakken is één { type = "paste", text = "..." } event. Dien geplakte nieuwe regels niet in als Enter; de single-line editor zet deze om in spaties.
  • State-objecten: ito.state(value) leest en schrijft via .value. Lees de status tijdens het bouwen van de view; update deze in acties. Het muteren van een gewone tabel meldt Ito niet. Vervang een statuswaarde of verhoog een revisiestatus voor mutabele collecties.
  • Compositie: ito.view(function(props) ... end) definieert een samengestelde view. Aanroepen naar status en ito.remember(function() ... end) daarbinnen moeten een consistente volgorde behouden. Gebruik unieke :id(key) waarden voor veranderende lijsten. Een false child wordt weggelaten.

Views en controls

APIDoel
Text(string)Terminal tekst. Gebruik tostring voor getallen. Accepteert ook { { text, TextStyle(...) }, ... } spans.
VStack({ views }), HStack({ views })Verticale/horizontale layout; :spacing(1) voegt één cel of rij toe.
TextField(state)Single-line bewerking; :label(text), :placeholder(text), :hidden() voor wachtwoorden.
Button(text, action)Activering via Enter, Spatie of pointer. action() neemt geen argumenten.
Checkbox(text, boolState), Toggle(text, boolState)Booleaanse terminal controls. :description(text) en :on_change(fn).
Slider(numberState, { min = 0, max = 100, step = 1 })Aanpassen via pijltjestoetsen; Home/End springen naar de grenzen. :label(text), :suffix(text), :on_change(fn).
Progress(fraction)Een terminal-meter, beperkt tot 0–1. :label(text) is optioneel.
List(items, function(item, index, active) ... end)Navigeerbare rijen. :selection(numberState), :on_choose(function(item, index) ... end), :height(rows).
Choices({ { label = "...", description = "..." }, ... })Genummerde keuzes plus een tekstantwoord. :onchoose(fn), :onother(fn).
ScrollView(view):state(ScrollState()):height(rows)Een begrensd scrollgebied. Wiel-input gebruikt terminal-coördinaten.
Grid({ GridRow({ views }), ... }), Group({ views }), ZStack({ views }), Spacer()Gedeelde terminal-compositie en layout.
Heading(text), Metric(value)Gemakkelijke, benadrukte tekst (geen browser-typografie).

Alle bovenstaande namen behoren tot ito. Button, checkbox, toggle en slider accepteren :disabled(condition). Uitgeschakelde en onzichtbare controls ontvangen geen focus.

Layout en uiterlijk

Gebruik de volgende modifiers: :padding(1), :padding({ horizontal = 2 }), :width(cells), :height(rows), :max_height(rows), :grow(), :share(0.5), :align(ito.Alignment.center), :id(key), en :invisible(condition).

:hidden(condition) verwijdert een view uit de layout; de :hidden() van TextField maskeert daarentegen de tekst. Geef de voorkeur aan flexibele breedtes en Text(...):wrap() voor kleine schermen. De playground staat maximaal 160 kolommen en 120 rijen toe. Gebruik scrolling voor meer.

Tekst ondersteunt: :bold(), :dim(), :italic(), :underline(), :strikethrough(), :reverse(), :foreground(ito.rgb(0xc65036)), en :style(ito.TextStyle({ bold = true })). :background(ito.rgb(...)) vult een view. Een border gebruikt :border(ito.theme().borders.rounded) of .plain; :title(text) labelt deze. Lees het host-thema binnen de view-functie. Padding vóór een border/background is binnen; padding daarna is buiten. :accessibility_label(text) benoemt een control zonder de weergave te wijzigen.

De browser levert toetsenbord-, pointer-, plak- en IME-input. Het voegt geen DOM, netwerk, bestandssysteem of raw ANSI output API's toe. Canvas bevat een tekst-fallback, maar reproduceert niet de toegankelijkheid van individuele native HTML-controls. Lua heeft een geheugenlimiet en een instructiebudget; oneindige loops worden gestopt.

Geldige bewerkingen herstarten de app; ongeldige bewerkingen houden de laatste werkende app bruikbaar. Controleer de toetsenbordnavigatie, submit/cancel-transities en smalle breedtes. Houd herhaalde waarden, zoals prijzen, in één variabele. Verzin geen methoden zoals :class(), :css() of :font_size().