tui

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: Apache-2.0 Imports: 31 Imported by: 0

Documentation

Overview

Package tui is a placeholder for a future Bubble Tea TUI.

Index

Constants

View Source
const (
	TabIndexSerial = 0
	TabIndexTCP    = 1
	TabIndexSCPI   = 2
	TabCount       = 3
)

Tab indices

View Source
const (
	SerialFieldPort  = 0
	SerialFieldBaud  = 1
	SerialFieldCount = 2
)

Field indices for Serial tab

View Source
const (
	TCPFieldHost  = 0
	TCPFieldPort  = 1
	TCPFieldCount = 2
)

Field indices for TCP tab

View Source
const (
	SCPIFieldAddress = 0
	SCPIFieldCount   = 1
)

Field indices for SCPI/VISA tab

View Source
const (
	ButtonIndexConfirm = 0
	ButtonIndexReset   = 1
)

Button indices

View Source
const (
	FocusModeTabs     = "tabs"
	FocusModeFields   = "fields"
	FocusModeButtons  = "buttons"
	FocusModeAdvanced = "advanced"
	FocusModeInfo     = "info"
)

Focus modes

View Source
const (
	SourceTypeSerial = "serial"
	SourceTypeTCP    = "tcp"
	SourceTypeSCPI   = "scpi"
)

Source type identifiers

View Source
const (
	HelpSeparator     = "•"
	HelpEnterEditMode = " (Enter to edit)"
	HelpArrowsChange  = " ←/→"
	WarnNoPortsFound  = "No ports found"
	PlaceholderNotSet = "(not set)"
)

UI text constants TODO: Centralize all Help Warn and Placholder strings for app-wide consistency

View Source
const (
	LabelWidth    = 14
	CursorPadding = "  "
)

Field formatting

View Source
const (
	// SpotlightMinIntensity is the minimum brightness for faded lines
	SpotlightMinIntensity = 0.3
	// SpotlightFocusRadius controls how wide the bright area is
	SpotlightFocusRadius = 0.4
	// ANSIEscapePrefix is the start of ANSI escape sequences
	ANSIEscapePrefix = "\x1b["
)
View Source
const (
	IconStatusInfo    = " " // nf-fa-info_circle
	IconStatusSuccess = " " // nf-fa-check
	IconStatusWarning = " " // nf-fa-exclamation_triangle
	IconStatusError   = " " // nf-fa-times

	IconMenuCapture    = " " // nf-fa-bar_chart
	IconMenuTCP        = "󰛶 " // nf-md-ethernet
	IconMenuListPorts  = " " // nf-fa-usb
	IconMenuMetadata   = " " // nf-fa-id_badge
	IconMenuViewRuns   = " " // nf-fa-database
	IconMenuUpload     = " " // nf-fa-upload
	IconMenuConfig     = " " // nf-fa-cog
	IconMenuConnection = "󱘖 " // nf-md-connection
	IconMenuNewFile    = " " // nf-fa-file_text
	IconSelectedItem   = "❯ "
	IconMenuSeparator  = "\ue621" // nf-indentation line

	IconTitlePorts = IconMenuListPorts
)

Icon Palette - Nerd Font glyphs Update these values as needed

View Source
const (
	// Status indicators
	IconAlchemyComplete = "🜏 "
	IconAlchemyUpload   = "🜍 "
	IconAlchemySuccess  = ""
	IconAlchemyWarning  = "⌽ "
	IconAlchemyError    = "⊗ "
	IconAlchemySettings = "⚖ "

	// Operational states
	IconAlchemyActive     = "🜃 " // Fire - operations in progress
	IconAlchemyProcess    = "⚗ " // Alembic - data transformation
	IconAlchemyCached     = "🜄 " // Earth - stored locally
	IconAlchemyStreaming  = "🜂 " // Water - live data flow
	IconAlchemyInfo       = "🜔 " // Quintessence - information/knowledge
	IconAlchemyDownload   = "🝱 " // Precipitate - download operations
	IconAlchemyConnected  = "🜁 " // Air - connection active
	IconAlchemyValidation = "🜨 " // Retort - validation/verification
)
View Source
const MaxBufferedLines = 1000

MaxBufferedLines defines the maximum number of lines to keep in the buffer

Variables

View Source
var (
	ColorPrimary   = lipgloss.Color("#c6a664") // Celestial Gold - main highlights, cursor
	ColorSecondary = lipgloss.Color("#7fa4b5") // Starlight - headers, info
	ColorSuccess   = lipgloss.Color("#5e8570") // Verdigris - selected items, success states
	ColorWarning   = lipgloss.Color("#d4a843") // Bright gold - warnings, active states
	ColorError     = lipgloss.Color("#c4523f") // Rust-red - errors
	ColorMuted     = lipgloss.Color("#5a5040") // Warm gray - unselected, help text
	ColorText      = lipgloss.Color("#f0e6d3") // Parchment - normal text
	ColorHighlight = lipgloss.Color("#1f160a") // Obsidian-brown - highlight background
)

Color Palette - centralized color definitions

View Source
var (
	// Text styles
	StyleBold = lipgloss.NewStyle().
				Bold(true)

	StyleItalic = lipgloss.NewStyle().
				Italic(true)

	StyleDim = lipgloss.NewStyle().
				Faint(true)

	StyleSelected = lipgloss.NewStyle().Bold(true).Italic(true).Foreground(ColorWarning).Background(ColorHighlight)

	// Component styles
	StyleBorder = lipgloss.NewStyle().
				Border(lipgloss.RoundedBorder()).
				Padding(0, 1)

	StyleTitle = lipgloss.NewStyle().
				Foreground(ColorPrimary).
				Bold(true).
				MarginTop(marginSize).
				MarginBottom(marginSize)

	StyleHeader = lipgloss.NewStyle().
				Foreground(ColorSecondary).
				Bold(true).
				MarginTop(marginSize)

	StyleSubheader = lipgloss.NewStyle().
					Foreground(ColorText).
					Bold(true)

	// Interactive element styles
	StyleCursor = lipgloss.NewStyle().
				Foreground(ColorPrimary).
				Bold(true)

	StyleUnselected = lipgloss.NewStyle().
					Foreground(ColorMuted).
					PaddingLeft(marginSize)

	StyleHighlight = lipgloss.NewStyle().
					Foreground(ColorWarning).
					Bold(true)

	// Status styles
	StyleSuccess = lipgloss.NewStyle().
					Foreground(ColorSuccess).
					Bold(true)

	StyleError = lipgloss.NewStyle().
				Foreground(ColorError).
				Bold(true).
				MarginTop(marginSize)

	StyleWarning = lipgloss.NewStyle().
					Foreground(ColorWarning).
					Bold(true)

	StyleMuted = lipgloss.NewStyle().
				Foreground(ColorMuted)

	StyleMenuItem = lipgloss.NewStyle().
					Foreground(ColorText).
					Padding(0, 2).
					Width(menuWidth)

	StyleMenuSelected = lipgloss.NewStyle().
						Background(ColorHighlight).
						Foreground(ColorWarning).
						Bold(true).
						Width(menuWidth)

	StyleHelp = lipgloss.NewStyle().
				Foreground(ColorMuted).
				MarginTop(marginSize).
				Italic(true)
	// Key-value display
	StyleKey = lipgloss.NewStyle().
				Foreground(ColorMuted)

	StyleValue = lipgloss.NewStyle().
				Foreground(ColorPrimary).
				Bold(true)

	// Icon styles
	StyleIcon = lipgloss.NewStyle().
				Foreground(ColorPrimary).
				Bold(true)
)

Common Styles - reusable across all TUI components

View Source
var (
	ProgressGradientStart   = lipgloss.Color("#c6a664") // Celestial Gold
	ProgressGradientEnd     = lipgloss.Color("#5e8570") // Verdigris
	DefaultProgressGradient = progress.WithGradient(string(ProgressGradientStart), string(ProgressGradientEnd))
)

Progress bar configuration Custom gradient that matches our color palette (cyan → purple)

View Source
var (
	// Status indicators
	StyledAlchemySuccess = lipgloss.NewStyle().Foreground(ColorSuccess).SetString(IconAlchemySuccess)
	StyledAlchemyError   = lipgloss.NewStyle().Foreground(ColorError).SetString(IconAlchemyError)
	StyledAlchemyWarning = lipgloss.NewStyle().Foreground(ColorWarning).SetString(IconAlchemyWarning)

	// Operational states
	StyledAlchemyActive     = lipgloss.NewStyle().Foreground(ColorWarning).SetString(IconAlchemyActive)     // Yellow for active ops
	StyledAlchemyProcess    = lipgloss.NewStyle().Foreground(ColorPrimary).SetString(IconAlchemyProcess)    // Cyan for processing
	StyledAlchemyCached     = lipgloss.NewStyle().Foreground(ColorMuted).SetString(IconAlchemyCached)       // Gray for cached
	StyledAlchemyStreaming  = lipgloss.NewStyle().Foreground(ColorPrimary).SetString(IconAlchemyStreaming)  // Cyan for streaming
	StyledAlchemyInfo       = lipgloss.NewStyle().Foreground(ColorSecondary).SetString(IconAlchemyInfo)     // Purple for info
	StyledAlchemyConnected  = lipgloss.NewStyle().Foreground(ColorSuccess).SetString(IconAlchemyConnected)  // Green for connected
	StyledAlchemyValidation = lipgloss.NewStyle().Foreground(ColorPrimary).SetString(IconAlchemyValidation) // Cyan for validation
)

Styled alchemy symbols for status display

Functions

func ClampFloat

func ClampFloat(value, min, max float64) float64

ClampFloat constrains a float64 value between min and max

func CountLines

func CountLines(content string) int

CountLines returns the number of lines in a string

func EaseOutCubic

func EaseOutCubic(t float64) float64

EaseOutCubic applies cubic easing to a value (0-1)

func NewAdvancedSettings

func NewAdvancedSettings(sourceType string, config sources.Config) *advancedSettingsModel

func NewCaptureTabs

func NewCaptureTabs() tea.Model

func NewConfigEditor

func NewConfigEditor() tea.Model

NewConfigEditor constructs the config TUI model pre-populated with existing values.

func NewDefaultProgress

func NewDefaultProgress(width int) progress.Model

NewDefaultProgress creates a progress bar with consistent styling across the application.

func NewDefaultSpinner

func NewDefaultSpinner() spinner.Model

NewDefaultSpinner creates a spinner with consistent styling across the application.

func NewListPorts

func NewListPorts() tea.Model

func NewMetadataEditor

func NewMetadataEditor(repo MetadataPort, meta MetadataValues, path string, loadErr error) tea.Model

NewMetadataEditor constructs the metadata TUI model pre-populated with existing values.

func NewRouterForTest

func NewRouterForTest(cfg RouterConfig) *router

NewRouterForTest exposes router construction for white-box tests.

func NewRunsViewer

func NewRunsViewer(cacheRoot string) tea.Model

NewRunsViewer constructs the runs viewer TUI model.

func NewSourceInfo

func NewSourceInfo(sourceType string, width, height int) *sourceInfoModel

NewSourceInfo builds the contextual diagnostics dialog for the given source type.

func NewUploadModel

func NewUploadModel(client UploadPort, runIDs []string) tea.Model

NewUploadModel constructs an upload screen model for use with the router.

func NewWelcome

func NewWelcome(status *StatusMessage) tea.Model

func RunTUI

func RunTUI(cfg RouterConfig) error

RunTUI launches the single Bubble Tea program for the entire application lifetime.

Types

type App

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

App represents the live capture TUI application

func NewApp

func NewApp(title string, feed <-chan string) *App

NewApp creates a new App instance

func (*App) Init

func (a *App) Init() tea.Cmd

Init initializes the app

func (*App) SaveRequested

func (a *App) SaveRequested() bool

SaveRequested returns true if the user requested to save the run

func (*App) Update

func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update handles messages and updates the model

func (*App) View

func (a *App) View() string

View renders the application UI

type CaptureConfig

type CaptureConfig struct {
	SourceType   string // SourceTypeSerial, SourceTypeTCP, or SourceTypeSCPI
	SerialConfig *sources.Config
	TCPHost      string
	TCPPort      string
	SCPIAddress  string // For future SCPI/VISA implementation
}

CaptureConfig holds the configuration for any capture source

type CaptureSession

type CaptureSession interface {
	Feed() <-chan string
	// Stop cancels the session, waits for finalization, and returns the outcome.
	Stop() CaptureSessionResult
	// RequestSave marks the session so that Stop promotes artifacts instead of discarding them.
	RequestSave()
}

CaptureSession represents an active capture session from the TUI's perspective.

type CaptureSessionPort

type CaptureSessionPort interface {
	Start(ctx context.Context, cfg CaptureConfig) (CaptureSession, error)
}

CaptureSessionPort abstracts the live capture subsystem so the router can start sessions without importing concrete source implementations.

type CaptureSessionResult

type CaptureSessionResult struct {
	Saved bool
	RunID string
	Err   error
}

CaptureSessionResult holds the outcome after a capture session ends.

type LineBuffer

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

LineBuffer manages buffering and processing of incoming text data

func NewLineBuffer

func NewLineBuffer() *LineBuffer

NewLineBuffer creates a new line buffer

func (*LineBuffer) AddData

func (lb *LineBuffer) AddData(data string)

AddData adds raw data to the buffer, processing complete lines

func (*LineBuffer) Clear

func (lb *LineBuffer) Clear()

Clear resets the buffer

func (*LineBuffer) GetDisplayLines

func (lb *LineBuffer) GetDisplayLines() []string

GetDisplayLines returns all complete lines plus any partial line

func (*LineBuffer) LineCount

func (lb *LineBuffer) LineCount() int

LineCount returns the number of complete lines

type LineWrapper

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

LineWrapper handles text wrapping logic

func NewLineWrapper

func NewLineWrapper(width int) *LineWrapper

NewLineWrapper creates a new line wrapper with the given width

func (*LineWrapper) Wrap

func (lw *LineWrapper) Wrap(lines []string) string

Wrap wraps lines to fit within the configured width

type MetadataPort

type MetadataPort interface {
	Load() (MetadataValues, error)
	Save(MetadataValues) (string, error)
	Path() (string, error)
}

MetadataPort abstracts loading and saving run metadata for the TUI.

type MetadataValues

type MetadataValues struct {
	Operator   string
	Location   string
	Device     core.DeviceInfo
	Test       core.TestInfo
	Tags       []string
	Attributes map[string]string
}

MetadataValues is the TUI-owned representation of editable metadata.

type NavigateMsg struct {
	To     ScreenID
	Status *StatusMessage
	Args   any
}

NavigateMsg is emitted by screens to request a transition.

type RouterConfig

type RouterConfig struct {
	InitialScreen ScreenID
	InitialStatus *StatusMessage
	CapturePort   CaptureSessionPort
	MetadataPort  MetadataPort
	UploadPort    UploadPort
	RunsCacheRoot string
}

RouterConfig holds router dependencies.

type ScreenContext

type ScreenContext struct {
	Status *StatusMessage
	Args   any
}

ScreenContext is passed to every ScreenFactory at construction time.

type ScreenFactory

type ScreenFactory func(ctx ScreenContext) (tea.Model, func(), error)

ScreenFactory constructs a screen on demand. The returned func() is a cleanup hook called when the router navigates away. Return nil for the func() if no cleanup is needed. Return a non-nil error to navigate back to welcome with a StatusError.

type ScreenID

type ScreenID string

ScreenID identifies a routable screen.

const (
	ScreenWelcome     ScreenID = "welcome"
	ScreenConfig      ScreenID = "config"
	ScreenMetadata    ScreenID = "metadata"
	ScreenRuns        ScreenID = "runs"
	ScreenUpload      ScreenID = "upload"
	ScreenCaptureTabs ScreenID = "capture-tabs"
	ScreenCaptureLive ScreenID = "capture-live"
)

type ScrollInfo

type ScrollInfo struct {
	ScrollPercent float64 // 0.0 to 1.0
	AtTop         bool
	AtBottom      bool
}

ScrollInfo contains information about the viewport's scroll position

type SpotlightEffect

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

SpotlightEffect applies a gradient fade effect to content based on scroll position

func NewSpotlightEffect

func NewSpotlightEffect() *SpotlightEffect

NewSpotlightEffect creates a new spotlight effect with default settings

func NewSpotlightEffectCustom

func NewSpotlightEffectCustom(minIntensity, focusRadius float64) *SpotlightEffect

NewSpotlightEffectCustom creates a new spotlight effect with custom settings

func (*SpotlightEffect) ApplyFade

func (s *SpotlightEffect) ApplyFade(content string, scroll ScrollInfo) string

ApplyFade applies a gradient fade to the visible content based on scroll position

type StatusKind

type StatusKind int

StatusKind determines the styling applied to a status message.

const (
	StatusInfo StatusKind = iota
	StatusSuccess
	StatusWarning
	StatusError
)

type StatusMessage

type StatusMessage struct {
	Kind  StatusKind
	Title string
	Body  string
}

StatusMessage represents a bordered notification rendered inside the TUI.

func NewStatusMessage

func NewStatusMessage(kind StatusKind, title, body string) *StatusMessage

NewStatusMessage constructs a new status message.

func (*StatusMessage) Render

func (m *StatusMessage) Render(width int) string

Render draws the status message within the provided width.

type UploadPort

type UploadPort interface {
	UploadRun(ctx context.Context, runID string) error
}

UploadPort abstracts run uploads for the TUI.

Jump to

Keyboard shortcuts

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