tui

package
v0.8.2 Latest Latest
Warning

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

Go to latest
Published: May 31, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ThemeDark  = "dark"
	ThemeLight = "light"
)

Theme constants.

Variables

This section is empty.

Functions

This section is empty.

Types

type App

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

App is the main Bubble Tea model for the TUI.

func NewApp

func NewApp(doc *markdown.Document, opts AppOptions) *App

NewApp creates a new App model.

func (*App) Init

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

Init implements tea.Model.

func (*App) Result

func (a *App) Result() AppResult

Result returns the final result after the TUI exits.

func (*App) Update

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

Update implements tea.Model.

func (*App) View

func (a *App) View() tea.View

View implements tea.Model.

func (*App) ViewedState

func (a *App) ViewedState() *markdown.ViewedState

ViewedState returns the current viewed state for persistence.

type AppMode

type AppMode int

AppMode represents the current application mode.

const (
	ModeNormal      AppMode = iota // Section list navigation
	ModeComment                    // Comment input
	ModeCommentList                // Comment list management
	ModeConfirm                    // Confirmation dialog
	ModeHelp                       // Help overlay
	ModeSearch                     // Section search
	ModeLineSelect                 // Visual line selection in raw view
)

type AppOptions

type AppOptions struct {
	Theme       string    // "dark" or "light"
	FilePath    string    // file path (displayed in title bar)
	TrackViewed bool      // persist viewed state to sidecar file
	PRMode      bool      // PR review mode: changes dialog text and enables diff view
	Diff        *DiffData // when set, raw view shows diff instead of full source
}

AppOptions configures the TUI appearance.

type AppResult

type AppResult struct {
	Review *markdown.ReviewResult
	Status markdown.Status
}

AppResult is the result returned when the TUI exits.

type CommentEditor

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

CommentEditor wraps a textarea for entering review comments.

func NewCommentEditor

func NewCommentEditor() *CommentEditor

NewCommentEditor creates a new CommentEditor.

func (*CommentEditor) Close

func (c *CommentEditor) Close()

Close closes the comment editor.

func (*CommentEditor) Cursor added in v0.8.1

func (c *CommentEditor) Cursor() *tea.Cursor

Cursor returns the textarea's cursor position relative to its own rendered output. The caller must offset it by the textarea's absolute screen origin before assigning it to tea.View.Cursor. Returns nil when the textarea is using the virtual cursor or is not focused.

func (*CommentEditor) CycleDecoration

func (c *CommentEditor) CycleDecoration()

CycleDecoration cycles to the next decoration.

func (*CommentEditor) CycleLabel

func (c *CommentEditor) CycleLabel()

CycleLabel cycles to the next action label.

func (*CommentEditor) CycleLabelReverse

func (c *CommentEditor) CycleLabelReverse()

CycleLabelReverse cycles to the previous action label.

func (*CommentEditor) DecorationLabel

func (c *CommentEditor) DecorationLabel() markdown.Decoration

DecorationLabel returns the current decoration.

func (*CommentEditor) FormatLabel

func (c *CommentEditor) FormatLabel() string

FormatLabel returns the combined action and decoration label for display.

func (*CommentEditor) FormatLineRef added in v0.6.0

func (c *CommentEditor) FormatLineRef() string

FormatLineRef returns a line reference string for display.

func (*CommentEditor) Label

func (c *CommentEditor) Label() markdown.ActionType

Label returns the current action label.

func (*CommentEditor) Open

func (c *CommentEditor) Open(sectionID string, existing *markdown.ReviewComment) tea.Cmd

Open opens the comment editor for a section, optionally pre-filling with existing comment.

func (*CommentEditor) OpenWithLines added in v0.6.0

func (c *CommentEditor) OpenWithLines(sectionID string, existing *markdown.ReviewComment, startLine, endLine int, side string) tea.Cmd

OpenWithLines opens the comment editor for a new line-level comment. existing must be nil; use Open directly when editing existing comments.

func (*CommentEditor) Result

func (c *CommentEditor) Result() *markdown.ReviewComment

Result returns the review comment from the editor content. Returns nil if the body is empty.

func (*CommentEditor) SectionID

func (c *CommentEditor) SectionID() string

SectionID returns the section ID being edited.

func (*CommentEditor) SetWidth

func (c *CommentEditor) SetWidth(w int)

SetWidth sets the width of the textarea.

func (*CommentEditor) Update

func (c *CommentEditor) Update(msg tea.Msg) tea.Cmd

Update handles tea messages for the textarea.

func (*CommentEditor) View

func (c *CommentEditor) View() string

View renders the comment editor.

type CommentList

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

CommentList manages the comment list view for a section.

func NewCommentList

func NewCommentList() *CommentList

NewCommentList creates a new CommentList.

func (*CommentList) Close

func (cl *CommentList) Close()

Close closes the comment list.

func (*CommentList) Cursor

func (cl *CommentList) Cursor() int

Cursor returns the current cursor position.

func (*CommentList) CursorDown

func (cl *CommentList) CursorDown()

CursorDown moves the cursor down.

func (*CommentList) CursorUp

func (cl *CommentList) CursorUp()

CursorUp moves the cursor up.

func (*CommentList) Open

func (cl *CommentList) Open(sectionID string, comments []*markdown.ReviewComment)

Open opens the comment list for a section.

func (*CommentList) Render

func (cl *CommentList) Render(width, height int, styles Styles) string

Render renders the comment list.

func (*CommentList) SectionID

func (cl *CommentList) SectionID() string

SectionID returns the section ID.

type DetailPane

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

DetailPane manages the right pane that shows section details.

func NewDetailPane

func NewDetailPane(width, height int, theme string) *DetailPane

NewDetailPane creates a new DetailPane.

func (*DetailPane) ScrollToSectionID

func (d *DetailPane) ScrollToSectionID(sectionID string)

ScrollToSectionID scrolls the viewport to the given section's offset.

func (*DetailPane) SectionIDAtOffset

func (d *DetailPane) SectionIDAtOffset(yOffset int) string

SectionIDAtOffset returns the section ID visible at the given vertical offset.

func (*DetailPane) SetSize

func (d *DetailPane) SetSize(width, height int)

SetSize updates the pane size. It does not re-render current content; call ShowSection or ShowOverview after resizing to refresh the viewport.

func (*DetailPane) ShowAll

func (d *DetailPane) ShowAll(doc *markdown.Document, getComments func(string) []*markdown.ReviewComment)

ShowAll renders the entire document in a single view.

func (*DetailPane) ShowOverview

func (d *DetailPane) ShowOverview(doc *markdown.Document, comments []*markdown.ReviewComment)

ShowOverview renders and displays the document overview (preamble).

func (*DetailPane) ShowSection

func (d *DetailPane) ShowSection(section *markdown.Section, comments []*markdown.ReviewComment)

ShowSection renders and displays a section's content.

func (*DetailPane) View

func (d *DetailPane) View() string

View returns the viewport view.

func (*DetailPane) Viewport

func (d *DetailPane) Viewport() *viewport.Model

Viewport returns a pointer to the viewport for event handling.

type DiffData added in v0.7.0

type DiffData struct {
	DisplayLines []string // formatted diff lines (with +/-/space prefix)
	LineMap      []int    // maps display index → file line number for commenting
	SideMap      []string // maps display index → "RIGHT" or "LEFT"
	TypeMap      []byte   // maps display index → diff line type ('+', '-', ' ')
}

DiffData holds parsed diff information for PR mode display.

type FilePicker added in v0.7.0

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

FilePicker is a Bubble Tea model for selecting files from a list.

func NewFilePicker added in v0.7.0

func NewFilePicker(files []string) *FilePicker

NewFilePicker creates a file picker with the given file list.

func (*FilePicker) Init added in v0.7.0

func (fp *FilePicker) Init() tea.Cmd

Init implements tea.Model.

func (*FilePicker) Result added in v0.7.0

func (fp *FilePicker) Result() FilePickerResult

Result returns the file picker result.

func (*FilePicker) Update added in v0.7.0

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

Update implements tea.Model.

func (*FilePicker) View added in v0.7.0

func (fp *FilePicker) View() tea.View

View implements tea.Model.

type FilePickerResult added in v0.7.0

type FilePickerResult struct {
	SelectedFiles []string
	Cancelled     bool
}

FilePickerResult is the result of the file picker interaction.

type Focus

type Focus int

Focus represents which pane has focus.

const (
	FocusLeft Focus = iota
	FocusRight
)

type KeyMap

type KeyMap struct {
	Up          key.Binding
	Down        key.Binding
	ScrollRight key.Binding
	ScrollLeft  key.Binding
	Toggle      key.Binding
	Tab         key.Binding
	Comment     key.Binding
	CommentList key.Binding
	Viewed      key.Binding
	Search      key.Binding
	Submit      key.Binding
	Quit        key.Binding
	Help        key.Binding
	Save        key.Binding
	Cancel      key.Binding

	// View mode
	FullView key.Binding

	// Right pane specific
	ScrollToStart key.Binding
	ScrollToEnd   key.Binding

	// Pane resizing
	PaneGrow   key.Binding
	PaneShrink key.Binding

	// Page scrolling
	HalfPageDown key.Binding
	HalfPageUp   key.Binding
	PageDown     key.Binding
	PageUp       key.Binding

	// Comment list specific
	Edit   key.Binding
	Delete key.Binding

	// Comment editor specific
	CommentLabelNext key.Binding
	CommentLabelPrev key.Binding
	CommentCycleDeco key.Binding

	// Line mode
	RawView      key.Binding
	VisualSelect key.Binding
}

KeyMap defines all key bindings for the TUI.

func DefaultKeyMap

func DefaultKeyMap() KeyMap

DefaultKeyMap returns the default key bindings.

type LinePane added in v0.6.0

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

LinePane renders raw source with line numbers for line-level commenting.

func NewLinePane added in v0.6.0

func NewLinePane(lines []string, width, height int, styles Styles, sections []*markdown.Section) *LinePane

NewLinePane creates a new LinePane.

func (*LinePane) AtRangeBottom added in v0.6.0

func (lp *LinePane) AtRangeBottom() bool

AtRangeBottom returns true if the cursor is at the bottom of the visible range.

func (*LinePane) AtRangeTop added in v0.6.0

func (lp *LinePane) AtRangeTop() bool

AtRangeTop returns true if the cursor is at the top of the visible range.

func (*LinePane) CanComment added in v0.7.0

func (lp *LinePane) CanComment() bool

CanComment returns whether the current cursor position allows commenting. All lines in the diff are commentable (added, removed, and context).

func (*LinePane) CancelVisualSelect added in v0.6.0

func (lp *LinePane) CancelVisualSelect()

CancelVisualSelect cancels visual line selection.

func (*LinePane) ClearViewRange added in v0.6.0

func (lp *LinePane) ClearViewRange()

ClearViewRange shows all lines.

func (*LinePane) Cursor added in v0.6.0

func (lp *LinePane) Cursor() int

Cursor returns the current 0-based cursor position.

func (*LinePane) CursorBottom added in v0.6.0

func (lp *LinePane) CursorBottom()

CursorBottom moves the cursor to the last visible line.

func (*LinePane) CursorDown added in v0.6.0

func (lp *LinePane) CursorDown()

CursorDown moves the cursor down one line.

func (*LinePane) CursorSide added in v0.7.0

func (lp *LinePane) CursorSide() string

CursorSide returns the diff side ("RIGHT" or "LEFT") at the cursor position. Returns "" in non-diff mode.

func (*LinePane) CursorTop added in v0.6.0

func (lp *LinePane) CursorTop()

CursorTop moves the cursor to the first visible line.

func (*LinePane) CursorUp added in v0.6.0

func (lp *LinePane) CursorUp()

CursorUp moves the cursor up one line.

func (*LinePane) HalfPageDown added in v0.6.0

func (lp *LinePane) HalfPageDown()

HalfPageDown moves the cursor down by half the viewport height.

func (*LinePane) HalfPageUp added in v0.6.0

func (lp *LinePane) HalfPageUp()

HalfPageUp moves the cursor up by half the viewport height.

func (*LinePane) IsVisualSelect added in v0.6.0

func (lp *LinePane) IsVisualSelect() bool

IsVisualSelect returns true if visual selection is active.

func (*LinePane) LineCount added in v0.6.0

func (lp *LinePane) LineCount() int

LineCount returns the total number of source lines.

func (*LinePane) PageDown added in v0.6.0

func (lp *LinePane) PageDown()

PageDown moves the cursor down by a full viewport height.

func (*LinePane) PageUp added in v0.6.0

func (lp *LinePane) PageUp()

PageUp moves the cursor up by a full viewport height.

func (*LinePane) ScrollToLine added in v0.6.0

func (lp *LinePane) ScrollToLine(line int)

ScrollToLine scrolls the viewport so the given 1-based line is visible, centered if possible.

func (*LinePane) SectionIDAtCursor added in v0.8.2

func (lp *LinePane) SectionIDAtCursor() string

SectionIDAtCursor returns the section ID for the line under the cursor. In diff mode the cursor is a display index, so it is mapped through diffLineMap to a file line before lookup; returns "" when the cursor is on a non-commentable line (no file line mapping). In non-diff mode the cursor index is the file line.

func (*LinePane) SectionIDAtLine added in v0.6.0

func (lp *LinePane) SectionIDAtLine(line int) string

SectionIDAtLine returns the section ID containing the given 1-based line number. Assumes sectionRanges is sorted by startLine in ascending order. Returns OverviewSectionID if the line is before any section.

func (*LinePane) SelectedRange added in v0.6.0

func (lp *LinePane) SelectedRange() (startLine, endLine int)

SelectedRange returns the 1-based line range for commenting. Without visual selection: returns (cursor+1, 0) for single line. With visual selection: returns (min+1, max+1) for range. In diff mode, maps display indices to actual file line numbers. Returns (0, 0) if the selected line is not commentable in diff mode.

func (*LinePane) SetComments added in v0.6.0

func (lp *LinePane) SetComments(comments []*markdown.ReviewComment)

SetComments sets the comments for inline display.

func (*LinePane) SetSize added in v0.6.0

func (lp *LinePane) SetSize(width, height int)

SetSize updates the pane dimensions.

func (*LinePane) SetViewRange added in v0.6.0

func (lp *LinePane) SetViewRange(startLine, endLine int)

SetViewRange sets the visible line range (1-based file line numbers, inclusive). In diff mode, maps file line numbers to diff display indices. Pass 0, 0 to show all lines.

func (*LinePane) StartVisualSelect added in v0.6.0

func (lp *LinePane) StartVisualSelect()

StartVisualSelect begins visual line selection from the current cursor position.

func (*LinePane) View added in v0.6.0

func (lp *LinePane) View() string

View renders the line pane content.

type ReviewAction added in v0.7.0

type ReviewAction int

ReviewAction represents the user's chosen action in the review dialog.

const (
	ReviewActionExit    ReviewAction = iota // do nothing
	ReviewActionApprove                     // approve the PR
	ReviewActionComment                     // submit as comment
)

type ReviewDialog added in v0.7.0

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

ReviewDialog is a Bubble Tea model for the post-review action selection.

func NewReviewDialog added in v0.7.0

func NewReviewDialog(fileSummary []string, hasComments bool) *ReviewDialog

NewReviewDialog creates a review dialog. fileSummary contains "file.md: N comment(s)" lines for display.

func (*ReviewDialog) Init added in v0.7.0

func (d *ReviewDialog) Init() tea.Cmd

Init implements tea.Model.

func (*ReviewDialog) Result added in v0.7.0

func (d *ReviewDialog) Result() ReviewDialogResult

Result returns the dialog result.

func (*ReviewDialog) Update added in v0.7.0

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

Update implements tea.Model.

func (*ReviewDialog) View added in v0.7.0

func (d *ReviewDialog) View() tea.View

View implements tea.Model.

type ReviewDialogResult added in v0.7.0

type ReviewDialogResult struct {
	Action ReviewAction
	Body   string // optional PR-level comment
}

ReviewDialogResult holds the outcome of the review dialog.

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

SearchBar wraps a textinput for section searching.

func NewSearchBar

func NewSearchBar() *SearchBar

NewSearchBar creates a new SearchBar.

func (*SearchBar) Close

func (s *SearchBar) Close()

Close deactivates the search bar.

func (*SearchBar) Open

func (s *SearchBar) Open() tea.Cmd

Open activates the search bar.

func (*SearchBar) Query

func (s *SearchBar) Query() string

Query returns the current search query.

func (*SearchBar) Update

func (s *SearchBar) Update(msg tea.Msg) tea.Cmd

Update handles tea messages for the textinput.

func (*SearchBar) View

func (s *SearchBar) View() string

View renders the search bar.

type SectionList

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

SectionList manages the left pane section tree.

func NewSectionList

func NewSectionList(doc *markdown.Document, state *markdown.ViewedState) *SectionList

NewSectionList creates a new SectionList from a parsed document.

func (*SectionList) AddComment

func (sl *SectionList) AddComment(sectionID string, comment *markdown.ReviewComment)

AddComment appends a comment for a section.

func (*SectionList) BuildReviewResult

func (sl *SectionList) BuildReviewResult() *markdown.ReviewResult

BuildReviewResult creates a ReviewResult from all comments.

func (*SectionList) ClearFilter

func (sl *SectionList) ClearFilter()

ClearFilter resets visibility to respect only expansion state.

func (*SectionList) CursorBottom

func (sl *SectionList) CursorBottom()

CursorBottom moves the cursor to the last visible item.

func (*SectionList) CursorDown

func (sl *SectionList) CursorDown()

CursorDown moves the cursor down to the next visible item.

func (*SectionList) CursorHalfPageDown added in v0.5.0

func (sl *SectionList) CursorHalfPageDown(pageHeight int)

CursorHalfPageDown moves the cursor down by half the visible page height.

func (*SectionList) CursorHalfPageUp added in v0.5.0

func (sl *SectionList) CursorHalfPageUp(pageHeight int)

CursorHalfPageUp moves the cursor up by half the visible page height.

func (*SectionList) CursorPageDown added in v0.5.0

func (sl *SectionList) CursorPageDown(pageHeight int)

CursorPageDown moves the cursor down by the visible page height.

func (*SectionList) CursorPageUp added in v0.5.0

func (sl *SectionList) CursorPageUp(pageHeight int)

CursorPageUp moves the cursor up by the visible page height.

func (*SectionList) CursorTop

func (sl *SectionList) CursorTop()

CursorTop moves the cursor to the first visible item.

func (*SectionList) CursorUp

func (sl *SectionList) CursorUp()

CursorUp moves the cursor up to the previous visible item.

func (*SectionList) DeleteComment

func (sl *SectionList) DeleteComment(sectionID string, index int)

DeleteComment removes a comment at the given index for a section.

func (*SectionList) FilterByQuery

func (sl *SectionList) FilterByQuery(query string)

FilterByQuery filters the section list to show only sections matching the query. Matching is case-insensitive against section ID, Title, and Body. If a child matches, its ancestors are shown. If a parent matches, its children are shown.

func (*SectionList) GetComments

func (sl *SectionList) GetComments(sectionID string) []*markdown.ReviewComment

GetComments returns all comments for a section.

func (*SectionList) HasComments

func (sl *SectionList) HasComments() bool

HasComments returns true if there are any comments.

func (*SectionList) IsOverviewSelected

func (sl *SectionList) IsOverviewSelected() bool

IsOverviewSelected returns true if the overview entry is selected.

func (*SectionList) IsViewed

func (sl *SectionList) IsViewed(sectionID string) bool

IsViewed returns whether a section is marked as viewed.

func (*SectionList) Render

func (sl *SectionList) Render(width, height int, styles Styles) string

Render renders the section list for display within the given height.

func (*SectionList) SelectBySectionID

func (sl *SectionList) SelectBySectionID(sectionID string)

SelectBySectionID moves the cursor to the item with the given section ID.

func (*SectionList) Selected

func (sl *SectionList) Selected() *markdown.Section

Selected returns the currently selected section (or nil for overview).

func (*SectionList) ToggleExpand

func (sl *SectionList) ToggleExpand()

ToggleExpand toggles the expand/collapse state of the current section.

func (*SectionList) ToggleViewed

func (sl *SectionList) ToggleViewed(sectionID string)

ToggleViewed toggles the viewed flag for a section.

func (*SectionList) TotalCommentCount

func (sl *SectionList) TotalCommentCount() int

TotalCommentCount returns the total number of comments across all sections.

func (*SectionList) TotalSectionCount

func (sl *SectionList) TotalSectionCount() int

TotalSectionCount returns the number of sections (excluding overview).

func (*SectionList) UpdateComment

func (sl *SectionList) UpdateComment(sectionID string, index int, comment *markdown.ReviewComment)

UpdateComment replaces a comment at the given index for a section.

func (*SectionList) ViewedCount

func (sl *SectionList) ViewedCount() int

ViewedCount returns the number of viewed sections.

func (*SectionList) ViewedState

func (sl *SectionList) ViewedState() *markdown.ViewedState

ViewedState returns the underlying ViewedState for persistence.

type SectionListItem

type SectionListItem struct {
	Section    *markdown.Section
	Depth      int
	Expanded   bool
	Visible    bool
	IsOverview bool // true for the overview (preamble) entry
}

SectionListItem is a flattened section for display in the section list.

type Styles

type Styles struct {
	ActiveBorder   lipgloss.Style
	InactiveBorder lipgloss.Style

	// Section list
	Title           lipgloss.Style
	SelectedSection lipgloss.Style
	NormalSection   lipgloss.Style
	SectionBadge    lipgloss.Style
	ViewedBadge     lipgloss.Style

	// Status bar
	StatusBar lipgloss.Style
	StatusKey lipgloss.Style

	// Comment
	CommentBorder lipgloss.Style

	// Line mode
	LineGutter   lipgloss.Style
	LineCursor   lipgloss.Style
	LineSelected lipgloss.Style

	// Diff mode
	DiffAdded   lipgloss.Style
	DiffRemoved lipgloss.Style
}

Styles holds all the lipgloss styles for the TUI.

Jump to

Keyboard shortcuts

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