ctlparse

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 2 Imported by: 0

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

func IsKnownNotification(name string) bool

IsKnownNotification reports whether name, given without its '%', is a notification this package recognises.

func ParseIDAndName

func ParseIDAndName(args string) (id, name string, ok bool)

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

func ParseTwoIDs(args string) (first, second string, ok bool)

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
)

func (Kind) String

func (k Kind) String() string

String names the kind for diagnostics.

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

func ParseLayoutChange(args string) (Layout, bool)

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.

func Classify

func Classify(line string) Line

Classify decides what a single control-mode line is.

The line must already have had its trailing newline removed.

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

func ParseExtendedOutput(args string) (Output, bool)

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

func ParseOutput(args string) (Output, bool)

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.

Jump to

Keyboard shortcuts

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