Documentation
¶
Overview ¶
Package hotty speaks HOTTY, HTML Over The TTY (https://github.com/neuroplastio/hotty), from a Go program.
A HOTTY host is a terminal that shows surfaces: small HTML documents placed on rectangles of cells. A program sends documents, placements and deltas as escape sequences in its ordinary output, and hears replies and the user's events on its input.
This package is the wire, and does no I/O:
- The command functions (Doc, Place, Delta, …) return escape sequences as strings. Write them to the terminal like any other output; in a Bubble Tea program, through tea.Raw, so they stay in order with its frames.
- A Decoder turns the OSC sequences the program reads back into Messages: replies (ReplyOf) and events (EventOf), their msgpack bodies read by the types in wire.go.
The packages beside it do the I/O: term for a command that prints and exits or asks a question, hottytea for a full-screen Bubble Tea program, and hottytest for testing either against a host that runs in the test.
Replies ¶
Every command asks for the replies that are usually wanted: Doc and Place are answered on error (EQUOTA, ENOENT), everything else never. The options change that: Q sets the quiet level, and N numbers a command and asks for its reply. Replies arrive on the program's input, mixed with keys. A program that exits leaves unread replies to whatever reads the terminal next, a shell for instance, which reads them as typing.
Names and ids ¶
A surface name is 1 to 64 of A–Z, a–z, 0–9, '_' and '-' (SurfaceName makes one). Other control values, such as element ids, may be any printable ASCII but ':', ';' and '='. Encode replaces each character outside those with '_', as the specification has hosts do (SPEC §3.2), so a value can never end a command early or add a key to it.
Index ¶
- Constants
- func Blur(surface string, opts ...ReplyOption) string
- func CellCSS(c Caps) (w, h float64)
- func CursorBelow(rows int) string
- func DecodeKeys(input []byte) []string
- func DefaultEdit(mod string) map[string][]string
- func Del(surface string, opts ...ReplyOption) string
- func DelAll(opts ...ReplyOption) string
- func DelRes(id string, opts ...ReplyOption) string
- func Delta(surface string, op Op, target, key string, payload []byte, opts ...ReplyOption) string
- func Detach(surface string, opts ...ReplyOption) string
- func Doc(surface, html string, opts ...DocOption) string
- func Drags(c Caps) bool
- func Edit(names []string, opts ...ReplyOption) string
- func Encode(ctl Control, payload []byte) string
- func EncodeEvent(e Event) string
- func EncodePlain(ctl Control, payload []byte) string
- func Err(r Reply) error
- func Focus(surface, target string, opts ...ReplyOption) string
- func Get(c Control, k string) string
- func Has(c Control, k string) bool
- func Hide(surface string, opts ...ReplyOption) string
- func Hovers(c Caps) bool
- func Light(c Caps) bool
- func Lookup(c Control, k string) (string, bool)
- func Menu(level *MenuLevel, opts ...ReplyOption) string
- func MorphTo(surface, target, html string, opts ...ReplyOption) string
- func ParseKey(name string) (canonical string, ok bool)
- func Place(surface string, p Placement, opts ...ReplyOption) string
- func PlaceAt(surface string, x, y int, p Placement, opts ...ReplyOption) string
- func Query(n int, opts ...QueryOption) string
- func RemoveAttr(surface, target, name string, opts ...ReplyOption) string
- func ReplyCaps(n string, caps Caps) string
- func ReplyErr(n, surface, re, code, detail string) string
- func ReplyOK(n, surface, re string, extra Control, body []byte) string
- func ReplyQuery(query Control, caps Caps) string
- func Res(id, mime string, data []byte, opts ...ReplyOption) string
- func Reveal(surface, target, where string, opts ...ReplyOption) string
- func Sanitize(v string) string
- func Sends(c Caps, kind string) bool
- func SetAttr(surface, target, name, value string, opts ...ReplyOption) string
- func SetText(surface, target, text string, opts ...ReplyOption) string
- func SetVar(surface, target, name, value string, opts ...ReplyOption) string
- func Speaks(query Control) bool
- func Supports(c Caps, op Op) bool
- func SurfaceName(s string) string
- func Sync(cmds ...string) string
- func ValidName(s string) bool
- func Views(c Caps) bool
- func WithdrawLate() string
- type Action
- type Area
- type Axes
- type Caps
- type Cell
- type Command
- type Control
- type Decoder
- type DetectState
- type Detector
- type DocOption
- type Drag
- type Error
- type Event
- type Hover
- type KV
- type Keymap
- type Keys
- type Link
- type MenuItem
- type MenuLevel
- type Message
- type Op
- type Placement
- type Platform
- type QueryOption
- type Quiet
- type Reply
- type ReplyOption
- type Result
- type Scanner
- type Segment
- type SegmentKind
- type Size
- type View
- type Window
Constants ¶
const ( RevealNearest = "" // as little as brings it into view RevealStart = "start" // its top at the top of each box that holds it RevealEnd = "end" // its bottom at the bottom )
Where Reveal brings an element (SPEC §6.1).
const ( DetectTimeout = 1500 * time.Millisecond DetectAfterDA1 = 150 * time.Millisecond DetectAfterReply = 300 * time.Millisecond )
The Detector's times (SPEC §4): how long to wait for any answer at all; after a DA1 answer that came before any reply, for a reply that may still be on its way, since the DA1 may answer a question asked before the query; and after the host's reply, for the DA1 answer behind it, which would otherwise be left for whoever reads the terminal next.
const ( // Number is HOTTY's OSC number: the ASCII codes of H and O. Number = "7279" // Chunk is the most payload bytes one OSC carries (SPEC §3.4). Chunk = 4096 // MaxSize is the most columns or rows a surface has (SPEC §5.2). MaxSize = 1000 // MaxName is the longest a surface name is (SPEC §3.5). MaxName = 64 // Version is the protocol version this package speaks: what its query // lists, and what a host's capabilities must name (SPEC §4). Version = "0.2" )
const ( EventClick = "click" // a button, link, summary or data-on~=click element was activated EventChange = "change" // a control's value was committed, or a box toggled EventInput = "input" // an edit of a control with data-on~=input EventSubmit = "submit" // a form was submitted; the detail is its fields EventPress = "press" // a press anywhere in a placement made with Press EventFocus = "focus" // the user focused an element; Target names it (SPEC §10.1) EventBlur = "blur" // the surface gave the keyboard back EventResize = "resize" // the surface's pixel size changed, its cells did not EventFit = "fit" // the rows the document needs changed, on a placement made with Fit EventHover = "hover" // the element under the pointer changed, or the pointer left, on a placement made with Hover EventView = "view" // which elements with data-on~=view are in view, or where, changed (SPEC §9.5) // The terminal's events, which belong to no surface: Surface and // Target are empty. EventCommand = "command" // an edit command the program takes, by its key or a menu (SPEC §10.6) EventCaps = "caps" // the capabilities mod, edit or keys changed (SPEC §4) // A drag (SPEC §9.1), on an element with data-on~=drag. In the host's // events (Drags), EventDrag stands for all three. EventDragStart = "dragstart" // the primary button pressed on the element EventDrag = "drag" // the element under the pointer changed EventDragEnd = "dragend" // the button released, or the drag cut short )
Event kinds (SPEC §9). A program ignores kinds it does not know: later versions add some.
const ( EINVAL = "EINVAL" // an unknown action or op, a bad name, a missing key, a value out of range ENOENT = "ENOENT" // no surface of that name ENOTARGET = "ENOTARGET" // no element with that id; the detail is the id, or ids comma-separated EDETACHED = "EDETACHED" // the surface is detached (SPEC §5.5) EQUOTA = "EQUOTA" // over one of the host's limits (SPEC §13) EBUDGET = "EBUDGET" // the host gave up on work over its time budget EVERSION = "EVERSION" // a query lists no version the host speaks; the detail is those it speaks (SPEC §4) )
Error codes, in a reply's Code (SPEC §3.6).
const DefaultMax = 16 << 20
DefaultMax is a Decoder's Max when it sets none: 16 MiB, enough for a document with its images inline, and a bound on what a peer can make a Decoder hold.
const MaxDepth = 32
MaxDepth is how deep a body may nest, its map being the first level (SDK.md §3.9). A body nested deeper does not decode, so that no body can exhaust a stack: TinyGo's is 64 KB.
const TerminalKeys = "ArrowLeft=char-backward Control+b=char-backward ArrowRight=char-forward Control+f=char-forward " +
"Alt+ArrowLeft=word-backward Control+ArrowLeft=word-backward Alt+b=word-backward " +
"Alt+ArrowRight=word-forward Control+ArrowRight=word-forward Alt+f=word-forward " +
"Home=line-start End=line-end Control+e=line-end " +
"Backspace=delete-char-backward Control+h=delete-char-backward " +
"Delete=delete-char-forward Control+d=delete-char-forward " +
"Alt+Backspace=delete-word-backward Control+w=delete-word-backward Control+Backspace=delete-word-backward " +
"Alt+Delete=delete-word-forward Alt+d=delete-word-forward Control+Delete=delete-word-forward " +
"Control+u=delete-to-line-start Control+k=delete-to-line-end " +
"ArrowUp=line-previous Control+p=line-previous ArrowDown=line-next Control+n=line-next " +
"PageUp=page-up PageDown=page-down " +
"Alt+<=input-start Control+Home=input-start Alt+>=input-end Control+End=input-end " +
"Mod+a=select-all " +
"Control+m=newline"
TerminalKeys is the SDK's keymap (SDK.md §3.10), as a data-keys value: the keys of Bubble Tea's text input and text area (bubbles), but for Mod+a, which selects all, as in a GUI field and SPEC §10.2's default keymap: Control+a on Linux, while on macOS Control+a stays the line's start. A program puts it in the data-keys of an element that holds its fields, and edits its fields in cells with Resolve(platform, multiline, TerminalKeys), so that they edit the same on a surface and in cells. It leaves Enter to SPEC §10.2's default.
Variables ¶
This section is empty.
Functions ¶
func Blur ¶
func Blur(surface string, opts ...ReplyOption) string
Blur takes the keyboard back from a surface. Its focused control commits its value first, so a change event may come before the blur event.
func CellCSS ¶
CellCSS is a cell's size in CSS pixels: what a document's layout and an SVG's viewBox are measured in. Before a host has said, or if it said nothing, it is a usual 9×18.
func CursorBelow ¶
CursorBelow is the cursor's move a placement without KeepCursor makes (SPEC §5.2): rows index operations (IND) and a carriage return, to the start of the line below the placement. A relay that keeps a placement from the screen it emulates feeds it this instead.
func DecodeKeys ¶
DecodeKeys reads input from the terminal, the bytes a program reads, as SPEC §10.4 names the keys in it: one entry for each key, its canonical name, or "" for input that is no key it names (a mouse report, a sequence it does not know, a key's release). It reads the input whole: an ESC at its end is Escape.
func DefaultEdit ¶
DefaultEdit is the default edit shortcuts for a Mod (SPEC §10.2), "Control" or "Meta", the keys canonical with Mod read.
func Del ¶
func Del(surface string, opts ...ReplyOption) string
Del deletes a surface and its placement (SPEC §5.4).
func Delta ¶
Delta changes one surface's document (SPEC §6). target is an element id, "" for a morph by top-level ids; key names the attribute or the custom property. It is never answered, unless an option asks.
func Detach ¶
func Detach(surface string, opts ...ReplyOption) string
Detach gives a surface up (SPEC §5.5): it stays on the screen as text does, placed, changed by deltas and deleted as before, but sends no more events and never has the keyboard; if it has it, the keyboard goes back to the terminal with no blur. A program that leaves surfaces on the screen when it exits detaches them first, unless it sent them Detached. The next Doc sent without Detached makes the surface the program's again.
It is never answered, unless an option asks: a host older than §5.5 refuses it (EINVAL), and a reply nobody reads would reach the shell as typing.
func Doc ¶
Doc creates a surface, or replaces its document (SPEC §5.1). The surface is the program's, even one it had detached: it reports what the user does in it, and takes the keyboard on the program's behalf (SPEC §5.5), unless the document is sent Detached. It is answered on error: EQUOTA when the host holds no more surfaces.
func Drags ¶
Drags reports whether the host sends drags (SPEC §9.1): drag in its events, which stands for dragstart, drag and dragend. Unlike Sends, a host that lists no kinds is taken not to, since drags came after the first hosts: a program offers another way to do what its drags do.
func Edit ¶
func Edit(names []string, opts ...ReplyOption) string
Edit takes the edit commands named (SPEC §10.6): "select-all", "copy", "cut", "paste", "undo", "redo". Their keys, the host's edit shortcuts (Caps.Edit), then reach the program as EventCommand in place of their bytes, and the terminal's menus send them with no key. Each Edit replaces the last; none takes nothing. It holds for the screen it is sent on: a full-screen program sends it after switching to the alternate screen, and leaving it drops it.
func Encode ¶
Encode returns one command: the control and the payload, compressed when that makes it smaller, base64-encoded, and split into chunks of at most Chunk bytes (SPEC §3.3, §3.4). Keys are sent as they are; values are cleaned (Sanitize). The keys o and m are Encode's to set: a control given with them goes out without them.
func EncodeEvent ¶
EncodeEvent is the event as a host sends it (SPEC §9): what a relay writes to a program, the surface named as the program knows it, or a host's own. The detail is e.Detail when it has one, as it came, and otherwise what e carries for its kind, each field as its type. Never compressed (SPEC §3.3).
func EncodePlain ¶
EncodePlain is Encode without compression: what a host, or a relay speaking as one, writes to a program, since hosts never compress (SPEC §3.3).
func Focus ¶
func Focus(surface, target string, opts ...ReplyOption) string
Focus gives a surface the keyboard (SPEC §10.1), at an element if target is not empty; else its focused element keeps focus, or its first focusable element takes it.
func Hide ¶
func Hide(surface string, opts ...ReplyOption) string
Hide removes a surface's placement and keeps its document, to place it again without sending it (SPEC §5.4). Deltas still apply to it.
func Hovers ¶
Hovers reports whether the host sends hover (SPEC §9.4). Like Drags, a host that lists no kinds is taken not to: without it a program never hears the pointer leave for a surface, and clears what it lit on the next key or press instead.
func Menu ¶
func Menu(level *MenuLevel, opts ...ReplyOption) string
Menu shows the which-key menu of a program's key sequence while it waits (SPEC §10.6), or with nil hides it. A host shows it only when it reports Caps.Menu.
func MorphTo ¶
func MorphTo(surface, target, html string, opts ...ReplyOption) string
MorphTo morphs an element into html, or with no target, each top-level element of html into the document's element with its id. Morphing keeps what the user is doing in what stays: focus, the text being typed, an open <details> (SPEC §6.2).
func ParseKey ¶
ParseKey reads a key's name as SPEC §10.4 writes it, its modifiers in any order ("Shift+Control+a", "Control+ "), and returns its canonical name ("Control+A", "Control+Space"): the modifiers in the order Mod, Control, Alt, Meta, Shift; Shift shown in a letter where it can be; Space for a space. A binding's Mod is kept: a Keymap reads it as its Platform's. ok is false for a name that does not parse.
func Place ¶
func Place(surface string, p Placement, opts ...ReplyOption) string
Place places a surface at the cursor (SPEC §5.2). Placing a surface that is placed moves it. It is answered on error: ENOENT when the host has no such surface (it may have dropped it), EINVAL for a size or window out of range. A reply to a placement with Rows 0 carries the rows chosen.
func PlaceAt ¶
func PlaceAt(surface string, x, y int, p Placement, opts ...ReplyOption) string
PlaceAt places a surface with its window's top-left corner at cell (x, y), counted from 0 at the screen's top-left, and leaves the cursor where it was: the way a full-screen program lays surfaces out without disturbing its own drawing. It saves the cursor (DECSC), moves it, places with C=1, and restores it (DECRC).
func Query ¶
func Query(n int, opts ...QueryOption) string
Query asks whether the terminal is a HOTTY host that speaks Version, fenced by Primary Device Attributes (SPEC §4): a host replies to the query, numbered n, before the DA1 answer every terminal sends, in Version or with EVERSION. A DA1 answer with no reply before it means there is no host. Late asks for a late answer as well.
func RemoveAttr ¶
func RemoveAttr(surface, target, name string, opts ...ReplyOption) string
RemoveAttr removes an attribute from an element.
func ReplyCaps ¶
ReplyCaps is a host's answer to a query numbered n (SPEC §4): caps.Raw as it is when caps has one, so that a relay passes on the fields it does not know, and caps written otherwise.
func ReplyOK ¶
ReplyOK is a host's success reply (SPEC §3.6), as a host or a relay answering for one writes it to a program: n and surface echo the command's, each left out when "", re names the action answered, extra keys follow it (a placement's c and r), and body is its msgpack, if any. Never compressed (SPEC §3.3).
func ReplyQuery ¶
ReplyQuery is a host's answer to a query (SPEC §4), for a host that speaks only Version: caps, as ReplyCaps writes them, when the query lists Version, and an EVERSION error naming Version when it does not. caps.V is Version.
func Res ¶
func Res(id, mime string, data []byte, opts ...ReplyOption) string
Res stores a resource that documents refer to as cid:<id> (SPEC §7.1): a stylesheet shared by several surfaces, an image, a font. Sending it again replaces it, and redraws every surface that refers to it.
func Reveal ¶
func Reveal(surface, target, where string, opts ...ReplyOption) string
Reveal scrolls an element into view (SPEC §6.1): each box that holds it, the innermost first, along the axes the document scrolls (Scroll). where is RevealStart, RevealEnd or RevealNearest. It moves no focus, so a list beside the document keeps the keyboard: a table of contents that jumps to a section. Elements that report whether they are in view report it after (EventView).
func Sanitize ¶
Sanitize makes v a control value (SPEC §3.2): each character a value may not hold becomes '_', one for each character, not each byte, and one for each byte that is not UTF-8. Above 0x7e is not merely untidy: UTF-8 can hold 0x9c, which a terminal that reads C1 controls takes for ST, ending the sequence early.
func Sends ¶
Sends reports whether the host sends an event kind. A host that lists no kinds is taken to send them all. Drag in its events stands for dragstart, drag and dragend (SPEC §4).
func SetAttr ¶
func SetAttr(surface, target, name, value string, opts ...ReplyOption) string
SetAttr sets an attribute on an element.
func SetText ¶
func SetText(surface, target, text string, opts ...ReplyOption) string
SetText replaces an element's children with one text node: a clock, a count. Hosts make it cheap (SPEC §6.1).
func SetVar ¶
func SetVar(surface, target, name, value string, opts ...ReplyOption) string
SetVar sets the custom property --name on an element: the cheap way to move a bar or a needle every frame, with CSS that reads it.
func Speaks ¶
Speaks reports whether a query lists Version among the versions the program speaks (v, SPEC §4). A host that speaks only Version answers it with its capabilities, and any other query with EVERSION: ReplyQuery.
func Supports ¶
Supports reports whether the host supports a delta op. A host that lists no ops is taken to support them all.
func SurfaceName ¶
SurfaceName makes s a valid surface name: each character a name may not hold becomes '_', and the name is cut to 64 bytes. An empty s is "_".
func Sync ¶
Sync wraps commands in synchronized output (DEC mode 2026, SPEC §6.3): the host shows the state after all of them, never one in between.
func ValidName ¶
ValidName reports whether s is a surface name a host accepts: 1 to 64 of A–Z, a–z, 0–9, '_' and '-' (SPEC §3.5).
func Views ¶
Views reports whether the host sends view (SPEC §9.5). Like Drags, a host that lists no kinds is taken not to: without it a program that needs to know what is shown draws that part in cells, or takes the element it last revealed as the one shown.
func WithdrawLate ¶
func WithdrawLate() string
WithdrawLate withdraws a query that asked for a late answer (SPEC §4): a query that wants no answer (a=q:q=2), which takes the held one's place. It has no fence, and nothing answers it.
Types ¶
type Action ¶
type Action string
Action is what a text field does with a key (SPEC §10.2): a keymap binds keys to actions, and Lookup says which one a key does.
const ( CharBackward Action = "char-backward" CharForward Action = "char-forward" WordBackward Action = "word-backward" WordForward Action = "word-forward" LineStart Action = "line-start" LineEnd Action = "line-end" DeleteCharBackward Action = "delete-char-backward" DeleteCharForward Action = "delete-char-forward" DeleteWordBackward Action = "delete-word-backward" DeleteWordForward Action = "delete-word-forward" DeleteToLineStart Action = "delete-to-line-start" DeleteToLineEnd Action = "delete-to-line-end" LinePrevious Action = "line-previous" LineNext Action = "line-next" PageUp Action = "page-up" PageDown Action = "page-down" InputStart Action = "input-start" InputEnd Action = "input-end" SelectAll Action = "select-all" Newline Action = "newline" Submit Action = "submit" // Program binds a key to nothing: it reaches the program. Program Action = "program" // Copy, Cut, Paste, Undo and Redo are the field's clipboard and // history (SPEC §10.2). A hottyedit.Field keeps neither, and does // nothing with them. Copy Action = "copy" Cut Action = "cut" Paste Action = "paste" Undo Action = "undo" Redo Action = "redo" // The scroll actions (SPEC §10.2, scrolling keys): outside a text field, // a key bound to one, which the element does not use, scrolls the // nearest element that scrolls, from the focused one outward; a text // field's keymap leaves them out. ScrollUp Action = "scroll-up" ScrollDown Action = "scroll-down" ScrollLeft Action = "scroll-left" ScrollRight Action = "scroll-right" ScrollPageUp Action = "scroll-page-up" ScrollPageDown Action = "scroll-page-down" ScrollHalfPageUp Action = "scroll-half-page-up" ScrollHalfPageDown Action = "scroll-half-page-down" ScrollStart Action = "scroll-start" ScrollEnd Action = "scroll-end" // Insert is what Lookup returns for a character the field types. A // keymap does not bind it. Insert Action = "insert" )
The actions a keymap binds (SPEC §10.2).
func (Action) Moves ¶
Moves reports whether the action is a move, which selects when done with Shift (SPEC §10.2, Shift selects; Keymap.Selects).
type Area ¶
Area is the cells an element covers (SPEC §9), counted as a drag's are: Col and Row are the first column and row it touches, from 0 at the surface's top left (not its window's), and W and H the columns and rows it spans. An element partly clipped or scrolled away has its whole area, so Col and Row may be negative or past the surface.
type Axes ¶
type Axes int
Axes are the directions a document scrolls in (SPEC §5.1): a bitmask of ScrollVertical and ScrollHorizontal.
type Caps ¶
type Caps struct {
// V is the protocol version the host implements: "0.2".
V string `msg:"v"`
// Ops are the delta ops it supports.
Ops []string `msg:"ops,omitempty"`
// Events are the event kinds it sends.
Events []string `msg:"events,omitempty"`
// Cell is a cell's size in device pixels; nil when the host did not
// say.
Cell *Cell `msg:"cell,omitempty"`
// Scale is device pixels per CSS pixel.
Scale float64 `msg:"scale,omitempty"`
// Scheme is the terminal's colour scheme: "dark" or "light".
Scheme string `msg:"scheme,omitempty"`
// Limits are the host's limits, such as "surfaces" (a count) and
// "resources" (bytes) (SPEC §13).
Limits map[string]int `msg:"limits,omitempty"`
// Net is the host's network policy, from directive to the sources it
// allows (SPEC §7.2): empty when it fetches nothing.
Net map[string][]string `msg:"net,omitempty"`
// Scroll is true when a document can ask to scroll (Scroll, SPEC §5.1);
// a host that does not says nothing, and clips.
Scroll bool `msg:"scroll,omitempty"`
// Passthrough is true when the pointer passes through the parts of a
// surface that take no pointer (SPEC §9.3); a host that does not says
// nothing, and every window takes the pointer wherever it is.
Passthrough bool `msg:"passthrough,omitempty"`
// Steps is true when a drag of an element with data-steps says where
// in the element the pointer is (Drag.X and Drag.Y, SPEC §9.1); a host
// that does not says nothing, and its drags carry cells only.
Steps bool `msg:"steps,omitempty"`
// Drop is true when an element with drop in its data-on can be a
// drag's t without being dragged, and a drag says where in it the
// pointer is when it has data-steps (Drag.TX and Drag.TY, SPEC §9.1); a host
// that does not says nothing, and only an element that opts in to
// drags is ever t.
Drop bool `msg:"drop,omitempty"`
// Count is true when a repeated click says its place in its run of
// clicks (Event.Count, SPEC §9); a host that does not says nothing, and
// every click reads as a single one.
Count bool `msg:"count,omitempty"`
// Mod is the modifier Mod stands for in bindings, "Control" or "Meta"
// (SPEC §10.4); "" when the host did not say, which is Control.
Mod string `msg:"mod,omitempty"`
// Edit is the host's edit shortcuts, from each action to its keys
// (SPEC §10.2); a host that reports them takes edit commands (Edit,
// SPEC §10.6).
Edit map[string][]string `msg:"edit,omitempty"`
// Keys is the user's leader and sequence timeout (SPEC §10.5); nil
// when the host reads no key sequences.
Keys *Keys `msg:"keys,omitempty"`
// Menu is true when the host shows a program's which-key menus (Menu,
// SPEC §10.6).
Menu bool `msg:"menu,omitempty"`
// Host names the implementation, if it says.
Host string `msg:"host,omitempty"`
// Version is the implementation's version, with Host: dot-separated
// numbers, compared one by one ("0.0.10" is after "0.0.9").
Version string `msg:"version,omitempty"`
// Raw is the body the capabilities were read from, fields this package
// does not know included: what a relay announces to the programs
// behind it (SPEC §2.7). Writing Caps writes the fields above, not Raw.
Raw []byte `msg:"-"`
}
Caps is what a host says about itself in its reply to a query (SPEC §4).
func CapsOf ¶
CapsOf reads capabilities from the body of a reply to a query (SPEC §4), and reports whether it decoded: what a relay that stored or was handed them reads them with. Raw is a copy of body.
func Merge ¶
Merge is c with the fields a caps event changed (Event.Changed) in place of its own (SPEC §4): those whose keys changed's Raw has. Its Raw is c's with those fields replaced, so a relay announces the capabilities as they are now.
type Cell ¶
Cell is a cell's size in device pixels.
type Command ¶
type Command struct {
// Name is the command: "copy", "cut", "paste", "undo", "redo",
// "select-all".
Name string
// Key is the key that sent it, named as SPEC §10.4 names it; empty for
// a command from the terminal's menu.
Key string
// Text is a paste's text, and HasText whether there is one: a paste
// with nothing on the clipboard, or from a host that cannot read it,
// has none.
Text string
HasText bool
}
Command is an edit command (SPEC §10.6): the program decides what it means, and with nothing to do takes it as its Key, as a text field does.
type Control ¶
type Control []KV
Control is a command's or a message's keys, in the order they are sent.
type Decoder ¶
type Decoder struct {
// Max is the most bytes a message's payload may decode to, after
// base64 and zlib; one that would decode to more is Invalid, and its
// chunks are not kept (SPEC §3.4 lets a host limit a message). Zero is
// DefaultMax. A host sets it to what it accepts from a program, at
// least 1 MiB.
Max int
// Invalid counts the malformed messages dropped so far, aborted
// chunked messages included.
Invalid int
// contains filtered or unexported fields
}
Decoder turns OSC sequences into messages, joining chunked ones (SPEC §3.4). Its zero value is ready to use. It is not safe for concurrent use.
func (*Decoder) Feed ¶
Feed takes one complete OSC sequence, as a terminal-input parser delivers it: ESC ] … terminated by ST or BEL. When the result is Complete, m is the message.
A malformed message (a control that does not parse, a payload that is not base64 or zlib) is Invalid. So is a chunked message that another message interrupts; the interrupting one is then decoded as usual, and its own result returned.
type DetectState ¶
type DetectState uint8
DetectState is what a Detector has found.
const ( // Detecting: nothing is known yet. Detecting DetectState = iota // Native: the terminal is a HOTTY host. Native // Text: it is not; the program draws in cells. Text )
The states of a Detector.
func (DetectState) String ¶
func (s DetectState) String() string
String names the state: "detecting", "native" or "text".
type Detector ¶
type Detector struct {
// N numbers the query: a reply that does not echo it answers someone
// else's. 0 is 1.
N int
// Late asks for a late answer (Late, SPEC §4).
Late bool
// State is what the Detector has found, and Caps the host's
// capabilities, when Native.
State DetectState
Caps Caps
// Decided is whether State is final; Done, whether detection is over.
Decided, Done bool
// Deadline is when to call Tick next; zero before Start and once Done.
Deadline time.Time
// contains filtered or unexported fields
}
Detector decides whether the terminal is a HOTTY host (SDK.md §3.8). It is a state machine with the time passed in, so it behaves the same however the program reads the terminal: the program sends what Start returns, gives it each DA1 answer and each reply it reads, calls Tick at Deadline, and End when the input ends or it gives up.
The terminal is a host when it answers the query with capabilities that decode and name Version. Any other answer, an error (EVERSION, from a host that speaks other versions) or capabilities this package cannot read (a 0.1 host's JSON), makes the State Text at once: a host, but not one this program can use (SPEC §4).
Every DA1 answer from the start until Done is detection's, and the program swallows it: it answers the query's fence, or a question asked before, and is no key. A reply that answers the query, ok or an error, is detection's whenever it comes.
With Late, the query asks for a late answer (SPEC §4): the first reply that answers it once the State is Text, and makes the terminal a host, makes the State Native, with the host's capabilities, Decided and Done as it was. The program then starts using HOTTY.
Decided and Done differ only when the terminal answers the query: what it is is known when its reply arrives, and detection is over when the DA1 answer behind it does. A program that must not wait acts when Decided; one that hands the terminal on, when Done.
Its zero value is ready to use. It is not safe for concurrent use.
func (*Detector) DA1 ¶
DA1 takes a DA1 answer that arrived at now, and reports whether it was detection's.
func (*Detector) End ¶
End ends detection at now: the input ended, or the program gave up. A terminal that has not answered is not a host.
func (*Detector) Reply ¶
Reply takes a reply that arrived at now, and reports whether it answers the query: re=q and the query's n, ok or an error. One that comes after the Detector decided changes nothing, unless the query asked for a late answer (Late): then the first one that comes once the State is Text and makes the terminal a host makes it Native.
type DocOption ¶
type DocOption interface {
// contains filtered or unexported methods
}
DocOption is an option of Doc: a ReplyOption, Detached, or Scroll.
func Detached ¶
func Detached() DocOption
Detached sends a document the program only shows (d=1, SPEC §5.5): the surface is created detached, or its document replaced and the surface detached, in the one command. It reports nothing, never takes the keyboard, and its controls act disabled; hover, selection, <details> and hyperlinks still work, and it is placed, changed by deltas, hidden and deleted as before.
It is what a command prints among its output, which outlives it: whatever reads the terminal next, a shell, would read the surface's events as typing. A host older than §5.5 ignores d=1.
func Scroll ¶
Scroll lets the document scroll along the axes given (scroll=<axes>, SPEC §5.1, §5.3), as a page does in a browser: its overflow scrolls, with scrollbars in its pixels, never its cells, and a gesture it cannot take further goes on to the terminal unless the document's CSS overscroll-behavior stops it. Scrolling is local: the program hears nothing of it, and a delta keeps the offsets.
Like Detached, it belongs to the document: one sent without it does not scroll. 0, the default, sends no key; any other value goes out as given, for the host to judge. A host that does not scroll (Caps.Scroll false) ignores it and clips, as it clips every other document.
type Drag ¶
type Drag struct {
// Col and Row are the surface's cell under the pointer, from 0 at its
// top left (not its window's). They go on past its edges: negative
// above it and to its left, its size or more below and to its right.
Col, Row int
// Keys are the modifier keys held: "shift", "ctrl", "alt" and "meta",
// in that order.
Keys []string
// X and Y are where in the dragged element the pointer is, for an
// element with data-steps (SPEC §9.1): a step from 0 to its count,
// along its width and down its height, measured against the element
// the drag started on wherever the pointer is. HasX and HasY say
// whether the detail has them: an element with no steps along an axis
// has none, and 0 is a step like any other.
X, Y int
HasX, HasY bool
// TX and TY are where in t the pointer is, for a t with drop in its
// data-on and data-steps (SPEC §9.1), in drag and dragend: measured as X and Y are, against
// t's box. HasTX and HasTY say whether the detail has them.
TX, TY int
HasTX, HasTY bool
}
Drag is where a drag's pointer is, and the modifier keys held (SPEC §9.1).
type Error ¶
type Error struct {
Code string // EINVAL, ENOENT, …
Detail string
Re string // the action answered
Surface string
}
Error is an error reply (SPEC §3.6).
type Event ¶
type Event struct {
Surface string
// Kind is one of the Event kinds, or one this package does not know.
Kind string
// Target is the id of the element that reported; empty for focus,
// blur and resize, for a link without one (its href is in the
// detail), and for a press on nothing with an id.
Target string
// Value is a control's value (change, input), or the value attribute
// of what was clicked (click).
Value string
// Checked is a checkbox's or a radio button's state, in a change.
Checked *bool
// Fields are a submitted form's fields by name.
Fields map[string]string
// Link is a clicked link's.
Link *Link
// Size is a resize's new size, in CSS pixels.
Size *Size
// FitRows is the rows a fit says the document needs now.
FitRows int
// Drag is a dragstart's, a drag's or a dragend's.
Drag *Drag
// Hover is a hover's (SPEC §9.4).
Hover *Hover
// View is a view's (SPEC §9.5).
View *View
// Area is the cells of the element a click or a press reports, a
// keyboard click's too: what a program places something next to the
// element by, as a browser places a select's list or a menu by its
// control.
Area *Area
// Count is a click's place in its run of clicks on its element, as
// the user's platform counts them (SPEC §9): 2 for the second click of
// a double click, 1 for a single click or the keyboard's. It is 0 for
// any other kind.
Count int
// Command is a command's (SPEC §10.6).
Command *Command
// Changed is a caps's: the capabilities that changed, with only the
// fields the detail has (its Raw), for Merge.
Changed *Caps
// Detail is the detail as it came, msgpack: nil when the event has
// none. It is what a relay passes on (EncodeEvent).
Detail []byte
}
Event is what the user did in a surface (SPEC §9).
type Hover ¶
type Hover struct {
// Out is true when the pointer left the window: onto the cells or
// another surface, through a part that lets it through, out of the
// terminal, or pressed with Alt. Col and Row are then 0.
Out bool
// Col and Row are the surface's cell under the pointer when the
// element changed, from 0 at its top left (not its window's).
Col, Row int
}
Hover is where a hover event says the pointer is (SPEC §9.4); the element is the event's Target, empty over nothing with an id and when Out.
type Keymap ¶
type Keymap struct {
// contains filtered or unexported fields
}
Keymap binds keys to actions (SPEC §10.2), read on a Platform. ParseKeymap reads one from a data-keys value; Resolve makes the one a field uses, whose Lookup says what the field does with a key, and Selects whether it selects as it moves. Program says whether any focused element's keymap gives a key to the program, and Scroll which scroll action it binds a key to.
func ParseKeymap ¶
ParseKeymap reads a data-keys value as SPEC §10.2 has hosts read it: bindings separated by ASCII white space, each key=action, split at its last '='. It drops the bindings a host ignores: a key that does not parse, an action it does not know, and Tab, Shift+Tab and Escape. Mod reads as the Platform's: on Control, Mod+a and Control+a are one key.
func Resolve ¶
Resolve makes a field's keymap (SPEC §10.2): the default keymap for the Platform's Mod, with its edit shortcuts, for an input or for a multi-line field, then each data-keys value in turn, the root's first, each overriding the bindings before it key by key. It leaves out each binding to a scroll action where it stands, in its own value too: one neither acts nor overrides an earlier binding of its key.
func (*Keymap) Bind ¶
Bind binds a key to an action, and reports whether it did: a host ignores the bindings ParseKeymap drops, and so does Bind.
func (*Keymap) Format ¶
Format writes the keymap as a data-keys value: each key once, where it was first bound, as its last binding wrote it (Mod kept), with its last action.
func (*Keymap) Lookup ¶
Lookup says what a field with this keymap does with a key (SPEC §10.2): an action; Insert for a character it types; or "" when the key is not the field's, and reaches the program (or, for Tab, moves focus). A key with Shift that no binding names is looked up without Shift.
func (*Keymap) Program ¶
Program reports whether the keymap gives a key to the program: binds it to program, or, for a key with Shift that no binding names, binds it without Shift (SPEC §10.2, keys for the program).
Every focused element has a keymap, and outside a text field program and the scroll actions are the only actions it gives. A host reads the element's as a field's, from the data-keys values of the elements from the root down to it, but with its scroll actions and no default keymap: ParseKeymap(platform, strings.Join(values, " ")). It gives a key the keymap binds to program to the program before the element uses it, and before the surface scrolls with it; a nearer binding of the key to another action takes it back. In a field, Lookup says as much.
func (*Keymap) Scroll ¶
Scroll is the scroll action the keymap binds a key to, or "" for none: the key's own binding, or, for a key with Shift that no binding names, the binding without Shift (SPEC §10.2, scrolling keys).
A host asks it of the keymap it asks Program of, for a key the focused element does not use (Space on a button, a character on a select are the element's). A key bound to one scrolls the nearest element that scrolls, from the focused one outward, never the terminal; along an axis the document does not scroll (Scroll, SPEC §5.1), it goes on as if the keymap did not bind it.
func (*Keymap) Selects ¶
Selects reports whether a field with this keymap selects with a key (SPEC §10.2, Shift selects): Lookup returns a move for it (Action.Moves), and its canonical name has Shift, bound so or looked up without it ("Shift+ArrowLeft", "Control+Shift+End", not "Alt+<"). The field then keeps its anchor and moves the caret (hottyedit.Field.Extend).
type Keys ¶
type Keys struct {
// Leader is the user's leader, a key sequence: what <leader> stands for.
Leader string `msg:"leader,omitempty"`
// Timeout is how long a sequence waits for its next key, in
// milliseconds.
Timeout int `msg:"timeout,omitempty"`
}
Keys is how a host reads key sequences (SPEC §10.5).
type Link ¶
type Link struct{ Href, URL string }
Link is a clicked link: its href, as the document has it, and its URL resolved against the document's base (SPEC §7.3), "" when the href resolves to nothing outside the document.
type MenuItem ¶
type MenuItem struct {
// Key is the key, named as SPEC §10.4 names it.
Key string `msg:"key"`
// Label is what it does; empty leaves it to the host.
Label string `msg:"label,omitempty"`
// Group is set when more keys follow it.
Group bool `msg:"group,omitempty"`
// Enabled is set when it does anything now.
Enabled bool `msg:"enabled"`
}
MenuItem is a key that can follow a menu's sequence.
type MenuLevel ¶
type MenuLevel struct {
// Seq is the keys typed so far, named as SPEC §10.4 names them.
Seq []string `msg:"seq"`
// Label is their group's label: "+file".
Label string `msg:"label,omitempty"`
// Items are the keys that can follow them.
Items []MenuItem `msg:"items"`
}
MenuLevel is a which-key level a program shows while its key sequence waits (Menu, SPEC §10.6), in myelin's names and order: a myelin Menu encodes as one.
type Message ¶
Message is one HOTTY message: a reply or an event from the host, or a command from the program (what a host, a relay or a test decodes). Its control is in the order the keys came, so a relay that forwards it sends the same bytes.
type Op ¶
type Op string
Op is a delta operation (SPEC §6.1).
const ( OpMorph Op = "morph" // morph the target into the payload; without a target, top-level elements by id OpInner Op = "inner" // morph the target's children into the payload's nodes OpReplace Op = "replace" // replace the target with the payload's nodes, without morphing OpAppend Op = "append" // add the payload's nodes as the target's last children OpPrepend Op = "prepend" // add the payload's nodes as the target's first children OpBefore Op = "before" // insert the payload's nodes before the target OpAfter Op = "after" // insert the payload's nodes after the target OpRemove Op = "remove" // remove the target OpAttr Op = "attr" // set the target's attribute named by the key OpUnattr Op = "unattr" // remove the target's attribute named by the key OpText Op = "text" // replace the target's children with one text node OpVar Op = "var" // set the custom property --key on the target OpReveal Op = "reveal" // scroll the target into view; the payload says where (Reveal) )
The delta operations.
type Placement ¶
type Placement struct {
// Cols and Rows are the surface's size in cells, 1 to 1000. Rows 0 is
// auto: the host lays the document out Cols wide and takes the rows
// its content needs, and says how many in the reply.
Cols, Rows int
// Window, if not zero, is the part of the surface shown: a full-screen
// program scrolling a surface out of view shows what is still in it.
Window Window
// Z stacks overlapping placements, from -1000 to 1000: greater is
// above, and 0 is the usual.
Z int
// Press asks for a press event wherever the user presses in the
// placement, on text and empty space too (p=1).
Press bool
// Fit asks for a fit event whenever the rows the document needs at
// this width change from the rows last heard, starting from this
// placement's (f=1): an image or font arrived, a resource was
// replaced, a delta landed. The placement keeps its size; placing the
// surface again is the program's to do (SPEC §5.2).
Fit bool
// Hover asks for a hover event each time the element with an id under
// the pointer changes, and when the pointer leaves the window (v=1):
// for a hint of the program's own, or to clear what it lit outside
// the surface when the pointer goes onto it (SPEC §9.4).
Hover bool
// KeepCursor leaves the cursor where it was (C=1). Otherwise the host
// moves it to the start of the line below the placement, as text would.
KeepCursor bool
}
Placement is where and how a surface is shown (SPEC §5.2).
func PlacementOf ¶
Placement reads a place command (SPEC §5.2), as a host or a relay does: Rows 0 for r=auto or none, and the window as the command gives it, its defaults filled in: w reaches the surface's right edge, and h its bottom, which with Rows 0 is the host's to find (H 0). A command out of range is an *Error with Code EINVAL, as a host answers it.
type Platform ¶
type Platform struct {
// Mod is "Control" or "Meta" (SPEC §10.4); "" is Control.
Mod string
// Edit is the host's edit shortcuts, from each action to its keys
// (SPEC §10.2); nil is DefaultEdit(Mod).
Edit map[string][]string
}
Platform is how a host reads bindings (SDK.md §3.10): the modifier Mod stands for, and its edit shortcuts. The zero Platform is Control with the default edit shortcuts.
func PlatformOf ¶
PlatformOf is the Platform of a host's capabilities: its Mod and Edit, the zero Platform's where it reports none.
type QueryOption ¶
type QueryOption interface {
// contains filtered or unexported methods
}
QueryOption is an option of Query: Late.
func Late ¶
func Late() QueryOption
Late asks for a late answer (late=1, SPEC §4). What stands between the program and the terminal and has no host yet, such as a multiplexer running the program's pane with no terminal attached, may hold the query, and answer it once there is a host, whenever that is. A program that asks takes that answer as detection finding a host: it can start using HOTTY after it fell back to cells. A host answers at once, as it answers any query.
A program that asked, and will no longer take the answer, such as one about to exit, sends WithdrawLate, or the answer would reach whatever reads the terminal after it.
type Reply ¶
type Reply struct {
OK bool
// Re is the action answered: "doc", "place", "q", ….
Re string
// N is the request number, if the command had one (option N).
N int
// Surface is the surface the command named, if any.
Surface string
// Cols and Rows are a placement's size, in a reply to place: with
// Placement.Rows 0, the rows the host chose.
Cols, Rows int
// Code and Detail say what went wrong, when not OK: empty when the
// error's body does not decode.
Code, Detail string
// Caps are the capabilities an ok reply to a query carries: nil when
// it carries none, or they do not decode.
Caps *Caps
// Message is the reply as it came.
Message Message
}
Reply is the host's answer to a command (SPEC §3.6).
type ReplyOption ¶
type ReplyOption struct {
// contains filtered or unexported fields
}
ReplyOption sets the reply a command asks for (SPEC §3.5): every command takes one, Doc as a DocOption. N and Q make them, in either order.
func N ¶
func N(n int) ReplyOption
N numbers the command and asks for its reply whatever the outcome (ReplyAlways): the reply echoes n, so the program can tell which command it answers. A Q given with it asks for less.
func Q ¶
func Q(q Quiet) ReplyOption
Q sets the command's quiet level. It wins over the level N implies, whichever comes first.
type Result ¶
type Result int
Result is what a Decoder made of one sequence.
const ( // NotHotty: the sequence is not HOTTY's, and the caller handles it. NotHotty Result = iota // Partial: a chunk of a message that is not complete yet (SPEC §3.4). Partial // Complete: the message is complete. Complete // Invalid: the sequence was malformed, or aborted a chunked message, // and is dropped (SPEC §3.7). Invalid )
The results of Decoder.Feed.
type Scanner ¶
type Scanner struct {
// DA1 makes the Scanner cut out answers to Primary Device Attributes
// as SegmentDA1, for a program that reads them itself (SDK.md §4.1).
// Without it they pass.
DA1 bool
// Invalid counts the HOTTY sequences dropped so far.
Invalid int
// contains filtered or unexported fields
}
Scanner cuts HOTTY sequences out of a byte stream, however the reads split it (SDK.md §3.7): a terminal's input, read raw, or a program's output, for a relay. Everything else goes out as it came, in order, in the Feed that brought it; the Scanner holds only what may still become a segment of its own, the start of ESC ] 7279 ; (or of a DA1 answer, with DA1) and a HOTTY sequence in progress. So the segments do not depend on how the stream was split, and a key is never kept waiting.
An ESC inside a HOTTY sequence that does not begin its ST ends the sequence unfinished: it is dropped as malformed, and the ESC begins what comes next. A sequence longer than 64 KiB is dropped up to its terminator.
Its zero value is ready to use. It is not safe for concurrent use.
func (*Scanner) Feed ¶
Feed takes the next bytes of the stream and returns its segments, in order. Adjacent SegmentPass segments are one.
func (*Scanner) Flush ¶
Flush ends the stream: what is held goes out as SegmentPass, except a HOTTY sequence in progress, which is dropped as malformed.
A program reading keys flushes a lone ESC that a read ended with, as the Escape key (SDK.md §4.1), at once or when no more bytes follow soon:
segs := s.Feed(buf[:n])
if h := s.Holding(); len(h) == 1 && !s.InSequence() {
segs = append(segs, s.Flush()...) // a lone ESC
}
func (*Scanner) Holding ¶
Holding returns the bytes the Scanner holds for the next Feed: the start of a segment, or a HOTTY sequence in progress. They are good until the next Feed or Flush.
func (*Scanner) InSequence ¶
InSequence reports whether a HOTTY sequence is in progress, or one too long is being dropped: the next Feed goes on with it, and Flush would drop it. Otherwise what Holding returns is the start of a segment, which a program reading keys may flush after a moment, as typing (an ESC, then ], is Alt+]).
type Segment ¶
type Segment struct {
Kind SegmentKind
// Data is the segment's bytes. It may share memory with the bytes
// given to Feed, so it is good until the caller changes those: a
// caller that reuses its read buffer copies what it keeps.
Data []byte
}
Segment is a piece of a scanned stream.
type SegmentKind ¶
type SegmentKind uint8
SegmentKind is what a Segment holds.
const ( // SegmentPass: bytes that are not HOTTY's, unchanged: keys, mouse // reports, text, other escape sequences, other OSCs. SegmentPass SegmentKind = iota // SegmentOSC: one complete HOTTY sequence, from ESC ] 7279 ; to its // terminator (ST or BEL), ready for a Decoder. SegmentOSC // SegmentDA1: an answer to Primary Device Attributes, CSI ? <digits // and ;> c, from a Scanner made to look for them (Scanner.DA1). SegmentDA1 )
The kinds of Segment.
func (SegmentKind) String ¶
func (k SegmentKind) String() string
String names the kind: "pass", "osc" or "da1".
type Size ¶
Size is a surface's size in CSS pixels, in a resize event.
type View ¶
type View struct {
// Areas are the elements in view by id, each with its whole area,
// however little of it is shown. One whose area lacks a field is left
// out.
Areas map[string]Area
// AtEnd is true when the document's root is scrolled as far down as it
// goes, as a root that does not scroll down always is.
AtEnd bool
}
View is what a view event reports (SPEC §9.5): every element with data-on~=view and an id that is in view, not only what changed.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package blocks draws bars in terminal cells with the block elements (U+2581–U+2588): a column's height in eighths of a row, as a bar chart or a histogram in text has it.
|
Package blocks draws bars in terminal cells with the block elements (U+2581–U+2588): a column's height in eighths of a row, as a bar chart or a histogram in text has it. |
|
Package braille draws in terminal cells with the Unicode braille patterns (U+2800–U+28FF): each cell is two dots across and four down, so a line chart in text has four times the rows and twice the columns of its cells.
|
Package braille draws in terminal cells with the Unicode braille patterns (U+2800–U+28FF): each cell is two dots across and four down, so a line chart in text has four times the rows and twice the columns of its cells. |
|
Package chart draws line charts for HOTTY surfaces, as inline SVG that a program changes with deltas as values arrive, and in cells for a terminal that is not a host (Spark).
|
Package chart draws line charts for HOTTY surfaces, as inline SVG that a program changes with deltas as values arrive, and in cells for a terminal that is not a host (Spark). |
|
Package form is a form for a HOTTY surface: a spec, the document it makes (real HTML controls, with ids a program can focus and change with deltas), and what a submit event brings back, read into typed answers.
|
Package form is a form for a HOTTY surface: a spec, the document it makes (real HTML controls, with ids a program can focus and change with deltas), and what a submit event brings back, read into typed answers. |
|
hottyedit
module
|
|
|
hottytea
module
|
|
|
hottyterm
module
|
|
|
hottytest
module
|
|
|
hottyvt
module
|
|
|
internal
|
|
|
docgen
command
Command docgen writes hotty-go's API reference from the code: a page per public package in docs/api, an index of them, and the tables of packages and examples in README.md, between its docgen markers.
|
Command docgen writes hotty-go's API reference from the code: a page per public package in docs/api, an index of them, and the tables of packages and examples in README.md, between its docgen markers. |
|
Package series reads numbers from a stream of text, as plotting tools such as youplot and asciigraph do: lines of numbers separated by spaces, tabs or commas, a column a series, and a first line with no numbers naming them.
|
Package series reads numbers from a stream of text, as plotting tools such as youplot and asciigraph do: lines of numbers separated by spaces, tabs or commas, a column a series, and a first line with no numbers naming them. |