Skip to content
Open
Show file tree
Hide file tree
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
35 changes: 30 additions & 5 deletions pkg/gui/presentation/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ func renderAux[T any](
}

isRoot := treeDepth == -1
hasChildren := len(node.Children) > 0

if node.IsFile() {
// Pure file node (no children) - render and return
if node.IsFile() && !hasChildren {
if isRoot {
return []string{}
}
Expand Down Expand Up @@ -128,6 +130,7 @@ func getFileLine(
var nameColor style.TextStyle

file := node.File
hasChildren := len(node.Children) > 0

indentation := strings.Repeat(" ", visualDepth)

Expand All @@ -140,7 +143,8 @@ func getFileLine(
}

if file == nil {
output += indentation + ""
// Pure directory node
output += indentation
arrow := EXPANDED_ARROW
if isCollapsed {
arrow = COLLAPSED_ARROW
Expand All @@ -149,7 +153,17 @@ func getFileLine(
arrowStyle := nameColor

output += arrowStyle.Sprint(arrow) + " "
} else if hasChildren {
// Node with both file and children (e.g., deleted symlink replaced with directory)
// Show file status followed by expand/collapse arrow
output += indentation + formatFileStatus(file, nameColor) + nameColor.Sprint(" ")
arrow := EXPANDED_ARROW
if isCollapsed {
arrow = COLLAPSED_ARROW
}
output += nameColor.Sprint(arrow) + " "
} else {
// Pure file node
// Sprinting the space at the end in the specific style is for the sake of
// when a reverse style is used in the theme, which looks ugly if you just
// use the default style
Expand All @@ -158,7 +172,7 @@ func getFileLine(

isSubmodule := file != nil && file.IsSubmodule(submoduleConfigs)
isLinkedWorktree := file != nil && file.IsWorktree
isDirectory := file == nil
isDirectory := file == nil || hasChildren

if showFileIcons {
icon := icons.IconForFile(name, isSubmodule, isLinkedWorktree, isDirectory, customIconsConfig)
Expand Down Expand Up @@ -231,7 +245,8 @@ func getCommitFileLine(
commitFile := node.File
output := indentation

isDirectory := commitFile == nil
hasChildren := len(node.Children) > 0
isDirectory := commitFile == nil || hasChildren

nameColor := theme.DefaultTextColor

Expand All @@ -244,14 +259,16 @@ func getCommitFileLine(
nameColor = theme.DefaultTextColor
}

if isDirectory {
if commitFile == nil {
// Pure directory node
arrow := EXPANDED_ARROW
if isCollapsed {
arrow = COLLAPSED_ARROW
}

output += nameColor.Sprint(arrow) + " "
} else {
// Node with file (with or without children)
var symbol string
symbolStyle := nameColor

Expand All @@ -266,6 +283,14 @@ func getCommitFileLine(
}

output += symbolStyle.Sprint(symbol) + " "

if hasChildren {
arrow := EXPANDED_ARROW
if isCollapsed {
arrow = COLLAPSED_ARROW
}
output += nameColor.Sprint(arrow) + " "
}
}

name = utils.EscapeSpecialChars(name)
Expand Down
66 changes: 66 additions & 0 deletions pkg/gui/presentation/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,39 @@ M file1
),
collapsedPaths: []string{"dir1"},
},
{
name: "deleted symlink replaced with directory containing files",
files: []*models.File{
{Path: "dir/link", ShortStatus: "D ", HasStagedChanges: true},
{Path: "dir/link/file1", ShortStatus: "A ", HasStagedChanges: true},
{Path: "dir/link/file2", ShortStatus: "A ", HasStagedChanges: true},
},
showRootItem: false,
expected: toStringSlice(
`
▼ dir
D ▼ link
A file1
A file2
`,
),
},
{
name: "deleted symlink replaced with directory - collapsed",
files: []*models.File{
{Path: "dir/link", ShortStatus: "D ", HasStagedChanges: true},
{Path: "dir/link/file1", ShortStatus: "A ", HasStagedChanges: true},
{Path: "dir/link/file2", ShortStatus: "A ", HasStagedChanges: true},
},
showRootItem: false,
collapsedPaths: []string{"dir/link"},
expected: toStringSlice(
`
▼ dir
D ▶ link
`,
),
},
}

oldColorLevel := color.ForceSetColorLevel(terminfo.ColorLevelNone)
Expand Down Expand Up @@ -200,6 +233,39 @@ M file1
),
collapsedPaths: []string{"dir1"},
},
{
name: "deleted symlink replaced with directory containing files",
files: []*models.CommitFile{
{Path: "dir/link", ChangeStatus: "D"},
{Path: "dir/link/file1", ChangeStatus: "A"},
{Path: "dir/link/file2", ChangeStatus: "A"},
},
showRootItem: false,
expected: toStringSlice(
`
▼ dir
D ▼ link
A file1
A file2
`,
),
},
{
name: "deleted symlink replaced with directory - collapsed",
files: []*models.CommitFile{
{Path: "dir/link", ChangeStatus: "D"},
{Path: "dir/link/file1", ChangeStatus: "A"},
{Path: "dir/link/file2", ChangeStatus: "A"},
},
showRootItem: false,
collapsedPaths: []string{"dir/link"},
expected: toStringSlice(
`
▼ dir
D ▶ link
`,
),
},
}

oldColorLevel := color.ForceSetColorLevel(terminfo.ColorLevelNone)
Expand Down