Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs
Submodule docs updated from 8ca9e5 to 725581
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
)

require (
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.3.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
Expand Down
34 changes: 31 additions & 3 deletions internal/tui/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,26 @@ type Model struct {

// initialModel creates the initial state of the application.
func initialModel() Model {
themeNames := ThemeNames()
themeNames := ThemeNames() //built-in themes load
cfg, _ := load_config()

var selectedThemeName string
if t, ok := Themes[cfg.Theme]; ok{
selectedThemeName = cfg.Theme
_ = t // to avoid unused variable warning
} else{
if _, err := load_custom_theme(cfg.Theme); err == nil{
selectedThemeName = cfg.Theme
} else{
//fallback
selectedThemeName = themeNames[0]
}
}

themeNames = ThemeNames() // reload

// fmt.Println("All themes:", themeNames)

gc := git.NewGitCommands()
repoName, branchName, _ := gc.GetRepoInfo()
initialContent := initialContentLoading
Expand All @@ -77,9 +96,9 @@ func initialModel() Model {
ta.SetHeight(5)

return Model{
theme: Themes[themeNames[0]],
theme: Themes[selectedThemeName],
themeNames: themeNames,
themeIndex: 0,
themeIndex: indexOf(themeNames, selectedThemeName),
focusedPanel: StatusPanel,
activeSourcePanel: StatusPanel,
help: help.New(),
Expand All @@ -95,6 +114,15 @@ func initialModel() Model {
}
}

func indexOf(arr []string, val string) int{
for i, s := range arr{
if s == val{
return i
}
}
return 0
}

// Init is the first command that is run when the program starts.
func (m Model) Init() tea.Cmd {
// fetch initial content for all panels.
Expand Down
71 changes: 71 additions & 0 deletions internal/tui/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@ import (
"sort"

"github.com/charmbracelet/lipgloss"

"os"

"path/filepath"

"github.com/BurntSushi/toml"

"fmt"
)

// DefaultThemeName is the name of the default theme.
const DefaultThemeName = "GitHub Dark"

// Palette defines a set of colors for a theme.
type Palette struct {
Black, Red, Green, Yellow, Blue, Magenta, Cyan, White,
Expand Down Expand Up @@ -139,6 +150,20 @@ type TreeStyle struct {
Connector, ConnectorLast, Prefix, PrefixLast string
}

//config.toml
type themeConfig struct{
Theme string `toml:"theme"`
}

// custom_theme.toml
type ThemeFile struct{
Fg string `toml:"fg"`
Bg string `toml:"bg"`
Normal map[string]string `toml:"normal"`
Bright map[string]string `toml:"bright"`
Dark map[string]string `toml:"dark"`
}

// Themes holds all the available themes, generated from palettes.
var Themes = map[string]Theme{}

Expand Down Expand Up @@ -216,3 +241,49 @@ func ThemeNames() []string {
sort.Strings(names)
return names
}

func load_config() (*themeConfig, error){
cfgPath := filepath.Join(os.Getenv("HOME"), ".config", "gitx", "config.toml")
if _,err := os.Stat(cfgPath); os.IsNotExist(err) {
return &themeConfig{Theme: DefaultThemeName}, nil //fallback
}

var cfg themeConfig
if _, err := toml.DecodeFile(cfgPath, &cfg); err != nil {
return nil, err
}

return &cfg, nil
}

func load_custom_theme(name string) (*Palette, error){
themePath := filepath.Join(os.Getenv("HOME"), ".config", "gitx", "themes", name+".toml")
if _,err := os.Stat(themePath); os.IsNotExist(err) {
return nil, fmt.Errorf("theme not found: %s", name)
}

var tf ThemeFile
if _, err := toml.DecodeFile(themePath, &tf); err != nil {
return nil, err
}

// Create a Palette from the ThemeFile
p := Palette{
Fg: tf.Fg,
Bg: tf.Bg,
Black: tf.Normal["Black"], Red: tf.Normal["Red"], Green: tf.Normal["Green"], Yellow: tf.Normal["Yellow"],
Blue: tf.Normal["Blue"], Magenta: tf.Normal["Magenta"], Cyan: tf.Normal["Cyan"], White: tf.Normal["White"],

BrightBlack: tf.Bright["Black"], BrightRed: tf.Bright["Red"], BrightGreen: tf.Bright["Green"], BrightYellow: tf.Bright["Yellow"],
BrightBlue: tf.Bright["Blue"], BrightMagenta: tf.Bright["Magenta"], BrightCyan: tf.Bright["Cyan"], BrightWhite: tf.Bright["White"],

DarkBlack: tf.Dark["Black"], DarkRed: tf.Dark["Red"], DarkGreen: tf.Dark["Green"], DarkYellow: tf.Dark["Yellow"],
DarkBlue: tf.Dark["Blue"], DarkMagenta: tf.Dark["Magenta"], DarkCyan: tf.Dark["Cyan"], DarkWhite: tf.Dark["White"],

}

Palettes[name] = p // Add to Palettes map for future use
Themes[name] = NewThemeFromPalette(p) // Add to Themes map

return &p, nil
}
Comment on lines 245 to 286
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the scope of this PR does not include adding proper functionality for the user provided config file, that is .config/gitx/config.toml. Would you be interested in refactoring this into a separate file? I'll help in the effort by pushing some changes in your branch if you are okay with that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey, can you please clarify what you mean by "proper functionality" for the config file.
And yeah, I’m cool with refactoring and happy to have your help on my branch.

Copy link
Member

@bakayu bakayu Oct 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not clarifying it properly.
By "proper functionality" I mean basic settings any cli or tui app may have that can be configured via the config file.
For example the Theme setting you have implemented that can be found in the users's .config folder, in the config.toml file.
To have a proper chat about this you can join the discord server linked in the readme file and ping mere there in the appropriate channel, my discord handle is @bakayu.
This is a big effort feature request and I appreciate your help in this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah got it, thanks for clarifying, I'll ping you on discord so we can discuss and refactor together.