Documentation
¶
Overview ¶
Package model is the Bubble Tea root: it owns the diff, the selection, and every child component, and routes each key to the handler for the current mode.
Index ¶
- func KeyPress(key rune) tea.KeyMsg
- func SpecialKey(keyType tea.KeyType) tea.KeyMsg
- func TestChanges() []diff.FileChange
- type Assertion
- func (a *Assertion) FileListFilterModeDisabled()
- func (a *Assertion) FileListFilterModeEnabled()
- func (a *Assertion) FocusedPanelIs(panel FocusedPanel)
- func (a *Assertion) HasChanges(count int)
- func (a *Assertion) HasDestination(dest string)
- func (a *Assertion) HasError()
- func (a *Assertion) HasHunkNotSelected(filePath string, hunkIdx int)
- func (a *Assertion) HasHunkSelected(filePath string, hunkIdx int)
- func (a *Assertion) HasLineCursor(position int)
- func (a *Assertion) HasNoError()
- func (a *Assertion) HasSelectedFile(idx int)
- func (a *Assertion) HasSelectedHunk(idx int)
- func (a *Assertion) HelpIsNotVisible()
- func (a *Assertion) HelpIsVisible()
- func (a *Assertion) IsInVisualMode()
- func (a *Assertion) IsNotInVisualMode()
- func (a *Assertion) ModeIs(mode OperatingMode)
- func (a *Assertion) NoModalsVisible()
- func (a *Assertion) SearchIsNotVisible()
- func (a *Assertion) SearchIsVisible()
- type DestinationSpec
- type DestinationType
- type FileSelection
- type FocusedPanel
- type HunkSelection
- type Model
- func NewModel(client *jj.Client, source, destination string, mode OperatingMode, ...) (Model, error)
- func NewModelWithSource(source diff.Source, client *jj.Client, destination string, mode OperatingMode, ...) (Model, error)
- func NewTestModel(t *testing.T, mode OperatingMode) Model
- func Update(t *testing.T, m Model, msg tea.Msg) Model
- type MultiSplitState
- type OperatingMode
- type SelectionState
- func (s *SelectionState) HasPartialSelection(filePath string, hunkIdx int) bool
- func (s *SelectionState) IsHunkSelected(filePath string, hunkIdx int) bool
- func (s *SelectionState) IsLineSelected(filePath string, hunkIdx, lineIdx int) bool
- func (s *SelectionState) SelectLineRange(filePath string, hunkIdx, startLine, endLine int)
- func (s *SelectionState) ToggleHunk(filePath string, hunkIdx int)
- func (s *SelectionState) ToggleLine(filePath string, hunkIdx, lineIdx int)
- type SplitTag
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SpecialKey ¶
SpecialKey builds the message Bubble Tea sends for a named key such as tea.KeyEsc.
func TestChanges ¶
func TestChanges() []diff.FileChange
TestChanges returns three file changes covering the modified, added, and deleted paths.
Types ¶
type Assertion ¶ added in v0.1.2
type Assertion struct {
// contains filtered or unexported fields
}
Assertion reads unexported Model state, which is why it lives in the package rather than a test file. Every check reports through t.Errorf and returns the receiver, so a chain runs to the end and reports every mismatch instead of stopping at the first.
func Assert ¶
Assert opens a chain of assertions over a snapshot of m. Later mutations of m are not observed.
func (*Assertion) FileListFilterModeDisabled ¶ added in v0.1.2
func (a *Assertion) FileListFilterModeDisabled()
FileListFilterModeDisabled checks that the file list has handed key handling back to the model.
func (*Assertion) FileListFilterModeEnabled ¶ added in v0.1.2
func (a *Assertion) FileListFilterModeEnabled()
FileListFilterModeEnabled checks that the file list is capturing keys for its inline filter.
func (*Assertion) FocusedPanelIs ¶ added in v0.1.2
func (a *Assertion) FocusedPanelIs(panel FocusedPanel)
FocusedPanelIs checks which panel receives navigation keys.
func (*Assertion) HasChanges ¶ added in v0.1.2
HasChanges checks how many file changes are loaded, ignoring any file-list filter.
func (*Assertion) HasDestination ¶ added in v0.1.2
HasDestination checks the revset the model will move changes to, which is empty until one is picked.
func (*Assertion) HasError ¶ added in v0.1.2
func (a *Assertion) HasError()
HasError checks that the model is holding an error for the view to render.
func (*Assertion) HasHunkNotSelected ¶ added in v0.1.2
HasHunkNotSelected checks that no part of the hunk is marked for apply.
func (*Assertion) HasHunkSelected ¶ added in v0.1.2
HasHunkSelected checks that the hunk is marked for apply. A partially selected hunk still counts.
func (*Assertion) HasLineCursor ¶ added in v0.1.2
HasLineCursor checks the line cursor as an index into the rendered rows of the selected hunk.
func (*Assertion) HasNoError ¶ added in v0.1.2
func (a *Assertion) HasNoError()
HasNoError checks that no error is pending, and prints the error it found when one is.
func (*Assertion) HasSelectedFile ¶ added in v0.1.2
HasSelectedFile checks the file-list cursor, which is an index into the unfiltered change list.
func (*Assertion) HasSelectedHunk ¶ added in v0.1.2
HasSelectedHunk checks the hunk cursor, which is an index within the currently selected file only.
func (*Assertion) HelpIsNotVisible ¶ added in v0.1.2
func (a *Assertion) HelpIsNotVisible()
HelpIsNotVisible checks that the help overlay is down.
func (*Assertion) HelpIsVisible ¶ added in v0.1.2
func (a *Assertion) HelpIsVisible()
HelpIsVisible checks that the help overlay is up.
func (*Assertion) IsInVisualMode ¶ added in v0.1.2
func (a *Assertion) IsInVisualMode()
IsInVisualMode checks that line-range selection is active.
func (*Assertion) IsNotInVisualMode ¶ added in v0.1.2
func (a *Assertion) IsNotInVisualMode()
IsNotInVisualMode checks that line-range selection is off, so space acts on the whole hunk.
func (*Assertion) ModeIs ¶ added in v0.1.2
func (a *Assertion) ModeIs(mode OperatingMode)
ModeIs checks the operating mode, which is fixed at construction and never changes at runtime.
func (*Assertion) NoModalsVisible ¶ added in v0.1.2
func (a *Assertion) NoModalsVisible()
NoModalsVisible checks every overlay and the file-list filter at once, reporting each one that is up.
func (*Assertion) SearchIsNotVisible ¶ added in v0.1.2
func (a *Assertion) SearchIsNotVisible()
SearchIsNotVisible checks that the search prompt is down.
func (*Assertion) SearchIsVisible ¶ added in v0.1.2
func (a *Assertion) SearchIsVisible()
SearchIsVisible checks that the search prompt is up, which is separate from the file-list filter.
type DestinationSpec ¶
type DestinationSpec struct {
ChangeID string
Description string
Type DestinationType
}
DestinationSpec is where one tag's hunks land. ChangeID is empty for DestNewCommit, where Description becomes the message of the commit that gets created.
type DestinationType ¶
type DestinationType int
DestinationType separates a split target that already exists from one that will be created.
const ( DestExistingRevision DestinationType = iota DestNewCommit )
Destinations a tag can be sent to. DestExistingRevision is the zero value, so a DestinationSpec that was never filled in reads as targeting an existing revision.
type FileSelection ¶
type FileSelection struct {
Hunks map[int]*HunkSelection
}
FileSelection holds one file's selected hunks, keyed by the hunk's index in the parsed file. The indices go stale when the diff is reloaded.
type FocusedPanel ¶
type FocusedPanel int
FocusedPanel is which of the two panes takes navigation keys.
const ( PanelFileList FocusedPanel = iota PanelDiffView )
The two panes Tab switches between. PanelFileList is the zero value, so a fresh model starts on the file list.
type HunkSelection ¶
HunkSelection is one hunk's selection. WholeHunk wins over SelectedLines, and selecting the whole hunk discards the per-line set, so the two are never both meaningful.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the whole application state. Bubble Tea passes it by value, so Update returns the updated copy and mutating a Model a handler received has no effect unless that copy is returned.
func NewModel ¶
func NewModel( client *jj.Client, source, destination string, mode OperatingMode, cfg config.Config, ) (Model, error)
NewModel builds a model reading its diff from a jj revision.
func NewModelWithSource ¶
func NewModelWithSource( source diff.Source, client *jj.Client, destination string, mode OperatingMode, cfg config.Config, ) (Model, error)
NewModelWithSource builds a model over any diff source, which is how diff-editor mode supplies two directories instead of a revision. The client is still needed for the write paths and may only be nil when nothing will be applied.
func NewTestModel ¶
func NewTestModel(t *testing.T, mode OperatingMode) Model
NewTestModel builds a Model backed by a jj client rooted at a fresh temp dir.
func Update ¶
Update runs one Update round and asserts the result is still a Model, discarding the command.
func (Model) Init ¶
Init starts the first diff load. Nothing is rendered until it returns and a window size arrives.
func (Model) Update ¶
Update handles one message and returns the model to use next. The concrete type is always Model, so callers chaining updates can assert it.
func (Model) View ¶
View renders the two panels, or the overlay that is up. It returns the empty string until the first tea.WindowSizeMsg arrives, because every width is derived from m.width.
func (Model) WithChanges ¶
func (m Model) WithChanges(changes []diff.FileChange) Model
WithChanges loads changes and selects the first file, mirroring what a real diff load does.
func (Model) WithDestination ¶
WithDestination sets the move destination without going through the picker.
type MultiSplitState ¶
type MultiSplitState struct {
Selections map[SplitTag]*SelectionState
Destinations map[SplitTag]*DestinationSpec
CurrentTag SplitTag
Active bool
}
MultiSplitState is an in-progress multi-way split: one selection and one destination per tag. A tag with a selection but no destination is incomplete and blocks the split from being applied.
func NewMultiSplitState ¶
func NewMultiSplitState() *MultiSplitState
NewMultiSplitState returns an inactive split with 'A' as the current tag.
type OperatingMode ¶
type OperatingMode int
OperatingMode is which of the three entry points the app was started for, which decides what the selection means and what applying it does.
const ( ModeBrowse OperatingMode = iota ModeInteractive ModeDiffEditor )
The three ways the app is launched. ModeBrowse is read-only, ModeInteractive moves selected hunks into another revision, and ModeDiffEditor writes the selection back into the trees jj passed.
type SelectionState ¶
type SelectionState struct {
Files map[string]*FileSelection
}
SelectionState is what the user has picked across every file, keyed by the diff's path. Build it with NewSelectionState, because the mutators assume the map exists.
func NewSelectionState ¶
func NewSelectionState() *SelectionState
NewSelectionState returns an empty selection.
func (*SelectionState) HasPartialSelection ¶
func (s *SelectionState) HasPartialSelection(filePath string, hunkIdx int) bool
HasPartialSelection reports whether a hunk has lines picked without being selected as a whole, which is what the renderer draws the partial marker for.
func (*SelectionState) IsHunkSelected ¶
func (s *SelectionState) IsHunkSelected(filePath string, hunkIdx int) bool
IsHunkSelected reports whether the whole hunk is selected, which is false for a hunk that only has individual lines picked.
func (*SelectionState) IsLineSelected ¶
func (s *SelectionState) IsLineSelected(filePath string, hunkIdx, lineIdx int) bool
IsLineSelected reports whether one line is selected, which is true for every line of a hunk selected as a whole.
func (*SelectionState) SelectLineRange ¶
func (s *SelectionState) SelectLineRange(filePath string, hunkIdx, startLine, endLine int)
SelectLineRange selects an inclusive range of lines, accepting the bounds in either order. It clears whole-hunk selection, and it only adds, so lines already selected outside the range stay.
func (*SelectionState) ToggleHunk ¶
func (s *SelectionState) ToggleHunk(filePath string, hunkIdx int)
ToggleHunk flips whole-hunk selection, creating the file and hunk entries as needed. Selecting a hunk discards any lines picked inside it, so a toggle out and back in loses the line selection.
func (*SelectionState) ToggleLine ¶
func (s *SelectionState) ToggleLine(filePath string, hunkIdx, lineIdx int)
ToggleLine flips one line's selection. It does nothing while the hunk is selected as a whole, because that state has no per-line detail to change.