package common import ( "log/slog" "strconv" "strings" // "github.com/charmbracelet/bubbles/table" "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" "tasksquire/taskwarrior" ) type TableStyle struct { Header lipgloss.Style Cell lipgloss.Style Selected lipgloss.Style } type Styles struct { Colors map[string]*lipgloss.Style Base lipgloss.Style Form *huh.Theme TableStyle TableStyle ColumnFocused lipgloss.Style ColumnBlurred lipgloss.Style ColumnInsert lipgloss.Style } func NewStyles(config *taskwarrior.TWConfig) *Styles { styles := Styles{} colors := make(map[string]*lipgloss.Style) for key, value := range config.GetConfig() { if strings.HasPrefix(key, "color.") { _, color, _ := strings.Cut(key, ".") colors[color] = parseColorString(value) } } styles.Colors = colors styles.Base = lipgloss.NewStyle() styles.TableStyle = TableStyle{ // Header: lipgloss.NewStyle().Bold(true).Padding(0, 1).BorderBottom(true), Cell: lipgloss.NewStyle().Padding(0, 1, 0, 0), Header: lipgloss.NewStyle().Bold(true).Padding(0, 1, 0, 0).Underline(true), Selected: lipgloss.NewStyle().Bold(true).Reverse(true), } formTheme := huh.ThemeBase() formTheme.Focused.Title = formTheme.Focused.Title.Bold(true) formTheme.Focused.SelectSelector = formTheme.Focused.SelectSelector.SetString("→ ") formTheme.Focused.SelectedOption = formTheme.Focused.SelectedOption.Bold(true) formTheme.Focused.MultiSelectSelector = formTheme.Focused.MultiSelectSelector.SetString("→ ") formTheme.Focused.SelectedPrefix = formTheme.Focused.SelectedPrefix.SetString("✓ ") formTheme.Focused.UnselectedPrefix = formTheme.Focused.SelectedPrefix.SetString("• ") formTheme.Blurred.Title = formTheme.Blurred.Title.Bold(true) formTheme.Blurred.SelectSelector = formTheme.Blurred.SelectSelector.SetString(" ") formTheme.Blurred.SelectedOption = formTheme.Blurred.SelectedOption.Bold(true) formTheme.Blurred.MultiSelectSelector = formTheme.Blurred.MultiSelectSelector.SetString(" ") formTheme.Blurred.SelectedPrefix = formTheme.Blurred.SelectedPrefix.SetString("✓ ") formTheme.Blurred.UnselectedPrefix = formTheme.Blurred.SelectedPrefix.SetString("• ") styles.Form = formTheme styles.ColumnFocused = lipgloss.NewStyle().Border(lipgloss.RoundedBorder(), true).Padding(1) styles.ColumnBlurred = lipgloss.NewStyle().Border(lipgloss.HiddenBorder(), true).Padding(1) styles.ColumnInsert = lipgloss.NewStyle().Border(lipgloss.RoundedBorder(), true).Padding(1) if styles.Colors["active"] != nil { styles.ColumnInsert = styles.ColumnInsert.BorderForeground(styles.Colors["active"].GetForeground()) } return &styles } func parseColorString(color string) *lipgloss.Style { if color == "" { return nil } style := lipgloss.NewStyle() if strings.Contains(color, "on") { fgbg := strings.Split(color, "on") fg := strings.TrimSpace(fgbg[0]) bg := strings.TrimSpace(fgbg[1]) if fg != "" { style = style.Foreground(parseColor(fg)) } if bg != "" { style = style.Background(parseColor(bg)) } } else { style = style.Foreground(parseColor(strings.TrimSpace(color))) } return &style } func parseColor(color string) lipgloss.Color { if strings.HasPrefix(color, "rgb") { return lipgloss.Color(convertRgbToAnsi(strings.TrimPrefix(color, "rgb"))) } if strings.HasPrefix(color, "color") { return lipgloss.Color(strings.TrimPrefix(color, "color")) } if strings.HasPrefix(color, "gray") { gray, err := strconv.Atoi(strings.TrimPrefix(color, "gray")) if err != nil { slog.Error("Invalid gray color format") return lipgloss.Color("0") } return lipgloss.Color(strconv.Itoa(gray + 232)) } if ansi, okcolor := colorStrings[color]; okcolor { return lipgloss.Color(strconv.Itoa(ansi)) } slog.Error("Invalid color format") return lipgloss.Color("0") } func convertRgbToAnsi(rgbString string) string { var err error if len(rgbString) != 3 { slog.Error("Invalid RGB color format") return "" } r, err := strconv.Atoi(string(rgbString[0])) if err != nil { slog.Error("Invalid value for R") return "" } g, err := strconv.Atoi(string(rgbString[1])) if err != nil { slog.Error("Invalid value for G") return "" } b, err := strconv.Atoi(string(rgbString[2])) if err != nil { slog.Error("Invalid value for B") return "" } return strconv.Itoa(16 + (36 * r) + (6 * g) + b) } var colorStrings = map[string]int{ "black": 0, "red": 1, "green": 2, "yellow": 3, "blue": 4, "magenta": 5, "cyan": 6, "white": 7, "bright black": 8, "bright red": 9, "bright green": 10, "bright yellow": 11, "bright blue": 12, "bright magenta": 13, "bright cyan": 14, "bright white": 15, }