Config-driven themes and keybindings (#7, #8) - #15
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #7 and #8. Brings the config-driven themes and keybindings work to
mainand 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/overlayborderstyle — configured undertheme.glyphsandtheme.border. Kept apart from the palette soNO_COLORstrips 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" } }#8 —
ctrl+qinto the table: the quit-from-editor/Repeater binding was the last one living outside the keymap. It's now a normalapp.quitbinding in theeditorandrepeatercontexts, dispatched through the table and shown in the generated help.Still open (noted, not in scope here)
high-contrastbuilt-in covers the main case).Verification
go build,go vet, andgo test ./...(14 packages) all pass;docs/configuration.mddocuments the newglyphs/borderkeys. Colors-only themes and default rendering are unchanged.🤖 Generated with Claude Code