| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
| |
EPUB reading prefs were scattered: a hardcoded Merriweather/180 font-remap in calibredb-epub-config's nov hook, no color control (the old sepia foreground had been stripped), and a frame-global EBook fontaine preset as the only way to size up. That preset resized the font in every buffer in the frame, not just the book.
I pulled the reading view into its own layer, modules/nov-reading.el, on top of stock nov (no fork). It owns three things, all buffer-local: a reading palette (sepia/dark/light, each a face the dupre theme owns, sepia the default), the serif typography (family plus a defcustom base height replacing the hardcoded 180), and page font sizing (+/- bump the size live, = resets to the base). Width moves to { }. calibredb-epub-config keeps the library and width/centering layout. Its nov hook now calls into the layer.
The three palette faces register as a nov-reading app in theme-studio (face_data.py), so they're tunable there like any other app. I dropped the EBook fontaine preset, since reading size is buffer-local now.
|
| |
|
|
|
|
| |
The first-line header on 33 modules named the file without its .el extension (;;; font-config --- ... rather than ;;; font-config.el --- ...), the form checkdoc and package-lint expect and the other modules already use. I normalized all 33 to the canonical ;;; name.el --- summary shape. The change is line 1 only.
A new test, test-meta-package-headers.el, locks the convention. It checks every module for the canonical first line, Commentary before Code, a provide footer, and no BOM, and unit-tests the checker against each malformed shape so the guard itself is proven.
|
| |
|
|
|
|
| |
Every calibredb launch (the dashboard "b", M-x, anywhere) now opens filtered to the in-progress books rather than the whole library, via an :after advice on calibredb. Clear with L or x to see everything.
The filter scopes to the tag field (calibredb-tag-filter-p), not a bare keyword search. A bare keyword matches any field, which surfaced books that only mention "in-progress" in their description.
|
| |
|
|
|
|
| |
Bookmark reformatting to "Author, Title" was nov-only, so PDF bookmarks kept the raw filename. PDFs open in pdf-view-mode, whose pdf-view-bookmark-make-record carried no advice.
I added a parallel :filter-return advice there, reusing the same extension-agnostic filename parser, and renamed the helpers off the nov- prefix to reading- since they now serve both EPUB and PDF. New tests cover a PDF filename and a PDF-shaped record.
|
| |
|
|
| |
The theme-studio and browser-choice generators now stamp their output with a header that names the authoritative source and says to regenerate rather than hand-edit. I regenerated both files to match. I also deleted six obvious "describe the next form" comments, replaced two stale placeholders in titlecase.el and an incomplete FIXME in org-checklist.el with real rationale, and condensed early-init's header and Commentary.
|
| |
|
|
| |
22 module headers carried long user-manual commentaries (quick-starts, keybinding matrices, setup walkthroughs) that belong in user docs, not source. Each now states the purpose, load contract, and entry points tersely. ai-term also drops its stale F9 keybinding references (the scheme is C-; a plus M-SPC now) and a header line claiming a vertical-split that's really host-aware.
|
| |
|
|
| |
eww and nov both render with shr, which paints buffers with manual face properties, and global font-lock was overwriting them with syntactic string fontification, the same bug just fixed for elfeed. An audit of live buffers caught nov directly (two open epub buffers, faces clobbered). eww has font-lock-defaults nil too and is the same shr-rendered pattern as the already-excluded elfeed-show and mu4e-view, so I excluded it alongside. The *sdcv* dictionary buffer has its own font-lock-defaults, so its font-lock is by design and left alone.
|
| |
|
|
| |
Remove every hardcoded color from the config so nothing assigns a non-themeable value. Stripped: the org-faces defface defaults (28 hex foregrounds, which the theme overrides at runtime anyway), the hl-todo keyword colors, the eshell prompt gray/white, the org-noter and music active-window #1d1b19 bg tint (face-remap is now a no-op), the pdf-view midnight palette, and the calibredb/nov epub sepia. The config now renders with default/theme faces, which surfaces where theming support is missing. Those gaps are tracked in todo.org as the next phase. 0 hex colors remain; validate-modules clean and the org-faces/build-theme/face-diagnostic tests pass.
|
| |
|
|
|
|
|
|
| |
tramp, diff, chrono, auth)
Add declare-function/defvar declarations for lazily-loaded package functions and variables so each module compiles cleanly standalone; config-utilities wraps two lazy EmacSQL oref slot reads in with-no-warnings. No behavior change.
Claude-Session: https://claude.ai/code/session_01BqrdWUo9GcznYX2pZr76gZ
|
| |
|
|
|
|
|
| |
Lift the render-preserving-position block and the margin/fringe block out of
cj/nov-update-layout into cj/nov--rerender-preserving-position and
cj/nov--center-in-window, dropping its nesting. Fold the thrice-repeated
#E8DCC0 sepia literal in cj/nov-apply-preferences into one local binding.
|
| |
|
|
|
|
|
|
| |
5bfd74fd rebound eww/elfeed/calibredb from M-S-e/r/b to the uppercase Meta events M-E/M-R/M-B, on the theory that the keyboard emits the uppercase event and the lowercase-shift spec never matched. It was wrong. keyboard-compat.el installs a key-translation-map entry (M-E -> M-S-e, etc.) in GUI frames, so the original M-S- bindings did reach the launchers. Binding M-E directly while that translation stayed in place rewrote the keypress to the now-unbound M-S-e, breaking all three in GUI on the next restart.
The audit and the review missed it because they checked key-binding, which ignores key-translation-map, and the running daemon still held the pre-fix bindings as stale state.
This restores M-S-e/r/b, deletes the key-binding-only test that certified the broken config, and reclassifies the task as not-a-bug. The real problem, that these chords are dead outside GUI, is the subject of the keybinding-console-safety spec.
|
| |
|
|
| |
Meta+Shift+<letter> emits the uppercase event (M-E/M-R/M-B), so the M-S-e/M-S-r/M-S-b :bind specs on lowercase letters were never reached by the keychord and the three launchers were dead. Rebind them to M-E/M-R/M-B. Three ERT tests assert each chord resolves to eww, cj/elfeed-open, and calibredb respectively.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Three things in the calibredb search buffer.
A curated transient on ? exposes just my frequent workflows (switch library, filter by format or author, sort by author/title/pubdate/format, open, describe) instead of leaving me to remember calibredb's top-level single keys. calibredb's own full dispatch moves to H. which-key can't help here: these are mode-map single keys, not a prefix. So a curated menu on ? is the discoverable entry point. The transient is defined in :config rather than top-level: its macro expands against the elpa transient, but a batch Emacs loads the older built-in transient and breaks the load.
The book-detail view (d, or v) now docks to the bottom 30% and q dismisses it. calibredb-show-entry-switch goes to pop-to-buffer so a display-buffer-alist rule applies. The default switch-to-buffer-other-window ignores it. It's the same bottom-dock pattern as the signal chat buffer.
Sorting kept dropping the active filter. calibredb's macro-generated sort commands all end in calibredb-search-refresh-and-clear-filter, which nulls every filter flag. I override each to refresh via calibredb-search-refresh-or-resume, which re-applies the filter, so a sort over a filtered list keeps it. I used named advice, so reloading the module doesn't stack it.
Tests cover the describe command and the sort helper. The transient, bindings, dock, and advice wiring need the elpa transient and a live calibredb, so they're verified in the running daemon.
|
| |
|
|
|
|
|
|
|
|
| |
In a nov buffer m is bound to bookmark-set. nov's nov-bookmark-make-record names the record after the buffer name, the raw EPUB filename. So bookmarks read like "Frege_ A Guide for the Perplexed - Edward Kanterian.epub".
I advise nov-bookmark-make-record to rebuild the name from the record's filename: split on the last " - " into title and author per Calibre's "<Title> - <Author>.epub" naming, restore the colon Calibre sanitized to "_ ", and reorder to "Author, Title". That book becomes "Edward Kanterian, Frege: A Guide for the Perplexed".
I pulled the name from the filename rather than the embedded EPUB metadata on purpose. In real books the embedded metadata is the worse copy (truncated titles, authors in "Last, First" sort form, lost punctuation), while the filenames come from Calibre's curated database. A separate task tracks embedding the good metadata back into the files.
cj/--nov-clean-title and cj/--nov-bookmark-name-from-file are pure and carry the logic. The advice is a thin wrapper. 10 ERT tests cover colon restoration, the last-separator split, and the no-separator fallback.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The 80% width from `2c80724' 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.
|
| |
|
|
| |
`e094f22' 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%).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
`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. `0b66424' 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.
|
| |
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
- 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
|
| |
|
|
|
|
|
| |
- Reduce variable-pitch font from 1.8x to 1.0x for normal reading size
- Add configurable margin percentage (cj/nov-margin-percent, default 25%)
- Calculate text width dynamically based on window size and margins
- Text now uses 50% of window width with 25% margins on each side
|
| |
|
|
|
|
|
|
|
| |
Introduce nov-mode for .epub files, bypassing archive-mode
detection. Enhance reading experience with
visual-fill-column-centered text, Merriweather font, and improved
color scheme. Provide utilities for paragraph navigation and
document rendering. Improve previous nov-mode preferences for
consistent visual adjustments and text wrapping.
|
| | |
|
| |
|
|
|
|
|
| |
Looks like there might be two modes for nov-mode?
Add epub-mode as an alternative handler for .epub files with the
same preference settings as nov-mode.
|
| |
|