<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/modules/custom-buffer-file.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-05-25T00:59:28+00:00</updated>
<entry>
<title>refactor(load-graph): route C-; registration through the keymap API</title>
<updated>2026-05-25T00:59:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-25T00:59:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=08014b2f15e099a1c5e662a17a41290f37aeebf4'/>
<id>urn:sha1:08014b2f15e099a1c5e662a17a41290f37aeebf4</id>
<content type='text'>
Migrated all 31 cj/custom-keymap registration sites across 24 modules from direct (keymap-set cj/custom-keymap ...) calls to cj/register-prefix-map and cj/register-command. Consumers no longer reference cj/custom-keymap directly, so keybindings.el is the sole owner of the C-; prefix and modules reach it only through the API (each already requires keybindings from Phase 2).

Behavior-preserving: I dumped every C-; binding before and after the migration and they're identical: 279 bindings, each resolving to the same command. The which-key label blocks are untouched, since they use string key descriptions and never assumed the keymap existed. I byte-compiled all 24 files (no new free-variable warnings, because the cj/custom-keymap references are gone), and make test, validate-modules, and an init load all pass.
</content>
</entry>
<entry>
<title>refactor(load-graph): make hidden module dependencies explicit</title>
<updated>2026-05-24T23:36:19+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-24T23:36:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=36a453d2c1237b49f594b23433858a0146dbf31e'/>
<id>urn:sha1:36a453d2c1237b49f594b23433858a0146dbf31e</id>
<content type='text'>
Phase 2 of the load-graph project. I fixed the seven hidden dependencies the classification surfaced, so each module declares what it uses instead of relying on init order.

- system-defaults now requires host-environment and user-constants at runtime. They were eval-when-compile only, but env-bsd-p and user-home-dir are read at load, so the compiled module couldn't load standalone.
- custom-buffer-file, dev-fkeys, calendar-sync, and video-audio-recording require keybindings and drop their (when (boundp 'cj/custom-keymap) ...) shims. The shim silently dropped the C-; binding when the module loaded before keybindings. The explicit require makes the dependency real.
- flycheck-config and mail-config require keybindings for their cj/custom-keymap bindings (a use-package :map and a direct keymap-set).
- Removed a dead eval-when-compile (defvar cj/custom-keymap) in transcription-config; nothing there used the variable.

No init.el load-order change. keybindings and the foundation modules already load before these, so the requires are no-ops at startup and only fix standalone and test loading.

I verified each fix with a fresh emacs --batch (require 'X), then swept all modules standalone: every one loads or fails only with a clear missing-package message. Full make test, make validate-modules, and an init smoke all pass. Module headers and the inventory's hidden-dependency section are updated to mark the seven resolved.
</content>
</entry>
<entry>
<title>docs(load-graph): classify text/editing command modules</title>
<updated>2026-05-24T21:20:01+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-24T21:20:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=1dfd02da826d61d528fe42c5bee3c5dbcf098c82'/>
<id>urn:sha1:1dfd02da826d61d528fe42c5bee3c5dbcf098c82</id>
<content type='text'>
Second classification batch: the nine custom-* text/editing command helpers (case, comments, datetime, buffer-file, line-paragraph, misc, ordering, text-enclose, whitespace). I annotated each with the load-graph header contract and added a Batch 2 table to the inventory. They're all Layer 2, eager only to register a C-; submap at load, with no necessary eager reason, so all are Phase 3/4 deferral candidates.

The inventory records a second hidden dependency for Phase 2: custom-buffer-file guards its C-; b registration with (when (boundp 'cj/custom-keymap) ...) and declares the keymap only via eval-when-compile, so the binding silently drops when the module loads without keybindings.
</content>
</entry>
<entry>
<title>fix(custom-buffer-file): Info dispatcher returns full org bracket link</title>
<updated>2026-05-15T07:22:06+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-15T07:22:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=b4039017e468f310c99c04810f010b5ceada07e1'/>
<id>urn:sha1:b4039017e468f310c99c04810f010b5ceada07e1</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(custom-buffer-file): extend buffer-source dispatch to mu4e and Info</title>
<updated>2026-05-15T05:54:01+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-15T05:54:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=d797b7ad5d6af70d7d1ab082f824df07cf5bd536'/>
<id>urn:sha1:d797b7ad5d6af70d7d1ab082f824df07cf5bd536</id>
<content type='text'>
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:&lt;id&gt;" 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.
</content>
</entry>
<entry>
<title>feat(custom-buffer-file): make C-; b p dispatch by major-mode, with tests</title>
<updated>2026-05-15T05:23:14+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-15T05:23:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=e3e904b33ed714d74fae01ae1b631d889b39003b'/>
<id>urn:sha1:e3e904b33ed714d74fae01ae1b631d889b39003b</id>
<content type='text'>
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         -&gt; (eww-current-url)
- elfeed-show-mode -&gt; (elfeed-entry-link elfeed-show-entry)
- dired-mode       -&gt; (dired-get-filename nil t)
- dirvish-mode     -&gt; 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.
</content>
</entry>
<entry>
<title>feat(window): kill the other window's buffer with C-; b K</title>
<updated>2026-05-11T20:35:43+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T20:35:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=0ddbcde1e9f17021377f4160b39cd0790afcbdcc'/>
<id>urn:sha1:0ddbcde1e9f17021377f4160b39cd0790afcbdcc</id>
<content type='text'>
`cj/kill-other-window-buffer' (in undead-buffers.el, on `C-; b K') kills or buries the buffer shown in the other window and leaves that window and the split alone. The window just shows whatever bury/kill surfaces next. It reuses `cj/kill-buffer-or-bury-alive', so buffers in `cj/undead-buffer-list' (like `*scratch*') get buried. With more than two windows it acts on `next-window'. Sibling of `cj/kill-other-window' (M-S-o), which deletes the other window. This one keeps it.
</content>
</entry>
<entry>
<title>feat(window): resize the split with C-; b &lt;arrow&gt;</title>
<updated>2026-05-11T20:16:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T20:16:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=f837e5f7464932fc49c10a7442dc1a23af61b257'/>
<id>urn:sha1:f837e5f7464932fc49c10a7442dc1a23af61b257</id>
<content type='text'>
`C-; b &lt;left&gt;/&lt;right&gt;/&lt;up&gt;/&lt;down&gt;' moves the active window's divider that way (via `windsize'), then keeps `cj/window-resize-map' active so bare arrows keep nudging until any other key (or `C-g'/`&lt;escape&gt;'). `C-u N C-; b &lt;right&gt;' resizes by N.

windsize was on `C-s-&lt;arrow&gt;' (Ctrl+Super), which a tiling WM intercepts, so those keys were useless. I dropped that binding. The package is now `:commands'-deferred, and `windsize-cols'/`windsize-rows' drop to 2 (8/4 overshoots in a held nudge loop). `cj/window-resize-sticky' dispatches on the arrow that triggered it and arms the loop.
</content>
</entry>
<entry>
<title>feat(keymap): bind eval-buffer to C-; b e</title>
<updated>2026-05-11T16:07:01+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T16:07:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=de8659c61e47787c635ad9a6184fcef655ae89d2'/>
<id>urn:sha1:de8659c61e47787c635ad9a6184fcef655ae89d2</id>
<content type='text'>
`C-; b e' read best for `eval-buffer', but `e' was `cj/view-email-in-buffer' and the requested fallback `C-; b m' is `cj/move-buffer-and-file', so email-view moves to `C-; b E' (docstring and which-key updated).
</content>
</entry>
<entry>
<title>fix: use file basename when moving buffer + file</title>
<updated>2026-05-04T00:24:40+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-04T00:24:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=389e85c020e7e59977e3c832a281f8b7844fecd4'/>
<id>urn:sha1:389e85c020e7e59977e3c832a281f8b7844fecd4</id>
<content type='text'>
`cj/--move-buffer-and-file` was building the destination as `(concat dir "/" (buffer-name))`. If the buffer had been renamed via `M-x rename-buffer`, or uniquified by Emacs with a `&lt;2&gt;` suffix when a second buffer visited the same filename, the move wrote a file with the wrong name on disk.

I derived the destination basename from `buffer-file-name` instead, in both the internal helper and the interactive wrapper. The wrapper's overwrite-prompt now also formats the real target filename rather than the buffer name.

I added two regression tests: one for a renamed buffer visiting `original.txt`, and one for a `&lt;2&gt;` uniquified buffer with a trailing-slash target directory.
</content>
</entry>
</feed>
