11package main
22
33import (
4+ "log"
45 "os"
56 "path/filepath"
67 "strings"
78
9+ "github.com/bluekeyes/go-gitdiff/gitdiff"
810 tea "github.com/charmbracelet/bubbletea"
911 "github.com/charmbracelet/lipgloss"
1012 "github.com/charmbracelet/lipgloss/tree"
1113)
1214
1315type ftModel struct {
14- files []string
16+ files []* gitdiff. File
1517 tree * tree.Tree
1618 selectedFile * string
1719}
1820
19- func (m ftModel ) SetFiles (files []string ) ftModel {
21+ func (m ftModel ) SetFiles (files []* gitdiff. File ) ftModel {
2022 m .files = files
2123 t := buildFullFileTree (files )
24+ log .Printf ("full: %v\n " , t )
2225 collapsed := collapseTree (t )
26+ log .Printf ("collapsed: %v\n " , collapsed )
2327 m .tree = truncateTree (collapsed , 0 )
2428 return m
2529}
2630
2731type FileNode struct {
28- path string
32+ file * gitdiff. File
2933 depth int
3034}
3135
36+ func (f FileNode ) path () string {
37+ return getFileName (f .file )
38+ }
39+
3240func (f FileNode ) Value () string {
33- return truncateValue (filepath .Base (f .path ), f .depth )
41+ icon := " "
42+ status := " "
43+ if f .file .IsNew {
44+ status += lipgloss .NewStyle ().Foreground (lipgloss .Color ("2" )).Render ("" )
45+ } else if f .file .IsDelete {
46+ status += lipgloss .NewStyle ().Foreground (lipgloss .Color ("1" )).Render ("" )
47+ } else {
48+ status += lipgloss .NewStyle ().Foreground (lipgloss .Color ("3" )).Render ("" )
49+ }
50+
51+ depth := f .depth
52+ if f .depth > 0 {
53+ depth = depth - 1
54+ }
55+ depthWidth := depth * 2
56+ iconsWidth := lipgloss .Width (icon ) + lipgloss .Width (status )
57+ nameMaxWidth := openFileTreeWidth - depthWidth - iconsWidth
58+ base := filepath .Base (f .path ())
59+ name := truncateValue (base , nameMaxWidth )
60+
61+ spacerWidth := openFileTreeWidth - lipgloss .Width (name ) - iconsWidth - depthWidth
62+ if len (name ) < len (base ) {
63+ spacerWidth = spacerWidth - 1
64+ }
65+ spacer := ""
66+ if spacerWidth > 0 {
67+ spacer = strings .Repeat (" " , spacerWidth )
68+ }
69+
70+ log .Printf ("name: %s, nameWidth: %d, nameMaxWidth: %d, iconsWidth: %d, depthWidth: %d, spacerWidth: %d\n " , name , lipgloss .Width (name ), nameMaxWidth , iconsWidth , depth * 2 , spacerWidth )
71+
72+ return lipgloss .JoinHorizontal (lipgloss .Top , icon , name , spacer , status )
3473}
3574
3675func (f FileNode ) String () string {
@@ -49,14 +88,15 @@ func (m ftModel) SetCursor(cursor int) ftModel {
4988 if len (m .files ) == 0 {
5089 return m
5190 }
52- m .selectedFile = & m .files [cursor ]
91+ name := getFileName (m .files [cursor ])
92+ m .selectedFile = & name
5393 applyStyles (m .tree , m .selectedFile )
5494 return m
5595}
5696
5797func initialFileTreeModel () ftModel {
5898 return ftModel {
59- files : []string {},
99+ files : []* gitdiff. File {},
60100 }
61101}
62102
@@ -117,12 +157,13 @@ func (m ftModel) printWithoutRoot() string {
117157 return s
118158}
119159
120- func buildFullFileTree (files []string ) * tree.Tree {
160+ func buildFullFileTree (files []* gitdiff. File ) * tree.Tree {
121161 t := tree .Root ("." )
122162 for _ , file := range files {
123163 subTree := t
124164
125- dir := filepath .Dir (file )
165+ name := getFileName (file )
166+ dir := filepath .Dir (name )
126167 parts := strings .Split (dir , string (os .PathSeparator ))
127168 path := ""
128169
@@ -147,12 +188,12 @@ func buildFullFileTree(files []string) *tree.Tree {
147188 }
148189
149190 // path does not exist from this point, need to creat it
150- leftover := strings .TrimPrefix (file , path )
191+ leftover := strings .TrimPrefix (name , path )
151192 parts = strings .Split (leftover , string (os .PathSeparator ))
152193 for i , part := range parts {
153194 var c * tree.Tree
154195 if i == len (parts )- 1 {
155- subTree .Child (FileNode {path : file })
196+ subTree .Child (FileNode {file : file })
156197 } else {
157198 c = tree .Root (part )
158199 subTree .Child (c )
@@ -164,12 +205,8 @@ func buildFullFileTree(files []string) *tree.Tree {
164205 return t
165206}
166207
167- func truncateValue (value string , depth int ) string {
168- d := depth
169- if depth > 0 {
170- d = d - 1
171- }
172- return TruncateString (value , openFileTreeWidth - d * 2 )
208+ func truncateValue (value string , width int ) string {
209+ return TruncateString (value , width )
173210}
174211
175212func collapseTree (t * tree.Tree ) * tree.Tree {
@@ -209,15 +246,19 @@ func collapseTree(t *tree.Tree) *tree.Tree {
209246}
210247
211248func truncateTree (t * tree.Tree , depth int ) * tree.Tree {
212- newT := tree .Root (truncateValue (t .Value (), depth ))
249+ d := depth
250+ if d > 0 {
251+ d = d - 1
252+ }
253+ newT := tree .Root (truncateValue (t .Value (), openFileTreeWidth - d * 2 ))
213254 children := t .Children ()
214255 for i := 0 ; i < children .Length (); i ++ {
215256 child := children .At (i )
216257 switch child := child .(type ) {
217258 case * tree.Tree :
218259 newT .Child (truncateTree (child , depth + 1 ))
219260 case FileNode :
220- newT .Child (FileNode {path : child .path , depth : depth + 1 })
261+ newT .Child (FileNode {file : child .file , depth : depth + 1 })
221262 default :
222263 newT .Child (child )
223264 }
@@ -252,7 +293,7 @@ func applyStyleToNode(node tree.Node, selectedFile *string) lipgloss.Style {
252293 st := lipgloss .NewStyle ().MaxHeight (1 )
253294 switch n := node .(type ) {
254295 case FileNode :
255- if selectedFile != nil && n .path == * selectedFile {
296+ if selectedFile != nil && n .path () == * selectedFile {
256297 return st .Background (lipgloss .Color ("#1b1b33" )).Bold (true )
257298 }
258299 case * tree.Tree :
@@ -262,3 +303,10 @@ func applyStyleToNode(node tree.Node, selectedFile *string) lipgloss.Style {
262303 }
263304 return st
264305}
306+
307+ func getFileName (file * gitdiff.File ) string {
308+ if file .NewName != "" {
309+ return file .NewName
310+ }
311+ return file .OldName
312+ }
0 commit comments