diff options
38 files changed, 465 insertions, 136 deletions
diff --git a/docs/Config.md b/docs/Config.md index f57f761a7..e1d0cb689 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -90,6 +90,7 @@ Default path for the config file: undo: 'z' redo: '<c-z>' filteringMenu: <c-s> + diffingMenu: '\' status: checkForUpdate: 'u' recentRepos: '<enter>' diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 6bf74b864..5958886c3 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -1021,11 +1021,6 @@ func (c *GitCommand) ResetSoft(ref string) error { return c.OSCommand.RunCommand("git reset --soft " + ref) } -// DiffCommits show diff between commits -func (c *GitCommand) DiffCommits(sha1, sha2 string) (string, error) { - return c.OSCommand.RunCommandWithOutput("git diff --color=%s --stat -p %s %s", c.colorArg(), sha1, sha2) -} - // CreateFixupCommit creates a commit that fixes up a previous commit func (c *GitCommand) CreateFixupCommit(sha string) error { return c.OSCommand.RunCommand("git commit --fixup=%s", sha) diff --git a/pkg/commands/remote_branch.go b/pkg/commands/remote_branch.go index 0435a050f..ca39ac4c1 100644 --- a/pkg/commands/remote_branch.go +++ b/pkg/commands/remote_branch.go @@ -5,3 +5,7 @@ type RemoteBranch struct { Name string RemoteName string } + +func (r *RemoteBranch) FullName() string { + return r.RemoteName + "/" + r.Name +} diff --git a/pkg/commands/stash_entry.go b/pkg/commands/stash_entry.go index 94e4417d4..eb70693ef 100644 --- a/pkg/commands/stash_entry.go +++ b/pkg/commands/stash_entry.go @@ -1,7 +1,13 @@ package commands +import "fmt" + // StashEntry : A git stash entry type StashEntry struct { Index int Name string } + +func (s *StashEntry) RefName() string { + return fmt.Sprintf("stash@{%d}", s.Index) +} diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index 360aee9e1..72e10b095 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -321,6 +321,7 @@ keybinding: undo: 'z' redo: '<c-z>' filteringMenu: <c-s> + diffingMenu: '\' status: checkForUpdate: 'u' recentRepos: '<enter>' diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index e2c09a4d8..c3bbcb059 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -42,6 +42,10 @@ func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error { branch := gui.getSelectedBranch() v.FocusPoint(0, gui.State.Panels.Branches.SelectedLine) + if gui.inDiffMode() { + return gui.renderDiff() + } + cmd := gui.OSCommand.ExecutableFromString( gui.GitCommand.GetBranchGraphCmdStr(branch.Name), ) @@ -85,7 +89,7 @@ func (gui *Gui) renderLocalBranchesWithSelection() error { branchesView := gui.getBranchesView() gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches)) - displayStrings := presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL) + displayStrings := presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref) gui.renderDisplayStrings(branchesView, displayStrings) if gui.g.CurrentView() == branchesView { if err := gui.handleBranchSelect(gui.g, branchesView); err != nil { diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index 810a732ec..4870876c0 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -7,7 +7,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gui/presentation" ) -func (gui *Gui) getSelectedCommitFile(g *gocui.Gui) *commands.CommitFile { +func (gui *Gui) getSelectedCommitFile() *commands.CommitFile { selectedLine := gui.State.Panels.CommitFiles.SelectedLine if selectedLine == -1 { return nil @@ -34,7 +34,7 @@ func (gui *Gui) handleCommitFileSelect(g *gocui.Gui, v *gocui.View) error { gui.handleEscapeLineByLinePanel() } - commitFile := gui.getSelectedCommitFile(g) + commitFile := gui.getSelectedCommitFile() if commitFile == nil { gui.renderString(g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles")) return nil @@ -99,7 +99,7 @@ func (gui *Gui) refreshCommitFilesView() error { return err } - commit := gui.getSelectedCommit(gui.g) + commit := gui.getSelectedCommit() if commit == nil { return nil } @@ -113,14 +113,14 @@ func (gui *Gui) refreshCommitFilesView() error { gui.refreshSelectedLine(&gui.State.Panels.CommitFiles.SelectedLine, len(gui.State.CommitFiles)) commitsFileView := gui.getCommitFilesView() - displayStrings := presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles) + displayStrings := presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles, gui.State.Diff.Ref) gui.renderDisplayStrings(commitsFileView, displayStrings) return gui.handleCommitFileSelect(gui.g, commitsFileView) } func (gui *Gui) handleOpenOldCommitFile(g *gocui.Gui, v *gocui.View) error { - file := gui.getSelectedCommitFile(g) + file := gui.getSelectedCommitFile() return gui.openFile(file.Name) } @@ -129,7 +129,7 @@ func (gui *Gui) handleToggleFileForPatch(g *gocui.Gui, v *gocui.View) error { return err } - commitFile := gui.getSelectedCommitFile(g) + commitFile := gui.getSelectedCommitFile() if commitFile == nil { gui.renderString(g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles")) return nil @@ -167,7 +167,7 @@ func (gui *Gui) startPatchManager() error { diffMap[commitFile.Name] = commitText } - commit := gui.getSelectedCommit(gui.g) + commit := gui.getSelectedCommit() if commit == nil { return errors.New("No commit selected") } @@ -185,7 +185,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error { return err } - commitFile := gui.getSelectedCommitFile(gui.g) + commitFile := gui.getSelectedCommitFile() if commitFile == nil { gui.renderString(gui.g, "commitFiles", gui.Tr.SLocalize("NoCommiteFiles")) return nil diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index d2bfd4b63..cda71eb42 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -12,7 +12,7 @@ import ( // list panel functions -func (gui *Gui) getSelectedCommit(g *gocui.Gui) *commands.Commit { +func (gui *Gui) getSelectedCommit() *commands.Commit { selectedLine := gui.State.Panels.Commits.SelectedLine if selectedLine == -1 { return nil @@ -49,16 +49,15 @@ func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { gui.getSecondaryView().Title = "Custom Patch" gui.handleEscapeLineByLinePanel() - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return gui.newStringTask("main", gui.Tr.SLocalize("NoCommitsThisBranch")) } v.FocusPoint(0, gui.State.Panels.Commits.SelectedLine) - // if specific diff mode is on, don't show diff - if gui.State.Panels.Commits.SpecificDiffMode { - return nil + if gui.inDiffMode() { + return gui.renderDiff() } cmd := gui.OSCommand.ExecutableFromString( @@ -509,7 +508,7 @@ func (gui *Gui) handleCreateFixupCommit(g *gocui.Gui, v *gocui.View) error { return err } - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return nil } @@ -533,7 +532,7 @@ func (gui *Gui) handleSquashAllAboveFixupCommits(g *gocui.Gui, v *gocui.View) er return err } - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return nil } @@ -555,7 +554,7 @@ func (gui *Gui) handleTagCommit(g *gocui.Gui, v *gocui.View) error { // TODO: bring up menu asking if you want to make a lightweight or annotated tag // if annotated, switch to a subprocess to create the message - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return nil } @@ -573,7 +572,7 @@ func (gui *Gui) handleCreateLightweightTag(commitSha string) error { } func (gui *Gui) handleCheckoutCommit(g *gocui.Gui, v *gocui.View) error { - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return nil } @@ -587,7 +586,7 @@ func (gui *Gui) renderBranchCommitsWithSelection() error { commitsView := gui.getCommitsView() gui.refreshSelectedLine(&gui.State.Panels.Commits.SelectedLine, len(gui.State.Commits)) - displayStrings := presentation.GetCommitListDisplayStrings(gui.State.Commits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap()) + displayStrings := presentation.GetCommitListDisplayStrings(gui.State.Commits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap(), gui.State.Diff.Ref) gui.renderDisplayStrings(commitsView, displayStrings) if gui.g.CurrentView() == commitsView && commitsView.Context == "branch-commits" { if err := gui.handleCommitSelect(gui.g, commitsView); err != nil { @@ -649,7 +648,7 @@ func (gui *Gui) handlePrevCommitsTab(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleCreateCommitResetMenu(g *gocui.Gui, v *gocui.View) error { - commit := gui.getSelectedCommit(g) + commit := gui.getSelectedCommit() if commit == nil { return gui.createErrorPanel(gui.Tr.SLocalize("NoCommitsThisBranch")) } diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go new file mode 100644 index 000000000..a42b6b335 --- /dev/null +++ b/pkg/gui/diffing.go @@ -0,0 +1,189 @@ +package gui + +import ( + "fmt" + "strings" + + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/commands" +) + +func (gui *Gui) inDiffMode() bool { + return gui.State.Diff.Ref != "" +} + +func (gui *Gui) exitDiffMode() error { + gui.State.Diff = DiffState{} + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) +} + +func (gui *Gui) renderDiff() error { + filterArg := "" + if gui.inFilterMode() { + filterArg = fmt.Sprintf(" -- %s", gui.State.FilterPath) + } + + cmd := gui.OSCommand.ExecutableFromString( + fmt.Sprintf("git diff --color %s %s", gui.diffStr(), filterArg), + ) + if err := gui.newPtyTask("main", cmd); err != nil { + gui.Log.Error(err) + } + return nil +} + +// currentDiffTerminals returns the current diff terminals of the currently selected item. +// in the case of a branch it returns both the branch and it's upstream name, +// which becomes an option when you bring up the diff menu, but when you're just +// flicking through branches it will be using the local branch name. +func (gui *Gui) currentDiffTerminals() []string { + names := []string{} + switch gui.g.CurrentView().Name() { + case "files": + file, err := gui.getSelectedFile() + if err == nil { + names = append(names, file.Name) + } + case "commitFiles": + file := gui.getSelectedCommitFile() + if file != nil { + names = append(names, file.Name) + } + case "commits": + var commit *commands.Commit + switch gui.getCommitsView().Context { + case "reflog-commits": + commit = gui.getSelectedReflogCommit() + case "branch-commits": + commit = gui.getSelectedCommit() + } + if commit != nil { + names = append(names, commit.Sha) + } + case "stash": + entry := gui.getSelectedStashEntry() + if entry != nil { + names = append(names, entry.RefName()) + } + case "branches": + switch gui.getBranchesView().Context { + case "local-branches": + branch := gui.getSelectedBranch() + if branch != nil { + names = append(names, branch.Name) + if branch.UpstreamName != "" { + names = append(names, branch.UpstreamName) + } + } + case "remotes": + remote := gui.getSelectedRemote() + if remote != nil { + names = append(names, remote.Name) + } + case "remote-branches": + remoteBranch := gui.getSelectedRemoteBranch() + if remoteBranch != nil { + names = append(names, remoteBranch.FullName()) + } + case "tags": + tag := gui.getSelectedTag() + if tag != nil { + names = append(names, tag.Name) + } + } + } + return names +} + +func (gui *Gui) currentDiffTerminal() string { + names := gui.currentDiffTerminals() + if len(names) == 0 { + return "HEAD" + } + return names[0] +} + +func (gui *Gui) diffStr() string { + left := gui.State.Diff.Ref + right := gui.currentDiffTerminal() + if gui.State.Diff.Reverse { + left, right = right, left + } + return fmt.Sprintf("%s %s", left, right) +} + +func (gui *Gui) handleCreateDiffingMenuPanel(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + + names := gui.currentDiffTerminals() + + menuItems := []*menuItem{} + for _, name := range names { + name := name + menuItems = append(menuItems, []*menuItem{ + { + displayString: fmt.Sprintf("%s %s", gui.Tr.SLocalize("diffFrom"), name), + onPress: func() error { + gui.State.Diff.Ref = name + gui.State.Diff.Reverse = false + // can scope this down based on current view but too lazy right now + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }, + }, + { + displayString: fmt.Sprintf("%s %s", gui.Tr.SLocalize("diffTo"), name), + onPress: func() error { + gui.State.Diff.Ref = name + gui.State.Diff.Reverse = true + // can scope this down based on current view but too lazy right now + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }, + }, + }...) + } + + menuItems = append(menuItems, []*menuItem{ + { + displayString: gui.Tr.SLocalize("enterRefToDiffFrom"), + onPress: func() error { + return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enteRefName"), "", func(g *gocui.Gui, promptView *gocui.View) error { + gui.State.Diff.Ref = strings.TrimSpace(promptView.Buffer()) + gui.State.Diff.Reverse = false + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }) + }, + }, + { + displayString: gui.Tr.SLocalize("enterRefToDiffTo"), + onPress: func() error { + return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enteRefName"), "", func(g *gocui.Gui, promptView *gocui.View) error { + gui.State.Diff.Ref = strings.TrimSpace(promptView.Buffer()) + gui.State.Diff.Reverse = true + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }) + }, + }, + }...) + + menuItems = append(menuItems, &menuItem{ + displayString: gui.Tr.SLocalize("swapDiff"), + onPress: func() error { + gui.State.Diff.Reverse = !gui.State.Diff.Reverse + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }, + }) + + if gui.inDiffMode() { + menuItems = append(menuItems, &menuItem{ + displayString: gui.Tr.SLocalize("exitDiffMode"), + onPress: func() error { + gui.State.Diff = DiffState{} + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }, + }) + } + + return gui.createMenu(gui.Tr.SLocalize("DiffingMenuTitle"), menuItems, createMenuOptions{showCancel: true}) +} diff --git a/pkg/gui/discard_changes_menu_panel.go b/pkg/gui/discard_changes_menu_panel.go index 0f01ad964..0d3b6989b 100644 --- a/pkg/gui/discard_changes_menu_panel.go +++ b/pkg/gui/discard_changes_menu_panel.go @@ -5,7 +5,7 @@ import ( ) func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { if err != gui.Errors.ErrNoFiles { return err diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 7cb094837..620453d5a 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -17,7 +17,7 @@ import ( // list panel functions -func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { +func (gui *Gui) getSelectedFile() (*commands.File, error) { selectedLine := gui.State.Panels.Files.SelectedLine if selectedLine == -1 { return &commands.File{}, gui.Errors.ErrNoFiles @@ -27,7 +27,7 @@ func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { } func (gui *Gui) selectFile(alreadySelected bool) error { - file, err := gui.getSelectedFile(gui.g) + file, err := gui.getSelectedFile() if err != nil { if err != gui.Errors.ErrNoFiles { return err @@ -39,12 +39,6 @@ func (gui *Gui) selectFile(alreadySelected bool) error { gui.getFilesView().FocusPoint(0, gui.State.Panels.Files.SelectedLine) - if file.HasInlineMergeConflicts { - gui.getMainView().Title = gui.Tr.SLocalize("MergeConflictsTitle") - gui.State.SplitMainPanel = false - return gui.refreshMergePanel() - } - if !alreadySelected { if err := gui.resetOrigin(gui.getMainView()); err != nil { return err @@ -54,6 +48,16 @@ func (gui *Gui) selectFile(alreadySelected bool) error { } } + if gui.inDiffMode() { + return gui.renderDiff() + } + + if file.HasInlineMergeConflicts { + gui.getMainView().Title = gui.Tr.SLocalize("MergeConflictsTitle") + gui.State.SplitMainPanel = false + return gui.refreshMergePanel() + } + if file.HasStagedChanges && file.HasUnstagedChanges { gui.State.SplitMainPanel = true gui.getMainView().Title = gui.Tr.SLocalize("UnstagedChanges") @@ -89,7 +93,7 @@ func (gui *Gui) refreshFiles() error { gui.State.RefreshingFilesMutex.Unlock() }() - selectedFile, _ := gui.getSelectedFile(gui.g) + selectedFile, _ := gui.getSelectedFile() filesView := gui.getFilesView() if filesView == nil { @@ -101,11 +105,11 @@ func (gui *Gui) refreshFiles() error { } gui.g.Update(func(g *gocui.Gui) error { - displayStrings := presentation.GetFileListDisplayStrings(gui.State.Files) + displayStrings := presentation.GetFileListDisplayStrings(gui.State.Files, gui.State.Diff.Ref) gui.renderDisplayStrings(filesView, displayStrings) if g.CurrentView() == filesView || (g.CurrentView() == gui.getMainView() && g.CurrentView().Context == "merging") { - newSelectedFile, _ := gui.getSelectedFile(gui.g) + newSelectedFile, _ := gui.getSelectedFile() alreadySelected := newSelectedFile.Name == selectedFile.Name return gui.selectFile(alreadySelected) } @@ -140,7 +144,7 @@ func (gui *Gui) trackedFiles() []*commands.File { } func (gui *Gui) stageSelectedFile(g *gocui.Gui) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { return err } @@ -152,7 +156,7 @@ func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error { - file, err := gui.getSelectedFile(gui.g) + file, err := gui.getSelectedFile() if err != nil { if err != gui.Errors.ErrNoFiles { return err @@ -173,7 +177,7 @@ func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error } func (gui *Gui) handleFilePress(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { if err == gui.Errors.ErrNoFiles { return nil @@ -237,7 +241,7 @@ func (gui *Gui) handleStageAll(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(gui.g) + file, err := gui.getSelectedFile() if err != nil { return gui.surfaceError(err) } @@ -345,7 +349,7 @@ func (gui *Gui) editFile(filename string) error { } func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { return gui.surfaceError(err) } @@ -354,7 +358,7 @@ func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { return gui.surfaceError(err) } @@ -379,7 +383,7 @@ func (gui *Gui) refreshStateFiles() error { } func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) { - item, err := gui.getSelectedFile(g) + item, err := gui.getSelectedFile() if err != nil { if err != gui.Errors.ErrNoFiles { return "", err @@ -489,7 +493,7 @@ func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error { - file, err := gui.getSelectedFile(g) + file, err := gui.getSelectedFile() if err != nil { if err != gui.Errors.ErrNoFiles { return gui.surfaceError(err) diff --git a/pkg/gui/filtering_menu_panel.go b/pkg/gui/filtering_menu_panel.go index 316ea95d0..856b71572 100644 --- a/pkg/gui/filtering_menu_panel.go +++ b/pkg/gui/filtering_menu_panel.go @@ -7,16 +7,20 @@ import ( "github.com/jesseduffield/gocui" ) -func (gui *Gui) handleCreateScopingMenuPanel(g *gocui.Gui, v *gocui.View) error { +func (gui *Gui) handleCreateFilteringMenuPanel(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + fileName := "" switch v.Name() { case "files": - file, err := gui.getSelectedFile(gui.g) + file, err := gui.getSelectedFile() if err == nil { fileName = file.Name } case "commitFiles": - file := gui.getSelectedCommitFile(gui.g) + file := gui.getSelectedCommitFile() if file != nil { fileName = file.Name } diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go index 5f0752a6c..5df00d56f 100644 --- a/pkg/gui/global_handlers.go +++ b/pkg/gui/global_handlers.go @@ -144,6 +144,14 @@ func (gui *Gui) handleInfoClick(g *gocui.Gui, v *gocui.View) error { } } + if gui.inDiffMode() { + if width-cx <= len(gui.Tr.SLocalize("(reset)")) { + return gui.exitDiffMode() + } else { + return nil + } + } + if cx <= len(gui.Tr.SLocalize("Donate")) { return gui.OSCommand.OpenLink("https://github.com/sponsors/jesseduffield") } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 62e18f8fd..2fc029b64 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -136,9 +136,8 @@ type tagsPanelState struct { } type commitPanelState struct { - SelectedLine int - SpecificDiffMode bool - LimitCommits bool + SelectedLine int + LimitCommits bool } type reflogCommitPanelState struct {< |