feat(daemon): publish copy configuration
- commit
- bb3050a377e9a58199a254730bb8071b9701971e
- author
- brice · · 2026-07-15 06:24 UTC
- committer
- brice · · 2026-07-15 09:45 UTC
- parent
- 1e1b557
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +27 -0
M internal/usecase/daemon/config.go +9 -0
| @@ -29,6 +29,8 @@ func (d *Daemon) ApplyConfig(cfg domain.Config) { | |||
| 29 | 29 | d.restoreProcessAllowlist.Store(&allowlist) | |
| 30 | 30 | floating := cfg.Floating | |
| 31 | 31 | d.floatingConfig.Store(&floating) | |
| 32 | + | copyConfig := cfg.Copy | |
| 33 | + | d.copyConfig.Store(©Config) | |
| 32 | 34 | palette := cfg.Palette | |
| 33 | 35 | d.paletteConfig.Store(&palette) | |
| 34 | 36 | tabs := cfg.Tabs | |
| @@ -182,6 +184,13 @@ func (d *Daemon) logConfigWarning(w domain.Warning) { | |||
| 182 | 184 | d.log.Warn("config warning", "msg", w.Msg) | |
| 183 | 185 | } | |
| 184 | 186 | ||
| 187 | + | func (d *Daemon) currentCopyConfig() domain.CopyConfig { | |
| 188 | + | if cfg := d.copyConfig.Load(); cfg != nil { | |
| 189 | + | return *cfg | |
| 190 | + | } | |
| 191 | + | return domain.Defaults().Copy | |
| 192 | + | } | |
| 193 | + | ||
| 185 | 194 | func (d *Daemon) currentPaletteConfig() domain.PaletteConfig { | |
| 186 | 195 | if cfg := d.paletteConfig.Load(); cfg != nil { | |
| 187 | 196 | return *cfg | |
| @@ -29,6 +29,8 @@ func (d *Daemon) ApplyConfig(cfg domain.Config) { | |||||
| 29 | d.restoreProcessAllowlist.Store(&allowlist) | 29 | d.restoreProcessAllowlist.Store(&allowlist) | ||
| 30 | floating := cfg.Floating | 30 | floating := cfg.Floating | ||
| 31 | d.floatingConfig.Store(&floating) | 31 | d.floatingConfig.Store(&floating) | ||
| 32 | + | copyConfig := cfg.Copy | |||
| 33 | + | d.copyConfig.Store(©Config) | |||
| 32 | palette := cfg.Palette | 34 | palette := cfg.Palette | ||
| 33 | d.paletteConfig.Store(&palette) | 35 | d.paletteConfig.Store(&palette) | ||
| 34 | tabs := cfg.Tabs | 36 | tabs := cfg.Tabs | ||
| @@ -182,6 +184,13 @@ func (d *Daemon) logConfigWarning(w domain.Warning) { | |||||
| 182 | d.log.Warn("config warning", "msg", w.Msg) | 184 | d.log.Warn("config warning", "msg", w.Msg) | ||
| 183 | } | 185 | } | ||
| 184 | 186 | ||||
| 187 | + | func (d *Daemon) currentCopyConfig() domain.CopyConfig { | |||
| 188 | + | if cfg := d.copyConfig.Load(); cfg != nil { | |||
| 189 | + | return *cfg | |||
| 190 | + | } | |||
| 191 | + | return domain.Defaults().Copy | |||
| 192 | + | } | |||
| 193 | + | ||||
| 185 | func (d *Daemon) currentPaletteConfig() domain.PaletteConfig { | 194 | func (d *Daemon) currentPaletteConfig() domain.PaletteConfig { | ||
| 186 | if cfg := d.paletteConfig.Load(); cfg != nil { | 195 | if cfg := d.paletteConfig.Load(); cfg != nil { | ||
| 187 | return *cfg | 196 | return *cfg | ||
M internal/usecase/daemon/config_test.go +15 -0
| @@ -50,6 +50,21 @@ func TestApplyConfigHotReloadSwapsBindingsAndCodes(t *testing.T) { | |||
| 50 | 50 | require.Equal(t, "NT", cmd.Code) | |
| 51 | 51 | } | |
| 52 | 52 | ||
| 53 | + | func TestApplyConfigPublishesCopyConfig(t *testing.T) { | |
| 54 | + | d := newTestDaemon(t, nil, stubClock{}) | |
| 55 | + | require.Equal(t, domain.CopyConfig{WordSeparators: domain.DefaultWordSeparators}, d.currentCopyConfig()) | |
| 56 | + | ||
| 57 | + | configured := domain.Defaults() | |
| 58 | + | configured.Copy = domain.CopyConfig{WordSeparators: "/:"} | |
| 59 | + | d.ApplyConfig(configured) | |
| 60 | + | require.Equal(t, domain.CopyConfig{WordSeparators: "/:"}, d.currentCopyConfig()) | |
| 61 | + | ||
| 62 | + | reloaded := domain.Defaults() | |
| 63 | + | reloaded.Copy = domain.CopyConfig{} | |
| 64 | + | d.ApplyConfig(reloaded) | |
| 65 | + | require.Equal(t, domain.CopyConfig{}, d.currentCopyConfig()) | |
| 66 | + | } | |
| 67 | + | ||
| 53 | 68 | func TestApplyConfigPublishesImmutablePaletteSnapshot(t *testing.T) { | |
| 54 | 69 | d := newTestDaemon(t, nil, stubClock{}) | |
| 55 | 70 | require.Equal(t, domain.Defaults().Palette, d.currentPaletteConfig()) | |
| @@ -50,6 +50,21 @@ func TestApplyConfigHotReloadSwapsBindingsAndCodes(t *testing.T) { | |||||
| 50 | require.Equal(t, "NT", cmd.Code) | 50 | require.Equal(t, "NT", cmd.Code) | ||
| 51 | } | 51 | } | ||
| 52 | 52 | ||||
| 53 | + | func TestApplyConfigPublishesCopyConfig(t *testing.T) { | |||
| 54 | + | d := newTestDaemon(t, nil, stubClock{}) | |||
| 55 | + | require.Equal(t, domain.CopyConfig{WordSeparators: domain.DefaultWordSeparators}, d.currentCopyConfig()) | |||
| 56 | + | ||||
| 57 | + | configured := domain.Defaults() | |||
| 58 | + | configured.Copy = domain.CopyConfig{WordSeparators: "/:"} | |||
| 59 | + | d.ApplyConfig(configured) | |||
| 60 | + | require.Equal(t, domain.CopyConfig{WordSeparators: "/:"}, d.currentCopyConfig()) | |||
| 61 | + | ||||
| 62 | + | reloaded := domain.Defaults() | |||
| 63 | + | reloaded.Copy = domain.CopyConfig{} | |||
| 64 | + | d.ApplyConfig(reloaded) | |||
| 65 | + | require.Equal(t, domain.CopyConfig{}, d.currentCopyConfig()) | |||
| 66 | + | } | |||
| 67 | + | ||||
| 53 | func TestApplyConfigPublishesImmutablePaletteSnapshot(t *testing.T) { | 68 | func TestApplyConfigPublishesImmutablePaletteSnapshot(t *testing.T) { | ||
| 54 | d := newTestDaemon(t, nil, stubClock{}) | 69 | d := newTestDaemon(t, nil, stubClock{}) | ||
| 55 | require.Equal(t, domain.Defaults().Palette, d.currentPaletteConfig()) | 70 | require.Equal(t, domain.Defaults().Palette, d.currentPaletteConfig()) | ||
M internal/usecase/daemon/daemon.go +3 -0
| @@ -130,6 +130,7 @@ type Daemon struct { | |||
| 130 | 130 | codeOverrides atomic.Pointer[map[string]string] | |
| 131 | 131 | restoreProcessAllowlist atomic.Pointer[map[string]struct{}] | |
| 132 | 132 | floatingConfig atomic.Pointer[domain.FloatingConfig] | |
| 133 | + | copyConfig atomic.Pointer[domain.CopyConfig] | |
| 133 | 134 | paletteConfig atomic.Pointer[domain.PaletteConfig] | |
| 134 | 135 | tabsConfig atomic.Pointer[domain.TabsConfig] | |
| 135 | 136 | themeMode atomic.Uint32 | |
| @@ -331,6 +332,8 @@ func New(ptys ports.PTYFactory, clock ports.Clock, log *slog.Logger, opts ...Opt | |||
| 331 | 332 | defaults := domain.Defaults() | |
| 332 | 333 | defaultFloating := defaults.Floating | |
| 333 | 334 | d.floatingConfig.Store(&defaultFloating) | |
| 335 | + | defaultCopy := defaults.Copy | |
| 336 | + | d.copyConfig.Store(&defaultCopy) | |
| 334 | 337 | defaultPalette := defaults.Palette | |
| 335 | 338 | d.paletteConfig.Store(&defaultPalette) | |
| 336 | 339 | for _, o := range opts { | |
| @@ -130,6 +130,7 @@ type Daemon struct { | |||||
| 130 | codeOverrides atomic.Pointer[map[string]string] | 130 | codeOverrides atomic.Pointer[map[string]string] | ||
| 131 | restoreProcessAllowlist atomic.Pointer[map[string]struct{}] | 131 | restoreProcessAllowlist atomic.Pointer[map[string]struct{}] | ||
| 132 | floatingConfig atomic.Pointer[domain.FloatingConfig] | 132 | floatingConfig atomic.Pointer[domain.FloatingConfig] | ||
| 133 | + | copyConfig atomic.Pointer[domain.CopyConfig] | |||
| 133 | paletteConfig atomic.Pointer[domain.PaletteConfig] | 134 | paletteConfig atomic.Pointer[domain.PaletteConfig] | ||
| 134 | tabsConfig atomic.Pointer[domain.TabsConfig] | 135 | tabsConfig atomic.Pointer[domain.TabsConfig] | ||
| 135 | themeMode atomic.Uint32 | 136 | themeMode atomic.Uint32 | ||
| @@ -331,6 +332,8 @@ func New(ptys ports.PTYFactory, clock ports.Clock, log *slog.Logger, opts ...Opt | |||||
| 331 | defaults := domain.Defaults() | 332 | defaults := domain.Defaults() | ||
| 332 | defaultFloating := defaults.Floating | 333 | defaultFloating := defaults.Floating | ||
| 333 | d.floatingConfig.Store(&defaultFloating) | 334 | d.floatingConfig.Store(&defaultFloating) | ||
| 335 | + | defaultCopy := defaults.Copy | |||
| 336 | + | d.copyConfig.Store(&defaultCopy) | |||
| 334 | defaultPalette := defaults.Palette | 337 | defaultPalette := defaults.Palette | ||
| 335 | d.paletteConfig.Store(&defaultPalette) | 338 | d.paletteConfig.Store(&defaultPalette) | ||
| 336 | for _, o := range opts { | 339 | for _, o := range opts { | ||