package config import ( "errors" "github.com/ayn2op/tview" "github.com/gdamore/tcell/v3" ) var errInvalidType = errors.New("invalid type") type AlignmentWrapper struct{ tview.Alignment } func (aw *AlignmentWrapper) UnmarshalTOML(v any) error { s, ok := v.(string) if !ok { return errInvalidType } switch s { case "left": aw.Alignment = tview.AlignmentLeft case "center": aw.Alignment = tview.AlignmentCenter case "right": aw.Alignment = tview.AlignmentRight } return nil } type StyleWrapper struct{ tcell.Style } func NewStyleWrapper(style tcell.Style) StyleWrapper { return StyleWrapper{Style: style} } func (sw *StyleWrapper) UnmarshalTOML(v any) error { m, ok := v.(map[string]any) if !ok { return errInvalidType } for key, val := range m { switch key { case "foreground": s, ok := val.(string) if !ok { continue } color := tcell.GetColor(s) sw.Style = sw.Foreground(color) case "background": s, ok := val.(string) if !ok { continue } color := tcell.GetColor(s) sw.Style = sw.Background(color) case "attributes": var attrs tcell.AttrMask switch val := val.(type) { case string: attrs |= stringToAttrMask(val) case []any: for _, attr := range val { s, ok := attr.(string) if !ok { continue } attrs |= stringToAttrMask(s) } } sw.Style = sw.Attributes(attrs) } } return nil } type BorderSetWrapper struct{ tview.BorderSet } func (bw *BorderSetWrapper) UnmarshalTOML(val any) error { s, ok := val.(string) if !ok { return errInvalidType } switch s { case "hidden": bw.BorderSet = tview.BorderSetHidden() case "plain": bw.BorderSet = tview.BorderSetPlain() case "round": bw.BorderSet = tview.BorderSetRound() case "thick": bw.BorderSet = tview.BorderSetThick() case "double": bw.BorderSet = tview.BorderSetDouble() } return nil } type ( ThemeStyle struct { NormalStyle StyleWrapper `toml:"normal_style"` ActiveStyle StyleWrapper `toml:"active_style"` } TitleTheme struct { ThemeStyle Alignment AlignmentWrapper `toml:"alignment"` } FooterTheme struct { ThemeStyle Alignment AlignmentWrapper `toml:"alignment"` } BorderTheme struct { ThemeStyle Enabled bool `toml:"enabled"` Padding [4]int `toml:"padding"` NormalSet BorderSetWrapper `toml:"normal_set"` ActiveSet BorderSetWrapper `toml:"active_set"` } GuildsTreeTheme struct { AutoExpandFolders bool `toml:"auto_expand_folders"` Graphics bool `toml:"graphics"` GraphicsColor string `toml:"graphics_color"` } MessagesListTheme struct { ReplyIndicator string `toml:"reply_indicator"` ForwardedIndicator string `toml:"forwarded_indicator"` AuthorStyle StyleWrapper `toml:"author_style"` MentionStyle StyleWrapper `toml:"mention_style"` EmojiStyle StyleWrapper `toml:"emoji_style"` URLStyle StyleWrapper `toml:"url_style"` AttachmentStyle StyleWrapper `toml:"attachment_style"` MessageStyle StyleWrapper `toml:"message_style"` SelectedMessageStyle StyleWrapper `toml:"selected_message_style"` } MentionsListTheme struct { MinWidth uint `toml:"min_width"` MaxHeight uint `toml:"max_height"` } DialogTheme struct { Style StyleWrapper `toml:"style"` BackgroundStyle StyleWrapper `toml:"background_style"` } Theme struct { Title TitleTheme `toml:"title"` Footer FooterTheme `toml:"footer"` Border BorderTheme `toml:"border"` GuildsTree GuildsTreeTheme `toml:"guilds_tree"` MessagesList MessagesListTheme `toml:"messages_list"` MentionsList MentionsListTheme `toml:"mentions_list"` Dialog DialogTheme `toml:"dialog"` } ) func stringToAttrMask(s string) tcell.AttrMask { switch s { case "bold": return tcell.AttrBold case "blink": return tcell.AttrBlink case "reverse": return tcell.AttrReverse case "dim": return tcell.AttrDim case "italic": return tcell.AttrItalic case "strikethrough": return tcell.AttrStrikeThrough default: return tcell.AttrNone } }