Developing denote-data - rename hook, stale entries and a lean cache
- YT :: https://www.youtube.com/watch?v=5xNWU8EcUeI
- Original title :: Emacs: new 'denote-data-mode' testing
Live stream continuing work on denote-data, an opt-in, dependency-free, in-memory cache for Denote that speeds up lookups at large scale (link previews, future completion at point). Prot slims the cache, adds an internal abnormal hook so renames update the hash table without saving, and drops the idea of checking file existence on every cache read. Stale entries are instead removed lazily, when a command such as denote-link or denote-find-link tries to use a file that no longer exists. He ends doubting that after-save-hook is the right update trigger. Chat Q&A covers his keyboard layout, themes, keyboard macros, Magit and Jujutsu.
What denote-data is for
- At huge scale Denote can be slow: e.g. previewing image links in an Org file means scanning all files per link. A cache does the work once and then only tracks deltas.
- Opt-in; core Denote behaves as before. It will become its own package; it lives in
denote.elfor now for easier testing. - Not a database: pure Emacs Lisp, so no external dependency, but other programs can't read it. The abstractions are designed so someone could write a database-backed alternative.
Changes made
- Use
locate-libraryinstead oflocate-file(returns the.elcwhen present). - TODO: the async cache build loads default Denote settings, so it must pick up user options like
denote-directory. - Removed the
textslot from the entry struct. Storing every file's buffer string would put gigabytes in memory. Renamedforelinkstolinks(list of identifier strings). Struct changes need an Emacs restart to take effect. - New internal abnormal hook for
denote-rename-file, called with old identifier, identifier, title, keywords, signature and new path. Useful beyonddenote-data. denote-datahandles renames:remhashthe old identifier key and write a fresh entry under the new one. Setting the struct's identifier in place was a bug, because the hash key stayed old. Verified that the cache updates while the buffer is still unsaved.- Removed the macro that ran
file-exists-pon everymaphash: checking the whole table on each read defeats the purpose of a cache. Replaced with plainmaphashlambdas (written via a keyboard macro). get-path-by-idno longer touches the hash table.- New abnormal hook called when
denote-linktargets a missing file.denote-datauses it to remove the entry (denote-data-remove-file) before the user error.denote-find-linkanddenote-find-backlinkcall it too. Tested: deleted files disappear from the completion candidates after one failed attempt. denote-rewrite-front-matternow callsfind-file-noselectonce and reuses the buffer.- Ideas noted as TODOs: use file modification time to refresh only changed files; perhaps
buffer-modified-por diff-based checks (rejected for now to avoid depending ondiff.el). No advice ondelete-file/ Dired deletion: removing entries lazily when used is cheaper and safer. - Final TODO:
after-save-hookis probably the wrong trigger (e.g.save-some-buffers); use Denote's own command hooks instead and keep it self-contained.
Side notes from chat
- Keyboard: HJKL layer for arrows, YUIO row for Home / PgDn / PgUp / End. Thumbs: Alt (stretch), Control (rest), Shift (curl); pinky Control-Meta and Super.
- Themes: using
modus-vivendi-deuteranopia. Tinted Modus variants are his pick for safe defaults. Open to a dark Ef Summer–like theme PR; has an unfinished Doric dark draft in that spirit. fill-paragraphbreaking long words annoys him.fill-region-as-paragraph-defaultis a 156-line function that should take a predicate option.- One
setqper variable is easier to move, sort and undo, and costs the same as onesetqwith many pairs. - Keyboard macros beat templates for dynamic, one-off edits.
- If only one third-party package: Magit, with Vertico and Consult close behind. Git history surgery is hard to teach without a mental model. Aware of Jujutsu but not an early adopter.
- Display scaling on a 14" 1080p laptop: try a lower 16:9 resolution, since font size scaling isn't uniform across apps.