Перейти к содержимому

TTY

Модуль терминального UI для событий сырого ввода, стилизованного вывода и утилит компоновки.

Этот модуль работает только в контексте терминала. Его нельзя использовать из обычных функций — только из процессов, запущенных на Terminal Host.
local tty = require("tty")

Запустите читалку сырого ввода, подпишитесь на события и обработайте их в цикле:

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

Включить режим сырого ввода терминала. Терминал переключается в raw-режим и начинает выдавать события.

local ok, err = tty.start()

Возвращает: boolean, error

Отключить сырой ввод и вернуть терминал в нормальный режим.

local ok, err = tty.stop()

Возвращает: boolean, error

Подписаться на события терминала и вернуть канал. События доставляются в виде таблиц с полем type.

local events = tty.events()

Возвращает: EventChannel, error

Запросить текущие размеры терминала.

local width, height, err = tty.screen_size()

Возвращает: number, number, error

Включить или отключить отслеживание событий мыши.

local ok, err = tty.mouse(true)
ПараметрТипОписание
enablebooleantrue для включения, false для отключения

Возвращает: boolean, error

События — это таблицы с полем type, которое определяет, какие другие поля присутствуют.

{
type = "key",
key = "a", -- печатный символ или имя клавиши
key_type = "runes", -- "runes" для печатных, или имя специальной клавиши
action = "press", -- "press" или "release"
alt = false,
ctrl = false,
shift = false
}

Требует tty.mouse(true).

{
type = "mouse",
action = "press", -- "press", "release", "motion", "wheel"
button = "left", -- имя кнопки
x = 10,
y = 5,
alt = false,
ctrl = false,
shift = false
}
{type = "resize", width = 120, height = 40}

Выдаётся один раз после tty.start() с начальными размерами.

{type = "start", width = 120, height = 40}
{type = "focus", focused = true}
{type = "paste", text = "pasted content"}

Создавайте переиспользуемые привязки клавиш, которые сопоставляются с событиями клавиш:

local quit = tty.bind({
keys = {"q", "ctrl+c"},
help = {key = "q/ctrl+c", desc = "quit"}
})
-- В цикле событий
if quit:matches(ev) then
break
end
ПолеТипОписание
keysstring[]Шаблоны клавиш для сопоставления (например, "a", "ctrl+c", "enter")
helptableОпционально. {key = "...", desc = "..."} для текста справки

Возвращает: KeyBinding

МетодВозвращаетОписание
matches(event)booleanПроверить, соответствует ли событие клавиши этой привязке
set_enabled(bool)selfВключить или отключить привязку
is_enabled()booleanПроверить, включена ли привязка
help()tableВозвращает справочную информацию {key, desc}

Создавайте стилизованный текстовый вывод с помощью стилизации на базе lipgloss. Все методы стиля возвращают новый стиль (immutable).

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"))

Создать новый пустой стиль.

Возвращает: Style

Все методы возвращают новый Style и могут быть зацеплены.

МетодПараметрОписание
foreground(color)stringЦвет текста (hex "#FF0000", ANSI "9" или имя)
background(color)stringЦвет фона
bold(enable?)booleanЖирный текст (по умолчанию: true)
italic(enable?)booleanКурсивный текст
underline(enable?)booleanПодчёркнутый текст
strikethrough(enable?)booleanПеречёркнутый текст
faint(enable?)booleanПриглушённый текст
blink(enable?)booleanМигающий текст
reverse(enable?)booleanПоменять местами цвет текста и фона
МетодПараметрОписание
width(n)numberФиксированная ширина
height(n)numberФиксированная высота
max_width(n)numberМаксимальная ширина
max_height(n)numberМаксимальная высота
padding(...)numbersВнутренний отступ (CSS-стиль: top, right, bottom, left)
margin(...)numbersВнешний отступ (CSS-стиль)
align(pos)numberГоризонтальное выравнивание
align_vertical(pos)numberВертикальное выравнивание
inline(enable?)booleanInline-режим рендеринга
МетодПараметрОписание
border(name, ...)string, booleansСтиль границы, опциональные переключатели по сторонам
border_foreground(...)stringsЦвет(а) границы
border_background(...)stringsЦвет(а) фона границы
МетодОписание
render(...)Отрендерить строки с применённым стилем
copy()Создать копию этого стиля
tty.borders.NORMAL
tty.borders.ROUNDED
tty.borders.THICK
tty.borders.DOUBLE
tty.borders.HIDDEN
tty.align.LEFT -- 0
tty.align.CENTER -- 0.5
tty.align.RIGHT -- 1

Функции компоновки и измерения для стилизованного текста. Доступны под tty.text.

local w = tty.text.width("hello") -- печатная ширина (с учётом ANSI)
local h = tty.text.height("a\nb\nc") -- количество строк
local w, h = tty.text.size("hello\nworld") -- оба значения
-- Соединить бок о бок, выровняв по верху
local row = tty.text.join_horizontal(tty.text.position.TOP, left, right)
-- Сложить вертикально, центрировано
local col = tty.text.join_vertical(tty.text.position.CENTER, top, bottom)
local w = tty.text.max_width({"short", "a longer string"}) -- самое широкое
local h = tty.text.max_height({"one\ntwo", "single"}) -- самое высокое

Поместить строку внутри области заданных размеров:

-- Центрировать в области 80x24
local out = tty.text.place(80, 24, tty.text.position.CENTER, tty.text.position.CENTER, content)
-- Только горизонтально
local out = tty.text.place_horizontal(80, tty.text.position.RIGHT, content)
-- Только вертикально
local out = tty.text.place_vertical(24, tty.text.position.BOTTOM, content)
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