commit e2e330cf6e9bbc943596dfb5947ee55ab9033e4a
parent 0da912f9c96725bff615d4fbb08ffdd1b44e6467
Author: Erik Loualiche <[email protected]>
Date: Tue, 3 Mar 2026 15:32:45 -0600
Merge pull request #8 from LouLouLibs/feat/tui-single-file-full-path
feat: show full path for single-file directory groups in TUI
Diffstat:
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/cmd/sync.go b/cmd/sync.go
@@ -408,8 +408,11 @@ type groupedEvent struct {
// groupFilesByTopLevel collapses file entries into top-level directories
// and root files. "cmd/sync.go" + "cmd/init.go" become one entry "cmd/" with count=2.
+// When a directory contains only one file, the full relative path is kept.
func groupFilesByTopLevel(files []syncer.FileEntry) []groupedEvent {
dirMap := make(map[string]*groupedEvent)
+ // Track the original filename for single-file groups.
+ dirFirstFile := make(map[string]string)
var rootFiles []groupedEvent
var dirOrder []string
@@ -429,6 +432,7 @@ func groupFilesByTopLevel(files []syncer.FileEntry) []groupedEvent {
g.bytes += f.Bytes
} else {
dirMap[dir] = &groupedEvent{name: dir, count: 1, bytes: f.Bytes}
+ dirFirstFile[dir] = f.Name
dirOrder = append(dirOrder, dir)
}
}
@@ -436,7 +440,11 @@ func groupFilesByTopLevel(files []syncer.FileEntry) []groupedEvent {
var out []groupedEvent
for _, dir := range dirOrder {
- out = append(out, *dirMap[dir])
+ g := *dirMap[dir]
+ if g.count == 1 {
+ g.name = dirFirstFile[dir]
+ }
+ out = append(out, g)
}
out = append(out, rootFiles...)
return out
diff --git a/internal/tui/dashboard.go b/internal/tui/dashboard.go
@@ -256,14 +256,14 @@ func (m DashboardModel) renderEvent(evt SyncEvent) string {
ts := dimStyle.Render(evt.Time.Format("15:04:05"))
switch evt.Status {
case "synced":
- name := padRight(evt.File, 30)
+ name := padRight(abbreviatePath(evt.File, 30), 30)
detail := ""
if evt.Size != "" {
detail = dimStyle.Render(fmt.Sprintf("%18s %s", evt.Size, evt.Duration.Truncate(100*time.Millisecond)))
}
return ts + " " + statusSynced.Render("✓") + " " + name + detail
case "error":
- name := padRight(evt.File, 30)
+ name := padRight(abbreviatePath(evt.File, 30), 30)
return ts + " " + statusError.Render("✗") + " " + name + statusError.Render("error")
default:
return ts + " " + evt.File
@@ -285,6 +285,29 @@ func (m DashboardModel) filteredEvents() []SyncEvent {
return out
}
+// abbreviatePath shortens a file path to fit within maxLen by replacing
+// leading directory segments with their first letter.
+// "internal/syncer/syncer.go" → "i/s/syncer.go"
+func abbreviatePath(p string, maxLen int) string {
+ if len(p) <= maxLen {
+ return p
+ }
+ parts := strings.Split(p, "/")
+ if len(parts) <= 1 {
+ return p
+ }
+ // Shorten directory segments from the left, keep the filename intact.
+ for i := 0; i < len(parts)-1; i++ {
+ if len(parts[i]) > 1 {
+ parts[i] = parts[i][:1]
+ }
+ if len(strings.Join(parts, "/")) <= maxLen {
+ break
+ }
+ }
+ return strings.Join(parts, "/")
+}
+
// padRight pads s with spaces to width n, truncating if necessary.
func padRight(s string, n int) string {
if len(s) >= n {