diff --git a/internal/config/config.go b/internal/config/config.go index 2b81094ed394e669b4d293200f911a875c2deacb..a6c72fab2b5fe103c2f6d9c475d851435a466724 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -2,10 +2,12 @@ package config import ( "fmt" + "os" "slices" "strings" "github.com/charmbracelet/crush/internal/fur/provider" + "github.com/tidwall/sjson" ) const ( @@ -274,6 +276,14 @@ func (c *Config) SmallModel() *provider.Model { return c.GetModel(model.Provider, model.Model) } +func (c *Config) SetCompactMode(enabled bool) error { + if c.Options == nil { + c.Options = &Options{} + } + c.Options.TUI.CompactMode = enabled + return c.SetConfigField("options.tui.compact_mode", enabled) +} + func (c *Config) Resolve(key string) (string, error) { if c.resolver == nil { return "", fmt.Errorf("no variable resolver configured") @@ -287,3 +297,25 @@ func UpdatePreferredModel(modelType SelectedModelType, model SelectedModel) erro cfg.Models[modelType] = model return nil } + +func (c *Config) SetConfigField(key string, value any) error { + configPath := globalConfigData() + // read the data + data, err := os.ReadFile(configPath) + if err != nil { + if os.IsNotExist(err) { + data = []byte("{}") + } else { + return fmt.Errorf("failed to read config file: %w", err) + } + } + + newValue, err := sjson.Set(string(data), key, value) + if err != nil { + return fmt.Errorf("failed to set config field %s: %w", key, err) + } + if err := os.WriteFile(configPath, []byte(newValue), 0o644); err != nil { + return fmt.Errorf("failed to write config file: %w", err) + } + return nil +} diff --git a/internal/tui/page/chat/chat.go b/internal/tui/page/chat/chat.go index daf6881426a6d1b59020ee98e06fb44d6c28f17e..73eeec6895e0591a37978c6cbc8c41fd34e74164 100644 --- a/internal/tui/page/chat/chat.go +++ b/internal/tui/page/chat/chat.go @@ -156,12 +156,15 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return p, p.setSession(msg) case commands.ToggleCompactModeMsg: p.forceCompact = !p.forceCompact + var cmd tea.Cmd if p.forceCompact { p.setCompactMode(true) + cmd = p.updateCompactConfig(true) } else if p.width >= CompactModeBreakpoint { p.setCompactMode(false) + cmd = p.updateCompactConfig(false) } - return p, p.SetSize(p.width, p.height) + return p, tea.Batch(p.SetSize(p.width, p.height), cmd) case pubsub.Event[session.Session]: // this needs to go to header/sidebar u, cmd := p.header.Update(msg) @@ -337,6 +340,19 @@ func (p *chatPage) View() tea.View { return view } +func (p *chatPage) updateCompactConfig(compact bool) tea.Cmd { + return func() tea.Msg { + err := config.Get().SetCompactMode(compact) + if err != nil { + return util.InfoMsg{ + Type: util.InfoTypeError, + Msg: "Failed to update compact mode configuration: " + err.Error(), + } + } + return nil + } +} + func (p *chatPage) setCompactMode(compact bool) { if p.compact == compact { return