Documentation
¶
Overview ¶
Package ctlparse classifies and decodes the lines of a tmux control-mode stream.
It deals in neutral structs rather than the library's public event types. That keeps the whole of the wire format testable from a table of raw lines, and avoids the import cycle that would otherwise exist between the parser and the package that defines the events.
Classification here is of one line in isolation, which is all this package sees. It is not on its own enough to dispatch on, and a reader that treats it as if it were has a hole in it: a command's output block is contiguous, so a line inside one is that command's output even when it is shaped like a notification, and capture-pane will happily print such a line. The block state that resolves it lives in the reader — see ControlClient.handleLine — and scripts/probe-interleave.sh is what says tmux never writes a notification into an open block, which is what makes that resolution correct rather than merely convenient.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsKnownNotification ¶
IsKnownNotification reports whether name, given without its '%', is a notification this package recognises.
func ParseIDAndName ¶
ParseIDAndName decodes notifications shaped "<id> <name...>", such as %window-renamed and %session-changed. The name is everything after the first space and may itself contain spaces.
func ParseTwoIDs ¶
ParseTwoIDs decodes notifications shaped "<id> <id>", such as %window-pane-changed.
Types ¶
type Kind ¶
type Kind int
Kind is what a control-mode line turned out to be.
const ( // KindData is a line that is not a control line. Inside a command block // it is one line of that command's output; outside one it is unexpected. // // A data line may begin with '%': "list-panes -F '#{pane_id}'" prints // "%0". Classification is therefore by the whole first token against the // set of known notification names, never by the '%' alone. KindData Kind = iota // KindBegin opens a command's output block. KindBegin // KindEnd closes a command's output block successfully. KindEnd // KindError closes a command's output block with a failure; the block // body is the error message. KindError // KindNotification is an asynchronous notification. KindNotification )
type Layout ¶
type Layout struct {
Window string
// Layout is the window's layout string.
Layout string
// Visible is the visible layout, present since tmux 2.x. Empty if absent.
Visible string
// Flags is the window flags field. Empty if absent.
Flags string
}
Layout is a decoded %layout-change notification.
func ParseLayoutChange ¶
ParseLayoutChange decodes "%layout-change @window layout [visible] [flags]".
type Line ¶
type Line struct {
Kind Kind
// Raw is the line as received, without its trailing newline.
Raw string
// Time, Number and Flags are the three arguments of %begin, %end and
// %error: epoch seconds, the command number, and a flags word.
//
// Number identifies the block: a %begin and the %end or %error that
// closes it carry the same one. It is not a key a client can predict —
// numbers neither start at zero nor run contiguously.
//
// Flags is 1 for a block that answers a command the control client sent
// and 0 for one tmux opened by itself, which is what makes an unsolicited
// block recognisable. In tmux's cmd-queue.c the field is
// !!(state->flags & CMDQ_STATE_CONTROL), and control.c sets that bit only
// for a line read from the control client's own input.
Time int64
Number int
Flags int
// HasFlags reports that the line carried a flags field at all. A tmux
// that stopped writing one would otherwise be indistinguishable from one
// writing zero, and zero is load-bearing.
HasFlags bool
// Name is a notification's name without its leading '%', for instance
// "output" or "window-add".
Name string
// Args is everything after the notification name, with one separating
// space removed.
Args string
// Malformed reports a line that looked like a control line but whose
// arguments did not parse. The line is still returned so a caller can
// surface it rather than silently dropping it.
Malformed bool
}
Line is one classified control-mode line.
type Output ¶
type Output struct {
Pane string
Data string
// Extended reports that this came from %extended-output, which replaces
// %output when flow control is enabled.
Extended bool
// AgeMS is how many milliseconds behind the data is. It is meaningful
// only when Extended is set.
AgeMS int64
}
Output is a decoded %output notification. Data is still escaped; the caller unescapes it, so that this package stays free of policy about allocation.
func ParseExtendedOutput ¶
ParseExtendedOutput decodes the arguments of %extended-output.
The documented shape is "%pane age ... : data": a pane id, a millisecond age, zero or more further fields reserved by tmux, then a lone colon and the escaped data. Parsing keys off the " : " separator rather than a fixed field count so that fields added later do not break it.
func ParseOutput ¶
ParseOutput decodes the arguments of %output: a pane id and the escaped data, separated by one space.
type Subscription ¶
type Subscription struct {
Name string
// Session, Window and Pane are whichever identifiers tmux included; each
// is empty when absent.
Session, Window, Pane string
// WindowIndex is the bare integer field tmux includes for window
// subscriptions, or -1 when absent.
WindowIndex int
// Value is the expanded format.
Value string
}
Subscription is a decoded %subscription-changed notification.
func ParseSubscriptionChanged ¶
func ParseSubscriptionChanged(args string) (Subscription, bool)
ParseSubscriptionChanged decodes %subscription-changed.
The shape is "<name> <ids...> : <value>". The identifier fields vary with the subscription's target, so they are matched by sigil rather than by position, and anything unrecognised is ignored rather than fatal.