mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
A diff renderer may lay a diff out however it likes: line numbers in a gutter, the +/- column replaced by colour, the two sides in columns. Once it has, we can only tell which line of which file a row shows if the renderer says so. Under a renderer that doesn't say, the main view holds a diff that can be read but not staged, edited or copied from. That is no good now that the main view is where you stage. So focusing it brings git's own diff instead, and every re-render while it stays focused keeps to that, so staging a hunk doesn't flip back. Browsing is untouched: you see what the renderer produced until you focus the view to act on it. Whether the renderer says anything is settled by asking it rather than by watching it work: run it on empty input and see whether it announces the protocol. Announcing is a property of the renderer, so the answer is known before we render anything, and a diff with no lines to describe can't fool it. Watching would have to see a diff go by first, and a binary file's diff holds nothing that would tell the two cases apart. The answer is remembered until the renderer changes. git itself is asked the same question, with the renderer's own arguments, since it announces itself for exactly the formats whose output can't be read back as a diff. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
106 lines
3.5 KiB
Go
106 lines
3.5 KiB
Go
package controllers
|
|
|
|
import (
|
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
|
"github.com/jesseduffield/lazygit/pkg/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
// This controller is for all contexts that can focus their main view.
|
|
|
|
var _ types.IController = &SwitchToFocusedMainViewController{}
|
|
|
|
type SwitchToFocusedMainViewController struct {
|
|
baseController
|
|
c *ControllerCommon
|
|
context types.Context
|
|
}
|
|
|
|
func NewSwitchToFocusedMainViewController(
|
|
c *ControllerCommon,
|
|
context types.Context,
|
|
) *SwitchToFocusedMainViewController {
|
|
return &SwitchToFocusedMainViewController{
|
|
baseController: baseController{},
|
|
c: c,
|
|
context: context,
|
|
}
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
|
bindings := []*types.Binding{
|
|
{
|
|
Keys: opts.GetKeys(opts.Config.Universal.FocusMainView),
|
|
Handler: self.handleFocusMainView,
|
|
Description: self.c.Tr.FocusMainView,
|
|
Tag: "global",
|
|
},
|
|
}
|
|
|
|
return bindings
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
|
return []*gocui.ViewMouseBinding{
|
|
{
|
|
ViewName: "main",
|
|
Key: gocui.MouseLeft,
|
|
Handler: self.onClickMain,
|
|
FocusedView: self.context.GetViewName(),
|
|
},
|
|
{
|
|
ViewName: "secondary",
|
|
Key: gocui.MouseLeft,
|
|
Handler: self.onClickSecondary,
|
|
FocusedView: self.context.GetViewName(),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) Context() types.Context {
|
|
return self.context
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) onClickMain(opts gocui.ViewMouseBindingOpts) error {
|
|
return self.focusMainView(self.c.Contexts().Normal, opts.Y)
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error {
|
|
return self.focusMainView(self.c.Contexts().NormalSecondary, opts.Y)
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) handleFocusMainView() error {
|
|
// Usually the main pane, but the content can be in the secondary one alone: a file
|
|
// with nothing but staged changes shows them there.
|
|
mainViewContext := self.c.Contexts().Normal
|
|
if self.c.State().GetRepoState().GetMainPanes() == types.SecondaryPaneOnly {
|
|
mainViewContext = self.c.Contexts().NormalSecondary
|
|
}
|
|
return self.focusMainView(mainViewContext, -1)
|
|
}
|
|
|
|
func (self *SwitchToFocusedMainViewController) focusMainView(mainViewContext *context.MainContext, clickedLineIdx int) error {
|
|
mainViewContext.ClearSearchString()
|
|
self.c.Context().Push(mainViewContext, types.OnFocusOpts{})
|
|
|
|
if _, ok := self.context.(types.DiffMainViewContext); !ok {
|
|
return nil
|
|
}
|
|
|
|
// The diff on screen was produced for reading, and the renderer that produced it may
|
|
// have laid it out in a way that says nothing about which line of which file each row
|
|
// is. Now that the user wants to act on it, it is re-rendered as git's own diff — the
|
|
// panel below decides that for itself, from the same question — and the selection
|
|
// goes on that instead of on rows we can't place.
|
|
if self.c.Helpers().DiffLine.MainViewDiffMode() == git_commands.DiffModeRaw {
|
|
self.c.Helpers().DiffLine.RenderFocusedMainViewAgain(mainViewContext.GetView(), self.context, func() {
|
|
self.c.Helpers().DiffLine.EstablishSelection(mainViewContext, clickedLineIdx)
|
|
})
|
|
return nil
|
|
}
|
|
|
|
self.c.Helpers().DiffLine.EstablishSelection(mainViewContext, clickedLineIdx)
|
|
return nil
|
|
}
|