114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/list"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/oug-t/difi/internal/tree"
|
|
)
|
|
|
|
type TreeDelegate struct {
|
|
Focused bool
|
|
}
|
|
|
|
func (d TreeDelegate) Height() int { return 1 }
|
|
func (d TreeDelegate) Spacing() int { return 0 }
|
|
func (d TreeDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
|
|
|
|
func (d TreeDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
|
i, ok := item.(tree.TreeItem)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// 1. Setup Indentation
|
|
indentSize := i.Depth * 2
|
|
indent := strings.Repeat(" ", indentSize)
|
|
|
|
// 2. Get Icon and Raw Name
|
|
iconStr, iconStyle := getIconInfo(i.Path, i.IsDir)
|
|
|
|
// 3. Truncation (Safety)
|
|
availableWidth := m.Width() - indentSize - 4
|
|
displayName := i.Path
|
|
if availableWidth > 0 && len(displayName) > availableWidth {
|
|
displayName = displayName[:max(0, availableWidth-1)] + "…"
|
|
}
|
|
|
|
// 4. Render Logic ("Oil" Block Cursor)
|
|
var row string
|
|
isSelected := index == m.Index()
|
|
|
|
if isSelected && d.Focused {
|
|
// -- SELECTED STATE (Oil Style) --
|
|
// We do NOT use iconStyle here. We want the icon to inherit the
|
|
// selection text color so the background block is unbroken.
|
|
// Content: Icon + Space + Name
|
|
content := fmt.Sprintf("%s %s", iconStr, displayName)
|
|
|
|
// Apply the solid block style to the whole content
|
|
renderedContent := SelectedBlockStyle.Render(content)
|
|
|
|
// Combine: Indent (unhighlighted) + Block (highlighted)
|
|
row = fmt.Sprintf("%s%s", indent, renderedContent)
|
|
|
|
} else {
|
|
// -- NORMAL / INACTIVE STATE --
|
|
// Render icon with its specific color
|
|
renderedIcon := iconStyle.Render(iconStr)
|
|
|
|
// Combine
|
|
row = fmt.Sprintf("%s%s %s", indent, renderedIcon, displayName)
|
|
|
|
// Apply generic padding/style
|
|
row = ItemStyle.Render(row)
|
|
}
|
|
|
|
fmt.Fprint(w, row)
|
|
}
|
|
|
|
// Helper: Returns raw icon string and its preferred style
|
|
func getIconInfo(name string, isDir bool) (string, lipgloss.Style) {
|
|
if isDir {
|
|
return "", FolderIconStyle
|
|
}
|
|
|
|
ext := filepath.Ext(name)
|
|
icon := ""
|
|
|
|
switch strings.ToLower(ext) {
|
|
case ".go":
|
|
icon = ""
|
|
case ".js", ".ts", ".tsx", ".jsx":
|
|
icon = ""
|
|
case ".md":
|
|
icon = ""
|
|
case ".json", ".yml", ".yaml", ".toml":
|
|
icon = ""
|
|
case ".css", ".scss":
|
|
icon = ""
|
|
case ".html":
|
|
icon = ""
|
|
case ".git":
|
|
icon = ""
|
|
case ".dockerfile":
|
|
icon = ""
|
|
case ".svelte":
|
|
icon = ""
|
|
}
|
|
|
|
return icon, FileIconStyle
|
|
}
|
|
|
|
func max(a, b int) int {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|