aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* fix(agenda): spawn the agenda frame tiled, not compositor-fullscreenCraig Jennings4 days5-15/+34
| | | | I dropped (fullscreen . fullboth) from the spawned frame so a tiling WM places it side by side with the working frame. "Fullscreen" was the wrong word for the intent: a normal frame at its full tiled position, not one covering the whole output. The engage-routing and focus logic are unchanged and matter more now, since a task opens in the adjacent working pane.
* feat(agenda): add S-<f8> dedicated fullscreen agenda frameCraig Jennings4 days6-201/+1780
| | | | | | | | I added a standing agenda surface in its own fullscreen frame of the daemon, placeable on its own workspace while the working frames stay untouched. S-<f8> spawns, raises, or closes it. The force-rescan moves to C-M-<f8>. It shows a today-anchored seven-day view and refreshes every five minutes through org-agenda-redo, so the now-line and synced events stay current without re-scanning the file list. A default-deny minor mode keeps it read-only: only navigation, the engage keys (routed to the working frame), and the frame's own controls are allowed. A failed redo falls back to the last-good snapshot with cloned markers, so the frame is never blank or unrestricted. I made it a frame of the daemon rather than a second process, so it shares the live state (calendar-sync, edits, the now-line). There's no startup auto-open, and the Hyprland-managed-window variant is a vNext once this proves out.
* docs(spec): redesign org-agenda spec to a fullscreen frame, mark READYCraig Jennings4 days1-102/+119
| | | | Craig redirected the right-side dock to a dedicated fullscreen frame of the daemon. I resolved all 8 decisions, reworked the design, alternatives, phases, and acceptance criteria to match, and flipped DRAFT to READY on the spec-review gate. One non-blocking finding: the frame view needs its own custom-command entry.
* feat(fontaine): rename Coding to Coding M, add Coding L at 14ptCraig Jennings4 days3-14/+21
| | | | | The Berkeley Mono code ladder is now Coding XS (11pt), Coding M (13pt), Coding L (14pt), and Coding XL (16pt).
* feat(ai-term): M-SPC cycles attached agents, M-S-SPC cycles allCraig Jennings4 days5-35/+142
| | | | | | | | | | | | M-SPC now steps only through attached agents (the ones with a live on-screen buffer), so the fast chord stays among what's already up. M-S-SPC steps through all active agents and attaches a detached tmux session when it lands on one, which is what M-SPC used to do. I moved the shared step logic into cj/--ai-term-step-among and added cj/--ai-term-attached-agent-dirs to filter the queue to attached buffers. I bound both chords globally and in eat-semi-char-mode-map so they work from inside an agent buffer. C-; a n keeps cycling all.
* refactor: drop unreachable nil after user-error in recording checksCraig Jennings4 days1-4/+2
|
* docs: fix broken file: links in theme-studio and ai-kb specsCraig Jennings4 days5-6/+6
|
* chore: version active working artifactsCraig Jennings5 days68-1/+3100
| | | | I made working/ a versioned home for in-progress project artifacts and moved disposable scratch to temp/. This preserves the full music UI design history and the deferred EAT XTWINOPS upstream patch.
* feat: add workflow font profilesCraig Jennings5 days10-221/+538
| | | | | | I replaced the mixed Fontaine presets with seven named profiles that persist across restarts. The mode line, echo area, and minibuffer stay in Berkeley Mono. Nov applies the shared Reading profile inside each EPUB buffer without changing the global selection.
* fix(shell): require external-open, scope tramp revert, drop dead configCraig Jennings6 days5-30/+50
| | | | | | | | - dirvish-config, dwim-shell-config: both call cj/xdg-open (external-open) but relied on init.el requiring it before them, and dirvish's require comment misattributed it to system-utils. Added the require to both and corrected the comment and both Runtime-requires headers. - tramp-config: revert-without-query was set to '(".*") inside the TRAMP module, so every file in Emacs reverted without confirmation. Scoped it to the TRAMP path regexp, so local files keep their revert prompt and remote files skip the round-trip. - tramp-config: removed the sshfast method (referenced nowhere, scp and sshx handle everything) and a duplicate tramp-own-remote-path add-to-list. Tests: new runtime-requires assertions for both modules, red first under make test-file. The tramp :config edits are verified in the daemon. Suite green.
* fix(dev): repair hunk jump, F4 hook leak, async clone, and nil guardsCraig Jennings6 days16-139/+628
| | | | | | | | | | | | - vc-config: C-; v d matched literal +/- source text via consult-line, not gutter hunks. It now completes over git-gutter's hunk list and jumps to the chosen line. - vc-config: clipboard clone ran git synchronously, freezing every frame for the whole clone. It now runs async with a sentinel that opens the clone on success and surfaces the process buffer on failure. - vc-config: magit-blame bound D and S to the same command. D is now difftastic-magit-diff, matching the transient. - vc-config: dropped the :commands autoload for git-timemachine-show-selected-revision, a function the package never defined. The phantom appeared in M-x and errored. - dev-fkeys: both F4 chained-compile handlers armed a hook on the global compilation-finish-functions before their compile ran, so a quit left it live and the next unrelated compile fired the chain. The one-shot hook now installs buffer-locally in the compilation buffer, same shape as the projectile cache-revert hooks. - test-runner: outside a project with no global test directory, three commands crashed with wrong-type-argument on a nil path. Discovery now returns nil and the commands signal user-error. - diff-config: removed the global "-w" ediff default, which made every session ignore whitespace (indentation-only changes compared as identical). Whitespace-ignore stays available as ediff's per-session toggle. - restclient-config: the C-; R bindings went through raw global-set-key, silently depending on keybindings.el loading first. They now use a prefix keymap registered like the other C-; prefixes. - httpd-config: simple-httpd loaded on a 1s timer and created www/ on every startup. It now defers until impatient-mode needs it, and the doc root is created at package load.
* refactor(go): drop exec-path registration now duplicated at top levelCraig Jennings6 days1-1/+0
|
* fix(prog): cover classic modes and warn for missing dev toolsCraig Jennings6 days8-11/+263
| | | | | | Classic go-mode and js-mode buffers got none of the ts-mode setup, and web-mode got the format key without the promised company/flyspell/LSP. All three now run the shared setup. The web-mode LSP attach guards on the HTML language server, so machines without it stay silent instead of prompting. gopls, clangd, clang-format, bash-language-server, shfmt, and shellcheck now warn at load when missing. The shfmt, shellcheck, and clang-format blocks gate on :if, which evaluates once at startup, so an absent tool silently disabled that setup until the next restart. I also put ~/go/bin on exec-path at load so the gopls check doesn't misreport a gopls installed there.
* refactor(media): extract the playback sentinel as a named builderCraig Jennings6 days2-10/+48
| | | | | - cj/media--play-sentinel returns the per-process closure. - Three new tests pin the reap-on-exit behavior.
* refactor: launch external processes with argv lists, not shellsCraig Jennings6 days6-67/+284
| | | | | | | | - open-this-file-with splits the typed command and calls call-process. - media-play-it resolves streams via a yt-dlp capture, then start-process. - Paths, URLs, and player args never meet a shell. - yt-dlp stderr is captured separately so warnings can't parse as URLs. - Stream resolution now blocks briefly. mpv (the default) is unaffected.
* test(ai-term): close the show-or-create subprocess mock holeCraig Jennings6 days1-3/+16
| | | | | | - The preserve-window test now mocks the tmux and color seams. - A recording process-file guard asserts nothing escapes. - The tmux helper's error handler would swallow a signaling guard.
* feat(music): add a delete-playlist commandCraig Jennings6 days2-1/+169
| | | | | | | - D in the playlist buffer deletes a saved playlist. - Candidates span both m3u sources: local library and MPD dir. - A typed yes/no confirms deletion. - Deleting the loaded playlist's file clears its association.
* refactor(music): single builder for the number-gutter stringCraig Jennings6 days1-13/+15
|
* feat(completion): right-align custom category annotationsCraig Jennings6 days5-44/+135
| | | | marginalia-align has been right for months, but annotations from the custom completion categories (radio stations, music files, and everything built through the system-lib table helpers) never went through marginalia. They rendered unaligned. A registration helper adds a builtin registry entry per category at table construction, which routes the table's own annotation function through marginalia's aligned field. The radio table converts from an affixation function with hand-rolled padding to a plain annotation, since marginalia now owns the alignment. Self-maintaining: any future custom category built through the helpers registers itself.
* feat(music): freeze the playlist header while the track list scrollsCraig Jennings6 days2-3/+87
| | | | The header block (playlist name, now-playing hero, key legend) is an overlay string anchored at buffer position 1, so scrolling the list carried it off the top, key legend included. A handler on the buffer-local window-scroll-functions re-anchors the overlay at the window's display start on every scroll, so the block stays pinned at the top of the window. The header refresh timer now anchors at the same position instead of the buffer top, so the once-a-second update can't yank a scrolled header back.
* fix(music): unstick arrows and number placement at the playlist topCraig Jennings6 days2-1/+39
| | | | | | The playlist header is a multi-line overlay string anchored at buffer position 1. With point on the top row, next-line's visual motion stepped through the header's screen lines. Those all map back to position 1, so arrows never moved point. The buffer now moves by logical lines (each row is one), which skips the header display entirely. The same shared anchor put row 1's number above the header instead of beside its track: both overlay strings sit at position 1 and the number rendered first. Number overlays now outrank the header's priority, so the number lands next to its own row.
* feat(music): mark the current playlist row on its numberCraig Jennings6 days2-2/+91
| | | | Emacs draws the filled cursor only in the selected window, and the playlist dock is glanced at from other windows constantly. The pinned cursor was invisible exactly when it was wanted. The current row's number now renders in inverse video, updated as point moves and re-applied after each renumber. The mark shows whether or not the window has focus, and the row band from hl-line was already sticky.
* fix(music): raise the playlist dock default to half the frameCraig Jennings6 days2-9/+10
|
* fix(music): show the cursor on the row number and open the dock tallerCraig Jennings6 days3-3/+66
| | | | | | With point pinned at the row start, redisplay drew the cursor after the number's before-string, on the album-art thumbnail, where a block cursor is invisible. A cursor property on the number string makes redisplay draw it on the number. The dock also kept reopening too short: its height memory remembered whatever size the window had at toggle-off, including squeezes from window churn. The squeezed fraction then overrode the default on every later open. The default rises to a third of the frame, and the toggle discards captured heights below it (a deliberate enlargement still sticks for the session).
* feat(music): pin the playlist cursor to the number gutterCraig Jennings6 days2-1/+93
| | | | Vertical motion over thumbnail rows and the stretch-space that right-aligns the metadata drifts point to arbitrary visual columns, usually line end. The rows aren't editable text, so the cursor now lives at the row start (the number column). A buffer-local post-command snap sends every landing back there. Kill, shift (C-up/C-down), and play already act on the whole row, so all track operations happen from the number. An active isearch keeps point until it ends, then the snap lands on the match's row.
* feat(music): playing-aware playlist landing and music-only addsCraig Jennings6 days6-30/+345
| | | | | | Opening the playlist used to jump to EMMS's selected track, which stays set while stopped, so the view opened deep in the list with point mid-row. It now lands on the playing track's row (beginning of line, upper third of the window) when a song is playing, and at the top of the list when stopped. Both entry points share the logic, and the playlist buffer gets hl-line so the current row stays findable on album art. Also fixed: directory adds handed the raw tree to emms-add-directory-tree, which adds every file it finds. Cover art and liner notes became playlist rows. All three add paths now route through a filtered walk that keeps only accepted music extensions. The m3u loader applies the same filter to local paths (stream URLs pass through), so old playlists with saved cover lines stop re-importing them.
* feat(music): tag completion, aligned listings, numbered playlist rowsCraig Jennings6 days4-18/+347
| | | | | | | | | | The radio tag search now completes over popular tags from radio-browser's /json/tags endpoint (station-count order, capped at 500, cached per session), so the prompt offers real tags instead of a blind guess. Free-form input still works, and a failed fetch degrades to plain input. Station listings align into columns: the votes field pads to a fixed width, and each annotation pads out to the widest candidate name. Playlist rows carry a numeric overlay prefix, rebuilt after every change by a debounced after-change hook, so the cursor stays visible on cover-art thumbnails and each row's position is readable. Overlays leave the buffer text to EMMS. Also fixed: the search now trims queries before they hit the API (a trailing space used to reach it as %20 and match nothing).
* docs(ai-term): match reuse-edge docstring to delete-window realityCraig Jennings6 days1-4/+7
| | | | The docstring promised toggle-off puts the displaced buffer back via quit-restore-window. Toggle-off deliberately deletes the window instead: the slot's quit-restore parameter goes stale when several agents share it. That staleness is the "F9 shows another agent" bug the delete-window design killed.
* fix(ai-term): key teardown session names off the buffer nameCraig Jennings6 days5-13/+87
| | | | ghostel retargets default-directory via OSC 7 on every cd in the agent shell, so close (and quit with no project argument) computed the wrong aiv- session name after a cd. The kill then missed the real session and orphaned the agent, or hit a different project's session. The buffer name ("agent [basename]") never changes, so teardown now derives the basename from it.
* fix(calendar-sync): honor BYDAY rules and drop cancelled eventsCraig Jennings6 days10-27/+528
| | | | | | | | The expander ignored BYDAY on monthly and yearly rules and stepped DTSTART's day-of-month instead, so a "2nd Wednesday" series rendered on the 12th of every month, the wrong weekday most months. It now resolves nth-weekday entries (2WE, -1TU), bare weekdays with BYSETPOS, and yearly BYMONTH+BYDAY, so each occurrence lands on the day the rule names. Nothing read the VEVENT STATUS property, so cancelled events rendered as normal meetings: a cancelled instance of a series reappeared at its original time, and standalone cancelled events stayed on the agenda. parse-event now drops STATUS:CANCELLED events, which also kills cancelled series masters. A cancelled RECURRENCE-ID override removes its occurrence instead of overriding it. The fixes are coupled: until BYDAY generates the right dates, a cancelled override can't match the occurrence it removes.
* chore: two-pass case handling in pre-commit secret scanCraig Jennings6 days1-5/+17
| | | | Split the patterns into a case-sensitive pass (AWS/sk-/PEM) and a case-insensitive one (keyword=value), so mixed-case base64 in an embedded image blob stops tripping the uppercase AWS-key pattern and blocking real commits.
* docs: add org-agenda dock-mode spec (draft)Craig Jennings6 days1-0/+181
| | | | A right-side full-height agenda dock: side-window display ignoring the 0.75 below-selected rule, a dock-scoped 5-min redo, and jump-to-task that opens in the working window. Four design decisions stay open (dock width, composite view shape, focus-on-open, auto-open default).
* feat(org-agenda): raise file-cache TTL to 24h and bind S-<f8> force-refreshCraig Jennings7 days1-3/+14
| | | | | | The agenda file-list cache held a 1h TTL, so once an hour the next agenda open re-walked projects-dir from scratch. That cache tracks only which files exist, never their contents, so task edits and completions are never staled by it. The only thing a long TTL delays is a new project's todo.org appearing. That's rare, so I raised it to 24h. For that case I bound cj/org-agenda-refresh-files (the manual force-rescan) to S-<f8>, the free slot in the F8 agenda family (<f8>, s-<f8>, C-<f8>, M-<f8>).
* test: assert recurring-events window against calendar-sync's own rangeCraig Jennings7 days1-7/+14
| | | | | | The rolling-window integration test hand-rolled its bound as now minus 90 days to now plus 365 days at the current clock time. The code's window is minus-3 / plus-12 calendar months at day granularity. So a boundary occurrence stamped at midnight sat inside the code's window but before the now-minus-90-days bound, and the test passed or failed by the day it ran (green 2026-07-16, red 2026-07-17). I switched the assertion to calendar-sync--get-date-range, so the test checks the invariant it names: every emitted occurrence lands within the window the pipeline computed, stable on any date.
* fix(test): stop silently skipping every integration testCraig Jennings8 days4-37/+101
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | INTEGRATION_TESTS globbed test-integration-%.el through $(wildcard ...), which takes a shell glob where % is a literal character, not a pattern. It expanded to nothing, so test-all skipped the integration phase and still printed "All tests complete". Fourteen files never ran, for as long as the variable has existed. The % is right one line up, because filter-out does take make patterns. The glob is now test-integration-*.el, and the counts add up: 597 unit + 14 integration = the 611 test files on disk. Turning the gate on surfaced five failures, none of them in production code. Four were rotting fixtures. parse-ics drops events outside a rolling window of today minus calendar-sync-past-months to plus future-months, and four tests fed it dates pinned to November 2025 or February 2026. They passed when written and began failing once the window slid past them. Their neighbours survived for two reasons: some hand their fixture to parse-event, which applies no window, and the weekly ones use unbounded RRULEs that keep generating into the window however old the DTSTART is. The fixtures now build dates relative to now, which is what the timezone file's own helper already did. The fifth was a real regression, caught five months late. The recording toggle test asserted on a fixture device and got whatever hardware is plugged into the developer's machine. cj/recording-get-devices runs --validate-system-audio, which shells to pactl, finds the fixture device isn't a real source, and auto-fixes the configured device to the default sink's monitor. The test mocked start-process-shell-command but not shell-command-to-string, so validation reached the real machine. It passes at 5bdd3420~1 and fails at 5bdd3420, the commit that added that validation in February. I faked pactl at the shell boundary rather than stubbing --validate-system-audio out, so the validation logic still runs, against a fixture machine.
* fix(calendar-sync): render multi-day events as org rangesCraig Jennings8 days2-12/+105
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | format-timestamp built its date from the start and took only the hour and minute from the end, so the end date was thrown away. A conference running Jul 20 09:00 to Jul 23 17:00 produced <2026-07-20 Mon 09:00-17:00>, byte for byte the same timestamp as a same-day meeting, and the agenda showed it on the first day only. All-day spans collapsed the same way, to a bare <2026-07-20 Mon>. An event whose last day is later than its start now renders as an org range, <start>--<end>, which org parses as an active-range and shows on every day it covers. DTEND is the non-inclusive end of the event (RFC 5545 3.6.1), so an all-day event's last day is DTEND-1. Getting that backwards would have been worse than the bug: a one-day all-day event carries DTEND = start+1, so a naive range would turn every single all-day event into a two-day one. The decrement only applies when both ends are date-only. A date-only start with a timed end is malformed, and treating it as all-day would put the last day before the start and emit a backwards range. That case falls through to the same-day form, as before. I split out format-stamp and format-hhmm so both halves of a range and the compact same-day form build from one place. Same-day events are unchanged, pinned by two tests: the compact HH:MM-HH:MM form, and a single all-day event staying a single stamp. One unrelated bug stays open. A timed event with no DTEND renders as <date> and drops its time, so a 09:00 meeting reads as all-day. I left it alone.
* fix(calendar-sync): keep the final occurrence of an UNTIL-bounded seriesCraig Jennings8 days5-10/+127
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | RFC 5545 3.3.10 bounds a recurrence inclusively: when UNTIL lines up with the recurrence, that date is the last instance. The expansion loops guarded on calendar-sync--before-date-p, a strict comparison, so the instance landing exactly on UNTIL was dropped. Every bounded series silently lost its last meeting from the agenda. A series whose UNTIL equals its start date lost the only instance it had and vanished. I added calendar-sync--date-on-or-before-p beside --before-date-p and swapped the three UNTIL sites: the simple-recurrence loop feeding daily, monthly and yearly, plus both weekly checks. --before-date-p is unchanged, since a date is still not before itself. The two UNTIL property tests asserted the wrong invariant. They required every occurrence to fall strictly before UNTIL, the exclusive reading the RFC contradicts, so they pinned the defect they should have caught. The property is now on-or-before. An upper bound alone can't catch a dropped occurrence, so I added one asserting the series reaches its UNTIL date. Reverting the fix failed three daily tests and one property test, and no weekly ones. The weekly loop was fixed but unguarded, so it has its own test now. The comparison stays date-granular, matching --date-to-time. An UNTIL carrying a time of day earlier than the event's start will include that final instance where the RFC would exclude it. Making it datetime-precise means reworking --date-to-time and the timezone conversions feeding it, a much larger change than this bug warrants.
* fix(org-agenda): hoist cj/timeformat out of the defun it was buried inCraig Jennings8 days2-1/+88
| | | | | | | | | | | | | | | | | | cj/timeformat was defvar'd inside cj/add-timestamp-to-org-entry, so the symbol wasn't special until the command had run once. Until then a let around the call bound it lexically and never reached the function. I moved it to top level with a docstring. It has no other callers. The nested defvar also poisons tests. ERT runs alphabetically, so an earlier test that calls the command makes the symbol special retroactively. A later special-variable-p check then passes on test ordering rather than on the code, reading green in a full-file run and red in isolation. The new guard snapshots special-variable-p into a defconst at load, before any test body runs. I filled in the missing coverage: point and the following line survive the insert, empty and unicode time strings, an empty buffer, and a read-only buffer signalling rather than dropping the stamp. The empty-string case pins a trailing space (current behavior, characterized rather than changed).
* feat(markdown): toggle between edit and view modes with C-c C-x vCraig Jennings9 days1-1/+14
| | | | One command flips markdown/gfm buffers to their view-mode partner and back. Checks the most-derived mode first; gfm-view derives from gfm-mode, so the dispatch resolves correctly for all four modes.
* feat(tramp): add phone FTP quick-access entry with passive-mode ange-ftpCraig Jennings9 days2-0/+8
| | | | The phone's FTP server can't open active-mode data connections back to the client, so LIST hangs under ange-ftp's default. Passive mode fixes it and is the safer default for any NAT'd server. Requires a CLI ftp client (GNU inetutils on Arch).
* fix(recording): delete the stub .mkv a failed video start leavesCraig Jennings10 days2-4/+171
| | | | | | | | - A failed wf-recorder start still writes a ~0.5s stub .mkv. - Stubs littered the recordings directory and matched *.mkv globs downstream. - The start path now stamps the output path on the process. - The sentinel's failed-start branch deletes that file. - User stops and real recordings never trigger the delete.
* chore: gitignore the working scratch directoryCraig Jennings10 days1-0/+1
|
* chore: gitignore the takuzu stats file until its path fix landsCraig Jennings10 days1-0/+1
|
* refactor(signal): retire the in-Emacs signel client to the archiveCraig Jennings10 days14-19/+25
| | | | Agents drive Signal via signal-cli and signal-mcp, so the interactive client earns no keep. I moved signal-config.el and its seven test files to archive/ per the pasture convention, dropped the require from init.el, removed the dashboard's Signal launcher (row sizes now 5 4 3 2, tests updated), and unregistered the C-; M prefix from the running daemon. The ~/code/signel fork repo is untouched. The spec record stays IMPLEMENTED with a retirement history line, and the messenger-unification draft carries a premise-shift note.
* docs(specs): retire the gloss spec, close signal-client as implementedCraig Jennings10 days2-324/+2
| | | | The gloss spec described a repo scaffold and implementation that shipped months ago (the package lives at its own repo and gloss-config.el already wires it in) — the file was a stale artifact, deleted on Craig's call. signal-client flips to IMPLEMENTED: v1 is in daily use, and the messenger-unification spec designates the smoke project as the ground-up successor, so further client work happens there.
* fix(prog-python): keep the pyright guard authoritative for LSP attachCraig Jennings10 days2-5/+78
| | | | | | lsp-pyright's :hook lambda called require and lsp-deferred unguarded on every python-ts buffer, so a machine without pyright still got the LSP attach prompt that cj/python-setup's guard exists to prevent. The guarded branch now owns the require and the attach, and the hook is gone. Classic python-mode now runs the same setup hooks as python-ts-mode, so treesit-auto's grammar-unavailable fallback keeps indentation, keys, and LSP. Four tests cover the guard branches and pin that every python hook entry stays a named function.
* fix(flycheck): drop the checkdoc suppression that never workedCraig Jennings10 days1-4/+6
| | | | The :custom block set checkdoc-arguments, a variable that doesn't exist. Checkdoc has no such option and this flycheck runs checkdoc through a fixed subprocess form, so the intended suppression of two warning types never happened. Removing it changes no behavior. If those checkdoc warnings need silencing, that's a feature against flycheck-emacs-lisp-checkdoc-form.
* fix(prog-lisp): let flycheck-package setup actually runCraig Jennings10 days1-1/+5
| | | | :after (flycheck package-lint) waits for both features, but nothing loads package-lint on its own (it's flycheck-package's dependency, pulled in by the require), so the setup never ran and elisp buffers never got the package-lint checker. Keying on flycheck alone loads the chain.
* fix(prog-json): make the jq query key actually reachableCraig Jennings10 days1-3/+8
| | | | C-c C-q was bound via :bind (:map json-ts-mode-map) inside the jq-mode use-package, which defers the binding to jq-mode's load. Nothing ever loaded jq-mode, so the key was dead. The binding now keys on json-ts-mode's load, and jq-interactively's autoload pulls jq-mode in on first press.
* fix(prog-training): stop enabling global url.el debug loggingCraig Jennings10 days1-2/+3
| | | | leetcode's :custom set url-debug t, a debugging leftover that turned on url.el request logging for the entire session the moment leetcode loaded. I also declared code-dir for the compiler.