diff --git a/pkg/commands/git_commands/commit.go b/pkg/commands/git_commands/commit.go index 084a6c8d4c7..2e839bad074 100644 --- a/pkg/commands/git_commands/commit.go +++ b/pkg/commands/git_commands/commit.go @@ -270,6 +270,7 @@ func (self *CommitCommands) ShowCmdObj(hash string, filterPaths []string) *oscom Arg("-p"). Arg(hash). ArgIf(self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space"). + ArgIf(self.UserConfig().Git.UseWordDiffInDiffView, "--word-diff"). Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)). Arg("--"). Arg(filterPaths...). diff --git a/pkg/commands/git_commands/commit_test.go b/pkg/commands/git_commands/commit_test.go index 8460164ccde..309877f78de 100644 --- a/pkg/commands/git_commands/commit_test.go +++ b/pkg/commands/git_commands/commit_test.go @@ -491,3 +491,28 @@ func TestAddCoAuthorToDescription(t *testing.T) { }) } } + +func TestWordDiffConfiguration(t *testing.T) { + userConfig := config.GetDefaultConfig() + userConfig.Git.UseWordDiffInDiffView = true + + repoPaths := RepoPaths{ + worktreePath: "/path/to/worktree", + } + + runner := oscommands.NewFakeRunner(t). + ExpectGitArgs([]string{ + "-C", "/path/to/worktree", "-c", "diff.noprefix=false", "show", + "--no-ext-diff", "--submodule", "--color=always", "--unified=3", + "--stat", "--decorate", "-p", "abc123", "--word-diff", + "--find-renames=50%", "--", + }, "", nil) + + instance := buildCommitCommands(commonDeps{runner: runner, userConfig: userConfig, repoPaths: &repoPaths}) + + cmdObj := instance.ShowCmdObj("abc123", []string{}) + err := cmdObj.Run() + + assert.NoError(t, err) + runner.CheckForMissingCalls() +} diff --git a/pkg/commands/git_commands/diff.go b/pkg/commands/git_commands/diff.go index 76b67788464..5fcafd8346c 100644 --- a/pkg/commands/git_commands/diff.go +++ b/pkg/commands/git_commands/diff.go @@ -23,6 +23,7 @@ func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj { useExtDiff := extDiffCmd != "" useExtDiffGitConfig := self.UserConfig().Git.Paging.UseExternalDiffGitConfig ignoreWhitespace := self.UserConfig().Git.IgnoreWhitespaceInDiffView + useWordDiff := self.UserConfig().Git.UseWordDiffInDiffView return self.cmd.New( NewGitCmd("diff"). @@ -32,6 +33,7 @@ func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj { Arg("--submodule"). Arg(fmt.Sprintf("--color=%s", self.UserConfig().Git.Paging.ColorArg)). ArgIf(ignoreWhitespace, "--ignore-all-space"). + ArgIf(useWordDiff, "--word-diff"). Arg(fmt.Sprintf("--unified=%d", self.UserConfig().Git.DiffContextSize)). Arg(diffArgs...). Dir(self.repoPaths.worktreePath). diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go index 2a979dd54ef..9907d70887e 100644 --- a/pkg/commands/git_commands/patch.go +++ b/pkg/commands/git_commands/patch.go @@ -347,6 +347,7 @@ func (self *PatchCommands) diffHeadAgainstCommit(commit *models.Commit) (string, cmdArgs := NewGitCmd("diff"). Config("diff.noprefix=false"). Arg("--no-ext-diff"). + ArgIf(self.UserConfig().Git.UseWordDiffInDiffView, "--word-diff"). Arg("HEAD.." + commit.Hash()). ToArgv() diff --git a/pkg/commands/git_commands/stash.go b/pkg/commands/git_commands/stash.go index f6b69ae7da6..96e95742280 100644 --- a/pkg/commands/git_commands/stash.go +++ b/pkg/commands/git_commands/stash.go @@ -94,6 +94,7 @@ func (self *StashCommands) ShowStashEntryCmdObj(index int) *oscommands.CmdObj { Arg(fmt.Sprintf("--color=%s", self.UserConfig().Git.Paging.ColorArg)). Arg(fmt.Sprintf("--unified=%d", self.UserConfig().Git.DiffContextSize)). ArgIf(self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space"). + ArgIf(self.UserConfig().Git.UseWordDiffInDiffView, "--word-diff"). Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)). Arg(fmt.Sprintf("refs/stash@{%d}", index)). Dir(self.repoPaths.worktreePath). diff --git a/pkg/commands/git_commands/working_tree.go b/pkg/commands/git_commands/working_tree.go index e6b066d346f..c9235ec783a 100644 --- a/pkg/commands/git_commands/working_tree.go +++ b/pkg/commands/git_commands/working_tree.go @@ -276,6 +276,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain Arg(fmt.Sprintf("--unified=%d", contextSize)). Arg(fmt.Sprintf("--color=%s", colorArg)). ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space"). + ArgIf(!plain && self.UserConfig().Git.UseWordDiffInDiffView, "--word-diff"). Arg(fmt.Sprintf("--find-renames=%d%%", self.UserConfig().Git.RenameSimilarityThreshold)). ArgIf(cached, "--cached"). ArgIf(noIndex, "--no-index"). @@ -319,6 +320,7 @@ func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reve Arg(to). ArgIf(reverse, "-R"). ArgIf(!plain && self.UserConfig().Git.IgnoreWhitespaceInDiffView, "--ignore-all-space"). + ArgIf(!plain && self.UserConfig().Git.UseWordDiffInDiffView, "--word-diff"). Arg("--"). Arg(fileName). Dir(self.repoPaths.worktreePath). diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index c30d030aeaf..006b8d5da7e 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -266,6 +266,8 @@ type GitConfig struct { AllBranchesLogCmds []string `yaml:"allBranchesLogCmds"` // If true, git diffs are rendered with the `--ignore-all-space` flag, which ignores whitespace changes. Can be toggled from within Lazygit with ``. IgnoreWhitespaceInDiffView bool `yaml:"ignoreWhitespaceInDiffView"` + // If true, git diffs use word-diff mode. Can be toggled from within Lazygit with ``. + UseWordDiffInDiffView bool `yaml:"useWordDiffInDiffView"` // The number of lines of context to show around each diff hunk. Can be changed from within Lazygit with the `{` and `}` keys. DiffContextSize uint64 `yaml:"diffContextSize"` // The threshold for considering a file to be renamed, in percent. Can be changed from within Lazygit with the `(` and `)` keys. @@ -828,6 +830,7 @@ func GetDefaultConfig() *UserConfig { BranchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --", AllBranchesLogCmds: []string{"git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium"}, IgnoreWhitespaceInDiffView: false, + UseWordDiffInDiffView: false, DiffContextSize: 3, RenameSimilarityThreshold: 50, DisableForcePushing: false, diff --git a/pkg/gui/controllers/diffing_menu_action.go b/pkg/gui/controllers/diffing_menu_action.go index a53ad65e5d1..6f1fcbbaed2 100644 --- a/pkg/gui/controllers/diffing_menu_action.go +++ b/pkg/gui/controllers/diffing_menu_action.go @@ -49,6 +49,17 @@ func (self *DiffingMenuAction) Call() error { }, }...) + menuItems = append(menuItems, []*types.MenuItem{ + { + Label: self.c.Tr.ToggleWordDiffInDiffView, + OnPress: func() error { + self.c.UserConfig().Git.UseWordDiffInDiffView = !self.c.UserConfig().Git.UseWordDiffInDiffView + self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) + return nil + }, + }, + }...) + if self.c.Modes().Diffing.Active() { menuItems = append(menuItems, []*types.MenuItem{ { diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index 734e6551608..fac52e1d73b 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -224,6 +224,10 @@ func (self *GlobalController) toggleWhitespace() error { return (&ToggleWhitespaceAction{c: self.c}).Call() } +func (self *GlobalController) toggleWordDiff() error { + return (&ToggleWordDiffAction{c: self.c}).Call() +} + func (self *GlobalController) canShowRebaseOptions() *types.DisabledReason { if self.c.Model().WorkingTreeStateAtLastCommitRefresh.None() { return &types.DisabledReason{ diff --git a/pkg/gui/controllers/toggle_word_diff_action.go b/pkg/gui/controllers/toggle_word_diff_action.go new file mode 100644 index 00000000000..1cc7275cc89 --- /dev/null +++ b/pkg/gui/controllers/toggle_word_diff_action.go @@ -0,0 +1,14 @@ +package controllers + +import "github.com/jesseduffield/lazygit/pkg/gui/types" + +type ToggleWordDiffAction struct { + c *ControllerCommon +} + +func (self *ToggleWordDiffAction) Call() error { + self.c.UserConfig().Git.UseWordDiffInDiffView = !self.c.UserConfig().Git.UseWordDiffInDiffView + + self.c.Context().CurrentSide().HandleFocus(types.OnFocusOpts{}) + return nil +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index d162d20dc20..67bba1554ef 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -737,6 +737,7 @@ type TranslationSet struct { CommandLogHeader string RandomTip string ToggleWhitespaceInDiffView string + ToggleWordDiffInDiffView string ToggleWhitespaceInDiffViewTooltip string IgnoreWhitespaceDiffViewSubTitle string IgnoreWhitespaceNotSupportedHere string @@ -1819,6 +1820,7 @@ func EnglishTranslationSet() *TranslationSet { CommandLogHeader: "You can hide/focus this panel by pressing '%s'\n", RandomTip: "Random tip", ToggleWhitespaceInDiffView: "Toggle whitespace", + ToggleWordDiffInDiffView: "Toggle word diff", ToggleWhitespaceInDiffViewTooltip: "Toggle whether or not whitespace changes are shown in the diff view.\n\nThe default can be changed in the config file with the key 'git.ignoreWhitespaceInDiffView'.", IgnoreWhitespaceDiffViewSubTitle: "(ignoring whitespace)", IgnoreWhitespaceNotSupportedHere: "Ignoring whitespace is not supported in this view",