aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* refactor(jumper): extract marker-traversal and location-candidates helpersCraig Jennings19 hours2-32/+93
| | | | jumper--location-exists-p and jumper--format-location both opened a marker with the same save-current-buffer/set-buffer/save-excursion/goto-char dance; jumper-jump-to-location and jumper-remove-location shared a verbatim candidate-list cl-loop. Extract jumper--with-marker-at (index fn) and jumper--location-candidates; the four callers delegate. Adds direct coverage of the candidate list.
* refactor(modeline): extract the clickable-segment keymap builderCraig Jennings19 hours2-11/+42
| | | | The buffer-name, vc, and major-mode segments each hand-rolled the same make-sparse-keymap + define-key [mode-line mouse-1/3] construction. Extract cj/--modeline-click-map (mouse-1 &optional mouse-3); the three segments call it. Adds coverage for the one- and two-button cases.
* refactor(ai-config): extract gptel model-apply step, drop dead branchCraig Jennings19 hours2-8/+61
| | | | cj/gptel-change-model applied the selection inline (scope dispatch + message) and re-checked (stringp model) on a value already interned to a symbol. Extract cj/--gptel-apply-model-selection (scope backend model backend-name), which sets the vars globally or buffer-locally and returns the message; the dead stringp branch is gone. Adds direct coverage of both scopes.
* refactor(ai-conversations): reuse the autosave-active predicate in the hooksCraig Jennings19 hours1-8/+2
| | | | cj/gptel--autosave-after-send and cj/gptel--autosave-after-response re-inlined the four-clause "should we autosave?" boolean that cj/gptel--autosave-active-p already encapsulates. Call the helper instead (after-send keeps its extra autosave-on-send flag). Behavior unchanged; one predicate to maintain.
* refactor(org-agenda): extract the agenda base-file listCraig Jennings19 hours2-5/+46
| | | | The fixed base list (inbox, schedule, and the three calendars) was spelled out as a literal in cj/--org-agenda-scan-files, cj/todo-list-single-project, and the chime initializer. Extract cj/--org-agenda-base-files so adding a calendar source is a one-place change; the single-project view prepends its todo.org with cons. Adds a test for the helper's contents and order.
* refactor(mail-config): build the account-nav keymaps from one templateCraig Jennings19 hours2-18/+87
| | | | The cmail/dmail/gmail navigation maps were three near-identical defvar-keymap blocks differing only by maildir prefix, with the unread/flagged/large query clauses repeated in each. Add cj/--mail-account-search-queries (account -> the four search strings) and cj/--mail-make-account-map (builds the keymap), wrapped in eval-and-compile so org-msg's :preface can call the builder during byte-compilation. The three maps become one-line builder calls. Adds direct coverage of the query strings and the per-account closures.
* refactor(org-capture): extract the find-or-create-top-heading blockCraig Jennings20 hours2-25/+69
| | | | cj/org-capture--goto-file-headline, cj/--org-capture-goto-open-work, and cj/--org-capture-goto-exact-headline each repeated the same positioning block: search from point-min, jump to the heading on a match, else append it at end of buffer and back up. Extract cj/--org-find-or-create-top-heading taking the search regexp and the heading line; the three sites delegate. Behavior unchanged; adds direct coverage of the helper with a plain regexp.
* docs(custom-ordering): correct point-position note on replace-region helperCraig Jennings20 hours1-1/+1
|
* refactor(custom-text-enclose): extract the region-or-word dispatchCraig Jennings20 hours2-48/+92
| | | | cj/surround/wrap/unwrap-word-or-region each repeated the same skeleton: target the active region, else the word at point, else show a message; then delete and re-insert the transformed text. Extract cj/--enclose-region-or-word, which takes the transform as a function and the no-target message, so each command reads its prompts then delegates. Behavior and messages unchanged; adds direct coverage of the dispatch helper.
* refactor(custom-datetime): generate the six inserters from one macroCraig Jennings20 hours2-33/+42
| | | | The six cj/insert-* commands were identical except their format variable and a one-word docstring noun. Replace them with a cj/--define-datetime-inserter macro and six table-style calls; the format defvars and the keymap are unchanged. Adds a test asserting all six stay interactive commands.
* refactor(custom-ordering): dedupe region guard, replace tail, and ↵Craig Jennings20 hours2-56/+98
| | | | | | arrayify-python Extract cj/--ordering-validate-region (the start>end guard copy-pasted across all seven pure helpers) and cj/--ordering-replace-region (the delete-region + insert tail repeated in every interactive command). Alias cj/arrayify-python to cj/arrayify-json, which it duplicated verbatim, leaving both keybindable. Behavior unchanged; adds direct Normal/Boundary/Error coverage for the two new helpers.
* refactor: extract shared format-region helper into system-libCraig Jennings20 hours4-54/+100
| | | | prog-json and prog-yaml each carried a byte-identical cj/--<lang>-format-region that runs a formatter over the buffer via call-process-region and replaces it on exit 0. Hoist it to system-lib as cj/format-region-with-program with a generic output buffer, and point both formatters at it. Adds the first direct unit coverage of the helper (Normal, Boundary, Error).
* refactor: remove dead wrappers and commented-out blocksCraig Jennings20 hours8-74/+1
| | | | Drop cj/apply-browser-choice (browser-config) and cj/load-fallback-theme (ui-theme), orphaned wrappers with no caller that just duplicated logic the live paths already inline, plus their tests. Delete commented-out blocks: a duplicate contact capture template (org-contacts-config), a disabled personal-info-dir :init (help-config), a stale TODO setq (org-config), and an old commented regex (test-runner).
* chore(todo): mark window pull-away manual check passedCraig Jennings20 hours1-8/+0
|
* fix(windows): shrink the pull-away reveal to the minimum window heightCraig Jennings20 hours2-2/+7
| | | | minimize-window floors at window-min-height (4 lines), leaving roughly a 10% reveal. Bind window-min-height to 1 around it so the reveal opens at the ~2-line floor and the current window keeps almost the whole frame before the windsize arrows take over.
* chore(todo): update window pull-away notes to shipped behaviorCraig Jennings21 hours1-5/+6
|
* fix(windows): keep the pulled-away window on the arrow's edgeCraig Jennings21 hours2-35/+45
| | | | The sole-window pull split toward the arrow at 50/50, so a fullscreen terminal jumped above the revealed buffer at half height. Now the reveal opens on the opposite side and is minimized to a sliver, so the current window keeps the arrow's edge near-full and the sticky windsize arrows shrink it step by step, matching the feel of resizing an existing split.
* chore(todo): close dirvish and window-pull tasks, file manual checksCraig Jennings21 hours1-12/+19
|
* feat(windows): pull a window away from a sole window with C-; b + arrowCraig Jennings21 hours2-8/+69
| | | | When the selected window fills the frame there is no divider to resize, so the arrow now splits toward its direction with the previous buffer and the original window shrinks from that edge. Multi-window resize is unchanged.
* feat(dirvish): bind d to duplicate, D to guarded force-deleteCraig Jennings21 hours2-2/+80
| | | | Drop delete-to-trash. d now duplicates the file at point. D force-deletes the marked files via sudo rm -rf behind a yes-or-no-p that names the targets, and reports success only when rm exits 0.
* chore(todo): stamp task-review on 7 audit-filed tasksCraig Jennings21 hours1-0/+21
|
* chore(todo): archive resolved org-lint follow-upsCraig Jennings25 hours1-4/+3
|
* chore(theme-studio): save WIP working stateCraig Jennings25 hours2-75/+130
|
* chore(todo): log the shipped theme-studio task batchCraig Jennings25 hours1-0/+12
| | | | Record the second studio batch as dated entries: expander hovers, view-dropdown lock indicator, expand/collapse-all, expander-stays-open-on-rebuild, 18 language previews, and the box column move.
* feat(theme-studio): move the box column between style and contrastCraig Jennings25 hours4-26/+26
| | | | Box now sits at column 5 in all three tables, after style and before contrast, instead of last. The contrast and example/preview columns shift right by one, and the position-based gates follow.
* feat(theme-studio): add 18 language previewsCraig Jennings25 hours4-2/+430
| | | | Add tokenized code samples for Racket, Scheme, Haskell, OCaml, Scala, Kotlin, Swift, Lua, Ruby, Perl, R, Erlang, SQL, PHP, Ada, Fortran, MATLAB, and Assembly, wired into the language dropdown. Each is an idiomatic snippet tagged by syntax category so the studio renders it in the assignment colors. A guard test checks every added language is registered and renders a non-trivial sample.
* fix(theme-studio): keep an expander open across a table rebuildCraig Jennings25 hours3-10/+64
| | | | A package edit rebuilds the whole table, which collapsed any open expander under the user mid-edit. Track open rows in a module-level EXPANDED set, keyed by element/face, and reopen them on rebuild. Editing a value inside an open expander now leaves the row open. The expand-all/collapse-all and per-row toggles keep the set in sync.
* feat(theme-studio): expand/collapse-all toggle and disclosure trianglesCraig Jennings25 hours4-18/+106
| | | | Each row's expander toggle now shows a disclosure triangle that tracks its state: a right triangle when collapsed, a down triangle when expanded (it was a static ellipsis). A header-level expand-all / collapse-all button per table opens or closes every row's detail at once and follows the aggregate state. The per-row triangles and the header button stay in sync across a table rebuild.
* feat(theme-studio): expander label hovers and a view-dropdown lock indicatorCraig Jennings25 hours3-8/+108
| | | | Each label in the expander detail row now carries an explanatory hover (DETAIL_HOVERS), matching the table-header labels. The view dropdown prefixes a lock glyph on any view whose elements are all locked, recomputed on every lock change through updateLockToggles.
* fix(todo): repoint the broken signel link and close the org-lint follow-upsCraig Jennings25 hours1-7/+5
| | | | The Signal task linked to a todo file in the old signel checkout, which no longer exists. I repointed it to the smoke project's todo (smoke is the evolved Signal package). I also reworded the bug-capture task's prose so its quoted TODO-heading strings stop tripping the misplaced-heading checker. A full org-lint pass now reports zero, so the follow-up task is closed.
* chore(todo): close shipped theme-studio widget tasksCraig Jennings25 hours1-2/+11
| | | | Mark the reduce-width, custom weight/slant dropdown, language-dropdown, and lock-to-leftmost tasks done as dated log entries. Refresh the org-lint follow-up list (current line numbers, plus the broken signel-todo link).
* feat(theme-studio): move the lock column to the leftmost positionCraig Jennings25 hours4-20/+20
| | | | Put the lock cell first in all three assignment tables, ahead of the element/face name. The lock and name columns swap, and every column from fg onward is unchanged. The element-name sort moves to column 1, and the sort and index gates follow it.
* feat(theme-studio): custom weight/slant dropdowns with previewsCraig Jennings26 hours4-42/+128
| | | | | | Replace the native weight and slant selects with a custom dropdown themed like the color dropdown. The values are spelled out (semibold instead of "semi", and an unset control reads "weight"/"slant" rather than "wt"/"sl"), and each popup option renders in its own weight or slant so the choice previews itself. The trigger shows the current value in that style too. mkEnumDropdown mirrors the color dropdown's popup, lock, and outside-click handling, so the new control opens, locks, and closes the same way. The style-cluster gates drive the popup instead of a native select and check the spelled-out range plus the per-option preview.
* feat(theme-studio): tighten the elements-table horizontal layoutCraig Jennings26 hours4-8/+8
| | | | Reduce the per-cell horizontal padding from 12px to 8px across the assignment tables, so more of each row fits without horizontal scroll on a narrow screen. Also shorten the mode-line-highlight label to "(hover)", since the face name already carries the "mode-line" part.
* feat(theme-studio): sort the language dropdown and add nav arrowsCraig Jennings26 hours4-4/+54
| | | | Sort the language list alphabetically and pin Elisp as the default selection. Add the ‹ › arrows flanking the dropdown that step the selection (clamped, no wrap), reusing the view-dropdown's stepViewIndex so you can walk languages without reopening the menu.
* feat(theme-studio): unify per-row widgets across the assignment tablesCraig Jennings26 hours7-63/+162
| | | | | | | | | | | | The color/code, UI, and package tables now share one per-row widget set, so the editing surface reads the same whatever view is selected. Column order is the same in all three: element, lock, fg, bg, style, contrast, example, box. Box moves to last in the color/code table, and the package table's inline inherit and size columns fold into the row expander, matching how UI and color/code already carry them. The UI overlay faces drop the inline PASS/FAIL word and the red FAIL badge on the preview swatch. They show a bare colored worst-case number with the WCAG verdict in the hover, like the other two tables. The orphaned .crerr style goes with it. The height picker now clamps a typed value into [0.1, 2.0]. A number input only enforces min/max on its stepper arrows, so a typed or pasted value reached the model unchecked. 0.1 is Emacs's own floor (a smaller height errors out), and 2.0 is the studio ceiling. Clearing the field still unsets to the inherited default. Tests: clampHeight unit tests plus a #heighttest browser gate. The column and contrast gates move to the new positions and the bare-number readout.
* chore(todo): archive resolved face-coverage generator taskCraig Jennings27 hours1-22/+21
|
* chore(theme-studio): save WIP working stateCraig Jennings27 hours2-5/+126
|
* feat(theme-studio): add ansi-color faces to drive all ANSI consumersCraig Jennings28 hours2-1/+17
| | | | | | theme-studio could theme ghostel-color-* but not the base ansi-color-* faces. build-inventory.el skips built-in faces, and ansi-color is part of Emacs core, so the 16 base ANSI faces never reached the dropdown. That left vterm, eshell, and compilation buffers on stock ANSI colors no matter the theme. I added ansi-color as a bespoke app (the same path shr already uses for a built-in library), with the 16 palette faces seeded to match the ghostel colors. Theming ansi-color-* now sets the 16 colors for every ANSI consumer at once. ghostel-color-* inherit these, so clearing a ghostel-color face lets it follow ansi-color rather than holding its own value.
* feat(theme-studio): export through the save-file picker to overwrite in placeCraig Jennings28 hours3-2/+56
| | | | | | Re-exporting a theme used to land a "name (1).json" duplicate. The export built a blob and clicked a download link, which routes through the browser's downloads folder, and the browser uniquifies a re-save rather than replacing the file. I switched export to the File System Access API (showSaveFilePicker): it writes straight to the file you pick, so re-exporting the same WIP.json overwrites it. Where the API is absent the old blob download still runs, mirroring importTheme's picker-with-fallback shape. A new #savetest browser gate stubs the picker and checks the written content and the close.
* chore(theme-studio): save WIP.json working stateCraig Jennings28 hours1-13/+45
|
* test(theme-studio): cover the face-docs dump helper and syntax mapCraig Jennings28 hours2-7/+87
| | | | I added ERT tests for face-docs-dump.el: the pure first-line extractor across Normal/Boundary/Error inputs (multi-line, leading blanks, whitespace collapse, empty, whitespace-only, nil/non-string), and the syntax-category resolution (kw to the keyword-face doc, bg and p to default, the faceless dec absent). run-tests.sh loads the new file alongside the build-theme tests in the same batch.
* feat(theme-studio): show face docstrings in element hoversCraig Jennings28 hours9-9/+183
| | | | | | Each table row's category cell now shows the face's Emacs docstring on hover, on top of whatever the cell showed before. The package cell keeps the face name underneath. The syntax and UI cells had no prior tooltip, so they show just the docstring. The label-span hints are left alone. I added face-docs-dump.el, which emits face-docs.json from a live Emacs: a face-name to first-doc-line map for the UI and package tables, and a category to doc map for the syntax table. The category to font-lock-face mapping is read from build-theme.el's own map, so it isn't copied a third time. generate.py inlines both maps. A pure composeHoverTitle helper composes the tooltip, covered by Node, Python, and a new browser gate.
* feat(windows): dock companion panels by a shared min-column ruleCraig Jennings29 hours8-47/+269
| | | | | | The F9 agent always docked as a right-side column on a landscape frame. On this 138-column frame that left ~68-column panes, too cramped to read code and the agent side by side. The F12 terminal and F10 playlist hardcoded a bottom split with no width-aware path. I added cj/preferred-dock-direction and the cj/window-dock-min-columns defcustom (default 80) to the window-geometry lib: dock side-by-side only when the narrower pane keeps at least the minimum width, otherwise stack below. All three toggles now route through it. F9 drops its pixel-aspect rule. F12 and F10 gain a right-column width default and become adaptive. F10 keeps width and height size memory in separate vars so a resize on one axis doesn't leak to the other.
* chore(theme-studio): save WIP.json working stateCraig Jennings37 hours1-472/+472
|
* test(theme-studio): cover defensive branches and the palette generatorCraig Jennings44 hours3-1/+140
| | | | Added the uncovered fallback branches in app-core (migrateLegacyFace null input, normalizePkgFace's source fallback chain, mergePackagesInto's null/new-app guards, boxCss shading a relief from the bg when no box color is set) and in colormath (apca's equal-luminance return-0 and low-contrast clamp, isPureEndpointHex). New test-palette-generator-core.mjs drives planPaletteGenerator across every scheme, vibe, source mode, and the fill-gaps intents, since those internals are only reachable through the public planner. colormath branch 96 -> 99%, palette-generator-core funcs 97 -> 100%, node suite 237 tests. The remaining gaps are the deep palette-column edge branches, deferred as diminishing returns on already line-covered code.
* test(theme-studio): cover the promoted faceCss helpersCraig Jennings44 hours1-0/+89
| | | | cssWeight, faceDecoration, boxCss, and faceCss moved into app-core in the CSS-builder refactor but had no node tests, leaving app-core at 96% line / 95% funcs. Added Normal/Boundary/Error cases for all four: every weight name plus the fallbacks, underline/strike/both/neither decoration, line/released/pressed boxes with and without color and width plus the no-color fallback, and faceCss's background/noBg/fontSize/box-order assembly. app-core is now 100% line; the node suite is 217 tests.
* refactor(theme-studio): share the spec-from-entries loop in build-themeCraig Jennings44 hours1-15/+14
| | | | The UI and package tier builders repeated the same "for each (face . obj) entry, build attrs, emit a non-empty spec" loop. Both now call one build-theme/--specs-from-entries helper; the package builder concatenates each app's specs in order. The syntax builder keeps its own form since it fans one category out to several font-lock faces. The 41 ERT tests stay green and the emitted themes are unchanged.
* refactor(theme-studio): dedup the palette harvest and color-pair walksCraig Jennings44 hours2-29/+25
| | | | | | generate.py's add_default_palette_colors repeated the same fg/bg/box-color harvest three times (syntax, ui, package faces); it now calls one _harvest_spec_colors helper, preserving the add order so the palette and generated page are byte-identical. default_faces' _build_color_hex and _build_color_names each walked the same faces -> chosen/effective -> foreground/background/distantForeground nesting; both now consume one _iter_color_pairs generator and only differ in their key choice and filter. The rebuilt color maps match the originals exactly. I left the lower-value generate.py items (a build() wrapper, dict-driven fill_data) and the capture/face-coverage script dedups for later: they touch import-time behavior or scripts the suite doesn't run, so they want their own verification rather than riding this change.
* refactor(theme-studio): single-source the bespoke-app list in face_dataCraig Jennings44 hours3-54/+40
| | | | The bespoke apps were listed twice: generate.py's _BESPOKE_APPS (key, label, preview, faces, prefix, seed) and app_inventory's BESPOKE_APPS set of keys, which had drifted (it carried both "org" and "org-mode"). The spec list now lives in face_data.py as BESPOKE_APP_SPECS, beside the FACES/SEED constants it references. generate.py builds APPS from it, and app_inventory derives its exclusion set from the same keys plus an explicit "org" alias of the "org-mode" app. Adding a bespoke app is now one row. APPS order and the generated page are unchanged.