detached bb3050a

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 VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · 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) {
2929 d.restoreProcessAllowlist.Store(&allowlist)
3030 floating := cfg.Floating
3131 d.floatingConfig.Store(&floating)
32+ copyConfig := cfg.Copy
33+ d.copyConfig.Store(&copyConfig)
3234 palette := cfg.Palette
3335 d.paletteConfig.Store(&palette)
3436 tabs := cfg.Tabs
@@ -182,6 +184,13 @@ func (d *Daemon) logConfigWarning(w domain.Warning) {
182184 d.log.Warn("config warning", "msg", w.Msg)
183185 }
184186
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+
185194 func (d *Daemon) currentPaletteConfig() domain.PaletteConfig {
186195 if cfg := d.paletteConfig.Load(); cfg != nil {
187196 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.Floating30 floating := cfg.Floating
31 d.floatingConfig.Store(&floating)31 d.floatingConfig.Store(&floating)
32+ copyConfig := cfg.Copy
33+ d.copyConfig.Store(&copyConfig)
32 palette := cfg.Palette34 palette := cfg.Palette
33 d.paletteConfig.Store(&palette)35 d.paletteConfig.Store(&palette)
34 tabs := cfg.Tabs36 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 *cfg196 return *cfg
M internal/usecase/daemon/config_test.go +15 -0
@@ -50,6 +50,21 @@ func TestApplyConfigHotReloadSwapsBindingsAndCodes(t *testing.T) {
5050 require.Equal(t, "NT", cmd.Code)
5151 }
5252
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+
5368 func TestApplyConfigPublishesImmutablePaletteSnapshot(t *testing.T) {
5469 d := newTestDaemon(t, nil, stubClock{})
5570 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 {
130130 codeOverrides atomic.Pointer[map[string]string]
131131 restoreProcessAllowlist atomic.Pointer[map[string]struct{}]
132132 floatingConfig atomic.Pointer[domain.FloatingConfig]
133+ copyConfig atomic.Pointer[domain.CopyConfig]
133134 paletteConfig atomic.Pointer[domain.PaletteConfig]
134135 tabsConfig atomic.Pointer[domain.TabsConfig]
135136 themeMode atomic.Uint32
@@ -331,6 +332,8 @@ func New(ptys ports.PTYFactory, clock ports.Clock, log *slog.Logger, opts ...Opt
331332 defaults := domain.Defaults()
332333 defaultFloating := defaults.Floating
333334 d.floatingConfig.Store(&defaultFloating)
335+ defaultCopy := defaults.Copy
336+ d.copyConfig.Store(&defaultCopy)
334337 defaultPalette := defaults.Palette
335338 d.paletteConfig.Store(&defaultPalette)
336339 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.Uint32136 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.Floating333 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.Palette337 defaultPalette := defaults.Palette
335 d.paletteConfig.Store(&defaultPalette)338 d.paletteConfig.Store(&defaultPalette)
336 for _, o := range opts {339 for _, o := range opts {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close