#+TITLE: Emacs Config Tasks #+AUTHOR: Craig Jennings * Emacs Open Work ** Org Mode *** VERIFY [#B] Continue org-noter custom workflow implementation (IN PROGRESS) Continue debugging and testing the custom org-noter workflow from 2025-11-21 session. This is partially implemented but has known issues that need fixing before it's usable. **Last worked on:** 2025-11-21 **Current status:** Implementation complete but has bugs, needs testing **Known Issues to Fix:** 1. **Double notes buffer appearing when pressing 'i' to insert note** - When user presses 'i' in document to insert a note, two notes buffers appear - Expected: single notes buffer appears - Need to debug why the insert-note function is creating duplicate buffers 2. **Toggle behavior refinement needed** - The toggle between document and notes needs refinement - May have edge cases with window management - Need to test various scenarios **Testing Needed:** 1. **EPUB files** - Test with EPUB documents (primary use case) 2. **Reopening existing notes** - Verify it works when notes file already exists 3. **Starting from notes file** - Test opening document from an existing notes file 4. **PDF files** - Verify compatibility with PDF workflow 5. **Edge cases:** - Multiple windows open - Splitting behavior - Window focus after operations **Implementation Files:** - modules/org-noter-config.el - Custom workflow implementation - Contains custom functions for document/notes toggling and insertion **Context:** This custom workflow is designed to make org-noter more ergonomic for Craig's reading/annotation workflow. It simplifies the toggle between document and notes, and streamlines note insertion. The core functionality is implemented but needs debugging before it's production-ready. **Next Steps:** 1. Debug the double buffer issue when pressing 'i' 2. Test all scenarios listed above 3. Refine toggle behavior based on testing 4. Document the final keybindings and workflow *** TODO [#B] Optimize org-capture target building performance 15-20 seconds every time capturing a task (12+ times/day). Major daily bottleneck - minutes lost waiting, plus context switching cost. ** Presentations *** TODO [#C] Add image insertion helper for slides Helper function to insert images with proper org-reveal attributes (sizing, background images, etc.) without remembering the syntax. *** TODO [#C] Adjust default font sizing for all slide elements Configure reveal.js font sizes for headings, body text, code blocks, etc. to better defaults via org-reveal-head-preamble CSS or custom theme. *** TODO [#C] Create custom dupre reveal.js theme Create a custom reveal.js CSS theme using colors from themes/dupre-palette.el. Install into reveal.js/css/theme/ for use with #+REVEAL_THEME: dupre. ** Slack *** VERIFY [#B] Test Slack desktop notifications (DM and @mention) Notifications were silently failing due to two bugs in cj/slack-notify: 1. ~slack-room-im-p~ (nonexistent) → ~slack-im-p~ (correct EIEIO predicate) 2. ~slack-message-to-string~ (propertized) → ~slack-message-body~ (plain text) **Testing Steps:** 1. Open slack-config.el and run ~M-x eval-buffer~ 2. Connect to Slack: ~C-; S s~ 3. In any Slack channel, type ~/remind me in 1 minute test notification~ 4. Wait for Slackbot DM — a desktop notification should appear 5. Verify notification shows "Slack: DM: Slackbot" as title with message body **If notification does NOT appear:** - Check ~*Messages*~ buffer for errors mentioning ~cj/slack-notify~ - Verify ~notify~ command works standalone: run ~notify info "Test" "Hello"~ in a terminal **Files Modified:** - modules/slack-config.el (cj/slack-notify function) *** VERIFY [#B] Test Slack mark-as-read and bury buffer (C-; S q) ~C-; S q~ was bound to ~slack-buffer-mark-as-read-and-bury~ which doesn't exist in the emacs-slack package. Replaced with ~cj/slack-mark-read-and-bury~. **Testing Steps:** 1. Open slack-config.el and run ~M-x eval-buffer~ 2. Connect to Slack: ~C-; S s~ 3. Open any channel with unread messages: ~C-; S c~ 4. Press ~C-; S q~ — buffer should bury without error 5. Reopen the same channel: ~C-; S c~ — it should no longer appear as unread **If it errors:** - Check ~*Messages*~ buffer for the specific error - Verify ~slack-current-buffer~ is bound in the Slack buffer: ~C-h v slack-current-buffer~ **Files Modified:** - modules/slack-config.el (new cj/slack-mark-read-and-bury function + keybinding) *** TODO [#C] Fix Slack reaction workflow (C-; S !) Reactions via ~C-; S !~ (~slack-message-add-reaction~) have two problems: 1. *Emoji picker only shows GitHub-style names* — without the ~emojify~ package, ~slack-select-emoji~ falls back to a flat ~completing-read~ over 1600+ names fetched from GitHub's iamcal/emoji-data. Common names like ~thumbsup~ and ~pray~ are buried. A curated shortlist of common reactions would fix the UX. 2. *CRITICAL: post-command-hook bug traps user in Slack buffer* — ~slack-reaction-echo-description~ is added to ~post-command-hook~ (buffer-local) in all Slack buffers. When the cursor lands on a reaction widget, it reads the ~reaction~ text property and calls ~slack-reaction-help-text~. If the reaction EIEIO object is malformed, the error fires on *every keystroke*, making it impossible to switch buffers, run M-x, or even C-g. The only escape is killing Emacs externally (~pkill emacs~). The fix must address this hook FIRST before any other reaction work. Approach: advise ~slack-reaction-echo-description~ with ~condition-case~ to silently catch errors, or remove it from ~post-command-hook~ entirely. Relevant code in emacs-slack: - ~slack-buffer.el:399~ — adds hook - ~slack-buffer.el:374~ — ~slack-reaction-echo-description~ definition - ~slack-reaction.el:72~ — ~slack-reaction-help-text~ method **Discovered:** 2026-03-06 ** AI / GPTel *** TODO [#B] Update stale model list in ai-config.el Model IDs are outdated. Update to current models. See cleanup task below for full list of issues. *** TODO [#C] Clean up ai-config.el **** Stale model list ~claude-opus-4-1-20250805~ and ~claude-3-5-sonnet-20241022~ are superseded. Update to current model IDs (claude-opus-4-6, claude-sonnet-4-6, etc.). **** ~gptel-backend~ set twice Lines 284 and 295 both do ~(setq gptel-backend gptel-claude-backend)~. Remove one. **** Dead code: ~cj/gptel-backends~ defvar Static alist at line 287 duplicates ~cj/gptel--available-backends~ (line 105) which dynamically builds the same thing. ~cj/gptel-backends~ is unused — delete it. **** Functions defined inside ~:config~ block ~cj/gptel--fresh-org-prefix~, ~cj/gptel--refresh-org-prefix~, ~cj/gptel-backend-and-model~, ~cj/gptel-insert-model-heading~ are defined inside use-package :config. Move outside like the other helpers for visibility and byte-compilation. **** ~gptel-confirm-tool-calls~ set to nil Allows LLMs to execute tool calls without confirmation. Intentional security trade-off — document or reconsider. **** ~gptel-include-reasoning~ set to ~'ignore~ Suppresses reasoning output from thinking models (o1, Claude extended thinking). Comment says TODO. Decide whether to enable. **** ~gptel-magit~ loads on every magit open Hook ~(magit-mode . gptel-magit-install)~ runs every magit session even when AI commit messages aren't needed. Minor overhead. **** Rewrite bound to ~&~ — unusual mnemonic ~gptel-rewrite~ bound to ~M-a &~. ~w~ is free in the keymap and more intuitive. **File:** modules/ai-config.el ** Calibre / EPUB *** TODO [#C] Clean up calibredb-epub-config.el 1. *Remove ~:defer 1~ from calibredb use-package* — loads calibredb 1 second after startup even though ~:commands~ and ~:bind~ already handle lazy loading. Free startup time. 2. *Double rendering on EPUB open* — ~cj/nov-apply-preferences~ calls ~(nov-render-document)~ explicitly, but it runs as a ~nov-mode~ hook which fires after nov already renders. Every EPUB open renders twice. 3. *visual-fill-column-width doesn't adapt on resize* — calculated once at open time based on window size. Resizing or splitting the window won't recalculate text width. Consider hooking ~window-size-change-functions~ or ~window-configuration-change-hook~. 4. *~calibredb-search-page-max-rows 20000~* — effectively disables pagination. Could slow down the search buffer if library grows large. Monitor or lower. 5. *Anonymous lambda for zathura keybinding* — ~("z" . (lambda ...))~ won't show a name in which-key or describe-key. Replace with a named function. **File:** modules/calibredb-epub-config.el ** Mail *** VERIFY [#B] Fix mail attachment workflow (currently awkward) Daily workflow improvement. ** Media & Recording *** TODO [#C] Consider Recording Enhancement via post-processing hooks Auto-compress after recording. Move to cloud sync directory. Generate transcript (once transcription workflow exists). ** UI, Keybindings & Completion *** TODO [#B] Review and rebind M-S- keybindings Changed from M-uppercase to M-S-lowercase for terminal compatibility. These may override useful defaults - review and pick better bindings: - M-S-b calibredb (was overriding backward-word) - M-S-c time-zones (was overriding capitalize-word) - M-S-d dwim-shell-menu (was overriding kill-word) - M-S-e eww (was overriding forward-sentence) - M-S-f fontaine (was overriding forward-word) - M-S-h split-below - M-S-i edit-indirect - M-S-k show-kill-ring (was overriding kill-sentence) - M-S-l switch-themes (was overriding downcase-word) - M-S-m kill-all-buffers - M-S-o kill-other-window - M-S-r elfeed - M-S-s window-swap - M-S-t toggle-split (was overriding transpose-words) - M-S-u winner-undo (was overriding upcase-word) - M-S-v split-right (was overriding scroll-down) - M-S-w wttrin (was overriding kill-ring-save) - M-S-y yank-media (was overriding yank-pop) - M-S-z undo-kill-buffer (was overriding zap-to-char) *** TODO [#C] Review and implement flycheck modeline customization spec Add flycheck status (error/warning counts) to custom modeline to make it visible again. **Spec Document:** [[file:docs/flycheck-modeline-customization-spec.org][flycheck-modeline-customization-spec.org]] **Summary:** Current custom modeline excludes minor-mode-alist where flycheck displays its status. Need to either: 1. Add flycheck's lighter directly to mode-line-format (simplest) 2. Customize flycheck prefix/indicator and add to modeline 3. Create custom flycheck segment with full control **Files to Modify:** - modules/flycheck-config.el (customize prefix/indicator) - modules/modeline-config.el (add to mode-line-format) **Recommended Approach:** Option 4 (Hybrid) from spec - customize flycheck variables + add to modeline. Simple, maintainable, respects flycheck's built-in logic. *** TODO [#C] Migrate from Company to Corfu :PROPERTIES: :COMPLETE_CONFIG: [[file:docs/someday-maybe.org::1611][todo.org:1611-1639]] :END: Complete config already exists in someday-maybe.org. Just needs to be executed. *** TODO [#C] Integrate prescient with Corfu (smart sorting) Already using prescient with vertico. Extend to Corfu after migration. ** Testing & CI *** TODO [#B] Add project-aware ERT test isolation when switching projects When switching between elisp projects (e.g., emacs.d to Chime), previously loaded ERT tests remain in memory causing confusion and wrong tests to run. **Problem:** - ERT tests globally registered in Emacs session - `M-x ert RET t RET` runs ALL loaded tests from ALL projects - Can accidentally run emacs.d tests when working on Chime - Current workaround: restart Emacs (loses session state) **Solution:** Create `cj/ert-clear-tests` and `cj/ert-run-current-project-tests`: - Clear tests when switching projects (hook into project-switch) - Use test name prefixes to selectively clear (cj/ vs chime-) - Only run current project's tests **Success Criteria:** - Switch projects -> old tests cleared - Only current project's tests run with `M-x ert` - Works with both interactive and batch runs *** TODO [#C] Evaluate and integrate Buttercup for behavior-driven integration tests Complex workflow testing capability. *** TODO [#C] Integrate undercover.el for test coverage Measure and track test coverage over time. *** TODO [#C] Set up melpazoid CI for MELPA submissions Validates packages meet MELPA standards. *** TODO [#C] Set up package-lint for elisp linting (chime, org-msg, wttrin) Catch packaging issues automatically. *** TODO [#C] Set up elisp-check GitHub Action Zero-config CI for Emacs packages. ** Code Architecture & Performance *** TODO [#B] Review all config and pull library functions into system-lib file Extract reusable utility functions scattered across modules into system-lib.el for better code organization and reusability. **Goal:** Create a centralized system utilities library where generic functions that check system state, detect programs, or provide low-level system operations can live. This makes them: - Easily discoverable - Reusable across modules - Testable in isolation - Following single-responsibility principle **Current State:** - system-lib.el exists with `cj/executable-exists-p` function - Already required at top of init.el (System Configuration section) - Has comprehensive test coverage (test-system-lib-executable-exists-p.el) **Task:** 1. Search entire config for candidate functions: - System queries (program detection, path checking, environment vars) - File system utilities (beyond buffer-file operations) - Process utilities - Platform detection helpers 2. Review each module for extraction candidates: - host-environment.el (already has some, may have more) - system-utils.el (may contain generic utilities) - Any module with functions that don't depend on mode-specific context 3. Move appropriate functions to system-lib.el: - Update function documentation - Add require statements where functions are used - Maintain backward compatibility (old locations can call new ones) 4. Add comprehensive test coverage for all moved functions 5. Document the purpose/scope of system-lib.el in its Commentary section **Criteria for inclusion in system-lib.el:** - Pure utility functions (no side effects) - System-level queries (executable detection, path operations) - Platform-agnostic where possible - No dependencies on mode-specific functionality - NOT buffer/file operations (those stay in custom-buffer-file.el) - NOT user-facing commands (those stay in their domain modules) *** TODO [#B] Build debug-profiling.el module Reusable profiling infrastructure for any future performance work. *** TODO [#C] Build localrepo and document limitations Repeatable installs and safe rollbacks. .localrepo only contains packages from package.el archives. Treesitter grammars are downloaded separately by treesit-auto on first use. For true offline reproducibility, need to cache treesitter grammars separately. *** TODO [#D] Optimize lorem-optimum performance and liber-primus.txt size Lorem-optimum text generation is generally slow but doesn't completely break workflow. Two benchmark tests were disabled (marked :slow) because they take MINUTES instead of seconds. **Current State:** - Tests disabled to unblock test suite (DONE 2025-11-09) - Performance is acceptable for daily use, but could be better - liber-primus.txt may be too large for optimal performance **Investigation:** 1. Profile lorem-optimum to find bottlenecks 2. Check if liber-primus.txt size needs optimization 3. Optimize performance to get tests under 5 seconds 4. Re-enable benchmark tests once performance is acceptable **Related Files:** - modules/lorem-optimum.el (needs profiling and optimization) - tests/test-lorem-optimum-benchmark.el (tests disabled with :tags '(:slow)) - liber-primus.txt (corpus file, may need size optimization) ** File Management & Shell *** TODO [#C] Create print function for dirvish bound to uppercase P Add a print function that works on printable files (PDF, txt, org, etc.) and bind it to uppercase P in dirvish-mode. Should detect file type and use appropriate print command (lpr for text files, print dialog for PDFs, etc.). *** TODO [#C] Investigate TRAMP/dirvish showing question marks for file dates Remote directories in dirvish show "?" instead of actual modification dates. Tried several approaches without success - needs deeper investigation. **Attempted fixes (all reverted):** 1. Connection-local dired-listing-switches with -alh (didn't help) 2. Disabling tramp-direct-async-process (reported to cause this, but disabling didn't fix it) 3. Hook to set different listing switches for remote vs local (didn't help) **Possible causes to investigate:** - dirvish may be using its own attribute fetching that bypasses dired-listing-switches - May need dirvish-specific configuration for remote file attributes - Could be an Emacs 29/30 + TRAMP + dirvish interaction issue - May require changes to how dirvish renders the file-size attribute on remote **Files involved:** - modules/tramp-config.el - modules/dirvish-config.el *** TODO [#D] Add status dashboard for dwim-shell-command processes Create a command to show all running dwim-shell-command processes with their status. Currently, there's no unified view of multiple running extractions/conversions. **Current behavior:** - Each command shows spinner in minibuffer while running - Process buffers created: `*Extract audio*`, etc. - On completion: buffer renamed to `*Extract audio done*` or `*Extract audio error*` - No way to see all running processes at once **Recommended approach:** Custom status buffer that reads `dwim-shell-command--commands`. Can add mode-line indicator later as enhancement. ** Authentication & Security *** TODO [#C] Finish terminal GPG pinentry configuration Continue work on terminal-mode GPG passphrase prompts (loopback mode). Branch: terminal-pinentry Changes in progress (modules/auth-config.el): - Use epa-pinentry-mode 'loopback in terminal - Use external pinentry (pinentry-dmenu) in GUI - Requires env-terminal-p from host-environment module ** API & Web Services *** VERIFY [#B] Test and review restclient.el implementation Test the new REST API client integration in a running Emacs session. **Keybindings to test:** - C-; R n — new scratch *restclient* buffer (should open in restclient-mode) - C-; R o — open .rest file (should default to data/ directory) - C-; R s — open SkyFi template (should auto-inject API key from authinfo) **Functional tests:** 1. Open tutorial-api.rest, run JSONPlaceholder GET (C-c C-c) — verify response inline 2. Run POST example — verify 201 response with fake ID 3. Run httpbin header echo — verify custom headers echoed back 4. Navigate between requests with C-c C-n / C-c C-p 5. Test jq filtering (requires jq installed): restclient-jq loaded? 6. Open scratch buffer (C-; R n), type a request manually, execute 7. which-key shows "REST client" menu under C-; R **SkyFi key injection (if authinfo entry exists):** - C-; R s should replace :skyfi-key = PLACEHOLDER with real key - Key should NOT be written to disk (verify file still shows PLACEHOLDER) * Emacs Resolved ** DONE [#B] Investigate missing yasnippet configuration CLOSED: [2026-02-16 Mon] Resolved: snippets were in ~/sync/org/snippets/ but directory was empty after machine migration. Restored 28 snippets from backup, relocated snippets-dir to ~/.emacs.d/snippets/ for source control. ** DONE [#B] Write Complete ERT Tests for This Config [13/13] CLOSED: [2026-02-16 Mon] All 13 modules covered: custom-case (43), custom-datetime (10), hugo-config (41), org-capture-config (22), modeline-config (26), config-utilities (11), org-agenda-config (31), org-contacts-config (40), ui-config (27), org-refile-config (16), org-webclipper (31), org-noter-config (30), browser-config (20). 172 test files, all passing. ** DONE [#B] Validate recording startup CLOSED: [2026-02-15 Sun 15:40] Check process status after starting. Parse ffmpeg output for errors. Show actual ffmpeg command for debugging. ** DONE [#C] Fix EMMS keybinding inconsistency with other buffers CLOSED: [2026-02-15 Sun 15:40] EMMS keybindings conflict with standard buffer keybindings, causing mistypes. Results in accidental destructive actions (clearing buffers), requires undo + context switch. Violates Intuitive value - muscle memory should help, not hurt.