# "TTY" _Path: en/lua/system/tty_ > " Terminal UI module for raw input events, styled output, and layout utilities. This module only works inside terminal context. You cannot use it from regular functions—only from processes running on a Terminal Host. ## Loading ```lua local tty = require("tty") ``` ## Input Loop Start the raw input reader, subscribe to events, and process them in a loop: ```lua local tty = require("tty") local io = require("io") local function handler() tty.start() local events = tty.events() while true do local ev = events:receive() if not ev then break end if ev.type == "key" then if ev.key == "q" or (ev.ctrl and ev.key == "c") then break end io.print("Key: " .. ev.key) elseif ev.type == "resize" then io.print("Size: " .. ev.width .. "x" .. ev.height) end end tty.stop() end ``` ### tty.start() Enable raw terminal input mode. The terminal switches to raw mode and begins emitting events. ```lua local ok, err = tty.start() ``` **Returns:** `boolean, error` ### tty.stop() Disable raw input and restore the terminal to normal mode. ```lua local ok, err = tty.stop() ``` **Returns:** `boolean, error` ### tty.events() Subscribe to terminal events and return a channel. Events are delivered as tables with a `type` field. ```lua local events = tty.events() ``` **Returns:** `EventChannel, error` ### tty.screen_size() Query current terminal dimensions. ```lua local width, height, err = tty.screen_size() ``` **Returns:** `number, number, error` ### tty.mouse(enable) Enable or disable mouse event tracking. ```lua local ok, err = tty.mouse(true) ``` | Parameter | Type | Description | |-----------|------|-------------| | `enable` | boolean | `true` to enable, `false` to disable | **Returns:** `boolean, error` ## Event Types Events are tables with a `type` field that determines which other fields are present. ### Key Event ```lua { type = "key", key = "a", -- printable character or key name key_type = "runes", -- "runes" for printable, or special key name action = "press", -- "press" or "release" alt = false, ctrl = false, shift = false } ``` ### Mouse Event Requires `tty.mouse(true)`. ```lua { type = "mouse", action = "press", -- "press", "release", "motion", "wheel" button = "left", -- button name x = 10, y = 5, alt = false, ctrl = false, shift = false } ``` ### Resize Event ```lua {type = "resize", width = 120, height = 40} ``` ### Start Event Emitted once after `tty.start()` with initial dimensions. ```lua {type = "start", width = 120, height = 40} ``` ### Focus Event ```lua {type = "focus", focused = true} ``` ### Paste Event ```lua {type = "paste", text = "pasted content"} ``` ## Key Bindings Create reusable key bindings that match against key events: ```lua local quit = tty.bind({ keys = {"q", "ctrl+c"}, help = {key = "q/ctrl+c", desc = "quit"} }) -- In event loop if quit:matches(ev) then break end ``` ### tty.bind(config) | Field | Type | Description | |-------|------|-------------| | `keys` | string[] | Key patterns to match (e.g. `"a"`, `"ctrl+c"`, `"enter"`) | | `help` | table | Optional. `{key = "...", desc = "..."}` for help text | **Returns:** `KeyBinding` ### KeyBinding Methods | Method | Returns | Description | |--------|---------|-------------| | `matches(event)` | boolean | Test if a key event matches this binding | | `set_enabled(bool)` | self | Enable or disable the binding | | `is_enabled()` | boolean | Check if the binding is enabled | | `help()` | table | Returns `{key, desc}` help info | ## Styles Create styled text output using lipgloss-based styling. All style methods return a new style (immutable). ```lua local tty = require("tty") local io = require("io") local title = tty.style() :bold() :foreground("#FF0000") :padding(0, 1) local box = tty.style() :border(tty.borders.ROUNDED) :border_foreground("#00FF00") :width(40) :padding(1, 2) io.print(box:render(title:render("Hello"), "World")) ``` ### tty.style() Create a new empty style. **Returns:** `Style` ### Style Methods All methods return a new `Style` and can be chained. #### Text Decoration | Method | Parameter | Description | |--------|-----------|-------------| | `foreground(color)` | string | Text color (hex `"#FF0000"`, ANSI `"9"`, or name) | | `background(color)` | string | Background color | | `bold(enable?)` | boolean | Bold text (default: true) | | `italic(enable?)` | boolean | Italic text | | `underline(enable?)` | boolean | Underline text | | `strikethrough(enable?)` | boolean | Strikethrough text | | `faint(enable?)` | boolean | Dimmed text | | `blink(enable?)` | boolean | Blinking text | | `reverse(enable?)` | boolean | Swap foreground/background | #### Layout | Method | Parameter | Description | |--------|-----------|-------------| | `width(n)` | number | Fixed width | | `height(n)` | number | Fixed height | | `max_width(n)` | number | Maximum width | | `max_height(n)` | number | Maximum height | | `padding(...)` | numbers | Padding (CSS-style: top, right, bottom, left) | | `margin(...)` | numbers | Margin (CSS-style) | | `align(pos)` | number | Horizontal alignment | | `align_vertical(pos)` | number | Vertical alignment | | `inline(enable?)` | boolean | Inline rendering mode | #### Borders | Method | Parameter | Description | |--------|-----------|-------------| | `border(name, ...)` | string, booleans | Border style, optional per-side toggles | | `border_foreground(...)` | strings | Border color(s) | | `border_background(...)` | strings | Border background color(s) | #### Other | Method | Description | |--------|-------------| | `render(...)` | Render strings with this style applied | | `copy()` | Create a copy of this style | ### Border Constants ```lua tty.borders.NORMAL tty.borders.ROUNDED tty.borders.THICK tty.borders.DOUBLE tty.borders.HIDDEN ``` ### Alignment Constants ```lua tty.align.LEFT -- 0 tty.align.CENTER -- 0.5 tty.align.RIGHT -- 1 ``` ## Text Utilities Layout and measurement functions for styled text. Available under `tty.text`. ### Measurement ```lua local w = tty.text.width("hello") -- printable width (ANSI-aware) local h = tty.text.height("a\nb\nc") -- line count local w, h = tty.text.size("hello\nworld") -- both ``` ### Joining ```lua -- Join side by side, aligned at top local row = tty.text.join_horizontal(tty.text.position.TOP, left, right) -- Stack vertically, centered local col = tty.text.join_vertical(tty.text.position.CENTER, top, bottom) ``` ### Max Dimensions ```lua local w = tty.text.max_width({"short", "a longer string"}) -- widest local h = tty.text.max_height({"one\ntwo", "single"}) -- tallest ``` ### Placement Place a string within a box of given dimensions: ```lua -- Center in a 80x24 box local out = tty.text.place(80, 24, tty.text.position.CENTER, tty.text.position.CENTER, content) -- Horizontal only local out = tty.text.place_horizontal(80, tty.text.position.RIGHT, content) -- Vertical only local out = tty.text.place_vertical(24, tty.text.position.BOTTOM, content) ``` ### Position Constants ```lua tty.text.position.TOP -- 0 tty.text.position.LEFT -- 0 tty.text.position.CENTER -- 0.5 tty.text.position.BOTTOM -- 1 tty.text.position.RIGHT -- 1 ``` ## See Also - [Terminal I/O](lua/system/io.md) — stdin/stdout/stderr operations - [Terminal Host](system/terminal.md) — Terminal host configuration ## Navigation Previous: "OS Time" (lua/system/ostime) Next: "Hub" (lua/system/hub)