Skip to content

Improve clicking in diff view to enter staging/patch building #3985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ gui:
# paragraphs of markdown text.
wrapLinesInStagingView: true

# If true, show a selection when the main view is focused.
showSelectionInFocusedMainView: false

# One of 'auto' (default) | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
language: auto

Expand Down
32 changes: 32 additions & 0 deletions pkg/commands/patch/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,38 @@ func (self *Patch) LineNumberOfLine(idx int) int {
return hunk.newStart + offset
}

// Takes a line number in the new file and returns the line index in the patch.
// This is the opposite of LineNumberOfLine.
// If the line number is not contained in any of the hunks, it returns the
// closest position.
func (self *Patch) PatchLineForLineNumber(lineNumber int) int {
if len(self.hunks) == 0 {
return len(self.header)
}

for hunkIdx, hunk := range self.hunks {
if lineNumber <= hunk.newStart {
return self.HunkStartIdx(hunkIdx)
}

if lineNumber < hunk.newStart+hunk.newLength() {
lines := hunk.bodyLines
offset := lineNumber - hunk.newStart
for i, line := range lines {
if offset == 0 {
return self.HunkStartIdx(hunkIdx) + i + 1
}

if line.Kind == ADDITION || line.Kind == CONTEXT {
offset--
}
}
}
}

return self.LineCount() - 1
}

// Returns hunk index containing the line at the given patch line index
func (self *Patch) HunkContainingLine(idx int) int {
for hunkIdx, hunk := range self.hunks {
Expand Down
37 changes: 20 additions & 17 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ type GuiConfig struct {
// makes it much easier to work with diffs that have long lines, e.g.
// paragraphs of markdown text.
WrapLinesInStagingView bool `yaml:"wrapLinesInStagingView"`
// If true, show a selection when the main view is focused.
ShowSelectionInFocusedMainView bool `yaml:"showSelectionInFocusedMainView"`
// One of 'auto' (default) | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
Language string `yaml:"language" jsonschema:"enum=auto,enum=en,enum=zh-TW,enum=zh-CN,enum=pl,enum=nl,enum=ja,enum=ko,enum=ru"`
// Format used when displaying time e.g. commit time.
Expand Down Expand Up @@ -735,23 +737,24 @@ type IconProperties struct {
func GetDefaultConfig() *UserConfig {
return &UserConfig{
Gui: GuiConfig{
ScrollHeight: 2,
ScrollPastBottom: true,
ScrollOffMargin: 2,
ScrollOffBehavior: "margin",
TabWidth: 4,
MouseEvents: true,
SkipDiscardChangeWarning: false,
SkipStashWarning: false,
SidePanelWidth: 0.3333,
ExpandFocusedSidePanel: false,
ExpandedSidePanelWeight: 2,
MainPanelSplitMode: "flexible",
EnlargedSideViewLocation: "left",
WrapLinesInStagingView: true,
Language: "auto",
TimeFormat: "02 Jan 06",
ShortTimeFormat: time.Kitchen,
ScrollHeight: 2,
ScrollPastBottom: true,
ScrollOffMargin: 2,
ScrollOffBehavior: "margin",
TabWidth: 4,
MouseEvents: true,
SkipDiscardChangeWarning: false,
SkipStashWarning: false,
SidePanelWidth: 0.3333,
ExpandFocusedSidePanel: false,
ExpandedSidePanelWeight: 2,
MainPanelSplitMode: "flexible",
EnlargedSideViewLocation: "left",
WrapLinesInStagingView: true,
ShowSelectionInFocusedMainView: false,
Language: "auto",
TimeFormat: "02 Jan 06",
ShortTimeFormat: time.Kitchen,
Theme: ThemeConfig{
ActiveBorderColor: []string{"green", "bold"},
SearchingActiveBorderColor: []string{"cyan", "bold"},
Expand Down
4 changes: 4 additions & 0 deletions pkg/gui/context/base_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,7 @@ func (self *BaseContext) Title() string {
func (self *BaseContext) TotalContentHeight() int {
return self.view.ViewLinesHeight()
}

func (self *BaseContext) SetHighlightOnFocus(value bool) {
self.highlightOnFocus = value
}
2 changes: 1 addition & 1 deletion pkg/gui/context/main_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewMainContext(
WindowName: windowName,
Key: key,
Focusable: true,
HighlightOnFocus: false,
HighlightOnFocus: c.UserConfig().Gui.ShowSelectionInFocusedMainView,
})),
SearchTrait: NewSearchTrait(c),
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/gui/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ func (gui *Gui) resetHelpersAndControllers() {

gpgHelper := helpers.NewGpgHelper(helperCommon)
viewHelper := helpers.NewViewHelper(helperCommon, gui.State.Contexts)
windowHelper := helpers.NewWindowHelper(helperCommon, viewHelper)
patchBuildingHelper := helpers.NewPatchBuildingHelper(helperCommon)
stagingHelper := helpers.NewStagingHelper(helperCommon)
stagingHelper := helpers.NewStagingHelper(helperCommon, windowHelper)
mergeConflictsHelper := helpers.NewMergeConflictsHelper(helperCommon)
searchHelper := helpers.NewSearchHelper(helperCommon)

Expand All @@ -75,7 +76,6 @@ func (gui *Gui) resetHelpersAndControllers() {
rebaseHelper,
)
bisectHelper := helpers.NewBisectHelper(helperCommon)
windowHelper := helpers.NewWindowHelper(helperCommon, viewHelper)
modeHelper := helpers.NewModeHelper(
helperCommon,
diffHelper,
Expand Down Expand Up @@ -115,6 +115,7 @@ func (gui *Gui) resetHelpersAndControllers() {
AmendHelper: helpers.NewAmendHelper(helperCommon, gpgHelper),
FixupHelper: helpers.NewFixupHelper(helperCommon),
Commits: commitsHelper,
CommitFiles: helpers.NewCommitFilesHelper(helperCommon),
Snake: helpers.NewSnakeHelper(helperCommon),
Diff: diffHelper,
Repos: reposHelper,
Expand Down
100 changes: 30 additions & 70 deletions pkg/gui/controllers/commits_files_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
toggle := func() error {
return self.c.WithWaitingStatus(self.c.Tr.UpdatingPatch, func(gocui.Task) error {
if !self.c.Git().Patch.PatchBuilder.Active() {
if err := self.startPatchBuilder(); err != nil {
if err := self.c.Helpers().CommitFiles.StartPatchBuilder(); err != nil {
return err
}
}
Expand Down Expand Up @@ -429,7 +429,7 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
})
}

from, to, reverse := self.currentFromToReverseForPatchBuilding()
from, to, reverse := self.c.Helpers().CommitFiles.CurrentFromToReverseForPatchBuilding()
if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) {
self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.DiscardPatch,
Expand All @@ -451,72 +451,8 @@ func (self *CommitFilesController) toggleAllForPatch(_ *filetree.CommitFileNode)
return self.toggleForPatch([]*filetree.CommitFileNode{root})
}

func (self *CommitFilesController) startPatchBuilder() error {
commitFilesContext := self.context()

canRebase := commitFilesContext.GetCanRebase()
from, to, reverse := self.currentFromToReverseForPatchBuilding()

self.c.Git().Patch.PatchBuilder.Start(from, to, reverse, canRebase)
return nil
}

func (self *CommitFilesController) currentFromToReverseForPatchBuilding() (string, string, bool) {
commitFilesContext := self.context()

from, to := commitFilesContext.GetFromAndToForDiff()
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from)
return from, to, reverse
}

func (self *CommitFilesController) enter(node *filetree.CommitFileNode) error {
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
}

func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode, opts types.OnFocusOpts) error {
if node.File == nil {
return self.handleToggleCommitFileDirCollapsed(node)
}

if self.c.AppState.DiffContextSize == 0 {
return fmt.Errorf(self.c.Tr.Actions.NotEnoughContextToStage,
keybindings.Label(self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView))
}

enterTheFile := func() error {
if !self.c.Git().Patch.PatchBuilder.Active() {
if err := self.startPatchBuilder(); err != nil {
return err
}
}

self.c.Context().Push(self.c.Contexts().CustomPatchBuilder, opts)
return nil
}

from, to, reverse := self.currentFromToReverseForPatchBuilding()
if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) {
self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.DiscardPatch,
Prompt: self.c.Tr.DiscardPatchConfirm,
HandleConfirm: func() error {
self.c.Git().Patch.PatchBuilder.Reset()
return enterTheFile()
},
})

return nil
}

return enterTheFile()
}

func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *filetree.CommitFileNode) error {
self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetInternalPath())

self.c.PostRefreshUpdate(self.context())

return nil
return self.c.Helpers().CommitFiles.EnterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
}

// NOTE: this is very similar to handleToggleFileTreeView, could be DRY'd with generics
Expand Down Expand Up @@ -545,11 +481,35 @@ func (self *CommitFilesController) expandAll() error {

func (self *CommitFilesController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error {
return func(mainViewName string, clickedLineIdx int) error {
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(mainViewName, clickedLineIdx)
if !ok {
line = -1
}

node := self.getSelectedItem()
if node != nil && node.File != nil {
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: clickedLineIdx})
if node == nil {
return nil
}
return nil

if !node.IsFile() && ok {
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
if err != nil {
return err
}
relativePath = "./" + relativePath
self.context().CommitFileTreeViewModel.ExpandToPath(relativePath)
self.c.PostRefreshUpdate(self.context())

idx, ok := self.context().CommitFileTreeViewModel.GetIndexForPath(relativePath)
if ok {
self.context().SetSelectedLineIdx(idx)
self.context().GetViewTrait().FocusPoint(
self.context().ModelIndexToViewIndex(idx))
node = self.context().GetSelected()
}
}

return self.c.Helpers().CommitFiles.EnterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: line, ClickedViewRealLineIdx: line})
}
}

Expand Down
33 changes: 28 additions & 5 deletions pkg/gui/controllers/files_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,34 @@ func (self *FilesController) GetOnClick() func() error {

func (self *FilesController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error {
return func(mainViewName string, clickedLineIdx int) error {
node := self.getSelectedItem()
if node != nil && node.File != nil {
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: clickedLineIdx})
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(mainViewName, clickedLineIdx)
if !ok {
line = -1
}
return nil

node := self.context().GetSelected()
if node == nil {
return nil
}

if !node.IsFile() && ok {
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
if err != nil {
return err
}
relativePath = "./" + relativePath
self.context().FileTreeViewModel.ExpandToPath(relativePath)
self.c.PostRefreshUpdate(self.context())

idx, ok := self.context().FileTreeViewModel.GetIndexForPath(relativePath)
if ok {
self.context().SetSelectedLineIdx(idx)
self.context().GetViewTrait().FocusPoint(
self.context().ModelIndexToViewIndex(idx))
}
}

return self.EnterFile(types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: line, ClickedViewRealLineIdx: line})
}
}

Expand Down Expand Up @@ -511,7 +534,7 @@ func (self *FilesController) getSelectedFile() *models.File {
}

func (self *FilesController) enter() error {
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
}

func (self *FilesController) collapseAll() error {
Expand Down
Loading
Loading