textview

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package textview is a read-only viewer for static text content, wrapped in a pane. Reach for it when the payload is a rendered document — a README, a diff, a kubectl describe, a PR body — where logview's streaming shape (append / follow / filter mode / MaxLines trim) is noise. textview drops all of that and keeps the machinery that read- static-text actually needs: scroll, search, wrap.

The body is a pkg/pane.Pane (so ↑↓/j/k/PgUp/PgDn scrolling work out of the box), plus an optional pkg/filter.Model for the "/-to-search" overlay. Content is replaced wholesale via SetContent; there is no Append or Clear — see pkg/logview for the streaming case.

Behavior:

  • SetContent replaces the buffer and resets scroll to the top.
  • Wrap is on by default: long lines wrap to the pane's inner width (ANSI-aware via x/ansi.Wrap). Toggle at runtime with `w`. Wrap-off mode falls back to pane's own truncation + horizontal scroll (rule 16).
  • "/" focuses an embedded filter input; typing highlights case- insensitive substring matches inline; enter blurs (keeps the query active for n/N); esc clears.
  • n / N step to the next / previous match.
  • g / G jump to top / bottom (rule 23: no `gg` — single g means top library-wide).
  • ctrl+u / ctrl+d half-page; pgup / pgdown full-page.
  • No filter mode. No follow. No MaxLines. If you want streaming + filter drop + tail-mode, use pkg/logview.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Keys

type Keys struct {
	Search, NextMatch, PrevMatch key.Binding
	Top, Bottom                  key.Binding
	Wrap                         key.Binding
	Pane                         pane.Keys
}

Keys is the textview's keymap. Each binding carries both its dispatch keys (WithKeys) and its help label (WithHelp) — Update and Help() read from the same struct, so a custom binding propagates everywhere. Pane covers horizontal scroll and pgup/pgdn/half-page; textview owns the search + wrap-toggle bindings.

func DefaultKeys

func DefaultKeys() Keys

DefaultKeys returns the textview's stock keymap.

type Model

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

Model is the textview widget. Embed by value; mutate via the setters.

func New

func New(opts Options) Model

New constructs a textview.

func (*Model) Blur added in v0.18.0

func (m *Model) Blur()

Blur releases the keyboard, clearing *both* regions. Leaving a filter focused on a blurred component is what lets a second filterable pane end up invisibly eating keys.

func (*Model) BlurFilter added in v0.18.1

func (m *Model) BlurFilter()

BlurFilter returns input from the filter to the body.

func (Model) Content

func (m Model) Content() string

Content returns the raw text (pre-wrap) currently loaded.

func (*Model) Focus added in v0.18.0

func (m *Model) Focus() tea.Cmd

Focus gives the component the keyboard, highlighting the body pane.

It deliberately does nothing when the filter already owns input: a click on the filter also asks the group for focus, and that grant arrives afterwards. Without this guard it would snatch the highlight back to the body while the filter kept the keystrokes.

func (*Model) FocusFilter added in v0.18.1

func (m *Model) FocusFilter() tea.Cmd

FocusFilter moves input to the filter and takes the highlight off the body, so exactly one region ever reads as active.

func (Model) FocusToken added in v0.18.0

func (m Model) FocusToken() focus.Token

FocusToken returns the textview's stable focus identity. See focus.Identified.

func (Model) Focused added in v0.18.0

func (m Model) Focused() bool

Focused reports whether either of the component's regions owns input.

func (Model) Help

func (m Model) Help() []key.Binding

Help returns the keys this textview responds to. While the embedded filter is focused, returns the filter's keys; otherwise the navigation + search + wrap bindings appropriate for the current state.

func (Model) Init

func (m Model) Init() tea.Cmd

Init satisfies tea.Model.

func (Model) IsCapturingKeys added in v0.18.0

func (m Model) IsCapturingKeys() bool

IsCapturingKeys reports whether the textview currently swallows printable keys — true while its search filter is focused. Satisfies focus.Capturer.

func (Model) Loading

func (m Model) Loading() bool

Loading reports whether the textview is currently in its loading state.

func (Model) Query

func (m Model) Query() string

Query returns the current search text ("" when no search is active).

func (Model) Searching

func (m Model) Searching() bool

Searching reports whether the embedded filter currently has focus. Mirror this from the enclosing screen's IsCapturingKeys() so the app shell keeps its global keys (q, t, esc) out of the search input.

func (*Model) SetActiveColor

func (m *Model) SetActiveColor(c lipgloss.TerminalColor)

SetActiveColor updates the body pane's active border color.

func (*Model) SetContent

func (m *Model) SetContent(s string)

SetContent replaces the buffer and resets scroll to the top. Any active search query is preserved; matches are recomputed against the new content and the current match resets to the first hit.

func (*Model) SetCurrentLineStyle

func (m *Model) SetCurrentLineStyle(s lipgloss.Style)

SetCurrentLineStyle updates the style applied to the line holding the current match.

func (*Model) SetInactiveColor

func (m *Model) SetInactiveColor(c lipgloss.TerminalColor)

SetInactiveColor updates the body pane's inactive border color.

func (*Model) SetLoading

func (m *Model) SetLoading(b bool) tea.Cmd

SetLoading toggles the loading state. When entering, returns the spinner's initial Tick command — propagate it back from your screen's Update so the spinner animates.

func (*Model) SetLoadingLabel

func (m *Model) SetLoadingLabel(s string)

SetLoadingLabel updates the text rendered next to the spinner while loading.

func (*Model) SetMatchStyle

func (m *Model) SetMatchStyle(s lipgloss.Style)

SetMatchStyle updates the highlight style applied to matched substrings.

func (*Model) SetQuery

func (m *Model) SetQuery(s string)

SetQuery sets the search text programmatically (no-op when not Searchable).

func (*Model) SetRect added in v0.18.0

func (m *Model) SetRect(r geom.Rect)

SetRect places the textview in the given rect. When searchable, the filter takes the top 3 rows and the body pane gets the rest, offset below it.

func (*Model) SetSpinnerStyle

func (m *Model) SetSpinnerStyle(s lipgloss.Style)

SetSpinnerStyle updates the lipgloss style applied to the spinner glyph.

func (*Model) SetTitle

func (m *Model) SetTitle(s string)

SetTitle sets the pane's top-left title.

func (*Model) SetWrap

func (m *Model) SetWrap(b bool)

SetWrap flips wrap on or off. When enabled, content re-wraps to the pane's inner width; when disabled, pane's own horizontal scroll takes over.

func (Model) Update

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)

Update dispatches search, match jumping, top/bottom jumps, wrap toggle, and forwards everything else to the body pane.

func (Model) View

func (m Model) View() string

View stacks the filter (when searchable) above the body pane.

func (Model) Wrap

func (m Model) Wrap() bool

Wrap reports whether word-wrap is currently enabled.

type Options

type Options struct {
	Width, Height int
	// Title sits on the pane's top-left border slot. Defaults to "text".
	Title string
	// Content is the initial body text. Replace at runtime via SetContent.
	Content string
	// Wrap enables word-wrapping to the pane's inner width. Default is
	// true; when false the pane's built-in truncation + horizontal scroll
	// handles overflow (rule 16).
	Wrap bool
	// Searchable embeds a filter.Model above the body pane (three rows).
	// When false, "/" is ignored and the full height is used for content.
	Searchable bool

	// MatchStyle is the lipgloss style applied to matched substrings while
	// a query is active. Pass via theme.TextView() for a sensible default.
	MatchStyle lipgloss.Style

	// CurrentLineStyle is applied to the entire line holding the current
	// match, padded to the pane's inner width so a Background paints the
	// whole row. Zero value leaves the row unstyled.
	CurrentLineStyle lipgloss.Style

	// Pane pass-throughs. See pkg/pane.Options for defaults.
	ActiveColor    lipgloss.TerminalColor
	InactiveColor  lipgloss.TerminalColor
	ActiveBorder   lipgloss.Border
	InactiveBorder lipgloss.Border
	SlotBrackets   pane.SlotBracketStyle

	// SpinnerStyle is applied to the spinner glyph rendered while the
	// textview is in its loading state (see SetLoading).
	SpinnerStyle lipgloss.Style
	// LoadingLabel is rendered next to the spinner while loading.
	LoadingLabel string

	// Filter configures the embedded filter. Ignored when Searchable=false.
	Filter filter.Options

	// Keys is the textview's keymap. Leave zero to use DefaultKeys.
	Keys Keys
}

Options configures a new textview. Zero-value fields fall back to defaults; start from theme.TextView() to fill in the color tokens.

Jump to

Keyboard shortcuts

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