Documentation
¶
Index ¶
- Constants
- func MapControlKey(raw string, controlKeys map[string]string) (string, bool)
- func NewKey() (string, error)
- func RunWatch(interval time.Duration, alive func() map[string]string, ...)
- func SanitizeName(raw string) (string, error)
- func SendInput(t Target, mapper ControlMapper, target string, item Input) error
- func ValidateDimensions(cfg config.Config, rawCols, rawRows string) (int, int, error)
- func ValidateIdentifier(raw string) (string, error)
- func WatchOutput(tmuxName string, scan func(out []byte, marks []string)) (chan struct{}, error)
- type Attachment
- type ControlInput
- func (c ControlInput) PaneForeground(name string) (tmux.PaneForeground, error)
- func (c ControlInput) PasteLiteral(name, text string) error
- func (c ControlInput) SendKey(name, key string) error
- func (c ControlInput) SendLiteral(name, text string) error
- func (c ControlInput) SendRaw(name string, data []byte) error
- type ControlMapper
- type ForegroundReporter
- type Hub
- func (h *Hub) Attach(name, rawCols, rawRows string) (Attachment, error)
- func (h *Hub) Clear(name string)
- func (h *Hub) Control(name string) *tmux.Control
- func (h *Hub) Delta(name string, offset int64) ([]byte, int64, bool)
- func (h *Hub) Detach(name string)
- func (h *Hub) Exited(name string) bool
- func (h *Hub) Modes(name string) (tmux.PaneModes, bool)
- func (h *Hub) Refresh(name string, generation int64) (Attachment, bool)
- func (h *Hub) Resize(name string, cols, rows int) error
- func (h *Hub) Resnapshot(name string) (Attachment, bool)
- func (h *Hub) ResumeLive(name string)
- func (h *Hub) Scroll(name, action string) bool
- func (h *Hub) Updated(name string) (<-chan struct{}, bool)
- type Input
- type Target
Constants ¶
const BellCooldown = 2 * time.Second
BellCooldown coalesces bell bursts: one event rings one bell, but nothing guarantees a redraw does not repeat it right after.
Variables ¶
This section is empty.
Functions ¶
func RunWatch ¶
func RunWatch(interval time.Duration, alive func() map[string]string, start func(tmuxName, id string) (chan struct{}, error))
RunWatch reconciles a set of live tmux sessions with one watcher goroutine each: alive lists the current tmux session names mapped to their public identifiers, start spawns a watcher and returns its stop channel. Blocks; run it in a goroutine.
func SanitizeName ¶
SanitizeName converts a user-supplied display name into a tmux-safe slug.
func SendInput ¶
func SendInput(t Target, mapper ControlMapper, target string, item Input) error
SendInput dispatches one queued user action to a tmux target. Exactly one field of item is non-empty.
func ValidateDimensions ¶
func ValidateIdentifier ¶
ValidateIdentifier ensures raw matches the strict tmux-safe alphabet.
func WatchOutput ¶
WatchOutput attaches a read-only control-mode client to a tmux session and feeds every output chunk to scan: the OSC-filtered bytes plus the payloads of completed OSC sequences. It never resizes, so pane geometry stays untouched. The returned channel stops the watcher when closed.
Types ¶
type Attachment ¶
type Attachment struct {
Session string
Offset int64
Generation int64
Snapshot []byte
Cols int
Rows int
MouseTracking bool // program has mouse reporting on (wheel -> mouse events)
MouseSGR bool // program uses SGR mouse encoding (mode 1006)
AltScreen bool // alternate screen active (wheel -> cursor keys)
AppCursor bool // application cursor keys mode (DECCKM)
}
Attachment is one active browser stream against a tmux session.
type ControlInput ¶
type ControlInput struct {
Ctl *tmux.Control
CLI *tmux.Client
// Gone is returned when a send fails on an exited control client, so each
// caller reports its own flavor of "not running" to the browser.
Gone error
}
ControlInput routes keystrokes through a session's persistent control-mode connection (no fork per key) and falls back to the forking CLI for buffer pastes, which control mode can't express on a single command line. A send that fails after the control client has exited is reported as a gone session so the caller still answers 410 instead of a generic error.
func (ControlInput) PaneForeground ¶
func (c ControlInput) PaneForeground(name string) (tmux.PaneForeground, error)
func (ControlInput) PasteLiteral ¶
func (c ControlInput) PasteLiteral(name, text string) error
func (ControlInput) SendKey ¶
func (c ControlInput) SendKey(name, key string) error
func (ControlInput) SendLiteral ¶
func (c ControlInput) SendLiteral(name, text string) error
type ControlMapper ¶
ControlMapper translates UI control IDs to tmux key names.
func DefaultControlMapper ¶
func DefaultControlMapper() ControlMapper
type ForegroundReporter ¶
type ForegroundReporter interface {
PaneForeground(name string) (tmux.PaneForeground, error)
}
ForegroundReporter is the optional Target capability behind Shift+Enter: both transports report the pane's foreground process, the fork-free control connection and the CLI fallback.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub tracks the active browser streams per tmux session and owns the control-mode client backing each one. All state is guarded by mu.
func (*Hub) Attach ¶
func (h *Hub) Attach(name, rawCols, rawRows string) (Attachment, error)
attach opens (or reuses) the control client and returns a fresh snapshot together with the stream offset that immediately follows it.
func (*Hub) Clear ¶
clear drops the stream state and closes the control client (the session is gone).
func (*Hub) Control ¶
control returns the live control client backing a stream, or nil when no browser is attached (or it has exited). Input uses it to send keystrokes over the persistent connection instead of forking the tmux CLI per key.
func (*Hub) Delta ¶
delta returns the buffered bytes after offset. reset is true when the caller must re-snapshot because offset fell out of the ring.
func (*Hub) Detach ¶
detach releases one browser stream and closes the control client after the last one.
func (*Hub) Modes ¶
Modes reads the pane's current terminal modes. A program switches into its full screen UI while somebody is already watching, and the browser has no way to see that in the stream: what it receives is rendered content, not the mode sequences. Without this, a page attached before the switch keeps scrolling like a normal screen, which for a coder means not at all.
func (*Hub) Refresh ¶
func (h *Hub) Refresh(name string, generation int64) (Attachment, bool)
refresh returns a new snapshot when another browser reset this stream.
func (*Hub) Resize ¶
resize drives the rendered size of an actively streamed session and republishes a fresh snapshot at that size. The republish matters twice: the cached size feeds the terminal-size event of every later resync (a stale cache would shrink the browser back), and programs that do not repaint on SIGWINCH (a plain shell prompt) would otherwise leave the old, smaller frame on screen until some other resync happens. Same settle-then-capture dance as Attach: TUIs repaint in bursts, a silent shell just lets the wait run out.
func (*Hub) Resnapshot ¶
func (h *Hub) Resnapshot(name string) (Attachment, bool)
resnapshot recaptures the screen when a browser has fallen out of the delta ring. It bumps the generation so other streams realign too.
func (*Hub) ResumeLive ¶
resumeLive returns a frozen history view to the live bottom. It is a no-op when the stream is already live, so it is cheap to call before every keystroke.
type Target ¶
type Target interface {
SendRaw(name string, data []byte) error
SendKey(name, key string) error
SendLiteral(name, text string) error
PasteLiteral(name, text string) error
}
Target is the minimal tmux input surface SendInput needs. Both the forking CLI client (*tmux.Client) and the persistent control client satisfy it, so input can take the fork-free path when a stream is attached.