app

package
v0.0.8 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: MIT Imports: 23 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 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.

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

	// 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 so bindings can be remapped via configuration. Two-key sequences (gg, ]c, …), numeric count prefixes, and overlay/input keys are handled by the grammar 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
	// 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 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.

Jump to

Keyboard shortcuts

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