tui

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 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() string

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) 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() string

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

	// 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) 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() string

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