app

package
v0.0.16 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package app is the Bubble Tea model/update/view for the review client. It is deliberately independent of Git and any forge: it consumes a parsed diff and a draft review, renders them, and turns key events into navigation, selection, and comment actions. Rendered rows are projections; comments anchor to semantic diff locations.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuiltinKeymapNames added in v0.0.12

func BuiltinKeymapNames() []string

BuiltinKeymapNames returns the built-in preset names, sorted. These names are reserved: a user-defined keymap may not shadow them.

func IsBuiltinKeymap added in v0.0.12

func IsBuiltinKeymap(name string) bool

IsBuiltinKeymap reports whether name is a built-in preset.

func KnownActions added in v0.0.3

func KnownActions() []string

KnownActions returns the sorted set of action names a key may bind to — the shared contract between the keymap, the CLI config validator, and the published config schema (a sync test keeps the latter honest).

func PickRequest

func PickRequest(entries []forge.ListedRequest, theme ui.Theme) (int, error)

PickRequest shows an interactive picker over the discovered requests and returns the chosen index, or -1 if the user dismissed it.

func ValidateBindings added in v0.0.11

func ValidateBindings(keys map[string]string, seqOverrides []SeqBinding) []string

ValidateBindings reports overlap problems the structural config validator cannot see: the grammar consumes digits (counts) and sequence prefixes before single-key dispatch, so bindings shadowed by that order are dead — exactly the kind of config mistake that otherwise surfaces as "my key does nothing". The effective tables (defaults + overrides) are what is checked, so removing the default sequence also clears the conflict.

func ValidateKeymapChoice added in v0.0.12

func ValidateKeymapChoice(name string, user map[string]NamedKeymap) []string

ValidateKeymapChoice reports problems with the keymap selection and the user-defined keymap table: an unknown name (silently falling back to the defaults would be the classic invisible typo), and user keymaps shadowing reserved built-in names.

Types

type Config

type Config struct {
	Files   []diff.FileDiff
	Title   string
	HeadOID string
	Draft   *review.DraftReview
	Store   *review.Store
	Editor  editor.Editor
	Theme   ui.Theme

	// PR is set in pull-request mode; nil for local/patch review.
	PR *PRContext

	// Highlighter, when set, overrides the environment-derived default.
	Highlighter *ui.Highlighter

	// Keys overrides individual normal-mode key bindings (key -> action).
	Keys map[string]string
	// Sequences overrides two-key sequence bindings; an empty action removes
	// the sequence.
	Sequences []SeqBinding
	// KeymapName selects the base binding set: a built-in preset (default,
	// vim, vscode, sublime, intellij) or a user-defined entry in UserKeymaps.
	KeymapName string
	// UserKeymaps are named keymaps from configuration, each layered on the
	// defaults when selected.
	UserKeymaps map[string]NamedKeymap

	// Wrap enables line/comment wrapping at start (default true when built via
	// the CLI); WrapWidth caps the unified wrap point (0 means the default).
	Wrap      bool
	WrapWidth int

	// RawPatch is the literal diff text, when the source can provide it. It
	// is what makes a review-exchange export (:export x.json) self-contained;
	// nil disables that export form.
	RawPatch []byte

	// FetchContext returns the full new-side content of a file, enabling the
	// full-file context view (T). nil disables the toggle for this source.
	FetchContext func(ctx context.Context, path string, side diff.Side) ([]byte, error)

	// Images selects comment-image rendering: auto, kitty, chafa, or off.
	Images string

	// FetchImage resolves a remote image reference (a forge attachment URL)
	// to its bytes, authenticated through the forge CLI; nil outside PR mode.
	FetchImage func(ctx context.Context, url string) ([]byte, error)

	// ChangeColors picks how +/- lines are colored when syntax highlighting
	// is on: "diff" (classic red/green, syntax for context only) or "syntax"
	// (syntax everywhere). Empty means "diff".
	ChangeColors string
	// ChangeTint backs syntax-mode changed lines with a faint red/green
	// background so the diff stays legible at a glance.
	ChangeTint bool

	// Author is the reviewer's name for attribution in review-exchange
	// conversations (comment replies); empty falls back to "reviewer".
	Author string
}

Config wires the model's dependencies together.

type Keymap

type Keymap map[string]string

Keymap maps a key (as reported by Bubble Tea's KeyMsg.String) to a normal-mode action name. Single-key normal-mode dispatch flows through this table, and two-key sequences through Sequences — both remappable via configuration. Numeric count prefixes and overlay/input keys are handled by the grammar and each overlay's own handler, and are not remappable.

func DefaultKeymap

func DefaultKeymap() Keymap

DefaultKeymap returns the built-in bindings as a fresh map on every call, so apply can mutate one model's keymap without affecting other instances or the knownActions set derived from the defaults.

type Layout

type Layout uint8

Layout selects unified vs split rendering.

const (
	// LayoutUnified interleaves old and new lines in one column.
	LayoutUnified Layout = iota
	// LayoutSplit shows old and new side by side.
	LayoutSplit
)

func (Layout) String

func (l Layout) String() string

String returns the lower-case layout name shown in the title bar and in the toggle-layout status message.

type Mode

type Mode uint8

Mode is the explicit interaction mode. Using an enum (rather than scattered booleans) keeps the update logic legible and testable.

const (
	// ModeNormal is navigation.
	ModeNormal Mode = iota
	// ModeVisual is an active line selection.
	ModeVisual
	// ModeFiles is the file picker.
	ModeFiles
	// ModeComments is the comment/thread list.
	ModeComments
	// ModeConfirm is a yes/no confirmation prompt.
	ModeConfirm
	// ModeHelp shows the key reference.
	ModeHelp
	// ModeThread shows a focused reader for the review thread under the cursor.
	ModeThread
	// ModePR shows the pull-request details (title, description, URL).
	ModePR
	// ModeConvo shows a focused reader for a draft comment's conversation,
	// where individual replies can be edited and deleted.
	ModeConvo
	// ModeGeneral is the PR's general (conversation-level) comment screen:
	// browse, reply (as quoted new comments), add, and manage drafts.
	ModeGeneral
	// ModeExternalEditor is a placeholder state while the editor is open.
	ModeExternalEditor
)

func (Mode) String

func (m Mode) String() string

String returns the upper-case label shown in the status bar. ModeNormal — and any unknown value — reads NORMAL, so the bar always shows a valid mode.

type Model

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

Model is the root Bubble Tea model.

func New

func New(cfg Config) *Model

New builds the initial model, filling in whatever cfg leaves unset: an empty draft, the environment-derived highlighter, the default wrap width, and the default keymap overlaid with the user's overrides. The cursor starts on the first commentable row rather than row 0, which is a hunk header.

func (*Model) Init

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

Init implements tea.Model. The only startup work is the optional whole-file content fetch that upgrades syntax highlighting for file 0.

func (*Model) SetExchangeWriteback added in v0.0.2

func (m *Model) SetExchangeWriteback(path string)

SetExchangeWriteback makes every draft save also rewrite the review-exchange file at path, keeping the on-disk conversation current without an explicit export step — the file is the contract with the other side of the review.

func (*Model) Update

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

Update implements tea.Model. It handles the async messages (window resize, external-editor exit, submission result) directly and funnels every keystroke through handleKey, which owns all mode-dependent dispatch.

func (*Model) View

func (m *Model) View() string

View implements tea.Model. Overlay modes replace the whole content area (via frame); otherwise it renders the diff body, prefixing each row with the sidebar column when it is shown, all sandwiched between the title and status bars.

type NamedKeymap added in v0.0.12

type NamedKeymap struct {
	Keys      map[string]string
	Sequences []SeqBinding
}

NamedKeymap is a user-defined keymap from configuration: overrides layered on top of the defaults, selectable by name via the keymap setting.

type PRContext

type PRContext struct {
	Forge   forge.Forge
	Ref     forge.PullRequestRef
	PR      *forge.PullRequest
	Threads []forge.Thread
	// General is the PR's conversation (non-inline) discussion, oldest
	// first, shown in the PR details overlay below the description.
	General []forge.Comment
}

PRContext carries everything the TUI needs to operate in pull-request mode: the forge to reply/submit through, the PR reference and metadata, and the existing review threads. It is nil in local/patch mode.

type SeqBinding added in v0.0.11

type SeqBinding struct {
	First  string
	Second string
	Action string
}

SeqBinding is one two-key sequence override from configuration: the two keys in press order plus the action, or "" to remove the sequence.

func DefaultSequenceBindings added in v0.0.11

func DefaultSequenceBindings() []SeqBinding

DefaultSequenceBindings returns the built-in two-key sequences in a stable order — the config generator spells them out so remapping starts from the real current bindings.

type Sequences added in v0.0.11

type Sequences map[seqKey]string

Sequences maps two-key sequences to action names. Unlisted combinations are discarded by the grammar.

func DefaultSequences added in v0.0.11

func DefaultSequences() Sequences

DefaultSequences returns the built-in two-key bindings as a fresh map on every call, so apply can mutate one model's sequences without affecting other instances or the knownActions set derived from the defaults.

Jump to

Keyboard shortcuts

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