# TTY _Path: en/lua/system/tty_ ## Table of Contents - TTY ## Content # 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` ### 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: Text (lua/text/text)