| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
| |
The yasnippet use-package block switches from `:hook (prog-mode . yas-minor-mode)` to `:demand t` + `(yas-global-mode 1)`. That makes yas-minor-mode active in every buffer, not just prog-mode-derived ones.
I added a small helper, `cj/--yas-activate-fundamental-extras`, attached as `:hook (yas-minor-mode . ...)`. It calls `(yas-activate-extra-mode 'fundamental-mode)` so the snippet table at `snippets/fundamental-mode/` is consulted in every buffer regardless of the buffer's own major mode. That's what makes universal triggers like `<cj` work everywhere.
The new `tests/test-prog-general-yas-activation.el` covers both wiring (yas-global-mode on, fundamental-mode in yas-extra-modes, yas-minor-mode active in org/text buffers) and end-to-end expansion (the marker snippet expands correctly in fundamental, text, org, emacs-lisp, and python-ts modes). 9 tests, all green; full unit suite green with no regressions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Info-mode entry in cj/buffer-source-functions copied the bare
target string info:(manual)Node. Per the task body that introduced
the dispatcher, the intended output is the labeled org-link form
[[info:(manual)Node][(manual) Node]] -- a paste into notes lands as
a clickable link with a human-readable label, not a bare URI.
The label uses (manual) Node so the manual name and node name are
both grep-friendly in note files.
Existing test on a compressed .info.gz file now asserts the bracket
form. Added a boundary test for an uncompressed .info file (the
other branch of the suffix-stripping logic) so both compression
shapes are locked in.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
make compile warned that cj/toggle-gptel is not known to be defined
when ai-vterm.el is byte-compiled. The M-F9 binding still worked
during normal startup because init.el loads ai-config.el after
ai-vterm.el, but the dependency was implicit -- byte-compile saw the
function symbol unresolved, and loading ai-vterm.el in isolation
left M-F9 bound to an undefined function.
Declare cj/toggle-gptel as an interactive autoload pointing at
ai-config. This silences the warning, keeps ai-vterm.el free of a
load-time (require 'ai-config), and makes the load-order contract
explicit: the binding works as long as ai-config eventually loads.
Test asserts that requiring ai-vterm in isolation leaves
cj/toggle-gptel fboundp as an autoload sigil (not a real function).
A regression that adds (require 'ai-config) at the top of
ai-vterm.el would flip this, and a regression that drops the
autoload form would leave fboundp nil.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add a tiny source-level architecture suite at
tests/test-architecture-startup-contracts.el with two checks:
- Only keybindings.el may globally own the exact C-; prefix. Catches
accidental cross-module rebinding before it ships.
- Top-level timer scheduling (run-with-timer / run-at-time /
run-with-idle-timer) must be guarded by (unless noninteractive ...)
so requiring a module in batch / test mode does not schedule
startup timers. Timer calls inside defuns are exempt -- the test
only rejects forms that execute their body when the module loads.
Four modules had unguarded top-level timer scheduling and would have
tripped the new test. Wrap their startup hooks/timers in
(unless noninteractive ...):
- modules/org-agenda-config.el: 10s idle cache build
- modules/org-refile-config.el: 5s idle cache build
- modules/quick-video-capture.el: after-init-hook + 2s fallback
- modules/wrap-up.el: emacs-startup-hook bury-buffers delay
The contract being protected is "requiring a module in batch should
not start a clock running." Test failures will now point straight at
the offending file/form.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
=make coverage= used to print a line-weighted percentage that only saw
files SimpleCov instrumented. 104 modules existed on disk but only 49
appeared in =.coverage/simplecov.json=, so the headline number was
flattering: untouched modules counted for nothing.
The summary script now adds two things on top of the existing report:
- A =Not in SimpleCov report= section listing modules present under
=modules/*.el= but absent from the SimpleCov output. Missing-module
detection is exactly direct =modules/*.el=; subdirectories and =.elc=
files are ignored.
- A =Project module coverage= line that is module-weighted across every
direct =modules/*.el= file. Tracked modules contribute their per-file
coverage percentage; missing modules contribute 0%.
The original line-weighted SimpleCov percentage stays as the
=instrumented coverage= number. The new module-weighted score is the
honest project-level reading: missing modules count as 0% without
inventing a fake executable-line denominator for them.
Tests assert the missing-module section, the new percentage, and the
ignore rules for .elc / nested files.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add two dispatchers to cj/buffer-source-functions so C-; b p yields a
useful link form in two more major modes.
mu4e-view-mode returns "mu4e:msgid:<id>" so the result pastes into org
as a clickable link and matches mu4e's own org-protocol handler.
Falls through to buffer-file-name when point isn't on a real message.
Info-mode returns "info:(manual)node" -- the form org-info-store-link
produces. file-name-base only strips one extension, so a compressed
"emacs.info.gz" comes back as "emacs.info"; trim the trailing ".info"
to get the bare manual name. Falls through when Info hasn't populated
its current-file / current-node vars yet.
Tests cover normal + boundary fallthrough for each new mode.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`cj/org-noter-insert-note-dwim' is the most-used action in a noter
session; it deserves the doubled-prefix letter. Move it from
`C-; n i' to `C-; n n'.
Sibling-stepping moves off `n'/`p' (which were sync-next /
sync-prev) onto the angle-bracket pair `>'/`<' to free up `n' and
to read more naturally as direction. `.' stays as
sync-current-note.
Updated `which-key' labels to match. Four new ERT tests in
`tests/test-org-noter-config-keymap.el' lock the keymap shape so a
casual edit doesn't silently drift the layout.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Old behavior: `C-; b p' called `cj/copy-path-to-buffer-file-as-kill',
which only worked in file-visiting buffers and errored otherwise.
That meant the most useful "give me a clickable handle on this
buffer" key did nothing in eww, elfeed, dired (file-at-point ≠
buffer's default-directory), and other browsing-shaped modes.
Replace with a `major-mode'-aware dispatch:
- `cj/buffer-source-functions' alist maps major-mode → thunk
returning a string (or nil to fall through).
- `cj/copy-buffer-source-as-kill' looks up the current mode,
calls the thunk, falls back to `buffer-file-name', errors only
when both yield nil.
- `cj/copy-path-to-buffer-file-as-kill' kept as a `defalias' for
backwards compat (the old name is referenced in adjacent tests).
First-batch dispatches:
- eww-mode -> (eww-current-url)
- elfeed-show-mode -> (elfeed-entry-link elfeed-show-entry)
- dired-mode -> (dired-get-filename nil t)
- dirvish-mode -> same
- doc-view / pdf-view: covered by the buffer-file-name fallback
(they already set buffer-file-name correctly).
10 new ERT tests cover the dispatch paths, the
buffer-file-name fallback, the user-error on nil source, the alias
target, and the `C-; b p' keymap entry.
which-key label flipped from "copy file path" to "copy buffer
source" to match.
Deferred to a follow-up task: mu4e-view-mode, org-mode at a
heading, help-mode, Info-mode, magit-log/commit/status, xref/grep/
compilation, image-mode, archive-mode -- each needs a format
decision before implementation.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
M-F9 used to invoke `cj/ai-vterm-pick-buffer' (a buffer picker
narrowed to alive AI-agent buffers). In practice the F9 plain-key
toggle + C-F9 project picker covered the common cases, and the
buffer picker rarely earned its keystroke. Rebind M-F9 to
`cj/toggle-gptel' so the F9 family covers the two main in-Emacs AI
surfaces at one keystroke each:
<f9> ai-vterm toggle (unchanged)
C-<f9> ai-vterm picker (unchanged)
M-<f9> gptel *AI-Assistant* (NEW)
Removed entirely:
- `cj/ai-vterm-pick-buffer' (the command itself).
- `cj/--ai-vterm-pick-buffer-candidates' (its helper).
- `tests/test-ai-vterm--pick-buffer-candidates.el' (deleted).
Updated:
- `tests/test-ai-vterm--f9-in-vterm.el' binding assertions
(vterm-mode-map and global) flipped to `cj/toggle-gptel'.
- Module commentary + `cj/ai-vterm' docstring describe the new
M-F9 behavior.
- `cj/toggle-gptel' lives in `modules/ai-config.el'; the binding
stays in `ai-vterm.el' next to the rest of the F9 family so the
dispatch shape is visible in one place.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`#+begin_src markdown ... #+end_src' blocks rendered and exported
fine but `org-lint' warned on every one of them ("Unknown source
block language: 'markdown'"), and `C-c '' inside the block fell
back to `fundamental-mode' instead of opening it in
`markdown-mode' for editing.
Add a `with-eval-after-load 'org' form that pushes
`("markdown" . markdown)' onto `org-src-lang-modes'. New ERT test
in `tests/test-markdown-config.el' asserts the entry resolves to
`markdown' after `(require 'markdown-config)'.
Surfaced while clearing `org-lint' on `todo.org' from 55 issues
down to 1 -- the last one was this warning on a Linear ticket-body
draft that was genuinely markdown. Registering the language is
the right fix; relabeling the block as `text' or `example' would
lose accuracy.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Narrowing and sparse-tree commands existed in the `:bind' block
on `C-c'-style shortcuts but nothing in `cj/org-map' surfaced
them, so which-key never showed them and discoverability was
poor.
Add direct bindings under `C-; O', flat (no sub-prefixes for
narrow / sparse-tree). Lowercase creates; capital of the same
letter cancels:
- `n' / `N' narrow-to-subtree / widen
- `s' / `S' match-sparse-tree / show-all
- `t' / `T' show-todo-tree / show-all
- `>' / `<' forward / backward sibling narrow (kept as-is)
- `R' reveal-context (no lowercase pair -- `r' is the
table-row sub-prefix)
Both `S' and `T' resolve to the same `org-show-all' command so
the mental model is just "capital cancels the lowercase I just
ran" without having to recall which letter the cancel actually
lives on.
Free up F2: the old `(<f2> . org-reveal)' binding in the org-mode
`:bind' block is now redundant with `C-; O R'. Drop it; F2
becomes available for whatever wants it next.
Four new ERT assertions in `test-org-config-keymap-ownership.el'
lock the shape -- the old sparse-tree-submap test was rewritten
for the flat layout and the narrow-submap test became
narrow-bindings (also flat).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Pressing `T' in dired/dirvish on an audio file already transcribed
it; on a video file it bounced with "Not an audio file". Real
recordings ship as .mp4 / .mkv at least as often as raw .m4a, so
the one-key flow ended at the wrong place.
Pipeline now:
- audio path -> direct into `cj/--start-transcription-process'
(unchanged).
- video path -> async ffmpeg extracts the audio track to a temp
.mp3 under `temporary-file-directory' (libmp3lame, VBR q:a 4,
~165kbps -- right size for speech, accepted by every backend),
then transcribes that file with the temp marked for cleanup
after the transcription sentinel fires.
Surface changes:
- `cj/video-file-extensions' added to user-constants.el (mp4, mkv,
mov, webm, avi, m4v, wmv, flv, mpg, mpeg, 3gp, ogv).
- New predicates `cj/--video-file-p' / `cj/--media-file-p'.
- New `cj/--extract-audio-from-video' (async ffmpeg with success
callback; surfaces `cj/--notify' on failure; user-errors if
ffmpeg isn't on PATH).
- `cj/--start-transcription-process' gains optional `cleanup-file'.
Sentinel deletes it after the existing logic runs. Backwards
compatible -- the audio flow doesn't pass it.
- `cj/transcribe-audio' renamed to `cj/transcribe-media' (dispatcher
on audio vs video). `cj/transcribe-audio-at-point' renamed to
`cj/transcribe-media-at-point'. Both old names kept as
`defalias' so M-x history and any external references still work.
- `T' in dired-mode-map + dirvish-mode-map points at
`cj/transcribe-media-at-point'.
- Module commentary USAGE block updated.
15 new ERT tests in `tests/test-transcription-video.el' cover the
predicates (happy/boundary/error), ffmpeg invocation (correct args
+ missing-ffmpeg path), the dispatcher (audio direct, video via
extraction, non-media rejected), the aliases, and the T binding.
One existing test in `test-transcription-status-and-commands.el'
updated to stub the new delegate name.
Verified locally that ffmpeg is on PATH with libmp3lame, and that
the exact arg list my code uses produces a valid MP3 from a
synthetic test video.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The transcription menu wasn't earning its top-level keymap slot --
the commands (transcribe-audio, switch-backend, view-transcriptions,
kill-transcription) are run rarely enough that `M-x' is fine. Drop
the `cj/transcribe-map' keymap, its `(keymap-set cj/custom-keymap
"T" ...)' binding, and the which-key labels. Commands stay
callable by name.
That frees `C-; T' for telega, where the mnemonic actually fits.
Move the launcher from `C-; G' to `C-; T'. Update the
which-key label, the module commentary, and the keymap-binding
test assertion. The dashboard `g' single-letter binding stays put
-- `t' there is vterm, so dashboard letters and the global
`C-;' prefix don't share a key space anyway.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Drop the `T' sub-prefix so table operations sit directly under
`C-; O': `O r i' / `O r d' for rows, `O c i' / `O c d' for columns.
Move `cj/org-clear-element-cache' from `c' (which now hosts the
table-column sub-prefix) to capital `C'. Single-key org commands
under this menu live on capitals from here on so the lowercase
letters stay free for table sub-prefixes.
Drop `cj/org-table-map' entirely -- its bindings now live directly
on `cj/org-map'. Three tests in `test-org-config-keymap-ownership.el'
updated/added: `C' for clear-cache, plus row and column binding
assertions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
missing
Without the guard, both `C-; G' and the dashboard Telegram icon
trigger telega's autoload stub directly. When the package isn't
installed yet the user sees `Cannot open load file: telega' in
`*Messages*' with no hint about what to do.
Wrap the launcher in `cj/telega' that checks `featurep' /
`locate-library' first. If telega is present, delegate to it.
Otherwise signal a `user-error' pointing at `scripts/setup-telega.sh'
and the manual `M-x package-install RET telega' fallback. Rebind
`C-; G' and the dashboard "g" key + Telegram icon callback to the
wrapper.
Two new tests in `test-telega-config.el' cover the wrapper paths
(absent -> user-error with the recovery hint; present -> delegates
to `telega') alongside the updated binding assertion.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
modules/telega-config.el uses `:ensure nil' on the use-package block
(a stale MELPA archive index can 404 and take startup down if
auto-install runs in init). The trade-off was that a fresh clone
needed a one-time `M-x package-install RET telega' before the
dashboard launcher or `C-; G' would work -- the autoload stub
would fail with `Cannot open load file: telega' instead.
Hit it on this machine just now: dashboard pressed, autoload tried
to load telega.el, no telega.el on the load-path, cryptic error.
Add `ensure_telega_package' to the setup script: probe with
`(package-installed-p 'telega)' under `emacs --batch'; if absent,
refresh MELPA and install via package.el; if that fails, surface
the manual recovery path. Wire it into `main' after the docker
checks. Four new bats tests cover the missing-emacs, already-
installed, install-succeeds, and install-fails paths with `emacs'
stubbed at the function level.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`cj/system-cmd' had `(interactive (list (read-shell-command "System
command: ")))' -- the destructured-list interactive spec. Undercover.el
relies on edebug instrumentation, which doesn't see past that form, so
the entire function body registered as 0 hits under coverage even
though tests call the function directly.
Switch to the equivalent string spec `(interactive "sSystem command: ")'.
Same UX (prompt, history, single-string result), but the body now
instruments correctly and coverage moves from 34/49 to 50/51.
Add one more test that captures the `run-at-time' lambda in
`cj/system-cmd-restart-emacs' and invokes it directly so the inner
`call-process-shell-command' branch registers, taking coverage to 51/51.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
instruments
The helper-functions test was per-test reloading system-defaults.el
via `(load ...)' inside a `cl-letf' sandbox that stubs the
side-effecting primitives (server-start, set-locale-environment,
etc). Tests passed, but the coverage gauge stayed stuck at 1/12
because undercover.el only instruments the first load of a matching
source; subsequent re-loads inside test bodies don't get tracked,
so the function bodies showed as uncovered even though every test
called them.
Rewrite the test to call `(require 'system-defaults)' once at top
level, wrapped in the same `cl-letf' stubs. The functions get
instrumented exactly once. Drop the now-unused per-test sandbox
macro. Add two more tests for the `(when (memq ...))' list-without-
comp guard and the non-string-message format branch so coverage
reaches 12/12.
(`test-system-defaults-vc-follow-symlinks.el' still uses the
per-test `(load ...)' pattern because that test *is* the
load-side-effect verification, not a function-body test.)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
`cj/org-roam-copy-todo-to-today' tried to save the target journal
buffer via `org-after-refile-insert-hook' bound to `#'save-buffer',
but that value is the wrong shape (single function instead of a
hook list), and the only other save mechanism -- the `:after' advice
on `org-refile' that calls `org-save-all-org-buffers' -- doesn't
attach until `:defer .5' elapses, so the very first DONE transition
after startup leaves the journal unsaved.
Drop the broken hook binding and save the target buffer explicitly
after the refile call. New ERT test asserts `buffer-modified-p' on
the journal buffer is nil after the function returns.
|
| |
|
|
| |
create-radio-station
|
| |
|
|
| |
next/previous, consume-toggle
|
| |
|
|
| |
context-clear
|
| | |
|
| | |
|
| |
|
|
| |
add-timestamp
|
| |
|
|
| |
bodies
|
| | |
|
| | |
|
| |
|
|
| |
mark-all-headers
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
Sibling tests covered `toggle-window-split` and the window-resize sticky map. This batch covers:
- `cj/split-and-follow-right`: split-window-right + other-window + consult-buffer in order.
- `cj/split-and-follow-below`: split-window-below + other-window + consult-buffer in order.
- `cj/undo-kill-buffer`: with no arg, opens the head of `recentf-list` that isn't currently visited; with N=1, opens the second entry; empty list -> no-op.
Top-level defvars for `recentf-mode` and `recentf-list` so let-bindings reach the dynamic vars under lexical scope.
|
| |
|
|
|
|
|
|
|
|
| |
Sibling `test-coverage-elisp--detect.el` covered the detect heuristic. This batch fills in the rest:
- `cj/--coverage-elisp-project-root`: explicit arg wins, falls back to projectile, falls back to `default-directory`.
- `cj/--coverage-elisp-report-path`: appends `.coverage/simplecov.json` to the resolved root.
- `cj/--coverage-elisp-run`: launches `make coverage` via `compilation-start`, fires the callback with the report path on `finished` status, skips the callback on failure.
projectile and compilation-start are stubbed; the compilation buffer is a real buffer the test creates and tears down.
|
| |
|
|
|
|
|
|
|
| |
Sibling `test-system-utils-eval-buffer.el` covered the eval-buffer wrapper. This batch covers:
- `cj/open-file-with-command`: a launcher routes through `call-process`; a non-launcher routes through `start-process-shell-command` into a dedicated `*Open with <cmd>: <file>*` buffer; a missing file signals an error.
- `cj/server-shutdown`: saves buffers and calls `kill-emacs`.
Process and prompt primitives are stubbed.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Sibling `test-system-commands-keymap.el` locked the keymap shape. This batch covers the runtime helpers and commands:
- `cj/system-cmd--resolve`: trims strings, errors on empty/non-string-non-symbol, round-trips a symbol whose value is a non-empty string, errors on a symbol with empty value.
- `cj/system-cmd`: wraps a plain string in `nohup ... &` and hands it to `start-process-shell-command`; a confirm-tagged var with an N response signals user-error.
- `cj/system-cmd-exit-emacs`: declining the prompt aborts; accepting calls `kill-emacs`.
- `cj/system-cmd-restart-emacs`: declining aborts before scheduling; accepting schedules two timers.
- `cj/system-command-menu`: the completing-read pick routes through `call-interactively` to the right command symbol.
Top-level defvars for `test-sc-my-cmd` and `test-sc-empty-cmd` make the let-bindings dynamic so `symbol-value` reaches them under lexical scope.
|
| |
|
|
|
|
|
|
|
|
| |
Sibling tests in `test-external-open-lib-*.el` covered the pure helpers (`cj/external-open-command`, `cj/external-open-launcher-p`). This batch covers the user-facing wrappers:
- `cj/xdg-open`: posix path triggers `call-process` with the open program; errors when no file is associated; errors when no command resolves on the host.
- `cj/open-this-file-with`: errors outside a file-visiting buffer; posix path spawns a detached process via `call-process-shell-command` with `nohup ... >/dev/null 2>&1 &`.
- `cj/find-file-auto`: routes a `.mp4` (in `default-open-extensions`) to `cj/xdg-open`, passes `.txt` through to the original `find-file`, and falls through cleanly for a nil filename argument.
Host predicates, call-process, and the underlying `cj/xdg-open` are stubbed throughout.
|
| |
|
|
|
|
|
|
|
|
|
| |
Same shape as the prog-python and prog-webdev setup tests: company-mode + electric-pair-mode + LSP gating + buffer-local preferences. New tests cover:
- `cj/go-setup`: tab-width 4, standard-indent 4, indent-tabs-mode t (Go convention); company-mode + electric-pair-mode both fire; LSP starts when gopls is on PATH, skips otherwise.
- `cj/go-staticcheck`: runs `compile` with `./...` when staticcheck is on disk; messages and skips compile otherwise.
- `cj/go-debug`: starts `gud-gdb` with `dlv debug` when delve is on PATH; messages otherwise.
- `cj/go-mode-keybindings`: wires `C-; f` -> gofmt, `S-<f5>` -> staticcheck, `S-<f6>` -> debug.
External modes and process primitives are stubbed.
|
| |
|
|
|
|
|
|
|
|
|
| |
Sibling `test-org-webclipper-process.el` covers the content-processing helper. This batch fills in the rest:
- `cj/webclipper-ensure-initialized`: registers the webclip protocol entry + the W and w capture templates on first call, is idempotent on subsequent calls.
- `cj/org-protocol-webclip`: stashes the url+title, triggers capture; missing title falls back to "Untitled".
- `cj/org-protocol-webclip-handler`: errors when no url stashed, returns processed org content on success (with the first heading stripped + subs demoted), wraps fetch failures in a "Failed to clip" error.
- `cj/org-webclipper-EWW`: routes through `org-eww-copy-for-org-mode` for eww-mode and `org-w3m-copy-for-org-mode` for w3m-mode; errors on any other source mode.
Top-level defvars for `org-protocol-protocol-alist`, `org-capture-templates`, and `webclipped-file` make let-bindings dynamic under lexical scope. org-web-tools and the eww/w3m copy commands are stubbed.
|
| |
|
|
|
|
|
|
|
|
| |
Sibling tests covered the ensure-org-mode helper and the build-targets pipeline. The three wrapper commands were uncovered:
- `cj/org-refile-refresh-targets`: passes the `force-rebuild` flag to `cj/build-org-refile-targets`.
- `cj/org-refile`: builds the cache, then calls `org-refile` with the four positional args.
- `cj/org-refile-in-file`: scopes `org-refile-targets` to the current file at maxlevel 6, then saves after the refile completes.
Top-level `defvar` for `org-refile-targets` so the let-binding inside the function is dynamic under lexical scope.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
aggregator
Sibling tests covered the capture-finalize hook and the email-string parser. This batch fills in the rest:
- `cj/org-contacts-template-name` / `-email`: fall back to `read-string` outside mu4e; pull from `mu4e-message-field` when inside.
- `cj/org-contacts-new`: delegates to `org-capture` with key "C".
- `cj/org-contacts--props-matching`: filters an entry's props by regexp.
- `cj/get-all-contact-emails`: formats each entry as "Name <email>", expands multi-email strings.
- `cj/insert-contact-email`: inserts the completing-read selection at point.
mu4e and org-contacts primitives are stubbed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Sibling tests covered the header template, title-to-filename slug, and the headers-remove pass. This file fills in the rest:
- `cj/--reveal-preview-export-on-save`: exports in org-mode, skips otherwise.
- `cj/--reveal-ensure-header`: inserts when absent, no-op (no prompt) when already present.
- `cj/reveal-export`: errors outside org-mode, opens HTML in browser otherwise.
- `cj/reveal-preview-start`: installs the buffer-local after-save-hook + exports once; errors outside org-mode.
- `cj/reveal-preview-stop`: removes the hook + messages.
- `cj/reveal-insert-header`: errors outside org-mode, errors when headers already present, inserts and reports otherwise.
- `cj/reveal-remove-headers`: errors outside org-mode, messages the removed line count.
- `cj/reveal-new`: errors when target file already exists.
ox-reveal's `org-reveal-export-to-html` and `browse-url-of-file` are stubbed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Sibling tests covered the preferred-split, title-to-slug, notes-template, and in-document / in-notes-file predicates. This batch fills in the rest:
- `cj/org-noter--get-document-path`: pdf-view-mode uses buffer-file-name, nov-mode uses `nov-file-name`, unrelated mode returns nil.
- `cj/org-noter--extract-document-title`: strips the extension.
- `cj/org-noter--find-notes-file`: returns the file containing the doc-path, nil when no doc or no match.
- `cj/org-noter--create-notes-file`: writes the template when absent.
- `cj/org-noter--session-active-p`: nil when unbound, non-nil when set.
- `cj/org-noter--toggle-notes-window`: deletes when visible, requests start when hidden.
- `cj/org-noter-start`: routes through the cond -- toggle in doc+session, switch-window in notes+session, message elsewhere.
- `cj/org-noter-insert-note-dwim`: with active session inserts directly; without one, starts then inserts.
org-noter / pdf-view / nov / org-id primitives are stubbed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Sibling `test-slack-config-reactions.el` covered the post-command-hook safety advice and the empty-buffer guard. This batch covers the rest:
- `cj/slack--get-credential`: string secret, function secret, missing entry.
- `cj/slack-start`: errors when token / cookie missing, registers + starts when both present.
- `cj/slack-stop`: calls `slack-ws-close` + messages.
- `cj/slack--reaction-candidates`: includes the (Other...) escape hatch.
- `cj/slack-select-reaction`: emoji-name return for a curated pick, delegation to `slack-message-reaction-input` for Other.
- `cj/slack-notify`: fires for IMs (not self), skips self-messages and non-IM non-mentions.
- `cj/slack-test-notify`: fires the notify pipeline directly.
- `cj/slack-mark-read-and-bury`: marks via the latest-ts + buries; outside slack, just buries.
- `cj/slack-close-all-buffers`: closes buffers with `slack-current-buffer` local, leaves non-slack buffers alone.
The close-all assertions check identity (the 2 slack buffers killed, the non-slack one preserved) instead of an exact total -- ERT-internal buffers leaking into `(buffer-list)` from earlier tests would otherwise inflate the count, and `cl-letf` over the `buffer-list` subr is unreliable under native-comp.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
insert-immediate
Sibling tests covered the slug helper, link-description, demote-subtree, format-roam-node, and the copy-todo-to-today hook. This batch covers the tag/find/insert family:
- `cj/org-roam-filter-by-tag`: returns a predicate; keeps matching nodes, rejects non-matching.
- `cj/org-roam-list-notes-by-tag`: returns file paths for matches, empty list when no matches.
- `cj/org-roam-add-node-to-agenda-files-finalize-hook`: removes itself, adds the captured buffer's file to `org-agenda-files` when not aborted, skips on abort.
- `cj/org-roam-find-node`: calls `org-roam-node-find` with a filter predicate + templates.
- `cj/org-roam-find-node-topic` / `-recipe`: delegate with the right tag + key (+ subdir).
- `cj/org-roam-node-insert-immediate`: appends `:immediate-finish t` to the first capture template before calling `org-roam-node-insert`.
Top-level `defvar`s for `org-note-abort`, `org-agenda-files`, `org-roam-capture-templates`, and `org-capture-after-finalize-hook` make the let-bindings reach the dynamic vars under lexical scope.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Sibling tests covered the pure helpers (`cj/hugo--post-file-path`, `cj/hugo--post-template`, `cj/hugo--post-metadata`, `cj/hugo--collect-drafts`, `cj/hugo-open-blog-dir-external`, `cj/hugo-toggle-draft`). This batch covers the remaining commands and preview helpers:
- `cj/hugo-new-post`: writes the template to a slugged file, errors when one already exists.
- `cj/hugo-export-post`: errors outside org-mode, delegates to `org-hugo-export-to-md` otherwise.
- `cj/hugo-open-blog-dir`: ensures the dir exists and opens dired on it.
- `cj/hugo-open-draft`: messages when no drafts, otherwise picks via `completing-read` and opens.
- `cj/hugo--preview-filter`: opens the browser when Hugo prints "Web Server is available", ignores arbitrary output.
- `cj/hugo--preview-sentinel`: clears the process var on clean exit, messages on a non-zero exit.
- `cj/hugo-preview`: stops a running server, starts one when stopped (verifying `start-process` got the "server" arg).
- `cj/hugo-publish`: hands off to `magit-status-setup-buffer` on `website-dir`.
ox-hugo's `org-hugo-slug` is stubbed via `defun` (the package isn't installed in batch); `require`, `org-hugo-export-to-md`, `dired`, `find-file`, `browse-url`, `start-process`, `kill-process`, and `magit-status-setup-buffer` are stubbed per-test.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Second pass on ai-config. First batch covered the auth-source, API-key caching, file-context, clear-buffer, context-clear, and model-heading helpers. This batch covers the gptel command wrappers and a couple of small helpers:
- `cj/gptel--refresh-org-prefix`: refreshes the org-mode entry in `gptel-prompt-prefix-alist`.
- `cj/gptel-backend-and-model`: formats a vector-backend's name + the current model + a timestamp; falls back to "AI:" when no backend is bound.
- `cj/gptel-switch-backend`: picks a backend and one of its models, updates both gptel vars; errors on an invalid backend choice.
- `cj/gptel-add-buffer-file`: hands the visited file off to `cj/gptel--add-file-to-context`, messages otherwise.
- `cj/gptel-add-this-buffer`: calls `gptel-add` with the (4) prefix-arg.
- `cj/toggle-gptel`: deletes the window when *AI-Assistant* is already shown.
gptel and projectile primitives are stubbed throughout.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Second pass on music-config. The first batch covered assertion guards, the M3U picker, EMMS lazy setup, and the smaller commands. This batch covers the remaining interactive playlist commands and the random-history navigation pair:
- `cj/music-playlist-load`: loads the selected file via `emms-play-playlist`, errors when the chosen file isn't on disk.
- `cj/music-playlist-reload`: replays the buffer-local playlist file, errors when none is associated.
- `cj/music-playlist-edit`: opens the M3U file in another window when the buffer is clean.
- `cj/music-next`: delegates to `emms-next` or `emms-random` based on `emms-random-playlist`.
- `cj/music-previous`: emms-previous when not random; with random + history pops the top, finds it in the playlist, selects + starts; with random + no history messages; with random and a missing track, messages.
- `cj/music--consume-track`: no-op when consume-mode is off, kills the selected track when on.
EMMS primitives (`emms-playlist-clear`, `emms-play-playlist`, `emms-stop`, `emms-random`, `emms-next`, `emms-previous`, `emms-start`, `emms-playlist-select`, `emms-playlist-mode-kill-track`) are stubbed throughout.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`test-test-runner.el` covered the `cj/test--do-*` helpers and the focus-add / focus-remove / extract-test-names families. The state machinery and small wrappers were the gap.
22 new tests cover:
- `cj/test--project-root`: nil when projectile is absent, expanded trailing-slash when present.
- `cj/test--state-key`: falls back to `default-directory` without a project root.
- `cj/test--project-state`: creates the entry lazily, reuses on second call.
- `cj/test--state-get` / `cj/test--state-put`: roundtrip + default fallback.
- `cj/test--current-focused-files` / `cj/test--current-mode` getter/setter pairs.
- `cj/test--sync-legacy-state`: mirrors per-project state into the public legacy vars.
- `cj/test--remember-loaded-project-root`: pushes once via `cl-pushnew`, no-op without a root.
- `cj/test--file-in-directory-p`: true for a subpath, false for a sibling.
- `cj/test--get-test-directory`: prefers `tests/` subdir, falls back to the global default.
- `cj/test--get-test-files`: lists `test-*.el` files only, basenames.
- `cj/test--ensure-test-dir-in-load-path`: adds the dir.
- `cj/test-focus-clear` / `cj/test-toggle-mode` / `cj/test-view-focused` / `cj/test-run-all`: behavior + messaging.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Sibling tests cover the move/rename/copy/clear family. The remaining helpers and dispatchers were uncovered:
- `cj/print--resolve-spooler`: explicit-string on PATH, explicit-string missing (error), `auto` prefers lpr, `auto` falls back to lp, `auto` with nothing on PATH (error), `auto` returns cached value, invalid spooler symbol (error).
- `cj/copy-buffer-name`: places the current buffer's name on the kill ring with a confirmation message.
- `cj/view-buffer-in-eww`: hands the file off to `eww-open-file` when visiting a file, errors otherwise.
- `cj/--email-handle-is-type-p`: prefix-matches content-types, handles nil handle without signaling.
- `cj/--diff-with-regular-diff`: writes a unified diff into the target buffer with header + diff output.
- `cj/diff-buffer-with-file`: errors when not visiting a file, messages "No differences" when diff -q returns 0.
16 new tests total. `call-process`, `executable-find`, `eww-open-file`, `mm-handle-type`, `diff-mode` are stubbed.
|