std/terminal_emulator

A terminal, as a program that draws terminals itself keeps one, instead of using xterm.js: the bytes a program writes are read as VT and xterm terminals read them (ECMA-48 and the xterm extensions in common use) and drawn into a grid of cells; the user's keys, pastes, mouse events, and focus changes are written as the program asked for them.

import "std/terminal_emulator"

Terminal t = terminal_emulator(80, 24)
t.feed(to_bytes("\u{1b}[1;31mred\u{1b}[0m and plain"))
print(t.line(0), t.cell(0, 0).style.foreground)    // red and plain 1
write_input(program, t.encode_key("up"))            // ESC [ A, or ESC O A
write_input(program, to_bytes(t.take_replies()))    // what the program asked
Method
t.feed(data), t.feed_text(text) reads and draws what the program wrote; a character or sequence cut in two waits for its end
t.text(), t.line(row), t.cell(row, column), t.cursor() the screen: its text, a row's, a TerminalCell's text and style, and the cursor's row and column, from 0
t.history() the lines scrolled off the top of the main screen, oldest first, at most scrollback_limit (10,000)
t.resize(columns, rows) another size; rows that no longer fit go to the scrollback, and the cursor stays on the screen
t.take_replies() the answers to what the program asked, as where the cursor is (DSR), what the terminal is (DA), and its size, to write back to it
t.encode_key(key, shift, alt, ctrl) what a key sends: "up", "down", "right", "left", "home", "end", "insert", "delete", "page_up", "page_down", "f1" to "f12", "enter", "tab", "backspace", "escape", or a character; arrows follow application cursor mode
t.encode_paste(text) pasted text, bracketed when the program asked for it
t.encode_mouse(action, button, row, column, shift, alt, ctrl) a mouse event, "press", "release", "move", "scroll_up", or "scroll_down", in the tracking mode and encoding (X10, SGR, UTF-8, urxvt) the program chose; nothing when it does not want it
t.encode_focus(focused) focus in or out, when asked for

A TerminalStyle has foreground, background, and underline_color (-1 for the terminal's own, 0 to 255 for the palette, 0x1000000 plus red, green, and blue for 24-bit), bold, dim, italic, underline and its underline_kind (1 single, 2 double, 3 curly, 4 dotted, 5 dashed), blink, inverse, hidden, strike, overline, and the link its text is part of. A Terminal also says its title, icon_title, directory (OSC 7), clipboard (OSC 52, in base64), bells, and the modes the program set: cursor_visible, cursor_shape, auto_wrap, origin_mode, insert_mode, new_line_mode, application_cursor, application_keypad, bracketed_paste, mouse_tracking, mouse_encoding, focus_events, and alternate.

What it reads: the C0 controls; ESC sequences for the cursor's saving and restoring, index, reverse index, next line, tab stops, keypad modes, the character sets G0 to G3 with the DEC line-drawing set, DECALN, and reset; CSI sequences for moving the cursor, erasing, inserting and deleting characters and lines, scrolling, scroll regions, tab stops, repeating, styles (SGR, with colons too), modes, reports, and the cursor's shape; control characters inside a CSI sequence, which act at once; and OSC strings for the title, the folder, links (OSC 8), and the clipboard. DCS, PM, APC, and SOS strings are read and passed over.