mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 04:15:48 +02:00
Add user config gui.showNumstatInFilesView
When enabled, it adds "+n -m" after each file in the Files panel to show how many lines were added and deleted, as with `git diff --numstat` on the command line.
This commit is contained in:
parent
f3a5c184e1
commit
f455f99705
9 changed files with 174 additions and 33 deletions
|
@ -164,6 +164,9 @@ gui:
|
||||||
# This can be toggled from within Lazygit with the '~' key, but that will not change the default.
|
# This can be toggled from within Lazygit with the '~' key, but that will not change the default.
|
||||||
showFileTree: true
|
showFileTree: true
|
||||||
|
|
||||||
|
# If true, show the number of lines changed per file in the Files view
|
||||||
|
showNumstatInFilesView: false
|
||||||
|
|
||||||
# If true, show a random tip in the command log when Lazygit starts
|
# If true, show a random tip in the command log when Lazygit starts
|
||||||
showRandomTip: true
|
showRandomTip: true
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package git_commands
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
@ -48,6 +49,14 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File
|
||||||
}
|
}
|
||||||
files := []*models.File{}
|
files := []*models.File{}
|
||||||
|
|
||||||
|
fileDiffs := map[string]FileDiff{}
|
||||||
|
if self.GitCommon.Common.UserConfig().Gui.ShowNumstatInFilesView {
|
||||||
|
fileDiffs, err = self.getFileDiffs()
|
||||||
|
if err != nil {
|
||||||
|
self.Log.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
if strings.HasPrefix(status.StatusString, "warning") {
|
if strings.HasPrefix(status.StatusString, "warning") {
|
||||||
self.Log.Warningf("warning when calling git status: %s", status.StatusString)
|
self.Log.Warningf("warning when calling git status: %s", status.StatusString)
|
||||||
|
@ -60,6 +69,11 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File
|
||||||
DisplayString: status.StatusString,
|
DisplayString: status.StatusString,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if diff, ok := fileDiffs[status.Name]; ok {
|
||||||
|
file.LinesAdded = diff.LinesAdded
|
||||||
|
file.LinesDeleted = diff.LinesDeleted
|
||||||
|
}
|
||||||
|
|
||||||
models.SetStatusFields(file, status.Change)
|
models.SetStatusFields(file, status.Change)
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
}
|
}
|
||||||
|
@ -87,6 +101,45 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FileDiff struct {
|
||||||
|
LinesAdded int
|
||||||
|
LinesDeleted int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fileLoader *FileLoader) getFileDiffs() (map[string]FileDiff, error) {
|
||||||
|
diffs, err := fileLoader.gitDiffNumStat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
splitLines := strings.Split(diffs, "\x00")
|
||||||
|
|
||||||
|
fileDiffs := map[string]FileDiff{}
|
||||||
|
for _, line := range splitLines {
|
||||||
|
splitLine := strings.Split(line, "\t")
|
||||||
|
if len(splitLine) != 3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
linesAdded, err := strconv.Atoi(splitLine[0])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
linesDeleted, err := strconv.Atoi(splitLine[1])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName := splitLine[2]
|
||||||
|
fileDiffs[fileName] = FileDiff{
|
||||||
|
LinesAdded: linesAdded,
|
||||||
|
LinesDeleted: linesDeleted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileDiffs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GitStatus returns the file status of the repo
|
// GitStatus returns the file status of the repo
|
||||||
type GitStatusOptions struct {
|
type GitStatusOptions struct {
|
||||||
NoRenames bool
|
NoRenames bool
|
||||||
|
@ -100,6 +153,16 @@ type FileStatus struct {
|
||||||
PreviousName string
|
PreviousName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fileLoader *FileLoader) gitDiffNumStat() (string, error) {
|
||||||
|
return fileLoader.cmd.New(
|
||||||
|
NewGitCmd("diff").
|
||||||
|
Arg("--numstat").
|
||||||
|
Arg("-z").
|
||||||
|
Arg("HEAD").
|
||||||
|
ToArgv(),
|
||||||
|
).DontLog().RunWithOutput()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *FileLoader) gitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
func (self *FileLoader) gitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
||||||
cmdArgs := NewGitCmd("status").
|
cmdArgs := NewGitCmd("status").
|
||||||
Arg(opts.UntrackedFilesArg).
|
Arg(opts.UntrackedFilesArg).
|
||||||
|
|
|
@ -11,29 +11,35 @@ import (
|
||||||
|
|
||||||
func TestFileGetStatusFiles(t *testing.T) {
|
func TestFileGetStatusFiles(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
similarityThreshold int
|
similarityThreshold int
|
||||||
runner oscommands.ICmdObjRunner
|
runner oscommands.ICmdObjRunner
|
||||||
expectedFiles []*models.File
|
showNumstatInFilesView bool
|
||||||
|
expectedFiles []*models.File
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"No files found",
|
testName: "No files found",
|
||||||
50,
|
similarityThreshold: 50,
|
||||||
oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"}, "", nil),
|
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"}, "", nil),
|
||||||
[]*models.File{},
|
expectedFiles: []*models.File{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Several files found",
|
testName: "Several files found",
|
||||||
50,
|
similarityThreshold: 50,
|
||||||
oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
||||||
"MM file1.txt\x00A file3.txt\x00AM file2.txt\x00?? file4.txt\x00UU file5.txt",
|
"MM file1.txt\x00A file3.txt\x00AM file2.txt\x00?? file4.txt\x00UU file5.txt",
|
||||||
nil,
|
nil,
|
||||||
|
).
|
||||||
|
ExpectGitArgs([]string{"diff", "--numstat", "-z", "HEAD"},
|
||||||
|
"4\t1\tfile1.txt\x001\t0\tfile2.txt\x002\t2\tfile3.txt\x000\t2\tfile4.txt\x002\t2\tfile5.txt",
|
||||||
|
nil,
|
||||||
),
|
),
|
||||||
[]*models.File{
|
showNumstatInFilesView: true,
|
||||||
|
expectedFiles: []*models.File{
|
||||||
{
|
{
|
||||||
Name: "file1.txt",
|
Name: "file1.txt",
|
||||||
HasStagedChanges: true,
|
HasStagedChanges: true,
|
||||||
|
@ -45,6 +51,8 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "MM file1.txt",
|
DisplayString: "MM file1.txt",
|
||||||
ShortStatus: "MM",
|
ShortStatus: "MM",
|
||||||
|
LinesAdded: 4,
|
||||||
|
LinesDeleted: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "file3.txt",
|
Name: "file3.txt",
|
||||||
|
@ -57,6 +65,8 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "A file3.txt",
|
DisplayString: "A file3.txt",
|
||||||
ShortStatus: "A ",
|
ShortStatus: "A ",
|
||||||
|
LinesAdded: 2,
|
||||||
|
LinesDeleted: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "file2.txt",
|
Name: "file2.txt",
|
||||||
|
@ -69,6 +79,8 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "AM file2.txt",
|
DisplayString: "AM file2.txt",
|
||||||
ShortStatus: "AM",
|
ShortStatus: "AM",
|
||||||
|
LinesAdded: 1,
|
||||||
|
LinesDeleted: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "file4.txt",
|
Name: "file4.txt",
|
||||||
|
@ -81,6 +93,8 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "?? file4.txt",
|
DisplayString: "?? file4.txt",
|
||||||
ShortStatus: "??",
|
ShortStatus: "??",
|
||||||
|
LinesAdded: 0,
|
||||||
|
LinesDeleted: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "file5.txt",
|
Name: "file5.txt",
|
||||||
|
@ -93,15 +107,17 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
HasInlineMergeConflicts: true,
|
HasInlineMergeConflicts: true,
|
||||||
DisplayString: "UU file5.txt",
|
DisplayString: "UU file5.txt",
|
||||||
ShortStatus: "UU",
|
ShortStatus: "UU",
|
||||||
|
LinesAdded: 2,
|
||||||
|
LinesDeleted: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"File with new line char",
|
testName: "File with new line char",
|
||||||
50,
|
similarityThreshold: 50,
|
||||||
oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"}, "MM a\nb.txt", nil),
|
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"}, "MM a\nb.txt", nil),
|
||||||
[]*models.File{
|
expectedFiles: []*models.File{
|
||||||
{
|
{
|
||||||
Name: "a\nb.txt",
|
Name: "a\nb.txt",
|
||||||
HasStagedChanges: true,
|
HasStagedChanges: true,
|
||||||
|
@ -117,14 +133,14 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Renamed files",
|
testName: "Renamed files",
|
||||||
50,
|
similarityThreshold: 50,
|
||||||
oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
||||||
"R after1.txt\x00before1.txt\x00RM after2.txt\x00before2.txt",
|
"R after1.txt\x00before1.txt\x00RM after2.txt\x00before2.txt",
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
[]*models.File{
|
expectedFiles: []*models.File{
|
||||||
{
|
{
|
||||||
Name: "after1.txt",
|
Name: "after1.txt",
|
||||||
PreviousName: "before1.txt",
|
PreviousName: "before1.txt",
|
||||||
|
@ -154,14 +170,14 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"File with arrow in name",
|
testName: "File with arrow in name",
|
||||||
50,
|
similarityThreshold: 50,
|
||||||
oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
ExpectGitArgs([]string{"status", "--untracked-files=yes", "--porcelain", "-z", "--find-renames=50%"},
|
||||||
`?? a -> b.txt`,
|
`?? a -> b.txt`,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
[]*models.File{
|
expectedFiles: []*models.File{
|
||||||
{
|
{
|
||||||
Name: "a -> b.txt",
|
Name: "a -> b.txt",
|
||||||
HasStagedChanges: false,
|
HasStagedChanges: false,
|
||||||
|
@ -185,8 +201,14 @@ func TestFileGetStatusFiles(t *testing.T) {
|
||||||
appState := &config.AppState{}
|
appState := &config.AppState{}
|
||||||
appState.RenameSimilarityThreshold = s.similarityThreshold
|
appState.RenameSimilarityThreshold = s.similarityThreshold
|
||||||
|
|
||||||
|
userConfig := &config.UserConfig{
|
||||||
|
Gui: config.GuiConfig{
|
||||||
|
ShowNumstatInFilesView: s.showNumstatInFilesView,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
loader := &FileLoader{
|
loader := &FileLoader{
|
||||||
GitCommon: buildGitCommon(commonDeps{appState: appState}),
|
GitCommon: buildGitCommon(commonDeps{appState: appState, userConfig: userConfig}),
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
config: &FakeFileLoaderConfig{showUntrackedFiles: "yes"},
|
config: &FakeFileLoaderConfig{showUntrackedFiles: "yes"},
|
||||||
getFileType: func(string) string { return "file" },
|
getFileType: func(string) string { return "file" },
|
||||||
|
|
|
@ -19,6 +19,8 @@ type File struct {
|
||||||
HasInlineMergeConflicts bool
|
HasInlineMergeConflicts bool
|
||||||
DisplayString string
|
DisplayString string
|
||||||
ShortStatus string // e.g. 'AD', ' A', 'M ', '??'
|
ShortStatus string // e.g. 'AD', ' A', 'M ', '??'
|
||||||
|
LinesDeleted int
|
||||||
|
LinesAdded int
|
||||||
|
|
||||||
// If true, this must be a worktree folder
|
// If true, this must be a worktree folder
|
||||||
IsWorktree bool
|
IsWorktree bool
|
||||||
|
|
|
@ -109,6 +109,8 @@ type GuiConfig struct {
|
||||||
// If true, display the files in the file views as a tree. If false, display the files as a flat list.
|
// If true, display the files in the file views as a tree. If false, display the files as a flat list.
|
||||||
// This can be toggled from within Lazygit with the '~' key, but that will not change the default.
|
// This can be toggled from within Lazygit with the '~' key, but that will not change the default.
|
||||||
ShowFileTree bool `yaml:"showFileTree"`
|
ShowFileTree bool `yaml:"showFileTree"`
|
||||||
|
// If true, show the number of lines changed per file in the Files view
|
||||||
|
ShowNumstatInFilesView bool `yaml:"showNumstatInFilesView"`
|
||||||
// If true, show a random tip in the command log when Lazygit starts
|
// If true, show a random tip in the command log when Lazygit starts
|
||||||
ShowRandomTip bool `yaml:"showRandomTip"`
|
ShowRandomTip bool `yaml:"showRandomTip"`
|
||||||
// If true, show the command log
|
// If true, show the command log
|
||||||
|
@ -714,6 +716,7 @@ func GetDefaultConfig() *UserConfig {
|
||||||
ShowBottomLine: true,
|
ShowBottomLine: true,
|
||||||
ShowPanelJumps: true,
|
ShowPanelJumps: true,
|
||||||
ShowFileTree: true,
|
ShowFileTree: true,
|
||||||
|
ShowNumstatInFilesView: false,
|
||||||
ShowRandomTip: true,
|
ShowRandomTip: true,
|
||||||
ShowIcons: false,
|
ShowIcons: false,
|
||||||
NerdFontsVersion: "",
|
NerdFontsVersion: "",
|
||||||
|
|
|
@ -30,7 +30,8 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
|
||||||
|
|
||||||
getDisplayStrings := func(_ int, _ int) [][]string {
|
getDisplayStrings := func(_ int, _ int) [][]string {
|
||||||
showFileIcons := icons.IsIconEnabled() && c.UserConfig().Gui.ShowFileIcons
|
showFileIcons := icons.IsIconEnabled() && c.UserConfig().Gui.ShowFileIcons
|
||||||
lines := presentation.RenderFileTree(viewModel, c.Model().Submodules, showFileIcons)
|
showNumstat := c.UserConfig().Gui.ShowNumstatInFilesView
|
||||||
|
lines := presentation.RenderFileTree(viewModel, c.Model().Submodules, showFileIcons, showNumstat)
|
||||||
return lo.Map(lines, func(line string, _ int) []string {
|
return lo.Map(lines, func(line string, _ int) []string {
|
||||||
return []string{line}
|
return []string{line}
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,12 +22,13 @@ func RenderFileTree(
|
||||||
tree filetree.IFileTree,
|
tree filetree.IFileTree,
|
||||||
submoduleConfigs []*models.SubmoduleConfig,
|
submoduleConfigs []*models.SubmoduleConfig,
|
||||||
showFileIcons bool,
|
showFileIcons bool,
|
||||||
|
showNumstat bool,
|
||||||
) []string {
|
) []string {
|
||||||
collapsedPaths := tree.CollapsedPaths()
|
collapsedPaths := tree.CollapsedPaths()
|
||||||
return renderAux(tree.GetRoot().Raw(), collapsedPaths, -1, -1, func(node *filetree.Node[models.File], treeDepth int, visualDepth int, isCollapsed bool) string {
|
return renderAux(tree.GetRoot().Raw(), collapsedPaths, -1, -1, func(node *filetree.Node[models.File], treeDepth int, visualDepth int, isCollapsed bool) string {
|
||||||
fileNode := filetree.NewFileNode(node)
|
fileNode := filetree.NewFileNode(node)
|
||||||
|
|
||||||
return getFileLine(isCollapsed, fileNode.GetHasUnstagedChanges(), fileNode.GetHasStagedChanges(), treeDepth, visualDepth, showFileIcons, submoduleConfigs, node)
|
return getFileLine(isCollapsed, fileNode.GetHasUnstagedChanges(), fileNode.GetHasStagedChanges(), treeDepth, visualDepth, showNumstat, showFileIcons, submoduleConfigs, node)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +112,7 @@ func getFileLine(
|
||||||
hasStagedChanges bool,
|
hasStagedChanges bool,
|
||||||
treeDepth int,
|
treeDepth int,
|
||||||
visualDepth int,
|
visualDepth int,
|
||||||
|
showNumstat,
|
||||||
showFileIcons bool,
|
showFileIcons bool,
|
||||||
submoduleConfigs []*models.SubmoduleConfig,
|
submoduleConfigs []*models.SubmoduleConfig,
|
||||||
node *filetree.Node[models.File],
|
node *filetree.Node[models.File],
|
||||||
|
@ -165,6 +167,12 @@ func getFileLine(
|
||||||
output += theme.DefaultTextColor.Sprint(" (submodule)")
|
output += theme.DefaultTextColor.Sprint(" (submodule)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if file != nil && showNumstat {
|
||||||
|
if lineChanges := formatLineChanges(file.LinesAdded, file.LinesDeleted); lineChanges != "" {
|
||||||
|
output += " " + lineChanges
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +194,23 @@ func formatFileStatus(file *models.File, restColor style.TextStyle) string {
|
||||||
return firstCharCl.Sprint(firstChar) + secondCharCl.Sprint(secondChar)
|
return firstCharCl.Sprint(firstChar) + secondCharCl.Sprint(secondChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatLineChanges(linesAdded, linesDeleted int) string {
|
||||||
|
output := ""
|
||||||
|
|
||||||
|
if linesAdded != 0 {
|
||||||
|
output += style.FgGreen.Sprintf("+%d", linesAdded)
|
||||||
|
}
|
||||||
|
|
||||||
|
if linesDeleted != 0 {
|
||||||
|
if output != "" {
|
||||||
|
output += " "
|
||||||
|
}
|
||||||
|
output += style.FgRed.Sprintf("-%d", linesDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
func getCommitFileLine(
|
func getCommitFileLine(
|
||||||
isCollapsed bool,
|
isCollapsed bool,
|
||||||
treeDepth int,
|
treeDepth int,
|
||||||
|
|
|
@ -19,11 +19,12 @@ func toStringSlice(str string) []string {
|
||||||
|
|
||||||
func TestRenderFileTree(t *testing.T) {
|
func TestRenderFileTree(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
name string
|
name string
|
||||||
root *filetree.FileNode
|
root *filetree.FileNode
|
||||||
files []*models.File
|
files []*models.File
|
||||||
collapsedPaths []string
|
collapsedPaths []string
|
||||||
expected []string
|
showLineChanges bool
|
||||||
|
expected []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "nil node",
|
name: "nil node",
|
||||||
|
@ -37,6 +38,22 @@ func TestRenderFileTree(t *testing.T) {
|
||||||
},
|
},
|
||||||
expected: []string{" M test"},
|
expected: []string{" M test"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "numstat",
|
||||||
|
files: []*models.File{
|
||||||
|
{Name: "test", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1, LinesDeleted: 1},
|
||||||
|
{Name: "test2", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 1},
|
||||||
|
{Name: "test3", ShortStatus: " M", HasStagedChanges: true, LinesDeleted: 1},
|
||||||
|
{Name: "test4", ShortStatus: " M", HasStagedChanges: true, LinesAdded: 0, LinesDeleted: 0},
|
||||||
|
},
|
||||||
|
showLineChanges: true,
|
||||||
|
expected: []string{
|
||||||
|
" M test +1 -1",
|
||||||
|
" M test2 +1",
|
||||||
|
" M test3 -1",
|
||||||
|
" M test4",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "big example",
|
name: "big example",
|
||||||
files: []*models.File{
|
files: []*models.File{
|
||||||
|
@ -72,7 +89,7 @@ M file1
|
||||||
for _, path := range s.collapsedPaths {
|
for _, path := range s.collapsedPaths {
|
||||||
viewModel.ToggleCollapsed(path)
|
viewModel.ToggleCollapsed(path)
|
||||||
}
|
}
|
||||||
result := RenderFileTree(viewModel, nil, false)
|
result := RenderFileTree(viewModel, nil, false, s.showLineChanges)
|
||||||
assert.EqualValues(t, s.expected, result)
|
assert.EqualValues(t, s.expected, result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,6 +293,11 @@
|
||||||
"description": "If true, display the files in the file views as a tree. If false, display the files as a flat list.\nThis can be toggled from within Lazygit with the '~' key, but that will not change the default.",
|
"description": "If true, display the files in the file views as a tree. If false, display the files as a flat list.\nThis can be toggled from within Lazygit with the '~' key, but that will not change the default.",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
|
"showNumstatInFilesView": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "If true, show the number of lines changed per file in the Files view",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"showRandomTip": {
|
"showRandomTip": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If true, show a random tip in the command log when Lazygit starts",
|
"description": "If true, show a random tip in the command log when Lazygit starts",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue