Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions pkg/ui/panes/diffviewer/diffviewer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"charm.land/bubbles/v2/viewport"
Expand Down Expand Up @@ -211,6 +212,13 @@ func (m *Model) GoToTop() {
// SetSideBySide updates the diff view mode and re-renders.
func (m *Model) SetSideBySide(sideBySide bool) tea.Cmd {
m.sideBySide = sideBySide
m.cache = make(nodeCache)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be rebased with your latest changes that use the cache key per mode

if m.file != nil {
m.file.diff = ""
}
if m.dir != nil {
m.dir.diff = ""
}
return m.diff()
}

Expand All @@ -224,6 +232,36 @@ func (m *Model) ScrollDown(lines int) {
m.vp.ScrollDown(lines)
}

// deltaConfigPath returns a path to a temporary gitconfig that includes
// the user's config but overrides the side-by-side setting. This is needed
// because delta's --side-by-side flag can only enable side-by-side mode,
// not disable it when the user's config has side-by-side = true.
func deltaConfigPath(sideBySide bool) (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
gitconfig := filepath.Join(home, ".gitconfig")
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm there are cases where this won't work.
For example, my git config sits under $XDG_CONFIG_HOME/git/config which resolves to ~/.config/git/config.
I think a more bullet proof approach would be to follow https://git-scm.com/docs/git-config#FILES.

Another approach would be to call git config --list --show-origin and look for a line relating side-by-side by delta.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, not sure about this PR, this is more a problem of delta (actually clap). I tried to solve it adding --no-* flag in delta itself:
dandavison/delta#2095

Another approach would be to call git config --list --show-origin and look for a line relating side-by-side by delta

sorry, I am not sure exactly what you mean here. Could you expand on it?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, not sure about this PR, this is more a problem of delta (actually clap). I tried to solve it adding --no-* flag in delta itself: dandavison/delta#2095

Oh that's nice! Let's see how it goes.

sorry, I am not sure exactly what you mean here. Could you expand on it?

In order to understand where the git config file is, you can call git config --list --show-origin. For me its output is something like:

...
file:/Users/dlvhdr/.config/git/config   delta.syntax-theme=tokyonight_night
file:/Users/dlvhdr/.config/git/config   delta.dark=true
file:/Users/dlvhdr/.config/git/config   delta.tabs=2
file:/Users/dlvhdr/.config/git/config   delta.file-style=omit
file:/Users/dlvhdr/.config/git/config   delta.file-decoration-style=none
file:/Users/dlvhdr/.config/git/config   delta.line-numbers=true
...

You can then take the file path from the 1st column.


val := "false"
if sideBySide {
val = "true"
}
content := fmt.Sprintf("[include]\n path = %s\n[delta]\n side-by-side = %s\n", gitconfig, val)

f, err := os.CreateTemp("", "diffnav-delta-*.gitconfig")
if err != nil {
return "", err
}
if _, err := f.WriteString(content); err != nil {
f.Close()
os.Remove(f.Name())
return "", err
}
f.Close()
return f.Name(), nil
}

func diffFile(node *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
if width == 0 || node == nil || len(node.files) != 1 {
return nil
Expand All @@ -233,16 +271,19 @@ func diffFile(node *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
return func() tea.Msg {
// Only use side-by-side if preference is true AND file is not new/deleted
useSideBySide := sideBySidePreference && !file.IsNew && !file.IsDelete
configPath, err := deltaConfigPath(useSideBySide)
if err != nil {
return common.ErrMsg{Err: err}
}
defer os.Remove(configPath)

args := []string{
"--paging=never",
fmt.Sprintf("--config=%s", configPath),
fmt.Sprintf("-w=%d", width),
fmt.Sprintf("--max-line-length=%d", width),
}
if useSideBySide {
args = append(args, "--side-by-side")
}
deltac := exec.Command("delta", args...)
deltac.Env = os.Environ()
deltac.Stdin = strings.NewReader(file.String() + "\n")
out, err := deltac.Output()
if err != nil {
Expand Down Expand Up @@ -275,11 +316,14 @@ func diffDir(dir *cachedNode, width int, sideBySidePreference bool) tea.Cmd {
fmt.Sprintf("-w=%d", width),
fmt.Sprintf("--max-line-length=%d", width),
}
if useSideBySide {
args = append(args, "--side-by-side")
configPath, err := deltaConfigPath(useSideBySide)
if err != nil {
return common.ErrMsg{Err: err}
}
defer os.Remove(configPath)

args = append(args, fmt.Sprintf("--config=%s", configPath))
deltac := exec.Command("delta", args...)
deltac.Env = os.Environ()
strs := strings.Builder{}
for _, file := range dir.files {
strs.WriteString(file.String())
Expand Down