1// Package lazygit provides a dialog component for embedding lazygit in the TUI.
2package lazygit
3
4import (
5 "context"
6 "fmt"
7 "image/color"
8 "os"
9
10 "github.com/charmbracelet/crush/internal/terminal"
11 "github.com/charmbracelet/crush/internal/tui/components/dialogs"
12 "github.com/charmbracelet/crush/internal/tui/components/dialogs/termdialog"
13 "github.com/charmbracelet/crush/internal/tui/styles"
14)
15
16// DialogID is the unique identifier for the lazygit dialog.
17const DialogID dialogs.DialogID = "lazygit"
18
19// NewDialog creates a new lazygit dialog. The context controls the lifetime
20// of the lazygit process - when cancelled, the process will be killed.
21func NewDialog(ctx context.Context, workingDir string) *termdialog.Dialog {
22 configFile := createThemedConfig()
23
24 cmd := terminal.PrepareCmd(
25 ctx,
26 "lazygit",
27 nil,
28 workingDir,
29 []string{"LG_CONFIG_FILE=" + configFile},
30 )
31
32 return termdialog.New(termdialog.Config{
33 ID: DialogID,
34 Title: "Lazygit",
35 LoadingMsg: "Starting lazygit...",
36 Term: terminal.New(terminal.Config{Context: ctx, Cmd: cmd}),
37 OnClose: func() {
38 if configFile != "" {
39 _ = os.Remove(configFile)
40 }
41 },
42 })
43}
44
45// colorToHex converts a color.Color to a hex string.
46func colorToHex(c color.Color) string {
47 r, g, b, _ := c.RGBA()
48 return fmt.Sprintf("#%02x%02x%02x", r>>8, g>>8, b>>8)
49}
50
51// createThemedConfig creates a temporary lazygit config file with Crush theme.
52// Theme mappings align with Crush's UX patterns:
53// - Borders: BorderFocus (purple) for active, Border (gray) for inactive
54// - Selection: Primary (purple) background matches app's TextSelected style
55// - Status: Success (green), Error (red), Info (blue), Warning (orange)
56func createThemedConfig() string {
57 t := styles.CurrentTheme()
58
59 config := fmt.Sprintf(`gui:
60 border: rounded
61 showFileTree: true
62 showRandomTip: false
63 showCommandLog: false
64 showBottomLine: true
65 showPanelJumps: false
66 nerdFontsVersion: ""
67 showFileIcons: false
68 theme:
69 activeBorderColor:
70 - "%s"
71 - bold
72 inactiveBorderColor:
73 - "%s"
74 searchingActiveBorderColor:
75 - "%s"
76 - bold
77 optionsTextColor:
78 - "%s"
79 selectedLineBgColor:
80 - "%s"
81 inactiveViewSelectedLineBgColor:
82 - "%s"
83 cherryPickedCommitFgColor:
84 - "%s"
85 cherryPickedCommitBgColor:
86 - "%s"
87 markedBaseCommitFgColor:
88 - "%s"
89 markedBaseCommitBgColor:
90 - "%s"
91 unstagedChangesColor:
92 - "%s"
93 defaultFgColor:
94 - default
95`,
96 colorToHex(t.BorderFocus),
97 colorToHex(t.FgMuted),
98 colorToHex(t.Info),
99 colorToHex(t.FgMuted),
100 colorToHex(t.Primary),
101 colorToHex(t.BgSubtle),
102 colorToHex(t.Success),
103 colorToHex(t.BgSubtle),
104 colorToHex(t.Info),
105 colorToHex(t.BgSubtle),
106 colorToHex(t.Error),
107 )
108
109 f, err := os.CreateTemp("", "crush-lazygit-*.yml")
110 if err != nil {
111 return ""
112 }
113 defer f.Close()
114
115 _, _ = f.WriteString(config)
116 return f.Name()
117}