Help us shape the future of Go! Take the 2026 Go Developer Survey

plugin

package
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package plugin is AutoDoc's plugins (ADR 0209, ADR 1791268009): the protocol between the TUI and a plugin it runs, and the SDK a plugin is written with.

A dialog plugin is a program the TUI starts when its Plugins menu entry is chosen. The TUI draws a dialog over the page and fills it with the plugin's frames; every key but Esc goes to the plugin, and Esc closes it. A non-modal one (a card) sits beside the page and takes the keys only when focused; a service has no surface at all. The two speak msgpack-RPC NOTIFICATIONS, both ways, over the plugin's stdin and stdout — never a request, which golib's RPC client cannot take:

host → plugin   plugin.open {protocol, width, height, theme}   the first, once; a service's has no size
                plugin.key {key, text, ctrl, alt, shift}
                plugin.pointer {kind, button, x, y, count}      6: a frame's left press or wheel
                plugin.resize {width, height}
                plugin.theme {theme}
                plugin.hide {}, plugin.show {}                  esc = "hide": hidden, shown again
                plugin.focus {focused}                          2: a card took or gave back the keys
                plugin.document {path, workspace, text,         2: the open note, as [feed] declares
                  cursor, selection, version, too_large,
                  cursor_byte, selection_bytes}                 4: the byte offsets
                plugin.command {id}                             2: one of the manifest's [[commands]]
                plugin.command {id, document}                   4: with the note as it stood, under [feed]
                plugin.result {call, ok, error}                 3: the answer to host.call
                plugin.table.fetch {id, n}                      4: up to n more rows of the table
                plugin.table.close {id}                         4: the table closed, or replaced
                plugin.close {}                                 the last
plugin → host   host.ready {protocol}                           the answer to plugin.open
                host.frame {rows}                               the whole dialog, any time
                host.title {title}
                host.call {call, id, args}                      3: run a command of AutoDoc's catalog
                host.table {id, title, fields, rows, more}      4: a table of rows, as [table] declares
                host.table {…, kinds}                           5: with each cell's kind
                host.rows {id, rows, more}                      4: the next rows, answering a fetch
                host.rows {…, kinds}                            5: with each cell's kind
                host.table_end {id, error}                      4: the table's rows ended early
                host.close {}

The notifications marked 2 are protocol 2's, those marked 3 protocol 3's, those marked 4 protocol 4's. A host sends them only to a plugin whose manifest says that protocol (or a later one) and declares them, so a protocol-1 plugin never sees one. The fields marked 5 are read only from a plugin whose manifest says protocol 5. Pointer notifications go only to protocol-6 plugins.

A table is the host's to show: the plugin sends its fields and its first rows (host.table), and AutoDoc shows them in a results panel, asking for more as the user nears the end of those loaded (plugin.table.fetch), one request at a time until host.rows answers it. more says rows remain; host.table_end ends them early, with why. A newer host.table replaces the table, and the host says plugin.table.close for the one it replaced, as it does when the panel closes. Each table has an id of its own: one that reuses the shown table's id is refused, and host.rows no fetch asked for is dropped.

From protocol 5 a table's cells may carry their kinds: kinds is one string per row, a byte per field, each one of KindText, KindNull, KindNumber, KindBool and KindJSON. A NULL is then told from the text "NULL", and a number's text is its literal. The host sorts by them and writes them into JSON. A kinds string of the wrong length, or with another byte, makes its message malformed.

host.call and plugin.result are a request and its answer made of two notifications, matched by call, a number the plugin chooses and does not reuse while it waits. The host runs only the command ids the manifest's calls = [...] declares, and answers every call it accepts exactly once: ok, or error "<code> <message>" with the code refused (an id not declared, a plugin's command, or more than MaxPendingCalls waiting: "refused busy"), unknown (no command has the id) or failed (the command's own error). A call reusing a number still waiting is a protocol violation: the host logs it, runs nothing, and sends no result for it, so the waiting call's is the only one with that number. Peer.Call does all of this for a plugin in Go.

A card or dialog need not draw its cells by hand: plugin/card is a native kit of pages and controls (inputs, buttons, lists, trees), and plugin/decl runs a golib QML layout. Both draw in AutoDoc's look and theme (docs/plugins.md, "Drawing a card").

A plugin in Go writes a Handler and calls Serve; one in another language speaks the table above. The frame's colours are the themes' vocabulary: "default", an ANSI name ("brightwhite"), or "#rrggbb" — golib's style.ParseColor reads them, as it reads the theme the plugin is sent.

Index

Constants

View Source
const (
	MaxNoticeBytes   = 1024 // the message, in bytes of UTF-8
	MaxNoticeIDBytes = 64   // the id: letters, digits, '.', '_' and '-'
	MaxActiveNotices = 16   // ongoing ids one run of a plugin may hold at once
)

The bounds of a notice: past any, host.notify is refused and nothing shows.

View Source
const (
	MinProtocol = 1
	Protocol    = 11 // 11: [[menu]] and host.menu (ADR 1792991184); 10: [surface] (ADR 1792797354)
)

The plugin protocol's versions this SDK speaks. A host speaks to each plugin the one its manifest says, and Serve answers any from MinProtocol to Protocol with that same one. The protocol rises when a manifest can declare something an older host must not run without, for a changed meaning, or for something a plugin must handle (ADR 1791268009 §1).

View Source
const (
	MethodOpen    = "plugin.open"
	MethodKey     = "plugin.key"
	MethodPointer = "plugin.pointer" // protocol 6: a plugin view's left press or vertical wheel
	MethodResize  = "plugin.resize"
	MethodTheme   = "plugin.theme"
	MethodClose   = "plugin.close"
	// MethodHide and MethodShow are a dialog whose manifest says esc = "hide": Esc hid it, and
	// its Plugins menu entry showed it again. A plugin may ignore them; it keeps running either way.
	MethodHide = "plugin.hide"
	MethodShow = "plugin.show"
	// MethodFocus is a non-modal card focused (a click, or its command's key) or given back (Esc).
	MethodFocus = "plugin.focus"
	// MethodDocument is the open note, to a plugin whose manifest declares [feed] document = true.
	MethodDocument = "plugin.document"
	// MethodCommand is one of the manifest's [[commands]], chosen.
	MethodCommand = "plugin.command"
	// MethodResult is the host's answer to a host.call, by its call number.
	MethodResult = "plugin.result"
	// MethodFetch asks for up to n more rows of the table id (protocol 4). The host sends another
	// only once host.rows (or host.table_end) has answered it.
	MethodFetch = "plugin.table.fetch"
	// MethodTableGone is the table id closed: its panel closed, or a newer table replaced it. The
	// plugin frees what serves its rows (a database cursor, say).
	MethodTableGone = "plugin.table.close"
)

The notifications the host sends.

View Source
const (
	MethodReady     = "host.ready"
	MethodFrame     = "host.frame"
	MethodTitle     = "host.title"
	MethodHostClose = "host.close"
	// MethodCall asks the host to run a command of its catalog, one the manifest's calls declares.
	MethodCall = "host.call"
	// MethodSession replaces the plugin's session slot (protocol 7, session.go): kept by the host
	// in memory until AutoDoc quits, and handed back in each plugin.open.
	MethodSession = "host.session"
	// MethodTable shows a table (protocol 4): its id, title, fields and first rows, and whether
	// more remain. It replaces the table shown, any plugin's.
	MethodTable = "host.table"
	// MethodRows is the table's next rows, answering plugin.table.fetch, and whether more remain.
	MethodRows = "host.rows"
	// MethodTableEnd is the table's rows ended before the last was sent: no more will come, and
	// error, when set, says why.
	MethodTableEnd = "host.table_end"
)

The notifications the plugin sends.

View Source
const (
	// MaxPendingCalls is how many of a plugin's calls the host keeps waiting; one more is answered
	// "refused busy".
	MaxPendingCalls = 64
	// CallTimeout is how long Peer.Call waits for the host's answer.
	CallTimeout = 10 * time.Second
)

The bounds of host.call (protocol 3).

View Source
const (
	CallRefused = "refused" // not declared, a plugin's command, or too many waiting (busy)
	CallUnknown = "unknown" // no command has the id
	CallFailed  = "failed"  // the command's own error
)

The codes of a plugin.result's error.

View Source
const (
	MaxRows       = 500
	MaxRunsPerRow = 1000
)

Limits on what the host reads of a frame: past them it is clipped.

View Source
const (
	KindText   byte = 't'
	KindNull   byte = 'z' // the cell is NULL; its text is what shows (the plugin's "NULL", say)
	KindNumber byte = 'n' // the cell's text is the number's literal
	KindBool   byte = 'b' // the cell's text is true or false
	KindJSON   byte = 'j' // the cell's text is a JSON value
)

The kinds of a table's cells (protocol 5), one byte each: golib's widget.TableCellKind bytes.

View Source
const (
	MaxSessionKeys  = 32
	MaxSessionValue = 8 << 10  // bytes, each value
	MaxSessionBytes = 64 << 10 // keys and values together
)

The bounds of a session slot: past any, host.session is refused and the slot kept as it was.

View Source
const (
	CloseQuit    = "quit"   // AutoDoc is quitting: the slot goes with it
	CloseOff     = "off"    // the user turned the plugin off; the slot stays for its next start
	CloseUpdate  = "update" // its new build is about to start; the slot stays
	CloseRemove  = "remove" // it is being removed: the slot is dropped
	CloseFailure = "failed" // the host stopped it for a fault (no answer, a wrong message)
	CloseClosed  = "closed" // closed as a dialog closes: Esc on a modal one, or its own host.close
)

The reasons a plugin.close gives (protocol 7). A plugin reads one with Peer.CloseReason inside Close. It is best-effort: a plugin that never finished opening, blocks, or has died is stopped without one.

View Source
const (
	// MethodSurface is a generation of the surface: its size in dp, the device scale and the frame
	// kinds the window draws. It follows plugin.open, and comes again at each resize, scale or caps
	// change; a host without pixels never sends it.
	MethodSurface = "plugin.surface"
	// MethodSurfacePointer is the pointer on a surface, in dp: it replaces plugin.pointer there.
	MethodSurfacePointer = "plugin.surface.pointer"
	// MethodPaste is the user's paste chord on a focused surface.
	MethodPaste = "plugin.paste"

	// MethodCaret is where the surface's text caret is, for the host's IME: it draws the preedit there
	// and places the candidate window by it.
	MethodCaret = "host.surface.caret"
	// MethodPointerShape is the pointer's shape over the surface.
	MethodPointerShape = "host.surface.cursor"
	// MethodClipboardWrite writes text to the clipboard. There is no read: a read is the user's paste.
	MethodClipboardWrite = "host.clipboard.write"
)

The notifications of protocol 10.

View Source
const (
	MaxSurfaceDatagram = 2048 // under macOS's AF_UNIX SOCK_DGRAM default, net.local.dgram.maxdgram
	MaxSurfaceFDs      = 4
	MaxPoolBuffers     = 3 // one shown, one pending, one being drawn
)

The side channel's limits.

View Source
const (
	OpBuffers       = "buffers"    // host → plugin: a generation's pool, an fd per buffer
	OpBufferAdd     = "buffer.add" // plugin → host: a DMA-BUF it exported, an fd per plane
	OpBufferDrop    = "buffer.remove"
	OpSurfaceAck    = "surface.ack"    // plugin → host: it holds a generation's plugin.surface and buffers
	OpFrame         = "frame"          // plugin → host: present a buffer
	OpFrameDone     = "frame.done"     // host → plugin: that frame's outcome
	OpBufferFree    = "buffer.free"    // host → plugin: the buffer may be drawn into again
	OpBufferRefused = "buffer.refused" // host → plugin: a buffer.add not taken ("budget", "size"); not a violation
)

The ops.

View Source
const MaxDocumentBytes = MaxMessageBytes

MaxDocumentBytes bounds a whole plugin.document as the link encodes it. It is the link's own limit: EncodedSize measures the notification exactly as the link writes it, envelope and all, and the link takes a message of MaxMessageBytes and refuses one byte more. A note whose document is larger is sent as too large, without its text (ADR 1791268009 §2.3).

View Source
const MaxMenuTitleBytes = 256

MaxMenuTitleBytes bounds a row's title, in bytes of UTF-8.

View Source
const MaxMessageBytes = 1 << 20

MaxMessageBytes bounds one notification either way: a frame of a dialog is a few kilobytes.

View Source
const MaxSurfaceKinds = 32

MaxSurfaceKinds bounds plugin.surface's kinds: a window draws a handful.

View Source
const MethodMenu = "host.menu"

MethodMenu sets one of the plugin's menu rows (protocol 11).

View Source
const MethodNotify = "host.notify"

MethodNotify posts a notification (protocol 8).

View Source
const SurfaceFDEnv = "AUTODOC_PLUGIN_SURFACE_FD"

SurfaceFDEnv names the side channel's fd in the plugin's environment.

View Source
const WriteTimeout = 2 * time.Second

WriteTimeout bounds one send: a peer that has not read for this long is not answering.

Variables

View Source
var (
	// ErrClosed is a call made, or waiting, when the link is gone.
	ErrClosed = errors.New("plugin: the link to the host is closed")
	// ErrCallTimeout is a call the host did not answer within CallTimeout. Its answer, if it comes,
	// is dropped.
	ErrCallTimeout = errors.New("plugin: the host did not answer the call in time")
	// ErrNoCalls is a call to a host that opened the plugin at a protocol before 3, which has no
	// host.call.
	ErrNoCalls = errors.New("plugin: the host speaks a protocol before 3, without host.call")
	// ErrNoTables is a table sent to a host that opened the plugin at a protocol before 4, which has
	// no host.table.
	ErrNoTables = errors.New("plugin: the host speaks a protocol before 4, without tables")
)

The errors of Peer.Call besides the host's own answer (a *CallError).

View Source
var ErrMenu = errors.New("plugin: a menu row update refused")

ErrMenu is a host.menu the protocol refuses: CheckMenu and ReadMenu say which rule.

View Source
var ErrNoMenu = errors.New("plugin: the host speaks a protocol before 11, without menu rows")

ErrNoMenu is a menu row update sent to a host speaking a protocol before 11.

View Source
var ErrNoNotify = errors.New("plugin: the host speaks a protocol before 8, without notifications")

ErrNoNotify is a notice sent to a host speaking a protocol before 8.

View Source
var ErrNoSession = errors.New("plugin: the host speaks a protocol before 7, without a session slot")

ErrNoSession is a slot set on a host that opened the plugin at a protocol before 7.

View Source
var ErrNoSurface = errors.New("plugin: the host gave no pixel surface")

ErrNoSurface is a surface call on a host that gave no pixel surface (protocol 10, [surface]).

View Source
var ErrNotice = errors.New("plugin: a notice refused")

ErrNotice is a notice the protocol refuses: CheckNotice and ReadNotice say which rule. Their errors never hold the message.

View Source
var ErrParams = errors.New("plugin: malformed parameters")

ErrParams is a notification whose parameters are not the protocol's.

View Source
var ErrSessionBounds = errors.New("plugin: a session slot over its bounds")

ErrSessionBounds is a slot over MaxSessionKeys, MaxSessionValue or MaxSessionBytes.

View Source
var ErrSurfaceClosed = errors.New("plugin: the side channel is closed")

ErrSurfaceClosed is a side channel whose peer went, or that was closed.

View Source
var ErrSurfaceWire = errors.New("plugin: malformed side-channel message")

ErrSurfaceWire is a malformed side-channel message: a violation, which closes the plugin.

Functions

func BufferFreeMsg added in v0.2.5

func BufferFreeMsg(id int) map[string]any

BufferFreeMsg is the buffer.free op.

func BuffersMsg added in v0.2.5

func BuffersMsg(gen int, specs []SurfaceBufferSpec) map[string]any

BuffersMsg is the buffers op: specs[i] is the buffer whose fd is the datagram's i-th.

func CallParams added in v0.1.40

func CallParams(c Call) []any

CallParams are host.call's.

func CaretParams added in v0.2.5

func CaretParams(c Caret) []any

CaretParams are host.surface.caret's; the zero Caret sends {}, no caret.

func CheckKinds added in v0.1.54

func CheckKinds(kinds []string, rows, fields int) string

CheckKinds is why kinds cannot be the kinds of rows of a table of fields fields ("" when they can): one string per row, each exactly fields bytes, every byte a kind.

func CheckMenu added in v0.3.1

func CheckMenu(u MenuUpdate) error

CheckMenu is nil when u is an update the protocol takes.

func CheckNotice added in v0.1.59

func CheckNotice(n Notice) error

CheckNotice is nil when n is a notice the protocol takes.

func CheckSession added in v0.1.56

func CheckSession(values map[string]string) error

CheckSession is nil when values fit a slot's bounds.

func ClipboardWriteParams added in v0.2.5

func ClipboardWriteParams(text string) []any

ClipboardWriteParams are host.clipboard.write's.

func CloseParams added in v0.1.56

func CloseParams(reason string) []any

CloseParams are plugin.close's: its reason from protocol 7, none before.

func CommandArgsParams added in v0.1.56

func CommandArgsParams(id string, args []string) []any

CommandArgsParams are plugin.command's with arguments (protocol 7).

func CommandDocParams added in v0.1.52

func CommandDocParams(id string, d Document) []any

CommandDocParams are plugin.command's with the document it runs on (protocol 4): the note as it stood when the command was chosen, carried inside the command so no queue can drop it as it drops a waiting plugin.document (FitCommand sizes it).

func CommandParams added in v0.1.21

func CommandParams(id string) []any

CommandParams are plugin.command's.

func DocumentParams added in v0.1.21

func DocumentParams(d Document) []any

DocumentParams are plugin.document's as protocols 2 and 3 have it, without the byte offsets. A TooLarge one carries its path, workspace and version alone.

func DocumentParamsAt added in v0.1.52

func DocumentParamsAt(protocol int, d Document) []any

DocumentParamsAt are plugin.document's as a plugin speaking protocol is sent it: from protocol 4 on with cursor_byte and selection_bytes, so a plugin written for an earlier one sees what it always has.

func EmptyParams

func EmptyParams() []any

EmptyParams are plugin.close's and host.close's.

func EncodedSize added in v0.1.21

func EncodedSize(method string, params []any) (int, error)

EncodedSize is the size of the notification method with params, as the link writes it.

func FetchParams added in v0.1.52

func FetchParams(f TableFetch) []any

FetchParams are plugin.table.fetch's.

func FileConn

func FileConn(r, w *os.File) net.Conn

FileConn is a net.Conn over two files: what the link reads from and what it writes to. The host makes it from its ends of the pipes it starts a plugin with, and Serve from the plugin's stdin and stdout.

golib's rpc.Client bounds every write with a deadline and refuses a connection that cannot take one, so the files must be pollable: os.Pipe's are, and Serve makes stdin and stdout so (stdio_unix.go). Close closes both.

func FitCommand added in v0.1.52

func FitCommand(id string, d Document) []any

FitCommand is plugin.command id carrying d (protocol 4), as it can be sent. The document is sized INSIDE the command, the whole notification as the link writes it, since a document that fits a plugin.document of its own can pass the link's limit once the command's envelope is added: one that does not fit goes as its too-large form, so the link never refuses the command, and the plugin learns the note was too large to send rather than running on a stale copy.

func FocusParams added in v0.1.21

func FocusParams(focused bool) []any

FocusParams are plugin.focus's.

func FrameDoneMsg added in v0.2.5

func FrameDoneMsg(d SurfaceFrameDone) map[string]any

FrameDoneMsg is the frame.done op.

func FrameMsg added in v0.2.5

func FrameMsg(f SurfaceFrame) map[string]any

FrameMsg is the frame op.

func FrameParams

func FrameParams(rows []Row) []any

FrameParams are host.frame's. A run's style keys are left out when they are their zero value.

func KeyCode added in v0.1.55

func KeyCode(name string) (rune, bool)

KeyCode is the golib tui key code of a key the protocol names ("Up", "F5"); false for a name it does not have.

func KeyName added in v0.1.55

func KeyName(code rune) string

KeyName is the protocol's name for the golib tui key code ("Up", "F5"); "" for a key with no name of its own (a printable key is sent as its text).

func KeyParams

func KeyParams(k Key) []any

KeyParams are plugin.key's.

func MenuParams(u MenuUpdate) []any

MenuParams are host.menu's.

func NotifyParams added in v0.1.59

func NotifyParams(n Notice) []any

NotifyParams are host.notify's.

func OpenParams

func OpenParams(o Open) []any

OpenParams are plugin.open's parameters. A service's (a size of 0 by 0) has no width or height.

func PasteParams added in v0.2.5

func PasteParams(text string) []any

PasteParams are plugin.paste's.

func PointerParams added in v0.1.54

func PointerParams(p Pointer) []any

PointerParams are plugin.pointer's coordinates in the plugin view's frame.

func PointerShapeParams added in v0.2.5

func PointerShapeParams(shape string) []any

PointerShapeParams are host.surface.cursor's.

func ReadBufferFreeMsg added in v0.2.5

func ReadBufferFreeMsg(m map[string]any) (int, error)

ReadBufferFreeMsg reads a buffer.free op.

func ReadClipboardWrite added in v0.2.5

func ReadClipboardWrite(params []any) (string, error)

ReadClipboardWrite reads host.clipboard.write.

func ReadClose added in v0.1.56

func ReadClose(params []any) string

ReadClose reads plugin.close's reason: "" when it has none.

func ReadCommand added in v0.1.21

func ReadCommand(params []any) (string, error)

ReadCommand reads plugin.command: the command's id.

func ReadCommandArgs added in v0.1.56

func ReadCommandArgs(params []any) []string

ReadCommandArgs reads plugin.command's arguments: nil when it has none.

func ReadFocus added in v0.1.21

func ReadFocus(params []any) (bool, error)

ReadFocus reads plugin.focus.

func ReadPaste added in v0.2.5

func ReadPaste(params []any) (string, error)

ReadPaste reads plugin.paste.

func ReadPointerShape added in v0.2.5

func ReadPointerShape(params []any) (string, error)

ReadPointerShape reads host.surface.cursor.

func ReadReady

func ReadReady(params []any) (int, error)

ReadReady reads host.ready: the plugin's protocol.

func ReadResize

func ReadResize(params []any) (w, h int, err error)

ReadResize reads plugin.resize.

func ReadRows added in v0.1.52

func ReadRows(params []any) (id string, rows [][]string, more bool, dropped int, err error)

ReadRows reads host.rows as protocol 4 has it: the table's id, its next rows and whether more remain; dropped counts the malformed rows and cells (readRows).

func ReadSession added in v0.1.56

func ReadSession(params []any) (map[string]string, error)

ReadSession reads host.session: a fresh map, checked against the bounds. Its error never holds a value: a slot holds secrets.

func ReadTableEnd added in v0.1.52

func ReadTableEnd(params []any) (id, why string, err error)

ReadTableEnd reads host.table_end: the table's id, and why its rows ended ("" when no error).

func ReadTableGone added in v0.1.52

func ReadTableGone(params []any) (string, error)

ReadTableGone reads plugin.table.close: the table's id.

func ReadTitle

func ReadTitle(params []any) (string, error)

ReadTitle reads host.title.

func ReadyParams

func ReadyParams(protocol int) []any

ReadyParams are host.ready's.

func ResizeParams

func ResizeParams(w, h int) []any

ResizeParams are plugin.resize's.

func ResultParams added in v0.1.40

func ResultParams(r Result) []any

ResultParams are plugin.result's; error only when it did not run.

func RowsKindsParams added in v0.1.54

func RowsKindsParams(id string, rows [][]string, kinds []string, more bool) []any

RowsKindsParams are host.rows' with each row's kinds (protocol 5); nil kinds sends none.

func RowsParams added in v0.1.52

func RowsParams(id string, rows [][]string, more bool) []any

RowsParams are host.rows'.

func Serve

func Serve(ctx context.Context, h Handler) error

Serve speaks the protocol on the plugin's stdin and stdout until the dialog closes, the host goes or ctx ends. It returns nil when the host closed the dialog. stdout is the protocol's: after Serve starts, os.Stdout is os.Stderr, which the host keeps in the plugin's log.

func ServeConn

func ServeConn(ctx context.Context, conn net.Conn, h Handler) error

ServeConn is Serve over conn: a test's pipes, say.

func SessionParams added in v0.1.56

func SessionParams(values map[string]string) []any

SessionParams are host.session's.

func SurfaceParams added in v0.2.5

func SurfaceParams(s SurfaceInfo) []any

SurfaceParams are plugin.surface's.

func SurfacePointerParams added in v0.2.5

func SurfacePointerParams(p SurfacePointer) []any

SurfacePointerParams are plugin.surface.pointer's.

func TableEndParams added in v0.1.52

func TableEndParams(id, why string) []any

TableEndParams are host.table_end's; error only when there is one.

func TableGoneParams added in v0.1.52

func TableGoneParams(id string) []any

TableGoneParams are plugin.table.close's.

func TableParams added in v0.1.52

func TableParams(t TableOpen) []any

TableParams are host.table's; kinds only when t has them.

func ThemeParams

func ThemeParams(t Theme) []any

ThemeParams are plugin.theme's.

func TitleParams

func TitleParams(title string) []any

TitleParams are host.title's.

func WireOp added in v0.2.5

func WireOp(m map[string]any) string

WireOp is a message's op.

func WithArgs added in v0.1.56

func WithArgs(params []any, args []string) []any

WithArgs is plugin.command's params, built by CommandParams or FitCommand, with args added (protocol 7); params as they are when there are none.

Types

type Base added in v0.1.21

type Base struct{}

Base is a Handler that does nothing: a service plugin, which has no dialog, embeds it and adds the optional interfaces it needs.

func (Base) Close added in v0.1.21

func (Base) Close()

func (Base) Key added in v0.1.21

func (Base) Key(Key)

func (Base) Open added in v0.1.21

func (Base) Open(*Peer, Open)

func (Base) Resize added in v0.1.21

func (Base) Resize(int, int)

func (Base) Theme added in v0.1.21

func (Base) Theme(Theme)

type Call added in v0.1.40

type Call struct {
	Num  int64
	ID   string
	Args []string
}

Call is host.call: its number, the command's id and its arguments.

func ReadCall added in v0.1.40

func ReadCall(params []any) (Call, error)

ReadCall reads host.call. Its Num is set whenever the call number is readable, even when the rest is not, so a host can answer a malformed call by its number.

type CallError added in v0.1.40

type CallError struct{ Code, Message string }

CallError is a call the host did not run, or whose command failed: its code (CallRefused, CallUnknown, CallFailed) and why.

func (*CallError) Error added in v0.1.40

func (e *CallError) Error() string

type Caret added in v0.2.5

type Caret struct{ X, Y, W, H, Baseline float32 }

Caret is the surface's text caret in dp, frame-local, with its baseline; the zero Caret is none.

func ReadCaret added in v0.2.5

func ReadCaret(params []any) (c Caret, ok bool, err error)

ReadCaret reads host.surface.caret: ok false for {}, no caret.

type CommandArgser added in v0.1.56

type CommandArgser interface {
	CommandArgs(id string, args []string)
}

CommandArgser takes a [[commands]] id with its arguments (protocol 7): `:autodb query …` from the plugin's Lua package. A Handler that is not one is handed Command(id), the arguments dropped.

type Commander added in v0.1.21

type Commander interface{ Command(id string) }

Commander takes the manifest's [[commands]], by id.

type Document added in v0.1.21

type Document struct {
	// Path is the note's path in its workspace, a slash path under Root; the absolute path of a
	// file outside every workspace, whose Workspace and Root are ""; "" for a draft
	Path, Workspace string
	// Root is the workspace's folder on this machine, absolute: what a plugin reading or writing
	// beside the note joins Path to (File). "" outside every workspace, and from a host that does
	// not send it (one before ADR 1792457255's lab files).
	Root      string
	Text      string
	Cursor    Position
	Selection []Range
	Version   int
	TooLarge  bool
	// CursorByte and SelectionBytes are Cursor and Selection as byte offsets into Text, each
	// selection range [start, end): the host counts them from the same grapheme clusters as the
	// columns, so a plugin slicing Text never counts clusters itself. Sent from protocol 4 on;
	// before it they are 0 and nil.
	CursorByte     int
	SelectionBytes [][2]int
}

Document is plugin.document: the note open in the editor, as it stands, saved or not. Path is "" when none is open. TooLarge says the note was too large to send: Path, Workspace, Root and Version are set, and the rest is empty. Version rises with every edit, so a plugin can drop a stale answer.

func FitDocument added in v0.1.21

func FitDocument(d Document) Document

FitDocument is d as it can be sent to a plugin speaking protocol 2 or 3 (FitDocumentAt).

func FitDocumentAt added in v0.1.52

func FitDocumentAt(protocol int, d Document) Document

FitDocumentAt is d as it can be sent to a plugin speaking protocol: d itself when its plugin.document, in that protocol's form, encodes to at most MaxDocumentBytes, else its too-large form, which keeps its path, workspace and version alone.

func ReadCommandDocument added in v0.1.52

func ReadCommandDocument(params []any) (Document, bool)

ReadCommandDocument reads the document a protocol-4 plugin.command carries; false when it carries none (an earlier protocol's, or a plugin without the feed) or the one it carries is malformed.

func ReadDocument added in v0.1.21

func ReadDocument(params []any) (Document, error)

ReadDocument reads plugin.document. A selection entry that is not a map is dropped, and so is a byte range that is not two offsets.

func (Document) File added in v0.2.1

func (d Document) File() string

File is the note's file on this machine: Root joined with Path, or Path when it is absolute (a file outside every workspace); "" for a draft, and for a workspace's note whose Root was not sent.

type DocumentReader added in v0.1.21

type DocumentReader interface{ Document(d Document) }

DocumentReader takes the feed ([feed] document = true): the open note, after each pause in editing. Only the latest waits for it: a newer document replaces one not yet handled. From protocol 4 a command carries the note as it stood when it was chosen, and the reader is handed that one first, just before the command runs.

type FDGuard added in v0.2.5

type FDGuard struct {
	// contains filtered or unexported fields
}

FDGuard owns a received message's fds until Take transfers each: CloseAll closes the rest.

func (*FDGuard) CloseAll added in v0.2.5

func (g *FDGuard) CloseAll() *FDGuard

CloseAll closes every fd not taken. Safe to call more than once.

func (*FDGuard) Len added in v0.2.5

func (g *FDGuard) Len() int

Len is how many fds came.

func (*FDGuard) Take added in v0.2.5

func (g *FDGuard) Take(i int) int

Take transfers fd i to the caller; -1 when there is none, or it was taken.

type Focuser added in v0.1.21

type Focuser interface{ Focus(focused bool) }

Focuser is a non-modal card told it took the keys (true) or gave them back (false).

type Frame

type Frame struct {
	// contains filtered or unexported fields
}

Frame is a plugin's dialog as a grid of cells, drawn and then sent whole (Peer.Frame). A cell holds one character as the screen shows it: a grapheme cluster ("é" written as e and a combining accent, a ZWJ emoji, a flag), measured as AutoDoc's screen measures it (golib's tui.StringWidth). A wide character (CJK, most emoji) takes two cells; the second is its continuation, which Rows leaves out, since the host's own measure gives the column back.

func NewFrame

func NewFrame(w, h int) *Frame

NewFrame is a blank frame w cells wide and h high.

func (*Frame) Clear

func (f *Frame) Clear(st Style)

Clear fills the frame with spaces in st.

func (*Frame) Fill

func (f *Frame) Fill(x, y, w, h int, r rune, st Style)

Fill sets every cell of the rectangle at (x, y), w wide and h high, to r in st, as Set does.

func (*Frame) Rows

func (f *Frame) Rows() []Row

Rows are the frame as host.frame sends it: each row's cells, run together where the style is the same, continuations left out. The host segments each run's text into grapheme clusters again, so two cells whose text would join into one cluster (two regional indicators written apart, a character and a variation selector written after it) are sent in runs of their own: the host never joins clusters across runs, and each keeps the column it was given.

func (*Frame) Set

func (f *Frame) Set(x, y int, r rune, st Style)

Set puts r at (x, y) in st, in that one cell: a wide r, which needs two, is a space. Outside the frame it does nothing.

func (*Frame) Size

func (f *Frame) Size() (w, h int)

Size is the frame's width and height.

func (*Frame) Text

func (f *Frame) Text(x, y int, s string, st Style) int

Text writes s from (x, y) rightwards in st, a grapheme cluster at a time, each taking its width: two cells for a wide one. A zero-width cluster (a combining mark on its own) joins the cell before it. A wide cluster that would cross the right edge is a space. Writing over half of a wide cell blanks its other half. It returns the x after the last cluster, past the edge if s runs over it.

type Handler

type Handler interface {
	// Open is the dialog opened: its size inside the border, and the theme. p sends frames.
	Open(p *Peer, o Open)
	// Key is a key typed into the dialog.
	Key(k Key)
	// Resize is the dialog's new size.
	Resize(w, h int)
	// Theme is the theme changed.
	Theme(t Theme)
	// Close is the dialog closing, or the host gone: save what is kept, stop, and return. The host
	// waits two seconds before it stops the process. It is called once, and only after Open.
	Close()
}

Handler is a dialog plugin. Serve calls its methods one at a time, in the order the host sent them, on one goroutine of its own. A plugin with a clock of its own (a game's gravity) runs it on another goroutine and sends through the Peer, which is safe for concurrent use. A method may Peer.Call: the host's answer never waits behind it.

type Hider added in v0.1.2

type Hider interface {
	Hide()
	Show()
}

Hider is a Handler that wants to know its dialog was hidden (Esc, when its manifest says esc = "hide"; a card's panel closed) and shown again: a game pauses. A Handler that is not one keeps running, unseen.

type Key

type Key struct {
	Key, Text        string
	Ctrl, Alt, Shift bool
}

Key is a key typed into the dialog. Key is its text for a printable key (" " for Space), or one of Up, Down, Left, Right, Enter, Tab, Backspace, Delete, Insert, Home, End, PageUp, PageDown, F1 to F12. Esc is never sent: it closes the dialog.

func ReadKey

func ReadKey(params []any) (Key, error)

ReadKey reads plugin.key.

type Link struct {
	// contains filtered or unexported fields
}

Link is one end of the protocol: notifications both ways over conn, the host's or the plugin's. Incoming ones are passed to on, one at a time in arrival order, from a goroutine of the link's. A burst larger than the link's queue (a paste of keys, say) waits for on to take them rather than failing the link, so on must not wait on the link itself: it never Calls, as the protocol has only notifications (host.call and plugin.result included), and it should hand each one on quickly, as the peer's writes slow to its pace. Notify is safe from any goroutine.

func NewLink(ctx context.Context, conn net.Conn, on func(method string, params []any)) (*Link, error)

NewLink starts the link over conn. It owns conn from here: Close closes it.

func (*Link) Close

func (l *Link) Close() error

Close ends the link and closes its connection.

func (*Link) Done

func (l *Link) Done() <-chan struct{}

Done is closed when the link ends: closed, or its peer gone.

func (*Link) Err

func (l *Link) Err() error

Err is why the link ended, once Done is closed.

func (*Link) Notify

func (l *Link) Notify(ctx context.Context, method string, params []any) error

Notify sends one notification.

type MenuUpdate struct {
	ID      string
	Title   *string
	Enabled *bool
}

MenuUpdate is host.menu's: a row's id, and its new title or enabled, each nil to leave as it is.

func ReadMenu added in v0.3.1

func ReadMenu(params []any) (MenuUpdate, error)

ReadMenu reads host.menu: each field of its type (an id string; a title string, or none; an enabled bool, or none), then CheckMenu.

type Notice added in v0.1.59

type Notice struct {
	Message string
	ID      string
	Ongoing bool
}

Notice is host.notify's.

func ReadNotice added in v0.1.59

func ReadNotice(params []any) (Notice, error)

ReadNotice reads host.notify: each field of its type (a message string; an id string, or none; an ongoing bool, or none), then CheckNotice. Its error names the rule broken, never the message.

type Open

type Open struct {
	Protocol      int
	Width, Height int
	Theme         Theme
	// Session is the slot as this plugin left it in this run of AutoDoc (protocol 7, session.go);
	// nil when it has none.
	Session map[string]string
}

Open is plugin.open: the protocol the host speaks, the dialog's size inside its border, and the theme. A service has no dialog: its size is 0 by 0.

func ReadOpen

func ReadOpen(params []any) (Open, error)

ReadOpen reads plugin.open. A service's has no size: both width and height are left out, and read as 0.

type Paster added in v0.2.5

type Paster interface{ Paste(text string) }

Paster takes the user's paste chord on a focused surface (protocol 10).

type Peer

type Peer struct {
	// contains filtered or unexported fields
}

Peer is the host, as a plugin sends to it.

func (*Peer) Call added in v0.1.40

func (p *Peer) Call(id string, args ...string) (bool, error)

Call asks the host to run a command of AutoDoc's catalog by its id, with args (protocol 3): one of the ids the manifest's calls = [...] declares. It waits for the host's answer, at most CallTimeout, and returns true, or false and why: a *CallError (refused, unknown, failed), or ErrCallTimeout, ErrClosed or ErrNoCalls. Each call has a number of its own, never one still waiting. It is safe from any goroutine, the Handler's own methods included: the answer is taken off the link as it arrives, never queued behind the method that waits for it.

func (*Peer) Close

func (p *Peer) Close() error

Close asks the host to close the dialog: it answers with plugin.close, and Handler.Close follows. A card's panel closes instead, and the plugin runs on: the host answers with plugin.hide.

func (*Peer) CloseReason added in v0.1.56

func (p *Peer) CloseReason() string

CloseReason is why the host is closing the plugin (protocol 7: CloseQuit, CloseOff, …), for Close to read; "" before protocol 7, or when the host closed it without a plugin.close.

func (*Peer) Frame

func (p *Peer) Frame(f *Frame) error

Frame sends f, the whole dialog.

func (*Peer) MenuRow added in v0.3.1

func (p *Peer) MenuRow(id string, title *string, enabled *bool) error

MenuRow (protocol 11) sets one of the plugin's [[menu]] rows, by its command's id: its title, or whether it's enabled, each nil to leave as it is, from the next time the editor's menu opens. As Notify, the negotiated protocol is checked first, then the update.

func (*Peer) Notify added in v0.1.59

func (p *Peer) Notify(n Notice) error

Notify posts n (protocol 8): a toast kept in the history, or with an id one updated in place while Ongoing and ended by a post without it (notify.go). As SetSession, the negotiated protocol is checked first, then n; a nil error means it was sent: the host drops a notice from a run that is stopping, and an ongoing one past MaxActiveNotices.

func (*Peer) Rows added in v0.1.52

func (p *Peer) Rows(id string, rows [][]string, more bool) error

Rows sends the next rows of table id, answering a FetchRows; more says rows remain.

func (*Peer) RowsKinds added in v0.1.54

func (p *Peer) RowsKinds(id string, rows [][]string, kinds []string, more bool) error

RowsKinds is Rows with each row's kinds (protocol 5; see TableOpen.Kinds): kinds[i] is rows[i]'s, one byte per field. Below protocol 5 the rows go without them.

func (*Peer) SetCaret added in v0.2.5

func (p *Peer) SetCaret(c Caret) error

SetCaret tells the host where the surface's text caret is, in frame-local dp, for its IME: it draws the preedit there and places the candidate window by it. The zero Caret is none.

func (*Peer) SetPointerShape added in v0.2.5

func (p *Peer) SetPointerShape(shape string) error

SetPointerShape asks for the pointer's shape over the surface: "default", "text", "hand", "crosshair", "move", "resize-ew", "resize-ns" or "not-allowed".

func (*Peer) SetSession added in v0.1.56

func (p *Peer) SetSession(values map[string]string) error

SetSession replaces this plugin's session slot (protocol 7). The host keeps it in memory, never on disk, until AutoDoc quits; Open.Session is it at the plugin's next start in this run of AutoDoc. A nil error means it was sent, not that the host kept it: the host drops a slot over the bounds, and one sent after the plugin began to stop, so a plugin sets its slot when it signs in, never in Close.

func (*Peer) Table added in v0.1.52

func (p *Peer) Table(t TableOpen) error

Table shows t in AutoDoc's results panel (protocol 4; the manifest declares [table]), replacing the table shown. Give each table a new ID (a query run again is a new table): a fetch for the table shown may still be on its way, so the host refuses a table that reuses the shown table's ID, keeping the one shown. Rows are taken only as the answer to a FetchRows. Keep each message under the link's limit, MaxMessageBytes as EncodedSize measures it: size the rows by their encoded bytes, not their count alone.

t.Kinds go only to a host that opened the plugin at protocol 5 or later; below it the table is sent without them, every cell text, as that host would read it.

func (*Peer) TableEnd added in v0.1.52

func (p *Peer) TableEnd(id string, err error) error

TableEnd ends table id's rows early: no more will come, and err, when not nil, says why (a query that failed on its third page, say). It answers a FetchRows as Rows does.

func (*Peer) Title

func (p *Peer) Title(title string) error

Title sets the dialog's title.

func (*Peer) WriteClipboard added in v0.2.5

func (p *Peer) WriteClipboard(text string) error

WriteClipboard writes text to the clipboard. A plugin reads it only by the user's paste (Paster).

type Pointer added in v0.1.54

type Pointer struct {
	Kind, Button string // "press"/"left", or "wheel"/"up"/"down"
	X, Y, Count  int
}

Pointer is a view-local, zero-based left press or vertical wheel step. Count is capped by the host, and the plugin checks the coordinates against its most recently opened/resized frame.

func ReadPointer added in v0.1.54

func ReadPointer(params []any) (Pointer, error)

ReadPointer refuses malformed or unsupported pointer actions before they reach a plugin.

type PointerHandler added in v0.1.54

type PointerHandler interface{ Pointer(Pointer) }

PointerHandler takes view-local left presses and vertical wheel movement (protocol 6).

type Position added in v0.1.21

type Position struct{ Line, Col int }

Position is a place in a note: its line and column, both from 1. A column counts characters as the editor's cursor does: grapheme clusters (what shows as one character, "é" written as e and a combining accent, say), not bytes or code points.

type Range added in v0.1.21

type Range struct{ Start, End Position }

Range is a selection, from Start to End.

type Result added in v0.1.40

type Result struct {
	Num   int64
	OK    bool
	Error string
}

Result is plugin.result: the call it answers, and whether the command ran; Error is "<code> <message>" when it did not.

func ReadResult added in v0.1.40

func ReadResult(params []any) (Result, error)

ReadResult reads plugin.result.

type Row

type Row []Run

Row is a frame's row: its runs, left to right.

func ReadFrame

func ReadFrame(params []any) (rows []Row, dropped int, err error)

ReadFrame reads host.frame. Rows past MaxRows and runs past MaxRunsPerRow are clipped; a run that is not a map with a string "t" is dropped, and dropped counts them, so the host can say so.

type Run

type Run struct {
	Text string
	Style
}

Run is text in one style.

type Style

type Style struct {
	FG, BG                  string
	Bold, Italic, Underline bool
}

Style is how a run of a frame looks: its colours, in the themes' vocabulary ("" is "default"), and its attributes.

type Surface added in v0.2.5

type Surface struct {
	// contains filtered or unexported fields
}

Surface is a card's or dialog's pixel surface. Its methods are safe for concurrent use: a plugin renders on a goroutine of its own.

func (*Surface) Buffer added in v0.2.5

func (s *Surface) Buffer(ctx context.Context) (*SurfaceBuffer, error)

Buffer is a free buffer of the current generation, waiting for one; an error once ctx ends or the surface is gone.

func (*Surface) Close added in v0.2.5

func (s *Surface) Close()

Close ends the surface, once: no buffer is granted after it, the side channel shuts down, and every mapping is reclaimed, a buffer being drawn into at its Present. Serve calls it as it ends.

func (*Surface) Done added in v0.2.5

func (s *Surface) Done() <-chan SurfaceFrameDone

Done is each frame's outcome, as the host answers it. A plugin that doesn't read it loses the oldest beyond 64; the credits come through Buffer regardless.

Done is a bounded, lossy view of the outcomes, not the wire's exactly-once delivery: when the handler doesn't keep up, the oldest are dropped. Credits are never dropped: they come through Buffer.

func (*Surface) Info added in v0.2.5

func (s *Surface) Info() SurfaceInfo

Info is the surface's latest generation.

func (*Surface) Present added in v0.2.5

func (s *Surface) Present(b *SurfaceBuffer, dirty image.Rectangle, inputT int64) (uint64, error)

Present shows b. Its pixels must be complete: there is no fence. dirty, when not empty, is what changed since b's last frame; inputT is the T of the latest input it shows (for latency).

type SurfaceBuffer added in v0.2.5

type SurfaceBuffer struct {
	ID, Gen     int
	W, H, Pitch int
	Format      string
	Pix         []byte
	// contains filtered or unexported fields
}

SurfaceBuffer is one buffer to draw into: Pix is W×H pixels of Format, Pitch bytes a row.

func (*SurfaceBuffer) RGBA added in v0.2.5

func (b *SurfaceBuffer) RGBA() *image.RGBA

RGBA is the buffer as an image (RGBA8 buffers only).

type SurfaceBufferSpec added in v0.2.5

type SurfaceBufferSpec struct {
	ID, Gen      int
	Kind, Format string // "memory"; "rgba8" or "bgra8"
	W, H, Pitch  int
	Size         int // bytes of the shared object
}

SurfaceBufferSpec is one buffer of a pool: its id (lifetime-unique; the host's even, a plugin's odd), the generation it belongs to, and its layout in pixels.

func ReadBuffersMsg added in v0.2.5

func ReadBuffersMsg(m map[string]any, fds int) (gen int, specs []SurfaceBufferSpec, err error)

ReadBuffersMsg reads a buffers op, refusing more buffers than a pool holds or than fds came.

type SurfaceConn added in v0.2.5

type SurfaceConn struct {
	// contains filtered or unexported fields
}

SurfaceConn is one end of the side channel. Send and Recv may run on different goroutines; Close unblocks a Recv.

func NewSurfacePair added in v0.2.5

func NewSurfacePair() (*SurfaceConn, *os.File, error)

NewSurfacePair is the host's end and the file to hand the plugin as fd 3 (exec.Cmd.ExtraFiles). Both are close-on-exec; ExtraFiles clears it on the child's fd 3 alone.

func OpenPluginSurfaceConn added in v0.2.5

func OpenPluginSurfaceConn() (*SurfaceConn, bool, error)

OpenPluginSurfaceConn is the plugin's end, from SurfaceFDEnv: close-on-exec first, so a process the plugin starts does not inherit it by accident (hygiene, not a boundary). ok false: no side channel.

func (*SurfaceConn) Close added in v0.2.5

func (c *SurfaceConn) Close() error

Close shuts the socket down and closes it, once. A reader must be done with it first (Shutdown).

func (*SurfaceConn) Recv added in v0.2.5

func (c *SurfaceConn) Recv() (map[string]any, *FDGuard, error)

Recv reads one datagram: its map, and a guard owning the fds it carried. Any error has closed them all. A truncated datagram or control message, a record that isn't SCM_RIGHTS, too many fds, or a map that doesn't decode is ErrSurfaceWire: a violation.

func (*SurfaceConn) Send added in v0.2.5

func (c *SurfaceConn) Send(m map[string]any, fds ...int) error

Send writes m, with fds as SCM_RIGHTS. The fds stay the caller's.

func (*SurfaceConn) Shutdown added in v0.2.5

func (c *SurfaceConn) Shutdown()

Shutdown ends the socket's traffic, which wakes a Recv blocked on it, and keeps the fd: a reader that loops back into Recv finds it shut, never a reused fd number. Close it once the reader is done.

type SurfaceFrame added in v0.2.5

type SurfaceFrame struct {
	Seq    uint64
	Gen    int
	Buffer int
	Dirty  image.Rectangle
	InputT int64
}

SurfaceFrame is a frame: present buffer Buffer of generation Gen. Seq rises strictly. A frame of a generation the host has retired is answered "retired", not refused: it was in transit. Dirty, when not empty, is the part that changed since the buffer's last frame. InputT is the T of the latest input it shows.

func ReadFrameMsg added in v0.2.5

func ReadFrameMsg(m map[string]any) (SurfaceFrame, error)

ReadFrameMsg reads a frame op.

type SurfaceFrameDone added in v0.2.5

type SurfaceFrameDone struct {
	Seq     uint64
	Outcome string
	WhenNS  int64
	// InputT is the InputT the frame was presented with: the SDK's own, never on the wire.
	InputT int64
}

SurfaceFrameDone is a frame's outcome: "drawn", "superseded", "not_shown", "unsupported", "closed", or "retired" (its generation ended before it arrived). WhenNS is when it was drawn.

func ReadFrameDoneMsg added in v0.2.5

func ReadFrameDoneMsg(m map[string]any) (SurfaceFrameDone, error)

ReadFrameDoneMsg reads a frame.done op.

type SurfaceHandler added in v0.2.5

type SurfaceHandler interface {
	Surface(s *Surface, info SurfaceInfo)
	SurfacePointer(p SurfacePointer)
}

SurfaceHandler draws a pixel surface (protocol 10, [surface]): Surface is each generation of it (the first after Open; again at a resize, a scale or a caps change), and SurfacePointer the pointer on it in dp. Consecutive moves reach it coalesced to the latest, and consecutive scrolls summed. A host that draws no pixels never calls Surface: the plugin draws cells.

type SurfaceInfo added in v0.2.5

type SurfaceInfo struct {
	Gen   int
	W, H  float32
	Scale float32
	Kinds []SurfaceKind
}

SurfaceInfo is one generation of a surface: Gen matches the buffers the side channel brings for it. W and H are in dp; Scale is device pixels per dp, so a frame of W×Scale by H×Scale pixels is drawn one to one.

func ReadSurface added in v0.2.5

func ReadSurface(params []any) (SurfaceInfo, error)

ReadSurface reads plugin.surface.

func (SurfaceInfo) Pixels added in v0.2.5

func (s SurfaceInfo) Pixels() (w, h int)

Pixels is the surface's size in device pixels, rounded up.

type SurfaceKind added in v0.2.5

type SurfaceKind struct {
	Kind, Format string
	Modifier     uint64
	MaxW, MaxH   int
}

SurfaceKind is a frame kind the window draws: "memory" or "dmabuf", its format ("rgba8", "bgra8"), its DRM modifier, and its largest size in pixels.

type SurfacePointer added in v0.2.5

type SurfacePointer struct {
	Kind, Button            string
	X, Y, DX, DY            float32
	Count                   int
	Ctrl, Alt, Shift, Super bool
	T                       int64
}

SurfacePointer is the pointer on a surface. Kind is "move", "press", "release", "scroll" or "leave"; Button is "left", "middle" or "right" for a press or release. X and Y are frame-local dp, and may lie outside the surface while a button holds the pointer. DX and DY are a scroll's, in dp. T is when the host dispatched it (Unix nanoseconds), for latency.

func ReadSurfacePointer added in v0.2.5

func ReadSurfacePointer(params []any) (SurfacePointer, error)

ReadSurfacePointer refuses a pointer event of an unknown kind or button.

type TableFetch added in v0.1.52

type TableFetch struct {
	ID string
	N  int
}

TableFetch is plugin.table.fetch: up to N more rows of the table ID.

func ReadFetch added in v0.1.52

func ReadFetch(params []any) (TableFetch, error)

ReadFetch reads plugin.table.fetch.

type TableFetcher added in v0.1.52

type TableFetcher interface {
	FetchRows(f TableFetch)
	TableClosed(id string)
}

TableFetcher serves the rows of the tables it sends (protocol 4, [table]): FetchRows is the host asking for up to f.N more of table f.ID, answered with Peer.Rows (or Peer.TableEnd); the host asks again only after the answer. TableClosed is the table gone: its panel closed, or a newer table replaced it.

type TableOpen added in v0.1.52

type TableOpen struct {
	ID, Title string
	Fields    []string
	Rows      [][]string
	Kinds     []string
	More      bool
}

TableOpen is host.table: a table the host shows in its results panel, by the plugin's id for it. Fields are the columns' titles; each row has a cell per field (a shorter row's last cells are empty, a longer one's extra cells dropped). More says rows remain, for the host to fetch.

Kinds (protocol 5) are each row's cells' kinds: Kinds[i] is row i's, one byte per field (see KindText). nil sends none, and every cell is text. A table's kinds are decided by its host.table: one sent with kinds (an empty list when it has no rows yet) reads them on every later page, and one sent without them reads every cell as text.

func ReadTable added in v0.1.52

func ReadTable(params []any) (t TableOpen, dropped int, err error)

ReadTable reads host.table as protocol 4 has it, with no kinds; dropped counts its malformed rows and cells (readRows).

func ReadTableAt added in v0.1.54

func ReadTableAt(params []any, protocol int) (t TableOpen, dropped int, err error)

ReadTableAt reads host.table from a plugin speaking protocol: from 5, with its kinds, which must fit its rows and fields (CheckKinds) or the table is malformed. Below 5 a kinds field is not read.

type TableRows added in v0.1.54

type TableRows struct {
	ID    string
	Rows  [][]string
	Kinds []string
	More  bool
}

TableRows is host.rows as protocol 5 reads it: table ID's next rows, their kinds (nil: none sent), and whether more remain.

func ReadTableRows added in v0.1.54

func ReadTableRows(params []any, protocol int) (r TableRows, dropped int, err error)

ReadTableRows reads host.rows from a plugin speaking protocol: from 5, with its kinds, one string per row. Their length is checked against the table's fields by whoever knows them, the host (CheckKinds), since host.rows does not carry the fields. Below 5 a kinds field is not read.

type Theme

type Theme struct {
	Name   string
	Colors map[string]string
}

Theme is the theme the TUI wears: its name, and its colours by their dotted names ("app.window": "white", "document.cursor": "#ffaf00").

func ReadTheme

func ReadTheme(params []any) (Theme, error)

ReadTheme reads plugin.theme.

Directories

Path Synopsis
Package card is AutoDoc's native UI kit for dialog and card plugins (ADR 1792254331): a plugin describes what its card shows as a Page of blocks and controls, and a Card fits it to the size AutoDoc gives, draws it in the theme's colours, and handles the keys, the focus and the pointer.
Package card is AutoDoc's native UI kit for dialog and card plugins (ADR 1792254331): a plugin describes what its card shows as a Page of blocks and controls, and a Card fits it to the size AutoDoc gives, draws it in the theme's colours, and handles the keys, the focus and the pointer.
Package decl runs a golib QML program (tui/decl) as an AutoDoc card or dialog (ADR 1792254331 §4.7–4.10): the program runs inside the plugin on a backend of its own, and every frame it draws is sent to AutoDoc as host.frame.
Package decl runs a golib QML program (tui/decl) as an AutoDoc card or dialog (ADR 1792254331 §4.7–4.10): the program runs inside the plugin on a backend of its own, and every frame it draws is sent to AutoDoc as host.frame.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL