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

pane

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 13 Imported by: 1

Documentation

Overview

Package pane runs Bubble Tea models as Concord remote panes: the same model a plugin uses as a standalone terminal app is driven by viewers' keys and resized to their panes, and its View() becomes their frames.

host := pane.NewHost(func(v *pane.Viewer) tea.Model {
	return newBoardModel(v.DisplayName) // your normal Bubble Tea model
})
plugin.Run(ctx, cfg, host.Handler())

Each viewer gets their own model (their own cursor, menus, scroll). Shared state -- a game, a board -- lives outside the models; after changing it, call Host.Broadcast with a message the models react to, and every viewer of that channel is re-rendered. A model returning tea.Quit hands that viewer's keyboard back to Concord (the pane stays on screen).

Colors: render with lipgloss as usual. Frames are produced in true color and converted down to each viewer's terminal (Viewer.Profile), so a model never needs to know who's looking.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Fit

func Fit(view string, width, height int) string

Fit trims a rendered view to at most width columns and height lines (never pads), keeping escape codes intact.

func KeyMsg

KeyMsg rebuilds the tea.KeyMsg a viewer's keypress would have produced in a real terminal, from its KeyString ("a", "enter", "ctrl+c", "alt+left").

Types

type Host

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

Host drives one model per viewer across all of a plugin's pane channels. Its methods must be called from Handler callbacks (which run one at a time), not from other goroutines -- send those work via Conn instead, or wrap the call in the plugin's own event.

func NewHost

func NewHost(newModel NewModel) *Host

NewHost makes a Host that builds each viewer's model with newModel.

func (*Host) Broadcast

func (h *Host) Broadcast(channelID uuid.UUID, msg tea.Msg)

Broadcast delivers msg to the model of everyone viewing channelID -- e.g. "the board changed" after a move -- and re-renders each of them. Like Send, it's safe to call from inside a model's own Update: delivery then waits until that update is done.

func (*Host) Enter

func (h *Host) Enter(c *plugin.Conn, e wire.PluginPaneEnterPayload)

Enter starts a model for a viewer (or rebuilds it: Concord replays Enter for current viewers after a reconnect).

func (*Host) Handler

func (h *Host) Handler() plugin.Handler

Handler returns plugin callbacks for pane events. To handle other events too, set more fields on the returned Handler (or wrap these).

func (*Host) Input

func (h *Host) Input(c *plugin.Conn, e wire.PluginPaneInputPayload)

Input feeds one keypress to the viewer's model.

func (*Host) Leave

func (h *Host) Leave(_ *plugin.Conn, e wire.PluginPaneLeavePayload)

Leave drops the viewer's model.

func (*Host) Resize

func (h *Host) Resize(c *plugin.Conn, e wire.PluginPaneResizePayload)

Resize tells the viewer's model its new size (and theme).

func (*Host) Send

func (h *Host) Send(viewerID uuid.UUID, msg tea.Msg)

Send delivers msg to one viewer's model and re-renders them.

func (*Host) Viewer

func (h *Host) Viewer(id uuid.UUID) *Viewer

Viewer returns the viewer with id, or nil.

func (*Host) Viewers

func (h *Host) Viewers(channelID uuid.UUID) []*Viewer

Viewers returns everyone currently viewing channelID.

type Imager

type Imager interface {
	Images() []wire.PaneImage
}

Imager is implemented by a pane model that places images from the plugin's client/ folder in its frames. Images is called after View, with boxes in the same cells (0-based, inside the pane). Leave sensible text under each box: viewers who turned images off see that instead.

type KeyClaimer

type KeyClaimer interface {
	ClaimedKeys() []string
}

KeyClaimer is implemented by a pane model that sometimes needs Esc, Tab or Shift+Tab (wire.PaneKeyEsc...). Concord uses those keys to move between panels, so they reach a model only while it claims them: ClaimedKeys is asked after every update, and its answer goes out with the frame. Claim Esc while there's something to cancel (a selection, a menu, a prompt, help), Tab and Shift+Tab while a form's fields are open; claim nothing otherwise, so Esc leaves the pane and Tab moves on.

type NewModel

type NewModel func(v *Viewer) tea.Model

NewModel builds a model for a viewer who just opened a pane. It's sent a tea.WindowSizeMsg with the pane's size before its first render, and again whenever the pane is resized.

type Viewer

type Viewer struct {
	ID          uuid.UUID
	ChannelID   uuid.UUID
	Name        string // username
	DisplayName string // how they appear in the server (nickname, display name or username)
	Width       int
	Height      int
	Theme       *wire.PaneTheme // their Concord theme; may be nil
	Profile     colorprofile.Profile
	// contains filtered or unexported fields
}

Viewer is one person with a pane open.

func (*Viewer) Color

func (v *Viewer) Color(name string, fallback lipgloss.TerminalColor) lipgloss.TerminalColor

Color returns the viewer's Concord theme color by name ("red", "cyan", "foreground", ...) as a lipgloss color, or fallback when unknown -- so a pane can match whatever theme each viewer uses.

Jump to

Keyboard shortcuts

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