Skip to content

Config-driven themes and keybindings (#7, #8) - #15

Merged
citizen-123 merged 5 commits into
mainfrom
config-themes-keybindings
Jul 29, 2026
Merged

Config-driven themes and keybindings (#7, #8)#15
citizen-123 merged 5 commits into
mainfrom
config-themes-keybindings

Conversation

@citizen-123

Copy link
Copy Markdown
Owner

Closes #7 and #8. Brings the config-driven themes and keybindings work to main and finishes the items each issue left open.

What's here

  • internal/config — user config at ~/.config/cli-capture/config.json (+ $XDG_CONFIG_HOME, presets, -config), merged layer by layer; unknown keys rejected.
  • internal/theme — the palette as plain data (no lipgloss): built-ins (dark/light/high-contrast/none), -theme, per-color overrides, NO_COLOR.
  • internal/tui/keymap.go — one action→keys table per context; dispatch and the ? overlay are generated from it, so they can't drift. Rebindable via config, including the leader.

Finishing the open items (this branch's new commit)

#7 — glyph theming (the decision the issue flagged): themes now carry the flag marker , the pointer , and the arrow , plus the pane/overlay border style — configured under theme.glyphs and theme.border. Kept apart from the palette so NO_COLOR strips colors without swapping a user's chosen characters back. Unknown glyph/border names fail at startup like unknown colors do.

{ "theme": { "glyphs": { "flag": "*" }, "border": "normal" } }

#8ctrl+q into the table: the quit-from-editor/Repeater binding was the last one living outside the keymap. It's now a normal app.quit binding in the editor and repeater contexts, dispatched through the table and shown in the generated help.

Still open (noted, not in scope here)

Verification

go build, go vet, and go test ./... (14 packages) all pass; docs/configuration.md documents the new glyphs/border keys. Colors-only themes and default rendering are unchanged.

🤖 Generated with Claude Code

claude and others added 5 commits July 28, 2026 11:07
Adds internal/config, internal/theme, and a keymap layer in the TUI, so
the palette and the bindings are data rather than literals.

Config lives at ~/.config/cli-capture/config.json ($XDG_CONFIG_HOME
honored), separate from -dir, which keeps holding the CA, sessions,
exports, and log. A config.json already sitting in the data directory is
still read, but only while the new-style file doesn't exist, so an
existing install keeps working without an empty new file silently
shadowing it.

-config takes files or preset names, repeats, and accepts comma-separated
lists: `-config work,light` merges ~/.config/cli-capture/work.json then
light.json on top of the default file. Merging is per field, so a preset
can change one color or one binding without restating the rest. It is a
flag.Value rather than a plain string specifically so a second -config
adds to the first instead of discarding it — the trap the -scope flag
still has.

Themes (#7): every color that was a package-level lipgloss var in
styles.go now comes from a theme.Theme, resolved once at startup by
ApplyTheme. Built-ins are dark (the original palette), light,
high-contrast, and none; -theme picks one and beats the config file, and
NO_COLOR strips color while leaving bold, reverse, and borders intact.
Unset colors leave the style with no foreground at all rather than a
color literally named "", which is what keeps NO_COLOR output clean.

Keybindings (#8): keys now resolve to actions through a table, and both
the dispatcher and the ? overlay read that one table — the overlay used
to be a second hand-written list, and had already drifted (it described
Repeater Tab as two-way when it cycles three focuses). Rebinding a key
updates the help; unbinding an action removes it. The leader is
configurable to any ctrl key, and the literal byte sent when it's pressed
twice follows it, since KeyType 1-26 is the ASCII control code.

Bad input fails at startup with a message naming the file and listing
what was expected — unknown theme, unknown color, out-of-range value,
unknown context, unknown action. Two cases are rejected that would
otherwise be silent no-ops: binding an action in a context that doesn't
have it, and binding the leader inside another context, which could never
fire because the leader is consumed first.

Behavior is unchanged for anyone with no config: the defaults reproduce
the previous palette and bindings exactly, and a zero-value Model still
dispatches and renders help, which is what the existing tests construct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MavUrTwm29bQRDy2Nufoq3
Adds docs/configuration.md — file location and the config/data split,
merging several files and presets via -config, the theme list and every
overridable color key, the leader constraint and the action table per
context, and where to look when a setting doesn't take (the startup log
records which files merged and what resolved).

Links it from the docs index, the README flag table, and the keybindings
page, which now says up front that everything it lists is a default.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MavUrTwm29bQRDy2Nufoq3
Addresses the "Still open" items on both issues.

#7 — glyph theming (the decision the issue flagged): a theme now carries the
flag marker, the paused/edit pointer, and the detail/Repeater arrow, plus the
pane/overlay border style, alongside its colors. Configured under
theme.glyphs ({flag,pointer,arrow}) and theme.border (rounded|normal|thick|
double|hidden). Empty glyph keeps the built-in default; an empty string removes
the glyph. Glyphs and border are kept apart from the palette so NO_COLOR strips
colors without swapping a user's chosen characters back. Unknown glyph names and
border styles fail at startup like unknown colors do. The help-overlay border
now follows the theme too.

#8 — ctrl+q (quit from the editor and Repeater) was the last binding living
outside the keymap table. It's now a normal ActQuit binding in the editor and
repeater contexts, dispatched through the table and shown in the generated help
like everything else.

Colors-only themes and default rendering are unchanged. Tests cover glyph/border
resolution, NO_COLOR preserving them, and every advertised glyph/border being
accepted; docs/configuration.md documents the new keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- keymap: validate a rebinding against the actions its *context* dispatches,
  not the global action set. Binding e.g. session.save in the traffic pane now
  errors instead of being stored as a binding that can never fire — honoring the
  documented "reject rather than silently ignore" guarantee (docs/configuration
  .md). Adds actionInContext/contextActions; test updated to bind each action in
  its own context and to reject a real action in the wrong one.
- rows: an empty flag glyph (a documented "remove the marker" value) no longer
  shifts flagged rows one column left — flagMark falls back to a one-cell space
  so columns stay aligned. Regression test added.
- help: compute inter-section spacing from whether a section already rendered,
  not the loop index, so a fully-unbound leading context can't open the overlay
  with a blank line.
- keymap: zero-value KeyMap.Action reads the cached defaultKeyMap instead of
  rebuilding it each call.

Not changed (evaluated): the leader-in-subcontext restriction (documented and
safe — errors loudly, never silent); -theme layering over a preset's colors
(the flag's precedence is over the base, and color overrides are a separate
intentional layer); detail j/k scroll is a viewport built-in, deliberately not
a keymap action.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@citizen-123
citizen-123 merged commit 8ed351b into main Jul 29, 2026
2 checks passed
@citizen-123
citizen-123 deleted the config-themes-keybindings branch July 29, 2026 02:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User-definable themes

2 participants