<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/modules/calibredb-epub-config.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-24T21:57:56+00:00</updated>
<entry>
<title>docs(load-graph): classify domain, integration, and optional modules</title>
<updated>2026-05-24T21:57:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-24T21:57:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=cad351ec00c3f78cfb6e203d87c7309a620e485c'/>
<id>urn:sha1:cad351ec00c3f78cfb6e203d87c7309a620e485c</id>
<content type='text'>
Eighth classification batch: 17 domain/integration/optional modules — ai-config, ai-vterm, browser-config, calendar-sync, calibredb-epub-config, chrono-tools, dirvish-config, dwim-shell-config, erc-config, eshell-config, eww-config, flyspell-and-abbrev, games-config, gloss-config, httpd-config, jumper, latex-config. I annotated each header, added a Batch 8 table to the inventory, and extended the validation allowlist. 82 of 102 modules are now classified.

Almost all are eager only by init order and become command/hook/mode-loaded. calendar-sync stays eager when its .local.el is present. One new hidden dependency: calendar-sync guards its C-; g registration with a boundp shim and doesn't require keybindings, so the binding drops standalone.

I deferred elfeed-config rather than annotate it. Its header edit triggers byte-compilation, and the existing tests only pass when the module loads as interpreted source — the compiled cj/elfeed-process-entries inlines an elfeed struct accessor the stubs can't intercept, and the batch test environment has no elfeed package to build real structs. It needs its tests rewritten first, recorded in the inventory and a new todo task.

Also made the header allowlist scoping test durable: it used games-config (now classified) as its unclassified example; switched to a sentinel name plus a duplicate-entry guard.
</content>
</entry>
<entry>
<title>refactor(calibredb-epub): reorder defuns above their use-package consumers</title>
<updated>2026-05-15T05:37:08+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-15T05:37:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=afe93aec6227dfe0f3a3b5965c0c802c278875cb'/>
<id>urn:sha1:afe93aec6227dfe0f3a3b5965c0c802c278875cb</id>
<content type='text'>
`make compile' had been flagging `cj/calibredb-clear-filters' and
`cj/nov-jump-to-calibredb' as "defined multiple times in this file"
since 2026-05-12.  Investigation: there's only one `(defun ...)' of
each in the source -- use-package's `:bind' expansion makes the
byte-compiler count the referenced symbol as a definition when the
function is defined in the same file, then it sees the real
`defun' later and warns about a redefinition.

Reorder so each `defun' appears before the `use-package' that
references it via `:bind':

- `cj/calibredb-clear-filters' moved above (use-package calibredb).
- `cj/nov--metadata-get', `cj/nov--file-path', and
  `cj/nov-jump-to-calibredb' moved above (use-package nov).  The
  two helpers had to move with the public function so the
  byte-compiler doesn't emit fresh free-function warnings.

Source content unchanged; only line positions move.  Both
duplicate-definition warnings are gone after this; full unit suite
still green.
</content>
</entry>
<entry>
<title>fix(calibredb-epub): point cj/nov--file-path at nov-file-name</title>
<updated>2026-05-13T11:32:08+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-13T11:32:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=3f44db4f7be24c6daacad0956f019610aeb5f868'/>
<id>urn:sha1:3f44db4f7be24c6daacad0956f019610aeb5f868</id>
<content type='text'>
The fallback chain was checking `nov-epub-filename` and `nov-epub-file`, but neither symbol exists in nov.el — the real var is `nov-file-name`, set by `nov-mode` from the visited file. Both `boundp` arms always returned nil, so the fallbacks were dead code. The bug was dormant rather than active: `buffer-file-name` always holds the EPUB path for normal nov buffers and covered the first arm of the `or`.

I replaced both wrong-named arms with a single live arm on `nov-file-name`, and added a Boundary test that exercises it.
</content>
</entry>
<entry>
<title>refactor(calibredb-epub): extract the nov image-padding helper</title>
<updated>2026-05-13T11:27:38+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-13T11:27:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=9487ffef982ad0f9fb9e0e1930b3c5d82a50085f'/>
<id>urn:sha1:9487ffef982ad0f9fb9e0e1930b3c5d82a50085f</id>
<content type='text'>
I pulled the image-centering math out of `cj/nov-center-images` into `cj/--nov-image-padding-cols`. The wrapper still loops over the image text properties and writes the line/wrap-prefix. The helper takes col-width, img-px, and font-width-px and returns the left padding. With the math in a pure helper I can unit-test the centering rule directly instead of building a buffer with image-display properties.
</content>
</entry>
<entry>
<title>fix(nov): center the EPUB text by setting window margins directly</title>
<updated>2026-05-12T12:17:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-12T12:17:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=b7c6b2c59a2ad74e8e886471ea57b2e87f812d4a'/>
<id>urn:sha1:b7c6b2c59a2ad74e8e886471ea57b2e87f812d4a</id>
<content type='text'>
The 80% width from `4d9a206' wasn't actually narrowing the page: `cj/nov-apply-preferences' set `nov-text-width' to t (nov renders the text unfilled, one long line per paragraph) and counted on `visual-fill-column-mode' to set the window's display margins, but those margins never got applied in nov-mode buffers (even after manually re-running the layout), so the text wrapped at the full window width. The cause is still unknown.

This drops `visual-fill-column' from nov entirely:
- `nov-text-width' is a column count (~80% of the window's natural width), so nov's `shr' fills the text itself.
- `cj/nov-update-layout' sets the window's left/right margins directly to `(natural - text-width) / 2' each, centering the block, and pushes the fringes out to the window edge so they don't show as thin lines beside the text. When the width changes it re-renders, restoring the reading position approximately.
- `cj/nov-apply-preferences' adds a `kill-buffer-hook' that drops the margins and fringes when the EPUB buffer goes away, so a later buffer in that window isn't left indented.
- `+'/`=' and `-'/`_' adjust `cj/nov-margin-percent' and re-flow + re-center.

The text-width math moved into a `cj/nov--natural-window-width' helper alongside the existing `cj/nov--text-width'. Known nit: the centering is a touch left-of-center because shr wraps at word boundaries, so the rendered text is a bit narrower than `nov-text-width' and the right margin ends up slightly larger. Logged as a follow-up.
</content>
</entry>
<entry>
<title>feat(nov): default the EPUB text column to 80% of the window</title>
<updated>2026-05-12T11:17:11+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-12T11:17:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=4d9a2066a26cc82e81855d9ad343d76fd715dcbf'/>
<id>urn:sha1:4d9a2066a26cc82e81855d9ad343d76fd715dcbf</id>
<content type='text'>
`1c5c8bd' had set `cj/nov-margin-percent' to 12 (~76% text); 10 gives a round 80%. Adjust per-buffer with the `+'/`-' keys; clamp is unchanged (0..25, i.e. 50%..100%).
</content>
</entry>
<entry>
<title>fix(nov): rework the EPUB reading-width layout</title>
<updated>2026-05-12T11:07:20+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-12T11:07:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=1c5c8bd4df3bd4fd71fad13b2b57e670a4e74355'/>
<id>urn:sha1:1c5c8bd4df3bd4fd71fad13b2b57e670a4e74355</id>
<content type='text'>
`cj/nov--text-width-for-window' computed the target column as a percentage of `(window-body-width)'. But body width is the column count *after* the display margins. `cj/nov-update-layout' runs from `window-configuration-change-hook': it sets `visual-fill-column''s margins, which changes the body width, which fires the hook, which re-runs the layout against the now-narrower body, and so on. It's a shrinking feedback loop that bottoms out at `cj/nov-min-text-width' (40 columns) no matter what `cj/nov-margin-percent' is. That's why the column was a thin strip regardless of the margin setting.

The width is now computed from the window's *natural* column count (body width plus any margins already set), so re-running the layout is idempotent. The margin math moved into a pure `cj/nov--text-width' helper, which is what the unit tests drive, and there's a regression test that the result is the same whether or not margins are already in place.

Also:
- `+'/`=' (`cj/nov-widen-text') and `-'/`_' (`cj/nov-narrow-text') step `cj/nov-margin-percent' by `cj/nov-margin-step' and re-lay-out, reporting the new percentage. `cj/nov-margin-percent' is now clamped to 0..25, so the text column runs from 50% (the floor) to 100% (the full window).
- `cj/nov-margin-percent' default is 12 (≈76% text) for a comfortable starting width.
- `cj/nov-apply-preferences' re-renders the document at the end again. `b3b537f' removed that on the theory `visual-fill-column' would re-trigger the render. The first page came up off-center until a manual resize, so it's back.
- `cj/nov-update-layout' is now a command.

The visible result (a ~75% centered column on first open, `+`/`-` to adjust) needs a restart to confirm. The tests cover the width math and clamping, idempotency, the adjust commands and their keybindings, the command status, and the re-render.
</content>
</entry>
<entry>
<title>refactor(epub): clean up calibredb-epub-config.el</title>
<updated>2026-05-11T22:17:54+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T22:17:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=b3b537fb74de7950ccd58d0f09cd7f5fbf39f546'/>
<id>urn:sha1:b3b537fb74de7950ccd58d0f09cd7f5fbf39f546</id>
<content type='text'>
Dropped the 1-second `:defer' from the calibredb use-package and the redundant explicit `nov-render-document' call in `cj/nov-apply-preferences'. Nov / visual-fill-column text width now recalculates on `window-configuration-change-hook'. `cj/nov--text-width-for-window' computes the (clamped, minimum-readable) width and `cj/nov-update-layout' installs it buffer-locally. Lowered `calibredb-search-page-max-rows' from 20000 to 500 (pagination was effectively disabled). Replaced the anonymous zathura keybinding with `cj/nov-open-external'. Tests cover the width computation and the external-open binding.
</content>
</entry>
<entry>
<title>feat(dashboard,calibredb): reorganize nav buttons, tweak display settings</title>
<updated>2026-02-15T18:46:20+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-02-15T18:46:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=94164eec69a50bfb58d525faafb47c3fbba11d40'/>
<id>urn:sha1:94164eec69a50bfb58d525faafb47c3fbba11d40</id>
<content type='text'>
Dashboard: reorder nav rows (Code/Email/Agenda/Files/Music, Feeds/IRC/
Flashcards/Books/Terminal), show 10 recent files with filename only,
exclude EMMS history from recents. Calibredb: use bookmark emoji for
favorites, change favorite keyword to in-progress.
</content>
</entry>
<entry>
<title>fix(terminal): add console/mosh compatibility</title>
<updated>2026-01-24T04:42:10+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-01-24T04:42:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=3ed0e8ea7c39ea0eaaa48506b7b99dee5ee6ca30'/>
<id>urn:sha1:3ed0e8ea7c39ea0eaaa48506b7b99dee5ee6ca30</id>
<content type='text'>
- Create terminal-compat.el for arrow key escape sequences
- Fix M-uppercase keybindings (M-O → M-S-o, etc.) that conflicted
  with terminal escape sequences ESC O A/B/C/D
- Add GUI-only guards for emojify and icon rendering
- 18 keybindings updated across 13 modules with override comments
</content>
</entry>
</feed>
