Merge pull request #6 from oug-t/feat/empty-state
feat: add contents for empty-state
This commit is contained in:
commit
54842591f5
11
README.md
11
README.md
|
|
@ -6,7 +6,7 @@
|
|||
</p>
|
||||
|
||||
<p align="center">
|
||||
<strong>The pixel-perfect terminal diff viewer.</strong><br />
|
||||
<strong>A calm, focused way to review Git diffs.</strong><br />
|
||||
Review code with clarity. Polish before you push.
|
||||
</p>
|
||||
|
||||
|
|
@ -14,14 +14,13 @@
|
|||
<img src="https://via.placeholder.com/800x450.png?text=Showcase+Your+UI+Here" alt="difi demo" width="100%" />
|
||||
</p>
|
||||
|
||||
|
||||
## Why difi?
|
||||
|
||||
- ⚡️ **Blazing Fast** — Built in Go. Starts instantly.
|
||||
- 🎨 **Semantic UI** — Split-pane layout with syntax highlighting and Nerd Font icons.
|
||||
- 🧠 **Context Aware** — Opens your editor (nvim/vim) at the exact line you are reviewing.
|
||||
- ⌨️ **Vim Native** — Navigate with `h j k l`. Zero mouse required.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Homebrew (macOS & Linux)
|
||||
|
|
@ -44,8 +43,10 @@ go install github.com/oug-t/difi/cmd/difi@latest
|
|||
- Download the binary from Releases and add it to your $PATH.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Run difi in any Git repository.
|
||||
- By default, it compares your current branch against main.
|
||||
|
||||
```bash
|
||||
cd my-project
|
||||
difi
|
||||
|
|
@ -54,7 +55,7 @@ difi
|
|||
## Controls
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| ------------- | -------------------------------------------- |
|
||||
| `Tab` | Toggle focus between File Tree and Diff View |
|
||||
| `j / k` | Move cursor down / up |
|
||||
| `h / l` | Focus Left (Tree) / Focus Right (Diff) |
|
||||
|
|
@ -72,5 +73,7 @@ git clone https://github.com/oug-t/difi
|
|||
cd difi
|
||||
go run cmd/difi/main.go
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<p align="center"> Made with ❤️ by <a href="https://github.com/oug-t">oug-t</a> </p>
|
||||
|
|
|
|||
|
|
@ -1,54 +1,20 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Colors struct {
|
||||
Border string `yaml:"border"`
|
||||
Focus string `yaml:"focus"`
|
||||
LineNumber string `yaml:"line_number"`
|
||||
DiffSelectionBg string `yaml:"diff_selection_bg"` // New config
|
||||
} `yaml:"colors"`
|
||||
UI struct {
|
||||
LineNumbers string `yaml:"line_numbers"`
|
||||
ShowGuide bool `yaml:"show_guide"`
|
||||
} `yaml:"ui"`
|
||||
UI UIConfig
|
||||
}
|
||||
|
||||
func DefaultConfig() Config {
|
||||
var c Config
|
||||
c.Colors.Border = "#D9DCCF"
|
||||
c.Colors.Focus = "#6e7781"
|
||||
c.Colors.LineNumber = "#808080"
|
||||
|
||||
// Default: "Neutral Light Transparent Blue"
|
||||
// Dark Mode: Deep subtle blue-grey | Light Mode: Very faint blue
|
||||
// We only set one default here, but AdaptiveColor handles the split in styles.go
|
||||
c.Colors.DiffSelectionBg = "" // Empty means use internal defaults
|
||||
|
||||
c.UI.LineNumbers = "hybrid"
|
||||
c.UI.ShowGuide = true
|
||||
return c
|
||||
type UIConfig struct {
|
||||
LineNumbers string // "relative", "absolute", "hybrid", "hidden"
|
||||
Theme string
|
||||
}
|
||||
|
||||
func Load() Config {
|
||||
cfg := DefaultConfig()
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return cfg
|
||||
// Default configuration
|
||||
return Config{
|
||||
UI: UIConfig{
|
||||
LineNumbers: "relative", // Default to relative numbers (vim style)
|
||||
Theme: "default",
|
||||
},
|
||||
}
|
||||
|
||||
configPath := filepath.Join(home, ".config", "difi", "config.yml")
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return cfg
|
||||
}
|
||||
|
||||
_ = yaml.Unmarshal(data, &cfg)
|
||||
return cfg
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@ 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"
|
||||
)
|
||||
|
||||
|
|
@ -19,95 +16,25 @@ type TreeDelegate struct {
|
|||
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)
|
||||
title := i.Title()
|
||||
|
||||
// If this item is selected
|
||||
if index == m.Index() {
|
||||
if d.Focused {
|
||||
// Render the whole line (including indent) with the selection background
|
||||
fmt.Fprint(w, SelectedBlockStyle.Render(title))
|
||||
} 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)
|
||||
// Dimmed selection if focus is on the other panel
|
||||
fmt.Fprint(w, SelectedBlockStyle.Copy().Foreground(ColorSubtle).Render(title))
|
||||
}
|
||||
} else {
|
||||
// Normal Item (No icons added, just the text)
|
||||
fmt.Fprint(w, ItemStyle.Render(title))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ import (
|
|||
"github.com/oug-t/difi/internal/tree"
|
||||
)
|
||||
|
||||
// REMOVED: const TargetBranch = "main" (Now dynamic)
|
||||
|
||||
type Focus int
|
||||
|
||||
const (
|
||||
|
|
@ -33,7 +31,7 @@ type Model struct {
|
|||
|
||||
selectedPath string
|
||||
currentBranch string
|
||||
targetBranch string // Added field for dynamic target
|
||||
targetBranch string
|
||||
repoName string
|
||||
|
||||
diffContent string
|
||||
|
|
@ -48,11 +46,9 @@ type Model struct {
|
|||
width, height int
|
||||
}
|
||||
|
||||
// Updated Signature: Accepts targetBranch string
|
||||
func NewModel(cfg config.Config, targetBranch string) Model {
|
||||
InitStyles(cfg)
|
||||
|
||||
// Use the dynamic targetBranch variable
|
||||
files, _ := git.ListChangedFiles(targetBranch)
|
||||
items := tree.Build(files)
|
||||
|
||||
|
|
@ -72,7 +68,7 @@ func NewModel(cfg config.Config, targetBranch string) Model {
|
|||
diffViewport: viewport.New(0, 0),
|
||||
focus: FocusTree,
|
||||
currentBranch: git.GetCurrentBranch(),
|
||||
targetBranch: targetBranch, // Store it
|
||||
targetBranch: targetBranch,
|
||||
repoName: git.GetRepoName(),
|
||||
showHelp: false,
|
||||
inputBuffer: "",
|
||||
|
|
@ -88,7 +84,6 @@ func NewModel(cfg config.Config, targetBranch string) Model {
|
|||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
if m.selectedPath != "" {
|
||||
// Use m.targetBranch instead of constant
|
||||
return git.DiffCmd(m.targetBranch, m.selectedPath)
|
||||
}
|
||||
return nil
|
||||
|
|
@ -119,6 +114,15 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
m.updateSizes()
|
||||
|
||||
case tea.KeyMsg:
|
||||
if msg.String() == "q" || msg.String() == "ctrl+c" {
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
// If list is empty, ignore other keys
|
||||
if len(m.fileTree.Items()) == 0 {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if len(msg.String()) == 1 && strings.ContainsAny(msg.String(), "0123456789") {
|
||||
m.inputBuffer += msg.String()
|
||||
return m, nil
|
||||
|
|
@ -130,10 +134,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m, nil
|
||||
}
|
||||
|
||||
if msg.String() == "q" || msg.String() == "ctrl+c" {
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
switch msg.String() {
|
||||
case "tab":
|
||||
if m.focus == FocusTree {
|
||||
|
|
@ -205,7 +205,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
if m.focus == FocusTree {
|
||||
if len(m.fileTree.Items()) > 0 && m.focus == FocusTree {
|
||||
if !keyHandled {
|
||||
m.fileTree, cmd = m.fileTree.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
|
|
@ -216,7 +216,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
m.selectedPath = item.FullPath
|
||||
m.diffCursor = 0
|
||||
m.diffViewport.GotoTop()
|
||||
// Use m.targetBranch
|
||||
cmds = append(cmds, git.DiffCmd(m.targetBranch, m.selectedPath))
|
||||
}
|
||||
}
|
||||
|
|
@ -229,7 +228,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
m.diffViewport.SetContent(msg.Content)
|
||||
|
||||
case git.EditorFinishedMsg:
|
||||
// Use m.targetBranch
|
||||
return m, git.DiffCmd(m.targetBranch, m.selectedPath)
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +265,12 @@ func (m Model) View() string {
|
|||
return "Loading..."
|
||||
}
|
||||
|
||||
// EMPTY STATE CHECK
|
||||
if len(m.fileTree.Items()) == 0 {
|
||||
return m.viewEmptyState()
|
||||
}
|
||||
|
||||
// 1. PANES
|
||||
treeStyle := PaneStyle
|
||||
if m.focus == FocusTree {
|
||||
treeStyle = FocusedPaneStyle
|
||||
|
|
@ -331,10 +335,10 @@ func (m Model) View() string {
|
|||
|
||||
mainPanes := lipgloss.JoinHorizontal(lipgloss.Top, treeView, diffView)
|
||||
|
||||
// 2. BOTTOM AREA
|
||||
repoSection := StatusKeyStyle.Render(" " + m.repoName)
|
||||
divider := StatusDividerStyle.Render("│")
|
||||
|
||||
// Use m.targetBranch in status bar
|
||||
statusText := fmt.Sprintf(" %s ↔ %s", m.currentBranch, m.targetBranch)
|
||||
if m.inputBuffer != "" {
|
||||
statusText += fmt.Sprintf(" [Cmd: %s]", m.inputBuffer)
|
||||
|
|
@ -390,6 +394,82 @@ func (m Model) View() string {
|
|||
return finalView
|
||||
}
|
||||
|
||||
// viewEmptyState renders a "Landing Page" when there are no changes
|
||||
func (m Model) viewEmptyState() string {
|
||||
// 1. Logo & Tagline
|
||||
logo := EmptyLogoStyle.Render("difi")
|
||||
desc := EmptyDescStyle.Render("A calm, focused way to review Git diffs.")
|
||||
|
||||
// 2. Status Message
|
||||
statusMsg := fmt.Sprintf("✓ No changes found against '%s'", m.targetBranch)
|
||||
status := EmptyStatusStyle.Render(statusMsg)
|
||||
|
||||
// 3. Usage Guide
|
||||
usageHeader := EmptyHeaderStyle.Render("Usage Patterns")
|
||||
|
||||
cmd1 := lipgloss.NewStyle().Foreground(ColorText).Render("difi")
|
||||
desc1 := EmptyCodeStyle.Render("Diff against main")
|
||||
|
||||
cmd2 := lipgloss.NewStyle().Foreground(ColorText).Render("difi develop")
|
||||
desc2 := EmptyCodeStyle.Render("Diff against target branch")
|
||||
|
||||
cmd3 := lipgloss.NewStyle().Foreground(ColorText).Render("difi HEAD~1")
|
||||
desc3 := EmptyCodeStyle.Render("Diff against previous commit")
|
||||
|
||||
usageBlock := lipgloss.JoinVertical(lipgloss.Left,
|
||||
usageHeader,
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, cmd1, desc1),
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, cmd2, desc2),
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, cmd3, desc3),
|
||||
)
|
||||
|
||||
// 4. Navigation Guide
|
||||
navHeader := EmptyHeaderStyle.Render("Navigation")
|
||||
|
||||
key1 := lipgloss.NewStyle().Foreground(ColorText).Render("Tab")
|
||||
keyDesc1 := EmptyCodeStyle.Render("Switch panels")
|
||||
|
||||
key2 := lipgloss.NewStyle().Foreground(ColorText).Render("j / k")
|
||||
keyDesc2 := EmptyCodeStyle.Render("Move cursor")
|
||||
|
||||
key3 := lipgloss.NewStyle().Foreground(ColorText).Render("?")
|
||||
keyDesc3 := EmptyCodeStyle.Render("Toggle help")
|
||||
|
||||
navBlock := lipgloss.JoinVertical(lipgloss.Left,
|
||||
navHeader,
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, key1, keyDesc1),
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, key2, keyDesc2),
|
||||
lipgloss.JoinHorizontal(lipgloss.Left, key3, keyDesc3),
|
||||
)
|
||||
|
||||
// Combine blocks
|
||||
guides := lipgloss.JoinHorizontal(lipgloss.Top,
|
||||
usageBlock,
|
||||
lipgloss.NewStyle().Width(8).Render(""), // Spacer
|
||||
navBlock,
|
||||
)
|
||||
|
||||
content := lipgloss.JoinVertical(lipgloss.Center,
|
||||
logo,
|
||||
desc,
|
||||
status,
|
||||
lipgloss.NewStyle().Height(1).Render(""),
|
||||
guides,
|
||||
)
|
||||
|
||||
// Center vertically
|
||||
var verticalPad string
|
||||
if m.height > lipgloss.Height(content) {
|
||||
lines := (m.height - lipgloss.Height(content)) / 2
|
||||
verticalPad = strings.Repeat("\n", lines)
|
||||
}
|
||||
|
||||
return lipgloss.JoinVertical(lipgloss.Top,
|
||||
verticalPad,
|
||||
lipgloss.PlaceHorizontal(m.width, lipgloss.Center, content),
|
||||
)
|
||||
}
|
||||
|
||||
func stripAnsi(str string) string {
|
||||
re := regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))")
|
||||
return re.ReplaceAllString(str, "")
|
||||
|
|
|
|||
|
|
@ -6,105 +6,112 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// -- Colors --
|
||||
ColorText = lipgloss.AdaptiveColor{Light: "#24292f", Dark: "#c9d1d9"}
|
||||
ColorSubtle = lipgloss.AdaptiveColor{Light: "#6e7781", Dark: "#8b949e"}
|
||||
|
||||
// UNIFIED SELECTION COLOR (The "Neutral Light Transparent Blue")
|
||||
// This is used for BOTH the file tree and the diff panel background.
|
||||
// Dark: Deep subtle slate blue | Light: Pale selection blue
|
||||
ColorVisualBg = lipgloss.AdaptiveColor{Light: "#daeaff", Dark: "#3a4b5c"}
|
||||
|
||||
// Tree Text Color (High Contrast for the block cursor)
|
||||
ColorVisualFg = lipgloss.AdaptiveColor{Light: "#000000", Dark: "#ffffff"}
|
||||
|
||||
ColorFolder = lipgloss.AdaptiveColor{Light: "#0969da", Dark: "#83a598"}
|
||||
ColorFile = lipgloss.AdaptiveColor{Light: "#24292f", Dark: "#ebdbb2"}
|
||||
|
||||
ColorBarBg = lipgloss.AdaptiveColor{Light: "#F2F2F2", Dark: "#1F1F1F"}
|
||||
ColorBarFg = lipgloss.AdaptiveColor{Light: "#6E6E6E", Dark: "#9E9E9E"}
|
||||
|
||||
// -- Styles --
|
||||
PaneStyle lipgloss.Style
|
||||
FocusedPaneStyle lipgloss.Style
|
||||
DiffStyle lipgloss.Style
|
||||
|
||||
ItemStyle lipgloss.Style
|
||||
SelectedBlockStyle lipgloss.Style // Tree (Opaque)
|
||||
DiffSelectionStyle lipgloss.Style // Diff (Transparent/BG only)
|
||||
|
||||
FolderIconStyle lipgloss.Style
|
||||
FileIconStyle lipgloss.Style
|
||||
LineNumberStyle lipgloss.Style
|
||||
|
||||
StatusBarStyle lipgloss.Style
|
||||
StatusKeyStyle lipgloss.Style
|
||||
StatusDividerStyle lipgloss.Style
|
||||
HelpTextStyle lipgloss.Style
|
||||
HelpDrawerStyle lipgloss.Style
|
||||
|
||||
// Global Config
|
||||
CurrentConfig config.Config
|
||||
)
|
||||
|
||||
func InitStyles(cfg config.Config) {
|
||||
CurrentConfig = cfg
|
||||
|
||||
ColorBorder := lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: cfg.Colors.Border}
|
||||
ColorFocus := lipgloss.AdaptiveColor{Light: "#6e7781", Dark: cfg.Colors.Focus}
|
||||
|
||||
// Allow user override for the selection background
|
||||
var selectionBg lipgloss.TerminalColor
|
||||
if cfg.Colors.DiffSelectionBg != "" {
|
||||
selectionBg = lipgloss.Color(cfg.Colors.DiffSelectionBg)
|
||||
} else {
|
||||
selectionBg = ColorVisualBg
|
||||
}
|
||||
// -- THEME COLORS --
|
||||
ColorBorder = lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#383838"}
|
||||
ColorFocus = lipgloss.AdaptiveColor{Light: "#000000", Dark: "#E5E5E5"}
|
||||
ColorText = lipgloss.AdaptiveColor{Light: "#1F1F1F", Dark: "#F8F8F2"}
|
||||
ColorSubtle = lipgloss.AdaptiveColor{Light: "#A8A8A8", Dark: "#626262"}
|
||||
ColorCursorBg = lipgloss.AdaptiveColor{Light: "#E5E5E5", Dark: "#3E3E3E"}
|
||||
ColorAccent = lipgloss.AdaptiveColor{Light: "#00ADD8", Dark: "#00ADD8"} // Go Blue
|
||||
|
||||
// -- PANE STYLES --
|
||||
PaneStyle = lipgloss.NewStyle().
|
||||
Border(lipgloss.NormalBorder(), false, cfg.UI.ShowGuide, false, false).
|
||||
Border(lipgloss.NormalBorder(), false, true, false, false).
|
||||
BorderForeground(ColorBorder)
|
||||
|
||||
FocusedPaneStyle = PaneStyle.Copy().
|
||||
BorderForeground(ColorFocus)
|
||||
|
||||
DiffStyle = lipgloss.NewStyle().Padding(0, 0)
|
||||
ItemStyle = lipgloss.NewStyle().PaddingLeft(2)
|
||||
|
||||
// Base Row
|
||||
ItemStyle = lipgloss.NewStyle().
|
||||
// -- LIST DELEGATE STYLES --
|
||||
SelectedItemStyle = lipgloss.NewStyle().
|
||||
PaddingLeft(1).
|
||||
PaddingRight(1).
|
||||
Foreground(ColorText)
|
||||
Background(ColorCursorBg).
|
||||
Foreground(ColorText).
|
||||
Bold(true).
|
||||
Width(1000)
|
||||
|
||||
// 1. LEFT PANE STYLE (Tree)
|
||||
// Uses the shared background + forces a foreground color for readability
|
||||
SelectedBlockStyle = lipgloss.NewStyle().
|
||||
Background(selectionBg).
|
||||
Foreground(ColorVisualFg).
|
||||
PaddingLeft(1).
|
||||
PaddingRight(1).
|
||||
Bold(true)
|
||||
Background(ColorCursorBg).
|
||||
Foreground(ColorText).
|
||||
Bold(true).
|
||||
PaddingLeft(1)
|
||||
|
||||
// 2. RIGHT PANE STYLE (Diff)
|
||||
// Uses the SAME shared background, but NO foreground.
|
||||
// This makes it "transparent" so Green(+)/Red(-) text colors show through.
|
||||
DiffSelectionStyle = lipgloss.NewStyle().
|
||||
Background(selectionBg)
|
||||
|
||||
FolderIconStyle = lipgloss.NewStyle().Foreground(ColorFolder)
|
||||
FileIconStyle = lipgloss.NewStyle().Foreground(ColorFile)
|
||||
// -- ICON STYLES --
|
||||
FolderIconStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#F7B96E", Dark: "#E5C07B"})
|
||||
FileIconStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#969696", Dark: "#ABB2BF"})
|
||||
|
||||
// -- DIFF VIEW STYLES --
|
||||
LineNumberStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color(cfg.Colors.LineNumber)).
|
||||
Foreground(ColorSubtle).
|
||||
PaddingRight(1).
|
||||
Width(4)
|
||||
|
||||
StatusBarStyle = lipgloss.NewStyle().Foreground(ColorBarFg).Background(ColorBarBg).Padding(0, 1)
|
||||
StatusKeyStyle = lipgloss.NewStyle().Foreground(ColorText).Background(ColorBarBg).Bold(true).Padding(0, 1)
|
||||
StatusDividerStyle = lipgloss.NewStyle().Foreground(ColorSubtle).Background(ColorBarBg).Padding(0, 0)
|
||||
DiffSelectionStyle = lipgloss.NewStyle().
|
||||
Background(ColorCursorBg).
|
||||
Width(1000)
|
||||
|
||||
// -- STATUS BAR STYLES --
|
||||
ColorBarBg = lipgloss.AdaptiveColor{Light: "#F2F2F2", Dark: "#1F1F1F"}
|
||||
ColorBarFg = lipgloss.AdaptiveColor{Light: "#6E6E6E", Dark: "#9E9E9E"}
|
||||
|
||||
StatusBarStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorBarFg).
|
||||
Background(ColorBarBg).
|
||||
Padding(0, 1)
|
||||
|
||||
StatusKeyStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorText).
|
||||
Background(ColorBarBg).
|
||||
Bold(true).
|
||||
Padding(0, 1)
|
||||
|
||||
StatusDividerStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorSubtle).
|
||||
Background(ColorBarBg).
|
||||
Padding(0, 0)
|
||||
|
||||
// -- HELP STYLES --
|
||||
HelpTextStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorSubtle).
|
||||
Padding(0, 1)
|
||||
|
||||
HelpTextStyle = lipgloss.NewStyle().Foreground(ColorSubtle).Padding(0, 1)
|
||||
HelpDrawerStyle = lipgloss.NewStyle().
|
||||
Border(lipgloss.NormalBorder(), true, false, false, false).
|
||||
BorderForeground(ColorBorder).
|
||||
Padding(1, 2)
|
||||
|
||||
// -- EMPTY STATE / LANDING PAGE STYLES --
|
||||
EmptyLogoStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorAccent).
|
||||
Bold(true).
|
||||
PaddingBottom(1)
|
||||
|
||||
EmptyDescStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorSubtle).
|
||||
PaddingBottom(2)
|
||||
|
||||
EmptyStatusStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorText).
|
||||
Background(ColorCursorBg).
|
||||
Padding(0, 2).
|
||||
MarginBottom(2)
|
||||
|
||||
EmptyCodeStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorSubtle).
|
||||
MarginLeft(2)
|
||||
|
||||
EmptyHeaderStyle = lipgloss.NewStyle().
|
||||
Foreground(ColorText).
|
||||
Bold(true).
|
||||
MarginBottom(1)
|
||||
)
|
||||
|
||||
func InitStyles(cfg config.Config) {
|
||||
CurrentConfig = cfg
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user